diff options
author | ss150715 <none@none> | 2007-02-09 16:50:26 -0800 |
---|---|---|
committer | ss150715 <none@none> | 2007-02-09 16:50:26 -0800 |
commit | c7e4935f5b755b4bbeaec416f1ad24337aeac7a4 (patch) | |
tree | b0f2f912e4898d18e49625b694ac3fee2ec32a85 | |
parent | 72b9fce97841381c0dae054e0dddd25d76672405 (diff) | |
download | illumos-joyent-c7e4935f5b755b4bbeaec416f1ad24337aeac7a4.tar.gz |
PSARC/2006/436 Public DLPI Library
PSARC/2006/634 Public DLPI Library Addendum
6266613 libdlpi should provide a default timeout
6336199 snoop should be ported to libdlpi
6340802 libdlpi needs a more robust mechanism of handling expected messages
6512059 public libdlpi library needed
--HG--
rename : usr/src/cmd/cmd-inet/usr.sbin/snoop/dlprims.c => deleted_files/usr/src/cmd/cmd-inet/usr.sbin/snoop/dlprims.c
33 files changed, 2155 insertions, 2208 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/dlprims.c b/deleted_files/usr/src/cmd/cmd-inet/usr.sbin/snoop/dlprims.c index b2a36c9525..b2a36c9525 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/dlprims.c +++ b/deleted_files/usr/src/cmd/cmd-inet/usr.sbin/snoop/dlprims.c diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c index c297c2c75a..f5207c1303 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c @@ -14,10 +14,7 @@ #include "strings.h" #include "ifconfig.h" #include <compat.h> - -#include <sys/dlpi.h> #include <libdlpi.h> - #include <inet/ip.h> #define LOOPBACK_IF "lo0" @@ -459,8 +456,7 @@ main(int argc, char *argv[]) } if (!all) { (void) fprintf(stderr, - "ifconfig: %s: no such interface\n", - name); + "ifconfig: %s: no such interface\n", name); exit(1); } foreachinterface(ifconfig, argc, argv, af, onflags, offflags, @@ -3778,21 +3774,33 @@ get_lun(char *rsrc) * the utility must use SIOCSLIFMUXID. */ static void -plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) +plumb_one_device(int af) { - int arp_fd = -1; int arp_muxid = -1, ip_muxid; - int mux_fd; + int mux_fd, ip_fd, arp_fd; + int retval; + uint_t ppa; char *udp_dev_name; - dlpi_if_attr_t dia; + char provider[DLPI_LINKNAME_MAX]; + dlpi_handle_t dh_arp, dh_ip; - if (debug) - (void) printf("plumb_one_device: ifname %s, ppa %d\n", - diap->ifname, diap->ppa); + /* + * We use DLPI_NOATTACH because the ip module will do the attach + * itself for DLPI style-2 devices. + */ + retval = dlpi_open(name, &dh_ip, DLPI_NOATTACH); + if (retval != DLPI_SUCCESS) + Perrdlpi_exit("cannot open link", name, retval); - if (diap->style == DL_STYLE2 && dlpi_detach(ip_fd, -1) < 0) - Perror0_exit("dlpi_detach"); + if ((retval = dlpi_parselink(name, provider, &ppa)) != DLPI_SUCCESS) + Perrdlpi_exit("dlpi_parselink", name, retval); + if (debug) { + (void) printf("ifconfig: plumb_one_device: provider %s," + " ppa %u\n", provider, ppa); + } + + ip_fd = dlpi_fd(dh_ip); if (ioctl(ip_fd, I_PUSH, IP_MOD_NAME) == -1) Perror2_exit("I_PUSH", IP_MOD_NAME); @@ -3813,7 +3821,6 @@ plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) * At this point in time the kernel also allows an * override of the CANTCHANGE flags. */ - lifr.lifr_name[0] = '\0'; if (ioctl(ip_fd, SIOCGLIFFLAGS, (char *)&lifr) == -1) Perror0_exit("plumb_one_device: SIOCGLIFFLAGS"); @@ -3828,7 +3835,7 @@ plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) } /* record the device and module names as interface name */ - lifr.lifr_ppa = diap->ppa; + lifr.lifr_ppa = ppa; (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name)); /* set the interface name */ @@ -3853,7 +3860,7 @@ plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) Perror0_exit("plumb_one_device: SIOCFLIFFLAGS"); if (debug) { - (void) printf("plumb_one_device: %s got flags: \n", + (void) printf("ifconfig: plumb_one_device: %s got flags:\n", lifr.lifr_name); print_flags(lifr.lifr_flags); (void) putchar('\n'); @@ -3885,9 +3892,8 @@ plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) * PLINK the interface stream so that ifconfig can exit * without tearing down the stream. */ - if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) { + if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) Perror0_exit("I_PLINK for ip"); - } (void) close(mux_fd); return; } @@ -3899,15 +3905,18 @@ plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) * Note: modules specified by the user are pushed * only on the interface stream, not on the ARP stream. */ - if (debug) - (void) printf("plumb_one_device: ifname: %s\n", - diap->ifname); - arp_fd = dlpi_if_open(diap->ifname, &dia, _B_FALSE); + (void) printf("ifconfig: plumb_one_device: ifname: %s\n", name); - if (dia.style == DL_STYLE2 && dlpi_detach(arp_fd, -1) < 0) - Perror0_exit("dlpi_detach"); + /* + * We use DLPI_NOATTACH because the arp module will do the attach + * itself for DLPI style-2 devices. + */ + retval = dlpi_open(name, &dh_arp, DLPI_NOATTACH); + if (retval != DLPI_SUCCESS) + Perrdlpi_exit("cannot open link", name, retval); + arp_fd = dlpi_fd(dh_arp); if (ioctl(arp_fd, I_PUSH, ARP_MOD_NAME) == -1) Perror2_exit("I_PUSH", ARP_MOD_NAME); @@ -3920,7 +3929,8 @@ plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) if (errno != EEXIST) Perror0_exit("SIOCSLIFNAME for arp"); Perror0("SIOCSLIFNAME for arp"); - (void) close(arp_fd); + dlpi_close(dh_arp); + dlpi_close(dh_ip); (void) close(mux_fd); return; } @@ -3928,9 +3938,8 @@ plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) * PLINK the IP and ARP streams so that ifconfig can exit * without tearing down the stream. */ - if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) { + if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) Perror0_exit("I_PLINK for ip"); - } if ((arp_muxid = ioctl(mux_fd, I_PLINK, arp_fd)) == -1) { (void) ioctl(mux_fd, I_PUNLINK, ip_muxid); Perror0_exit("I_PLINK for arp"); @@ -3938,7 +3947,8 @@ plumb_one_device(dlpi_if_attr_t *diap, int ip_fd, int af) if (debug) (void) printf("arp muxid = %d\n", arp_muxid); - (void) close(arp_fd); + dlpi_close(dh_ip); + dlpi_close(dh_arp); (void) close(mux_fd); } @@ -4061,8 +4071,6 @@ static int inetplumb(char *arg, int64_t param) { char *strptr; - int dev_fd; - dlpi_if_attr_t dia; boolean_t islo; zoneid_t zoneid; @@ -4123,13 +4131,7 @@ inetplumb(char *arg, int64_t param) if (debug) (void) printf("inetplumb: %s af %d\n", name, afp->af_af); - if ((dev_fd = dlpi_if_open(name, &dia, _B_FALSE)) < 0) { - Perror2_exit("plumb", name); - /* NOTREACHED */ - } - - plumb_one_device(&dia, dev_fd, afp->af_af); - (void) close(dev_fd); + plumb_one_device(afp->af_af); return (0); } @@ -4216,6 +4218,23 @@ Perror2_exit(char *cmd, char *str) /* NOTREACHED */ } +void +Perrdlpi(const char *cmd, const char *linkname, int err) +{ + (void) fprintf(stderr, "ifconfig: %s \"%s\": %s\n", cmd, + linkname, dlpi_strerror(err)); +} + +/* + * Print out error message (Perrdlpi()) and exit + */ +void +Perrdlpi_exit(const char *cmd, const char *linkname, int err) +{ + Perrdlpi(cmd, linkname, err); + exit(1); +} + /* * If the last argument is non-NULL allow a <addr>/<n> syntax and * pass out <n> in *plenp. @@ -4515,63 +4534,31 @@ add_ni(char *name) static int devfs_entry(di_node_t node, di_minor_t minor, void *arg) { - char *provider; - int fd; - uint_t ppa; - dl_info_ack_t dlia; - char ifname[LIFNAMSIZ]; + char *provider; + char linkname[DLPI_LINKNAME_MAX]; + dlpi_handle_t dh; provider = di_minor_name(minor); - - if (strlen(provider) > LIFNAMSIZ) - return (DI_WALK_CONTINUE); - if (debug > 2) - fprintf(stderr, "provider = %s\n", provider); + (void) fprintf(stderr, "provider = %s\n", provider); - if ((fd = dlpi_open(provider)) < 0) + if (dlpi_makelink(linkname, provider, + di_instance(node)) != DLPI_SUCCESS) return (DI_WALK_CONTINUE); - if (debug > 2) - fprintf(stderr, "getting DL_INFO_ACK\n"); - - if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) < 0) - goto done; - - if (dlia.dl_provider_style == DL_STYLE1) { - if (debug > 2) - fprintf(stderr, "provider is DL_STYLE1\n"); - add_ni(provider); - goto done; - } - - if (debug > 2) - fprintf(stderr, "provider is DL_STYLE2\n"); + if (dlpi_open(linkname, &dh, 0) != DLPI_SUCCESS) + return (DI_WALK_CONTINUE); - if (di_minor_type(minor) != DDM_ALIAS) { + if (di_minor_type(minor) == DDM_ALIAS) { if (debug > 2) - (void) fprintf(stderr, - "non-alias node, ignoring\n"); - goto done; - } - - if (debug > 2) - (void) fprintf(stderr, - "alias node, using instance\n"); - ppa = di_instance(node); - - if (dlpi_attach(fd, -1, ppa) < 0) { + (void) fprintf(stderr, "alias node, using instance\n"); + add_ni(linkname); + } else { if (debug > 2) - (void) fprintf(stderr, - "non-existent PPA, ignoring\n"); - goto done; + (void) fprintf(stderr, "non-alias node, ignoring\n"); } - (void) snprintf(ifname, LIFNAMSIZ, "%s%d", provider, ppa); - add_ni(ifname); - -done: - (void) dlpi_close(fd); + dlpi_close(dh); return (DI_WALK_CONTINUE); } diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.h b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.h index be5990ce13..49af9e8f0a 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.h +++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.h @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* @@ -25,8 +25,6 @@ extern "C" { #define BAD_ADDR -1 /* prefix is invalid */ #define NO_PREFIX -2 /* no prefix was found */ -#define MAX_MODS 9 /* max modules that can be pushed on intr */ - /* No suitable header file defines this, though it's in libsocket */ extern int getnetmaskbyaddr(struct in_addr, struct in_addr *); @@ -36,11 +34,13 @@ extern void Perror0(char *); extern void Perror0_exit(char *); extern void Perror2(char *, char *); extern void Perror2_exit(char *, char *); +extern void Perrdlpi(const char *, const char *, int); +extern void Perrdlpi_exit(const char *, const char *, int); -extern int doifrevarp(char *, struct sockaddr_in *); +extern int doifrevarp(const char *, struct sockaddr_in *); -extern int dlpi_set_address(char *, uchar_t *, int); -extern void dlpi_print_address(char *); +extern int dlpi_set_address(const char *, uchar_t *, uint_t); +extern void dlpi_print_address(const char *); #ifdef __cplusplus } diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/revarp.c b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/revarp.c index 6b20803da5..af798ca2c6 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/revarp.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/ifconfig/revarp.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -31,13 +30,15 @@ #include "defs.h" #include "ifconfig.h" #include <sys/types.h> -#include <sys/dlpi.h> #include <libdlpi.h> #include <sys/sysmacros.h> +#include <sys/time.h> #include <deflt.h> #define IPADDRL sizeof (struct in_addr) #define RARPRETRIES 5 +#define MSEC2NSEC(msec) ((msec) * 1000000) +#define NSEC2MSEC(nsec) ((nsec) / 1000000) /* * The following value (8) is determined to work reliably in switched 10/100MB @@ -50,71 +51,66 @@ static char retries_var[] = "RARP_RETRIES="; static int rarp_timeout = RARPTIMEOUT; static int rarp_retries = RARPRETRIES; -static int rarp_write(int, struct arphdr *, uchar_t *, size_t, size_t); -static int rarp_open(char *, t_uscalar_t, size_t *, uchar_t **, - uchar_t **); +static dlpi_handle_t rarp_open(const char *, size_t *, uchar_t *, uchar_t *); +static int rarp_recv(dlpi_handle_t, struct arphdr *, size_t, size_t, int64_t); -/* ARGSUSED */ int -doifrevarp(char *ifname, struct sockaddr_in *laddr) +doifrevarp(const char *linkname, struct sockaddr_in *laddr) { - int if_fd; - struct pollfd pfd; - int s, flags, ret; - char *ctlbuf, *databuf, *cause; - struct strbuf ctl, data; + int s, retval; struct arphdr *req, *ans; struct in_addr from; struct in_addr answer; - union DL_primitives *dlp; struct lifreq lifr; - struct timeval senttime; - struct timeval currenttime; - int waittime; int tries_left; - size_t ifaddrlen, ifrarplen; - uchar_t *my_macaddr = NULL, *my_broadcast = NULL; + size_t physaddrlen, ifrarplen; + uchar_t my_macaddr[DLPI_PHYSADDR_MAX]; + uchar_t my_broadcast[DLPI_PHYSADDR_MAX]; + dlpi_handle_t dh; - - if (ifname[0] == '\0') { + if (linkname[0] == '\0') { (void) fprintf(stderr, "ifconfig: doifrevarp: name not set\n"); exit(1); } if (debug) - (void) printf("doifrevarp interface %s\n", ifname); + (void) printf("doifrevarp interface %s\n", linkname); - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) Perror0_exit("socket"); - } - (void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); - if (ioctl(s, SIOCGLIFFLAGS, (char *)&lifr) < 0) + + (void) strlcpy(lifr.lifr_name, linkname, sizeof (lifr.lifr_name)); + if (ioctl(s, SIOCGLIFFLAGS, (char *)&lifr) < 0) { + (void) close(s); Perror0_exit("SIOCGLIFFLAGS"); + } /* don't try to revarp if we know it won't work */ if ((lifr.lifr_flags & IFF_LOOPBACK) || (lifr.lifr_flags & IFF_NOARP) || - (lifr.lifr_flags & IFF_POINTOPOINT)) + (lifr.lifr_flags & IFF_POINTOPOINT)) { + (void) close(s); return (0); + } /* open rarp interface */ - if_fd = rarp_open(ifname, ETHERTYPE_REVARP, &ifaddrlen, &my_macaddr, - &my_broadcast); - if (if_fd < 0) + dh = rarp_open(linkname, &physaddrlen, my_macaddr, my_broadcast); + if (dh == NULL) { + (void) close(s); return (0); + } /* * RARP looks at /etc/ethers and NIS, which only works * with 6 byte addresses currently. */ - if (ifaddrlen != ETHERADDRL) { - (void) close(if_fd); - free(my_macaddr); - free(my_broadcast); + if (physaddrlen != ETHERADDRL) { + dlpi_close(dh); + (void) close(s); return (0); } - ifrarplen = sizeof (struct arphdr) + (2 * IPADDRL) + (2 * ifaddrlen); + ifrarplen = sizeof (struct arphdr) + (2 * IPADDRL) + (2 * physaddrlen); /* look for adjustments to rarp_retries in the RARP defaults file */ if (defopen(defaultfile) == 0) { @@ -131,12 +127,11 @@ doifrevarp(char *ifname, struct sockaddr_in *laddr) } /* allocate request and response buffers */ - if (((req = (struct arphdr *)malloc(ifrarplen)) == NULL) || - ((ans = (struct arphdr *)malloc(ifrarplen)) == NULL)) { - (void) close(if_fd); + if (((req = malloc(ifrarplen)) == NULL) || + ((ans = malloc(ifrarplen)) == NULL)) { + dlpi_close(dh); + (void) close(s); free(req); - free(my_macaddr); - free(my_broadcast); return (0); } @@ -144,385 +139,249 @@ doifrevarp(char *ifname, struct sockaddr_in *laddr) (void) memset(req, 0, ifrarplen); req->ar_hrd = htons(ARPHRD_ETHER); req->ar_pro = htons(ETHERTYPE_IP); - req->ar_hln = ifaddrlen; + req->ar_hln = physaddrlen; req->ar_pln = IPADDRL; req->ar_op = htons(REVARP_REQUEST); - (void) memcpy((uchar_t *)req + sizeof (struct arphdr), my_macaddr, - ifaddrlen); + (void) memcpy(&req[1], my_macaddr, physaddrlen); (void) memcpy((uchar_t *)req + sizeof (struct arphdr) + IPADDRL + - ifaddrlen, my_macaddr, ifaddrlen); - - tries_left = rarp_retries; -rarp_retry: - /* send the request */ - if (rarp_write(if_fd, req, my_broadcast, ifaddrlen, ifrarplen) < 0) - goto fail; - - gettimeofday(&senttime, NULL); - - if (debug) - (void) printf("rarp sent\n"); - - - /* read the answers */ - if ((databuf = malloc(BUFSIZ)) == NULL) { - (void) fprintf(stderr, "ifconfig: malloc() failed\n"); - goto fail; - } - if ((ctlbuf = malloc(BUFSIZ)) == NULL) { - (void) fprintf(stderr, "ifconfig: malloc() failed\n"); - goto fail; - } - for (;;) { - ctl.len = 0; - ctl.maxlen = BUFSIZ; - ctl.buf = ctlbuf; - data.len = 0; - data.maxlen = BUFSIZ; - data.buf = databuf; - flags = 0; - - /* - * Check to see when the packet was last sent. - * If we have not sent a packet in the last - * RARP_TIMEOUT seconds, we should send one now. - * Note that if some other host on the network is - * sending a broadcast packet, poll will return and we - * will find out that it does not match the reply we - * are waiting for and then go back to poll. If the - * frequency of such packets is > rarp_timeout, we don't - * want to just go back to poll. We should send out one - * more RARP request before blocking in poll. - */ - - gettimeofday(¤ttime, NULL); - waittime = rarp_timeout - - (currenttime.tv_sec - senttime.tv_sec); - - if (waittime <= 0) { - if (--tries_left > 0) { - if (debug) - (void) printf("rarp retry\n"); - goto rarp_retry; - } else { - if (debug) - (void) printf("rarp timeout\n"); - goto fail; - } - } - - /* start RARP reply timeout */ - pfd.fd = if_fd; - pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; - if ((ret = poll(&pfd, 1, waittime * 1000)) == 0) { - if (--tries_left > 0) { - if (debug) - (void) printf("rarp retry\n"); - goto rarp_retry; - } else { - if (debug) - (void) printf("rarp timeout\n"); - goto fail; - } - } else if (ret == -1) { - perror("ifconfig: RARP reply poll"); - goto fail; + physaddrlen, my_macaddr, physaddrlen); + + for (tries_left = rarp_retries; tries_left > 0; --tries_left) { + /* send the request */ + retval = dlpi_send(dh, my_broadcast, physaddrlen, req, + ifrarplen, NULL); + if (retval != DLPI_SUCCESS) { + Perrdlpi("doifrevarp: cannot send rarp request", + linkname, retval); + break; } - /* poll returned > 0 for this fd so getmsg should not block */ - if ((ret = getmsg(if_fd, &ctl, &data, &flags)) < 0) { - perror("ifconfig: RARP reply getmsg"); - goto fail; - } + if (debug) + (void) printf("rarp sent\n"); - if (debug) { - (void) printf("rarp: ret[%d] ctl.len[%d] data.len[%d] " - "flags[%d]\n", ret, ctl.len, data.len, flags); - } - /* Validate DL_UNITDATA_IND. */ - /* LINTED: malloc returns a pointer aligned for any use */ - dlp = (union DL_primitives *)ctlbuf; - if (debug) { - (void) printf("rarp: dl_primitive[%lu]\n", - dlp->dl_primitive); - if (dlp->dl_primitive == DL_ERROR_ACK) { - (void) printf( - "rarp: err ak: dl_errno %lu errno %lu\n", - dlp->error_ack.dl_errno, - dlp->error_ack.dl_unix_errno); - } - if (dlp->dl_primitive == DL_UDERROR_IND) { - (void) printf("rarp: ud err: err[%lu] len[%lu] " - "off[%lu]\n", - dlp->uderror_ind.dl_errno, - dlp->uderror_ind.dl_dest_addr_length, - dlp->uderror_ind.dl_dest_addr_offset); - } - } - (void) memcpy(ans, databuf, ifrarplen); - cause = NULL; - if (ret & MORECTL) - cause = "MORECTL flag"; - else if (ret & MOREDATA) - cause = "MOREDATA flag"; - else if (ctl.len == 0) - cause = "missing control part of message"; - else if (ctl.len < 0) - cause = "short control part of message"; - else if (dlp->dl_primitive != DL_UNITDATA_IND) - cause = "not unitdata_ind"; - else if (ctl.len < DL_UNITDATA_IND_SIZE) - cause = "short unitdata_ind"; - - else if (data.len < ifrarplen) - cause = "short arp"; - else if (ans->ar_hrd != htons(ARPHRD_ETHER)) - cause = "hrd"; - else if (ans->ar_pro != htons(ETHERTYPE_IP)) - cause = "pro"; - else if (ans->ar_hln != ifaddrlen) - cause = "hln"; - else if (ans->ar_pln != IPADDRL) - cause = "pln"; - if (cause) { - (void) fprintf(stderr, - "sanity check failed; cause: %s\n", cause); - continue; - } + retval = rarp_recv(dh, ans, ifrarplen, physaddrlen, + rarp_timeout * MILLISEC); - switch (ntohs(ans->ar_op)) { - case ARPOP_REQUEST: - if (debug) - (void) printf("Got an arp request\n"); + if (retval != DLPI_ETIMEDOUT) break; - case ARPOP_REPLY: - if (debug) - (void) printf("Got an arp reply.\n"); - break; - - case REVARP_REQUEST: - if (debug) - (void) printf("Got a rarp request.\n"); - break; + if (debug) + (void) printf("rarp retry\n"); + } - case REVARP_REPLY: + if (retval == DLPI_SUCCESS) { + (void) memcpy(&answer, (uchar_t *)ans + + sizeof (struct arphdr) + (2 * physaddrlen) + IPADDRL, + sizeof (answer)); + (void) memcpy(&from, (uchar_t *)ans + physaddrlen + + sizeof (struct arphdr), sizeof (from)); - (void) memcpy(&answer, (uchar_t *)ans + - sizeof (struct arphdr) + (2 * ifaddrlen) + - IPADDRL, sizeof (answer)); - (void) memcpy(&from, (uchar_t *)ans + - sizeof (struct arphdr) + ifaddrlen, sizeof (from)); - if (debug) { - (void) printf("answer: %s", inet_ntoa(answer)); - (void) printf(" [from %s]\n", inet_ntoa(from)); - } - laddr->sin_addr = answer; - (void) close(if_fd); - free(req); - free(ans); - free(my_macaddr); - free(my_broadcast); - return (1); - - default: - (void) fprintf(stderr, - "ifconfig: unknown opcode 0x%xd\n", ans->ar_op); - break; + if (debug) { + (void) printf("answer: %s", inet_ntoa(answer)); + (void) printf(" [from %s]\n", inet_ntoa(from)); } + laddr->sin_addr = answer; + } else if (debug) { + Perrdlpi("doifrevarp: could not receive rarp reply", + linkname, retval); } - /* NOTREACHED */ -fail: - (void) close(if_fd); + + dlpi_close(dh); + (void) close(s); free(req); free(ans); - free(my_macaddr); - free(my_broadcast); - return (0); + return (retval == DLPI_SUCCESS); } /* * Open the datalink provider device and bind to the REVARP type. - * Return the resulting descriptor. + * Return the resulting DLPI handle. */ -static int -rarp_open(char *ifname, t_uscalar_t type, size_t *alen, uchar_t **myaddr, - uchar_t **mybaddr) +static dlpi_handle_t +rarp_open(const char *linkname, size_t *alen, uchar_t *myaddr, uchar_t *mybaddr) { - int fd, len; - char *str; - dl_info_ack_t dlinfo; - dlpi_if_attr_t dia; - int i; + int retval; + char *physaddr, *bcastaddr; + dlpi_info_t dlinfo; + dlpi_handle_t dh; if (debug) - (void) printf("rarp_open %s\n", ifname); + (void) printf("rarp_open %s\n", linkname); - fd = dlpi_if_open(ifname, &dia, _B_FALSE); - if (fd < 0) { - (void) fprintf(stderr, "ifconfig: could not open device for " - "%s\n", ifname); - return (-1); + if ((retval = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) { + Perrdlpi("rarp_open: dlpi_open failed", linkname, retval); + return (NULL); } - if (dlpi_info(fd, -1, &dlinfo, NULL, NULL, NULL, NULL, NULL, - NULL) < 0) { - (void) fprintf(stderr, "ifconfig: info req failed\n"); + if ((retval = dlpi_bind(dh, ETHERTYPE_REVARP, NULL)) != DLPI_SUCCESS) { + Perrdlpi("rarp_open: dlpi_bind failed", linkname, retval); goto failed; } - if ((*mybaddr = malloc(dlinfo.dl_brdcst_addr_length)) == NULL) { - (void) fprintf(stderr, "rarp_open: malloc() failed\n"); + if ((retval = dlpi_info(dh, &dlinfo, 0)) != DLPI_SUCCESS) { + Perrdlpi("rarp_open: dlpi_info failed", linkname, retval); goto failed; } - if (dlpi_info(fd, -1, &dlinfo, NULL, NULL, NULL, NULL, *mybaddr, - NULL) < 0) { - (void) fprintf(stderr, "ifconfig: info req failed\n"); + if (dlinfo.di_bcastaddrlen == 0) { + (void) fprintf(stderr, "ifconfig: rarp_open: %s broadcast " + "not supported\n", linkname); goto failed; } - if (debug) { - (void) printf("broadcast addr: "); - for (i = 0; i < dlinfo.dl_brdcst_addr_length; i++) - (void) printf("%02x", (*mybaddr)[i]); - (void) printf("\n"); - } + /* we assume the following are equal and fill in 'alen' */ + assert(dlinfo.di_bcastaddrlen == dlinfo.di_physaddrlen); - len = *alen = dlinfo.dl_addr_length - abs(dlinfo.dl_sap_length); + (void) memcpy(mybaddr, dlinfo.di_bcastaddr, dlinfo.di_bcastaddrlen); - if (debug) - (void) printf("rarp_open: addr length = %d\n", len); + *alen = dlinfo.di_physaddrlen; - if ((*myaddr = malloc(len)) == NULL) { - (void) fprintf(stderr, "rarp_open: malloc() failed\n"); - goto failed; - } - - if (dlpi_bind(fd, -1, type, DL_CLDLS, _B_FALSE, NULL, NULL, - *myaddr, NULL) < 0) { - (void) fprintf(stderr, "rarp_open: dlpi_bind failed\n"); - goto failed; - } + (void) memcpy(myaddr, dlinfo.di_physaddr, dlinfo.di_physaddrlen); if (debug) { - str = _link_ntoa(*myaddr, str, len, IFT_OTHER); - if (str != NULL) { - (void) printf("device %s mac address %s\n", - ifname, str); - free(str); + bcastaddr = _link_ntoa(mybaddr, NULL, dlinfo.di_bcastaddrlen, + IFT_OTHER); + + physaddr = _link_ntoa(myaddr, NULL, dlinfo.di_physaddrlen, + IFT_OTHER); + + if (physaddr != NULL && bcastaddr != NULL) { + (void) printf("device %s: broadcast address %s, mac " + "address %s\n", linkname, bcastaddr, physaddr); } + + free(physaddr); + free(bcastaddr); + + (void) printf("rarp_open: addr length = %d\n", + dlinfo.di_physaddrlen); } - return (fd); + return (dh); failed: - (void) dlpi_close(fd); - free(*mybaddr); - free(*myaddr); - return (-1); + dlpi_close(dh); + return (NULL); } +/* + * Read reply for RARP request. If a reply is received within waitms, + * validate the reply. If it is a correct RARP reply return DLPI_SUCCESS, + * otherwise return DLPI_ETIMEDOUT. If there is an error while reading retrun + * the error code. + */ static int -rarp_write(int fd, struct arphdr *ahdr, uchar_t *dhost, size_t maclen, - size_t rarplen) +rarp_recv(dlpi_handle_t dh, struct arphdr *ans, size_t msglen, + size_t physaddrlen, int64_t waitms) { - struct strbuf ctl, data; - union DL_primitives *dlp; - char *ctlbuf; - int ret; - ushort_t etype = ETHERTYPE_REVARP; + int retval; + char *cause; + size_t anslen = msglen; + hrtime_t endtime = gethrtime() + MSEC2NSEC(waitms); + hrtime_t currtime; + + while ((currtime = gethrtime()) < endtime) { + waitms = NSEC2MSEC(endtime - currtime); + retval = dlpi_recv(dh, NULL, NULL, ans, &anslen, waitms, NULL); + if (retval == DLPI_SUCCESS) { + cause = NULL; + + if (anslen < msglen) + cause = "short packet"; + else if (ans->ar_hrd != htons(ARPHRD_ETHER)) + cause = "hardware type not Ethernet"; + else if (ans->ar_pro != htons(ETHERTYPE_IP)) + cause = "protocol type not IP"; + else if (ans->ar_hln != physaddrlen) + cause = "unexpected hardware address length"; + else if (ans->ar_pln != IPADDRL) + cause = "unexpected protocol address length"; + if (cause != NULL) { + (void) fprintf(stderr, "RARP packet received " + "but discarded (%s)\n", cause); + continue; + } + switch (ntohs(ans->ar_op)) { + case REVARP_REQUEST: + if (debug) + (void) printf("Got a rarp request.\n"); + break; - /* - * Construct DL_UNITDATA_REQ. Allocate at least BUFSIZ bytes. - */ - ctl.len = DL_UNITDATA_REQ_SIZE + maclen + sizeof (ushort_t); - if ((ctl.buf = ctlbuf = malloc(ctl.len)) == NULL) { - (void) fprintf(stderr, "ifconfig: malloc() failed\n"); - return (-1); + case REVARP_REPLY: + return (DLPI_SUCCESS); + + default: + (void) fprintf(stderr, "ifconfig: unknown " + "RARP opcode 0x%x\n", ans->ar_op); + break; + } + } else if (retval != DLPI_ETIMEDOUT) { + Perrdlpi("doifrevarp: dlpi_recv failed", + dlpi_linkname(dh), retval); + return (retval); + } } - /* LINTED: malloc returns a pointer aligned for any use */ - dlp = (union DL_primitives *)ctlbuf; - dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; - dlp->unitdata_req.dl_dest_addr_length = maclen + sizeof (ushort_t); - dlp->unitdata_req.dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE; - dlp->unitdata_req.dl_priority.dl_min = 0; - dlp->unitdata_req.dl_priority.dl_max = 0; - /* - * XXX FIXME Assumes a specific DLPI address format. - */ - (void) memcpy(ctlbuf + DL_UNITDATA_REQ_SIZE, dhost, maclen); - (void) memcpy(ctlbuf + DL_UNITDATA_REQ_SIZE + maclen, &etype, - sizeof (etype)); - - /* Send DL_UNITDATA_REQ. */ - data.len = rarplen; - data.buf = (char *)ahdr; - ret = putmsg(fd, &ctl, &data, 0); - free(ctlbuf); - return (ret); + return (DLPI_ETIMEDOUT); } int -dlpi_set_address(char *ifname, uchar_t *ea, int length) +dlpi_set_address(const char *linkname, uchar_t *physaddr, uint_t physaddrlen) { - int fd; - dlpi_if_attr_t dia; + int retval; + dlpi_handle_t dh; - fd = dlpi_if_open(ifname, &dia, _B_FALSE); - if (fd < 0) { - (void) fprintf(stderr, "ifconfig: could not open device for " - "%s\n", ifname); + if ((retval = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) { + Perrdlpi("dlpi_open failed", linkname, retval); return (-1); } - if (dlpi_set_phys_addr(fd, -1, ea, length) < 0) { - (void) dlpi_close(fd); + if ((retval = dlpi_set_physaddr(dh, DL_CURR_PHYS_ADDR, physaddr, + physaddrlen)) != DLPI_SUCCESS) { + Perrdlpi("dlpi_set_physaddr failed", linkname, retval); + dlpi_close(dh); return (-1); } - (void) dlpi_close(fd); + dlpi_close(dh); return (0); } void -dlpi_print_address(char *ifname) +dlpi_print_address(const char *linkname) { - int fd, len; - uchar_t *laddr; - dl_info_ack_t dl_info; - char *str = NULL; - dlpi_if_attr_t dia; - - fd = dlpi_if_open(ifname, &dia, _B_FALSE); - if (fd < 0) { + uint_t physaddrlen = DLPI_PHYSADDR_MAX; + uchar_t physaddr[DLPI_PHYSADDR_MAX]; + char *str; + int retv; + dlpi_handle_t dh; + dlpi_info_t dlinfo; + + if (dlpi_open(linkname, &dh, 0) != DLPI_SUCCESS) { /* Do not report an error */ return; } - if (dlpi_info(fd, -1, &dl_info, NULL, NULL, NULL, NULL, NULL, - NULL) < 0) { - (void) fprintf(stderr, "ifconfig: info req failed\n"); - (void) dlpi_close(fd); + retv = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, physaddr, &physaddrlen); + if (retv != DLPI_SUCCESS) { + Perrdlpi("dlpi_get_physaddr failed", linkname, retv); + dlpi_close(dh); return; } - len = dl_info.dl_addr_length - abs(dl_info.dl_sap_length); - if ((laddr = malloc(len)) == NULL) { - goto failed; + retv = dlpi_info(dh, &dlinfo, 0); + if (retv != DLPI_SUCCESS) { + Perrdlpi("dlpi_info failed", linkname, retv); + dlpi_close(dh); + return; } + dlpi_close(dh); - if (dlpi_phys_addr(fd, -1, DL_CURR_PHYS_ADDR, laddr, NULL) < 0) { - (void) fprintf(stderr, "ifconfig: phys_addr failed\n"); - goto failed; - } + str = _link_ntoa(physaddr, NULL, physaddrlen, IFT_OTHER); - (void) dlpi_close(fd); - str = _link_ntoa(laddr, str, len, IFT_OTHER); if (str != NULL) { - switch (dl_info.dl_mac_type) { + switch (dlinfo.di_mactype) { case DL_IB: (void) printf("\tipib %s \n", str); break; @@ -532,8 +391,4 @@ dlpi_print_address(char *ifname) } free(str); } - -failed: - free(laddr); - (void) dlpi_close(fd); } diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile index 4be340b128..ee1dec05cb 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/Makefile @@ -28,7 +28,7 @@ # PROG= snoop -OBJS= dlprims.o nfs4_xdr.o snoop.o snoop_aarp.o snoop_adsp.o snoop_aecho.o \ +OBJS= nfs4_xdr.o snoop.o snoop_aarp.o snoop_adsp.o snoop_aecho.o \ snoop_apple.o snoop_arp.o snoop_atp.o snoop_bparam.o \ snoop_capture.o snoop_dhcp.o snoop_dhcpv6.o snoop_display.o \ snoop_dns.o snoop_ether.o \ diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c index ff43c225a7..fc083aeeb0 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -110,7 +110,6 @@ main(int argc, char **argv) int Cflg = 0; int first = 1; int last = 0x7fffffff; - int ppa; int use_kern_pf; char *p, *p2; char names[MAXPATHLEN + 1]; @@ -123,6 +122,7 @@ main(int argc, char **argv) stack_t sigstk; char *output_area; int nbytes; + dlpi_handle_t dh; names[0] = '\0'; /* @@ -361,7 +361,7 @@ main(int argc, char **argv) * requested was chosen, but that's too hard. */ if (!icapfile) { - use_kern_pf = check_device(&device, &ppa); + use_kern_pf = check_device(&dh, &device); } else { cap_open_read(icapfile); @@ -479,11 +479,12 @@ main(int argc, char **argv) timeout.tv_usec = 0; } - initdevice(device, snaplen, chunksize, &timeout, fp, ppa); + initdevice(dh, snaplen, chunksize, &timeout, fp); if (! qflg && ocapfile) show_count(); resetperm(); - net_read(chunksize, filter, proc, flags); + net_read(dh, chunksize, filter, proc, flags); + dlpi_close(dh); if (!(flags & F_NOW)) (void) printf("\n"); @@ -733,6 +734,25 @@ pr_err(const char *fmt, ...) } /* + * Store a copy of linkname associated with the DLPI handle. + * Save errno before closing the dlpi handle so that the + * correct error value is used if 'err' is a system error. + */ +void +pr_errdlpi(dlpi_handle_t dh, const char *cmd, int err) +{ + int save_errno = errno; + char linkname[DLPI_LINKNAME_MAX]; + + (void) strlcpy(linkname, dlpi_linkname(dh), sizeof (linkname)); + + dlpi_close(dh); + errno = save_errno; + + pr_err("%s on \"%s\": %s", cmd, linkname, dlpi_strerror(err)); +} + +/* * Ye olde usage proc * PLEASE keep this up to date! * Naive users *love* this stuff. diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h index ff40866bd4..e9274319f2 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop.h @@ -44,6 +44,7 @@ #include <netinet/ip_icmp.h> #include <netinet/icmp6.h> #include <net/pppoe.h> +#include <libdlpi.h> #ifdef __cplusplus extern "C" { @@ -176,14 +177,14 @@ extern int pf_compile(char *, int); extern void compile(char *, int); extern void load_names(char *); extern void cap_write(struct sb_hdr *, char *, int, int); -extern void cap_open_read(char *); -extern void cap_open_write(char *); +extern void cap_open_read(const char *); +extern void cap_open_write(const char *); extern void cap_read(int, int, int, void (*)(), int); extern void cap_close(void); -extern boolean_t check_device(char **, int *); -extern void initdevice(char *, ulong_t, ulong_t, struct timeval *, - struct Pf_ext_packetfilt *, int); -extern void net_read(int, int, void (*)(), int); +extern boolean_t check_device(dlpi_handle_t *, char **); +extern void initdevice(dlpi_handle_t, ulong_t, ulong_t, struct timeval *, + struct Pf_ext_packetfilt *); +extern void net_read(dlpi_handle_t, size_t, int, void (*)(), int); extern void click(int); extern void show_pktinfo(int, int, char *, char *, struct timeval *, struct timeval *, int, int); @@ -193,6 +194,7 @@ extern char *showxdr_time(char *); extern char *addrtoname(int, const void *); extern char *show_string(const char *, int, int); extern void pr_err(const char *, ...); +extern void pr_errdlpi(dlpi_handle_t, const char *, int); extern void check_retransmit(char *, ulong_t); extern char *nameof_prog(int); extern char *getproto(int); diff --git a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c index 5d24744e66..206835c407 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_capture.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,7 +45,6 @@ #include <sys/stat.h> #include <sys/stropts.h> #include <sys/bufmod.h> -#include <sys/dlpi.h> #include <unistd.h> #include <stropts.h> @@ -75,74 +74,27 @@ void convert_to_network(); void convert_from_network(); static void convert_old(struct ohdr *); extern sigjmp_buf jmp_env, ojmp_env; -static int netfd; -static union DL_primitives netdl; /* info_ack for interface */ +static dlpi_info_t dlinfo; static char *bufp; /* pointer to read buffer */ static int strioctl(int, int, int, int, void *); /* - * Convert a device id to a ppa value - * e.g. "le0" -> 0 - */ -static int -device_ppa(char *device) -{ - char *p; - char *tp; - - p = strpbrk(device, "0123456789"); - if (p == NULL) - return (0); - /* ignore numbers within device names */ - for (tp = p; *tp != '\0'; tp++) - if (!isdigit(*tp)) - return (device_ppa(tp)); - return (atoi(p)); -} - -/* - * Convert a device id to a pathname. - * Level 1 devices: "le0" -> "/dev/le0". - * Level 2 devices: "le0" -> "/dev/le". - */ -static char * -device_path(char *device) -{ - static char buff[IF_NAMESIZE + 1]; - struct stat st; - char *p; - - (void) strcpy(buff, "/dev/"); - (void) strlcat(buff, device, IF_NAMESIZE); - - if (stat(buff, &st) == 0) - return (buff); - - for (p = buff + (strlen(buff) - 1); p > buff; p--) { - if (isdigit(*p)) - *p = '\0'; - else - break; - } - return (buff); -} - -/* - * Open up the device, and start finding out something about it, - * especially stuff about the data link headers. We need that information + * Open up the device in raw mode and passive mode + * (see dlpi_open(3DLPI)) and start finding out something about it, + * especially stuff about the data link headers. We need that information * to build the proper packet filters. */ boolean_t -check_device(char **devicep, int *ppap) +check_device(dlpi_handle_t *dhp, char **devicep) { - char *devname; + int retval; + /* * Determine which network device * to use if none given. * Should get back a value like "le0". */ - if (*devicep == NULL) { char *cbuf; static struct ifconf ifc; @@ -199,78 +151,51 @@ check_device(char **devicep, int *ppap) (void) close(s); } - devname = device_path(*devicep); - if ((netfd = open(devname, O_RDWR)) < 0) - pr_err("%s: %m", devname); - - *ppap = device_ppa(*devicep); - - /* - * Check for DLPI Version 2. - */ - dlinforeq(netfd, &netdl); - if (netdl.info_ack.dl_version != DL_VERSION_2) - pr_err("DL_INFO_ACK: incompatible version %d", - netdl.info_ack.dl_version); - - /* - * Attach for DLPI Style 2. - */ - if (netdl.info_ack.dl_provider_style == DL_STYLE2) { - dlattachreq(netfd, *ppap); - /* Reread more specific information */ - dlinforeq(netfd, &netdl); + retval = dlpi_open(*devicep, dhp, DLPI_PASSIVE|DLPI_RAW); + if (retval != DLPI_SUCCESS) { + pr_err("cannot open \"%s\": %s", *devicep, + dlpi_strerror(retval)); } - /* Enable passive mode so that we can snoop on aggregated links. */ - dlpi_passive(netfd, -1); + if ((retval = dlpi_info(*dhp, &dlinfo, 0)) != DLPI_SUCCESS) + pr_errdlpi(*dhp, "dlpi_info failed", retval); for (interface = &INTERFACES[0]; interface->mac_type != -1; interface++) - if (interface->mac_type == netdl.info_ack.dl_mac_type) + if (interface->mac_type == dlinfo.di_mactype) break; - /* allow limited functionality even is interface isn't known */ + /* allow limited functionality even if interface isn't known */ if (interface->mac_type == -1) { - fprintf(stderr, - "snoop: WARNING: Mac Type = %lx not supported\n", - netdl.info_ack.dl_mac_type); + (void) fprintf(stderr, "snoop: WARNING: Mac Type = %x " + "not supported\n", dlinfo.di_mactype); } /* for backward compatibility, allow known interface mtu_sizes */ - if (interface->mtu_size > (uint_t)netdl.info_ack.dl_max_sdu) - netdl.info_ack.dl_max_sdu = (t_scalar_t)interface->mtu_size; + if (interface->mtu_size > dlinfo.di_max_sdu) + dlinfo.di_max_sdu = interface->mtu_size; return (interface->try_kernel_filter); } /* * Do whatever is necessary to initialize the interface - * for packet capture. Bind the device opened and attached (if DL_STYLE2) - * in check_device(), request raw ethernet packets and set promiscuous mode, - * push the streams buffer module and packet filter module, set various buffer - * parameters. + * for packet capture. Bind the device opened in check_device(), set + * promiscuous mode, push the streams buffer module and packet filter + * module, set various buffer parameters. */ -/* ARGSUSED */ void -initdevice(device, snaplen, chunksize, timeout, fp, ppa) - char *device; - ulong_t snaplen, chunksize; - struct timeval *timeout; - struct Pf_ext_packetfilt *fp; - int ppa; +initdevice(dlpi_handle_t dh, ulong_t snaplen, ulong_t chunksize, + struct timeval *timeout, struct Pf_ext_packetfilt *fp) { extern int Pflg; + int retv; + int netfd; - /* - * Bind to SAP 2 on token ring, 0 on other interface types. - * (SAP 0 has special significance on token ring) - */ - if (interface->mac_type == DL_TPR) - dlbindreq(netfd, 2, 0, DL_CLDLS, 0); - else - dlbindreq(netfd, 0, 0, DL_CLDLS, 0); + retv = dlpi_bind(dh, DLPI_ANY_SAP, NULL); + if (retv != DLPI_SUCCESS) + pr_errdlpi(dh, "cannot bind on", retv); - (void) fprintf(stderr, "Using device %s ", device_path(device)); + (void) fprintf(stderr, "Using device %s ", dlpi_linkname(dh)); /* * If Pflg not set - use physical level @@ -278,67 +203,59 @@ initdevice(device, snaplen, chunksize, timeout, fp, ppa) */ if (!Pflg) { (void) fprintf(stderr, "(promiscuous mode)\n"); - dlpromiscon(netfd, DL_PROMISC_PHYS); + retv = dlpi_promiscon(dh, DL_PROMISC_PHYS); + if (retv != DLPI_SUCCESS) { + pr_errdlpi(dh, "promiscuous mode(physical) failed", + retv); + } } else { (void) fprintf(stderr, "(non promiscuous)\n"); - dlpromiscon(netfd, DL_PROMISC_MULTI); + retv = dlpi_promiscon(dh, DL_PROMISC_MULTI); + if (retv != DLPI_SUCCESS) { + pr_errdlpi(dh, "promiscuous mode(multicast) failed", + retv); + } } - dlpromiscon(netfd, DL_PROMISC_SAP); + retv = dlpi_promiscon(dh, DL_PROMISC_SAP); + if (retv != DLPI_SUCCESS) + pr_errdlpi(dh, "promiscuous mode(SAP) failed", retv); - if (ioctl(netfd, DLIOCRAW, 0) < 0) { - (void) close(netfd); - pr_err("ioctl: DLIOCRAW: %s: %m", device_path(device)); - } + netfd = dlpi_fd(dh); if (fp) { /* * push and configure the packet filtering module */ - if (ioctl(netfd, I_PUSH, "pfmod") < 0) { - (void) close(netfd); - pr_err("ioctl: I_PUSH pfmod: %s: %m", - device_path(device)); - } + if (ioctl(netfd, I_PUSH, "pfmod") < 0) + pr_errdlpi(dh, "cannot push \"pfmod\"", DL_SYSERR); if (strioctl(netfd, PFIOCSETF, -1, sizeof (*fp), - (char *)fp) < 0) { - (void) close(netfd); - pr_err("PFIOCSETF: %s: %m", device_path(device)); - } + (char *)fp) < 0) + pr_errdlpi(dh, "PFIOCSETF", DL_SYSERR); } - if (ioctl(netfd, I_PUSH, "bufmod") < 0) { - (void) close(netfd); - pr_err("push bufmod: %s: %m", device_path(device)); - } + if (ioctl(netfd, I_PUSH, "bufmod") < 0) + pr_errdlpi(dh, "cannot push \"bufmod\"", DL_SYSERR); if (strioctl(netfd, SBIOCSTIME, -1, sizeof (struct timeval), - (char *)timeout) < 0) { - (void) close(netfd); - pr_err("SBIOCSTIME: %s: %m", device_path(device)); - } + (char *)timeout) < 0) + pr_errdlpi(dh, "SBIOCSTIME", DL_SYSERR); if (strioctl(netfd, SBIOCSCHUNK, -1, sizeof (uint_t), - (char *)&chunksize) < 0) { - (void) close(netfd); - pr_err("SBIOCGCHUNK: %s: %m", device_path(device)); - } + (char *)&chunksize) < 0) + pr_errdlpi(dh, "SBIOCGCHUNK", DL_SYSERR); if (strioctl(netfd, SBIOCSSNAP, -1, sizeof (uint_t), - (char *)&snaplen) < 0) { - (void) close(netfd); - pr_err("SBIOCSSNAP: %s: %m", device_path(device)); - } + (char *)&snaplen) < 0) + pr_errdlpi(dh, "SBIOCSSNAP", DL_SYSERR); /* * Flush the read queue, to get rid of anything that * accumulated before the device reached its final configuration. */ - if (ioctl(netfd, I_FLUSH, FLUSHR) < 0) { - (void) close(netfd); - pr_err("I_FLUSH: %s: %m", device_path(device)); - } + if (ioctl(netfd, I_FLUSH, FLUSHR) < 0) + pr_errdlpi(dh, "cannot flush \"I_FLUSH\"", DL_SYSERR); } /* @@ -349,54 +266,38 @@ initdevice(device, snaplen, chunksize, timeout, fp, ppa) * or interpreted for display on the fly. */ void -net_read(chunksize, filter, proc, flags) - int chunksize, filter; - void (*proc)(); - int flags; +net_read(dlpi_handle_t dh, size_t chunksize, int filter, void (*proc)(), + int flags) { - int r = 0; - struct strbuf data; - int flgs; + int retval; extern int count; + size_t msglen; - data.len = 0; count = 0; /* allocate a read buffer */ - bufp = malloc(chunksize); if (bufp == NULL) - pr_err("no memory for %dk buffer", chunksize); + pr_err("no memory for %d buffer", chunksize); /* - * read frames + * read frames */ for (;;) { - data.maxlen = chunksize; - data.len = 0; - data.buf = bufp; - flgs = 0; - - r = getmsg(netfd, NULL, &data, &flgs); + msglen = chunksize; + retval = dlpi_recv(dh, NULL, NULL, bufp, &msglen, -1, NULL); - if (r < 0 || quitting) + if (retval != DLPI_SUCCESS || quitting) break; - if (data.len <= 0) - continue; - - scan(bufp, data.len, filter, 0, 0, proc, 0, 0, flags); + if (msglen != 0) + scan(bufp, msglen, filter, 0, 0, proc, 0, 0, flags); } free(bufp); - (void) close(netfd); - if (!quitting) { - if (r < 0) - pr_err("network read failed: %m"); - else - pr_err("network read returned %d", r); - } + if (!quitting) + pr_errdlpi(dh, "network read failed", retval); } #ifdef DEBUG @@ -512,24 +413,24 @@ scan(char *buf, int len, int filter, int cap, int old, void (*proc)(), (nhdrp->sbh_totlen < nhdrp->sbh_msglen) || (nhdrp->sbh_timestamp.tv_sec == 0)) { if (cap) - fprintf(stderr, "(warning) bad packet header " - "in capture file"); + (void) fprintf(stderr, "(warning) bad packet " + "header in capture file"); else - fprintf(stderr, "(warning) bad packet header " - "in buffer"); + (void) fprintf(stderr, "(warning) bad packet " + "header in buffer"); (void) fprintf(stderr, " offset %d: length=%d\n", bp - buf, nhdrp->sbh_totlen); goto err; } if (nhdrp->sbh_totlen > - (uint_t)(netdl.info_ack.dl_max_sdu + MAX_HDRTRAILER)) { + (dlinfo.di_max_sdu + MAX_HDRTRAILER)) { if (cap) - fprintf(stderr, "(warning) packet length " - "greater than MTU in capture file"); + (void) fprintf(stderr, "(warning) packet length" + " greater than MTU in capture file"); else - fprintf(stderr, "(warning) packet length " - "greater than MTU in buffer"); + (void) fprintf(stderr, "(warning) packet length" + " greater than MTU in buffer"); (void) fprintf(stderr, " offset %d: length=%d\n", bp - buf, nhdrp->sbh_totlen); @@ -542,7 +443,7 @@ scan(char *buf, int len, int filter, int cap, int old, void (*proc)(), * a warning. */ if (pktp + nhdrp->sbh_msglen > bufstop) { - fprintf(stderr, "truncated packet buffer\n"); + (void) fprintf(stderr, "truncated packet buffer\n"); nhdrp->sbh_msglen = bufstop - pktp; } @@ -574,7 +475,8 @@ scan(char *buf, int len, int filter, int cap, int old, void (*proc)(), } if (maxcount && count >= maxcount) { - fprintf(stderr, "%d packets captured\n", count); + (void) fprintf(stderr, "%d packets captured\n", + count); exit(0); } @@ -692,8 +594,7 @@ static const int snoop_idlen = 8; static const int snoop_version = 2; void -cap_open_write(name) - char *name; +cap_open_write(const char *name) { int vers; @@ -721,8 +622,7 @@ static int cap_len = 0; static int cap_new; void -cap_open_read(name) - char *name; +cap_open_read(const char *name) { struct stat st; int cap_vers; @@ -795,15 +695,11 @@ cap_open_read(name) if (mprotect(cap_buffp, cap_len, PROT_READ | PROT_WRITE) < 0) pr_err("mprotect: %s: %m", name); } - netdl.info_ack.dl_max_sdu = MAXINT; /* Decode any stored packet. */ + dlinfo.di_max_sdu = MAXINT; /* Decode any stored packet. */ } void -cap_read(first, last, filter, proc, flags) - int first, last; - int filter; - void (*proc)(); - int flags; +cap_read(int first, int last, int filter, void (*proc)(), int flags) { extern int count; @@ -816,10 +712,7 @@ cap_read(first, last, filter, proc, flags) /* ARGSUSED */ void -cap_write(hdrp, pktp, num, flags) - struct sb_hdr *hdrp; - char *pktp; - int num, flags; +cap_write(struct sb_hdr *hdrp, char *pktp, int num, int flags) { int pktlen, mac; static int first = 1; diff --git a/usr/src/cmd/cmd-inet/usr.sbin/syncinit.c b/usr/src/cmd/cmd-inet/usr.sbin/syncinit.c index d93bd2a531..de300e4d92 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/syncinit.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/syncinit.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -98,22 +97,21 @@ static char *portab[] = { #endif #define equal(a, b) (strcmp((a), (b)) == 0) -#define MAXWAIT 15 int main(int argc, char **argv) { - char cnambuf[MAXPATHLEN]; + char cnambuf[DLPI_LINKNAME_MAX], device[DLPI_LINKNAME_MAX]; struct scc_mode sm; struct strioctl sioc; int fd, speed; + int retval; char *arg, *cp; char loopchange = 0; char echochange = 0; char clockchange = 0; - char *devstr = "/dev/"; - int devstrlen; - ulong_t ppa; + uint_t ppa; + dlpi_handle_t dh; if (argc == 1) { usage(); @@ -121,41 +119,35 @@ main(int argc, char **argv) } argc--; argv++; - devstrlen = strlen(devstr); - if (strncmp(devstr, argv[0], devstrlen) != 0) { - if (snprintf(cnambuf, sizeof (cnambuf), "%s%s", devstr, - argv[0]) >= sizeof (cnambuf)) { - (void) fprintf(stderr, - "syncinit: invalid device name (too long) %s\n", - argv[0]); - exit(1); - } + + if (strlcpy(cnambuf, argv[0], sizeof (cnambuf)) >= + sizeof (cnambuf)) { + (void) fprintf(stderr, + "syncinit: invalid device name (too long) %s\n", argv[0]); + exit(1); } + cp = cnambuf; while (*cp) /* find the end of the name */ cp++; cp--; if (!isdigit(*cp)) { (void) fprintf(stderr, - "syncinit: %s missing minor device number\n", argv[0]); - exit(1); - } - while (isdigit(*(cp - 1))) - cp--; - ppa = strtoul(cp, NULL, 10); - *cp = '\0'; /* drop number, leaving name of clone device. */ - fd = open(cnambuf, O_RDWR|O_EXCL, 0); - if (fd < 0) { - perror("syncinit: open"); + "syncinit: %s missing minor device number\n", cnambuf); exit(1); } - if (dlpi_attach(fd, MAXWAIT, ppa) != 0) { - perror("syncinit: dlpi_attach"); + retval = dlpi_open(cnambuf, &dh, DLPI_EXCL|DLPI_SERIAL); + if (retval != DLPI_SUCCESS) { + (void) fprintf(stderr, "syncinit: dlpi_open %s: %s\n", cnambuf, + dlpi_strerror(retval)); exit(1); } - (void) printf("device: %s ppa: %d\n", cnambuf, (int)ppa); + (void) dlpi_parselink(cnambuf, device, &ppa); + (void) printf("device: %s ppa: %u\n", device, ppa); + + fd = dlpi_fd(dh); argc--; argv++; @@ -164,6 +156,7 @@ main(int argc, char **argv) sioc.ic_timout = -1; sioc.ic_len = sizeof (struct scc_mode); sioc.ic_dp = (char *)&sm; + if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCGETMODE"); (void) fprintf(stderr, @@ -266,7 +259,7 @@ main(int argc, char **argv) exit(1); } (void) printf( -"speed=%d, loopback=%s, echo=%s, nrzi=%s, txc=%s, rxc=%s\n", + "speed=%d, loopback=%s, echo=%s, nrzi=%s, txc=%s, rxc=%s\n", sm.sm_baudrate, yesno[((int)(sm.sm_config & CONN_LPBK) > 0)], yesno[((int)(sm.sm_config & CONN_ECHO) > 0)], diff --git a/usr/src/cmd/cmd-inet/usr.sbin/syncloop.c b/usr/src/cmd/cmd-inet/usr.sbin/syncloop.c index 59865b0ecd..d2df175428 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/syncloop.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/syncloop.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -54,7 +53,6 @@ static void first_packet(); static void many_packets(); static void printhex(char *cp, int len); -static char *portname = NULL; static unsigned int speed = 9600; static int reccount = 100; static int reclen = 100; @@ -94,17 +92,20 @@ static char *rxnames[] = { }; #define MAXPACKET 4096 -#define MAXWAIT 15 int main(int argc, char **argv) { - char cnambuf[MAXPATHLEN], dnambuf[MAXPATHLEN], *cp, *cpp; + char *portname; + char dnambuf[MAXPATHLEN], *cp; + char device[DLPI_LINKNAME_MAX]; struct scc_mode sm; struct strioctl sioc; - ulong_t ppa; + uint_t ppa; char *devstr = "/dev/"; int devstrlen; + int retval; + dlpi_handle_t dh; argc--; argv++; @@ -171,37 +172,40 @@ main(int argc, char **argv) perror(dnambuf); exit(1); } - for (cp = portname; (*cp) && (!isdigit(*cp)); cp++) {} - ppa = strtoul(cp, &cpp, 10); - if (cpp == cp) { + + cp = portname; + while (*cp) /* find the end of the name */ + cp++; + cp--; + if (!isdigit(*cp)) { (void) fprintf(stderr, - "syncloop: %s missing minor device number\n", portname); + "syncloop: %s missing minor device number\n", portname); exit(1); } - *cp = '\0'; /* drop number, leaving name of clone device. */ - /* the following won't fail since cnambuf and dnambuf are same size */ - if (strncmp(devstr, portname, devstrlen) != 0) { - (void) snprintf(cnambuf, sizeof (cnambuf), "%s%s", devstr, + + if (strlen(portname) >= DLPI_LINKNAME_MAX) { + (void) fprintf(stderr, + "syncloop: invalid device name (too long) %s\n", portname); - } - cfd = open(cnambuf, O_RDWR); - if (cfd < 0) { - (void) fprintf(stderr, "syncloop: cannot open %s\n", cnambuf); - perror(cnambuf); exit(1); } - if (dlpi_attach(cfd, MAXWAIT, ppa) != 0) { - perror("syncloop: dlpi_attach"); + if ((retval = dlpi_open(portname, &dh, DLPI_SERIAL)) != DLPI_SUCCESS) { + (void) fprintf(stderr, "syncloop: dlpi_open %s: %s\n", portname, + dlpi_strerror(retval)); exit(1); } + (void) dlpi_parselink(portname, device, &ppa); + if (reclen < 0 || reclen > MAXPACKET) { (void) printf("invalid packet length: %d\n", reclen); exit(1); } - (void) printf("[ Data device: %s | Control device: %s, ppa=%ld ]\n", - dnambuf, cnambuf, ppa); + (void) printf("[ Data device: %s | Control device: %s, ppa=%u ]\n", + dnambuf, device, ppa); + + cfd = dlpi_fd(dh); sioc.ic_cmd = S_IOCGETMODE; sioc.ic_timout = -1; @@ -209,8 +213,8 @@ main(int argc, char **argv) sioc.ic_dp = (char *)&sm; if (ioctl(cfd, I_STR, &sioc) < 0) { perror("S_IOCGETMODE"); - (void) fprintf(stderr, - "syncloop: can't get sync mode info for %s\n", cnambuf); + (void) fprintf(stderr, "syncloop: can't get sync mode info " + "for %s\n", portname); exit(1); } while (looptype < 1 || looptype > 4) { @@ -273,7 +277,7 @@ main(int argc, char **argv) if (ioctl(cfd, I_STR, &sioc) < 0) { perror("S_IOCSETMODE"); (void) fprintf(stderr, - "syncloop: can't set sync mode info for %s\n", cnambuf); + "syncloop: can't set sync mode info for %s\n", portname); exit(1); } @@ -285,8 +289,8 @@ no_params: sioc.ic_dp = (char *)&sm; if (ioctl(cfd, I_STR, &sioc) < 0) { perror("S_IOCGETMODE"); - (void) fprintf(stderr, - "syncloop: can't get sync mode info for %s\n", cnambuf); + (void) fprintf(stderr, "syncloop: can't get sync mode info " + "for %s\n", portname); exit(1); } (void) printf("speed=%d, loopback=%s, nrzi=%s, txc=%s, rxc=%s\n", diff --git a/usr/src/cmd/cmd-inet/usr.sbin/syncstat.c b/usr/src/cmd/cmd-inet/usr.sbin/syncstat.c index b939067405..9add6a4776 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/syncstat.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/syncstat.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,33 +42,28 @@ #include <sys/ser_sync.h> #include <libdlpi.h> -#define MAXWAIT 15 - static struct scc_mode sm; static struct sl_stats st; static void usage(void); static void sample(int count, int period); -/* - * errstr is MAXPATHLEN + 11; 11 = 10 for "syncstat: " + null - */ -static char errstr[11 + MAXPATHLEN] = "syncstat: /dev/"; -static char *ifdevice = errstr + 10; -static char *ifname = errstr + 15; +static char sername[DLPI_LINKNAME_MAX]; static int fd; int main(int argc, char **argv) { - int len; char *cp; + char serdevice[DLPI_LINKNAME_MAX]; int do_clear = 0; int period = 0; int isize, osize; int count; + int retval; struct strioctl sioc; - ulong_t ppa; + uint_t ppa; + dlpi_handle_t dh; if (argc == 1) { usage(); @@ -102,15 +96,14 @@ main(int argc, char **argv) period = atoi(*argv); if (period == 0) { (void) fprintf(stderr, - "syncstat: bad interval: %s\n", *argv); + "syncstat: bad interval: %s\n", *argv); exit(1); } } else { - len = sizeof (errstr) - strlen(errstr); - if (snprintf(ifname, len, "%s", *argv) >= len) { - (void) fprintf(stderr, - "syncstat: invalid device name " - "(too long) %s\n", *argv); + if (snprintf(sername, sizeof (sername), "%s", + *argv) >= sizeof (sername)) { + (void) fprintf(stderr, "syncstat: invalid " + "device name (too long) %s\n", *argv); exit(1); } } @@ -118,27 +111,23 @@ main(int argc, char **argv) argv++; } - for (cp = ifname; (*cp) && (!isdigit(*cp)); cp++) {} + for (cp = sername; (*cp) && (!isdigit(*cp)); cp++) {} if (*cp == '\0') { /* hit the end without finding a number */ (void) fprintf(stderr, - "syncstat: %s missing minor device number\n", ifname); - exit(1); - } - ppa = strtoul(cp, NULL, 10); - *cp = '\0'; /* drop number, leaving name of clone device. */ - fd = open(ifdevice, O_RDWR); - if (fd < 0) { - perror(errstr); + "syncstat: %s missing minor device number\n", sername); exit(1); } - if (dlpi_attach(fd, MAXWAIT, ppa) != 0) { - perror("syncstat: dlpi_attach"); + if ((retval = dlpi_open(sername, &dh, DLPI_SERIAL)) != DLPI_SUCCESS) { + (void) fprintf(stderr, "syncstat: dlpi_open %s: %s\n", sername, + dlpi_strerror(retval)); exit(1); } - (void) printf("syncstat: control device: %s, ppa=%ld\n", ifdevice, ppa); + (void) dlpi_parselink(sername, serdevice, &ppa); + (void) printf("syncstat: control device: %s, ppa=%u\n", serdevice, ppa); + fd = dlpi_fd(dh); sioc.ic_cmd = S_IOCGETMODE; sioc.ic_timout = -1; sioc.ic_len = sizeof (struct scc_mode); @@ -146,8 +135,7 @@ main(int argc, char **argv) if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCGETMODE"); (void) fprintf(stderr, - "syncstat: can't get sync mode info for %s\n", - ifname); + "syncstat: can't get sync mode info for %s\n", sername); exit(1); } if (do_clear) { @@ -158,8 +146,7 @@ main(int argc, char **argv) if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCCLRSTATS"); (void) fprintf(stderr, - "syncstat: can't clear stats for %s\n", - ifname); + "syncstat: can't clear stats for %s\n", sername); exit(1); } } @@ -171,7 +158,7 @@ main(int argc, char **argv) if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCGETSTATS"); (void) fprintf(stderr, "syncstat: can't get stats for %s\n", - ifname); + sername); exit(1); } if (period) { @@ -190,17 +177,11 @@ main(int argc, char **argv) osize = st.ochar / st.opack; if (st.ipack) isize = st.ichar / st.ipack; - (void) printf( -" speed ipkts opkts undrun ovrrun abort crc isize osize\n"); - (void) printf(" %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - sm.sm_baudrate, - st.ipack, - st.opack, - st.underrun, - st.overrun, - st.abort, - st.crc, - isize, osize); + (void) printf(" speed ipkts opkts undrun ovrrun abort " + "crc isize osize\n"); + (void) printf(" %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", sm.sm_baudrate, + st.ipack, st.opack, st.underrun, st.overrun, st.abort, st.crc, + isize, osize); return (0); } @@ -218,7 +199,7 @@ sample(int count, int period) if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCGETSTATS"); (void) fprintf(stderr, "syncstat: can't get stats for %s\n", - ifname); + sername); exit(1); } @@ -234,16 +215,11 @@ sample(int count, int period) iutil = 100 * iutil / sm.sm_baudrate; outil = 8 * st.ochar / period; outil = 100 * outil / sm.sm_baudrate; - if ((count % 20) == 0) (void) printf( -" ipkts opkts undrun ovrrun abort crc iutil outil\n"); - (void) printf(" %7d %7d %7d %7d %7d %7d %6d%% %6d%%\n", - st.ipack, - st.opack, - st.underrun, - st.overrun, - st.abort, - st.crc, - iutil, outil); + if ((count % 20) == 0) + (void) printf(" ipkts opkts undrun ovrrun abort " + "crc iutil outil\n"); + (void) printf(" %7d %7d %7d %7d %7d %7d %6d%% %6d%%\n", st.ipack, + st.opack, st.underrun, st.overrun, st.abort, st.crc, iutil, outil); st = nst; } @@ -251,6 +227,5 @@ sample(int count, int period) static void usage() { - (void) fprintf(stderr, "%s\n", - "Usage: syncstat [-c] device [period]"); + (void) fprintf(stderr, "Usage: syncstat [-c] device [period]\n"); } diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c index c088f44b68..e7a5b8e744 100644 --- a/usr/src/cmd/dladm/dladm.c +++ b/usr/src/cmd/dladm/dladm.c @@ -32,7 +32,6 @@ #include <stdarg.h> #include <stdlib.h> #include <fcntl.h> -#include <stdarg.h> #include <string.h> #include <stropts.h> #include <errno.h> @@ -670,11 +669,11 @@ do_down_aggr(int argc, char *argv[]) static void print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy) { - char type[TYPE_WIDTH]; + char type[TYPE_WIDTH]; if (!legacy) { - char drv[LIFNAMSIZ]; - int instance; + char drv[DLPI_LINKNAME_MAX]; + uint_t instance; if (dap->da_vid != 0) { (void) snprintf(type, TYPE_WIDTH, "vlan %u", @@ -682,8 +681,10 @@ print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy) } else { (void) snprintf(type, TYPE_WIDTH, "non-vlan"); } - if (dlpi_if_parse(dap->da_dev, drv, &instance) != 0) + + if (dlpi_parselink(dap->da_dev, drv, &instance) != DLPI_SUCCESS) return; + if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) { (void) printf("%s type=%s mtu=%d key=%u\n", name, type, dap->da_max_sdu, instance); @@ -700,11 +701,11 @@ print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy) static void print_link(const char *name, dladm_attr_t *dap, boolean_t legacy) { - char type[TYPE_WIDTH]; + char type[TYPE_WIDTH]; if (!legacy) { - char drv[LIFNAMSIZ]; - int instance; + char drv[DLPI_LINKNAME_MAX]; + uint_t instance; if (dap->da_vid != 0) { (void) snprintf(type, TYPE_WIDTH, gettext("vlan %u"), @@ -712,7 +713,8 @@ print_link(const char *name, dladm_attr_t *dap, boolean_t legacy) } else { (void) snprintf(type, TYPE_WIDTH, gettext("non-vlan")); } - if (dlpi_if_parse(dap->da_dev, drv, &instance) != 0) + + if (dlpi_parselink(dap->da_dev, drv, &instance) != DLPI_SUCCESS) return; if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) { (void) printf(gettext("%-9s\ttype: %s\tmtu: %d" @@ -737,26 +739,27 @@ get_if_info(const char *name, dladm_attr_t *dlattrp, boolean_t *legacy) if ((err = dladm_info(name, dlattrp)) == 0) { *legacy = B_FALSE; } else if (err < 0 && errno == ENODEV) { - int fd; - dlpi_if_attr_t dia; - dl_info_ack_t dlia; + dlpi_handle_t dh; + dlpi_info_t dlinfo; /* * A return value of ENODEV means that the specified * device is not gldv3. */ - if ((fd = dlpi_if_open(name, &dia, B_FALSE)) != -1 && - dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, - NULL, NULL) != -1) { - (void) dlpi_close(fd); - - *legacy = B_TRUE; - bzero(dlattrp, sizeof (*dlattrp)); - dlattrp->da_max_sdu = (uint_t)dlia.dl_max_sdu; - } else { + if (dlpi_open(name, &dh, 0) != DLPI_SUCCESS) { errno = ENOENT; return (-1); } + if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) { + dlpi_close(dh); + errno = EINVAL; + return (-1); + } + dlpi_close(dh); + *legacy = B_TRUE; + bzero(dlattrp, sizeof (*dlattrp)); + dlattrp->da_max_sdu = dlinfo.di_max_sdu; + } else { /* * If the return value is not ENODEV, this means that @@ -1308,8 +1311,8 @@ do_show_dev(int argc, char *argv[]) usage(); if (dev != NULL) { - int index; - char drv[LIFNAMSIZ]; + uint_t ppa; + char drv[DLPI_LINKNAME_MAX]; dladm_attr_t dlattr; boolean_t legacy; @@ -1317,9 +1320,9 @@ do_show_dev(int argc, char *argv[]) * Check for invalid devices. * aggregations and vlans are not considered devices. */ - if (strncmp(dev, "aggr", 4) == 0 || - dlpi_if_parse(dev, drv, &index) < 0 || - index >= 1000 || get_if_info(dev, &dlattr, &legacy) < 0) + if (dlpi_parselink(dev, drv, &ppa) != DLPI_SUCCESS || + strcmp(drv, "aggr") == 0 || ppa >= 1000 || + get_if_info(dev, &dlattr, &legacy) < 0) die("invalid device '%s'", dev); } @@ -1521,10 +1524,10 @@ bail: static void get_mac_stats(const char *dev, pktsum_t *stats) { - char module[LIFNAMSIZ]; - int instance; + char module[DLPI_LINKNAME_MAX]; + uint_t instance; - if (dlpi_if_parse(dev, module, &instance) != 0) + if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) return; bzero(stats, sizeof (*stats)); get_stats(module, instance, "mac", stats); @@ -1533,10 +1536,10 @@ get_mac_stats(const char *dev, pktsum_t *stats) static void get_link_stats(const char *link, pktsum_t *stats) { - char module[LIFNAMSIZ]; - int instance; + char module[DLPI_LINKNAME_MAX]; + uint_t instance; - if (dlpi_if_parse(link, module, &instance) != 0) + if (dlpi_parselink(link, module, &instance) != DLPI_SUCCESS) return; bzero(stats, sizeof (*stats)); get_stats(module, instance, (char *)link, stats); @@ -1546,18 +1549,19 @@ static int get_single_mac_stat(const char *dev, const char *name, uint8_t type, void *val) { - char module[LIFNAMSIZ]; - int instance; + char module[DLPI_LINKNAME_MAX]; + uint_t instance; kstat_ctl_t *kcp; kstat_t *ksp; + if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS) + return (-1); + if ((kcp = kstat_open()) == NULL) { warn("kstat open operation failed"); return (-1); } - if (dlpi_if_parse(dev, module, &instance) != 0) - return (-1); if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL && (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) { /* diff --git a/usr/src/cmd/iscsi/iscsitgtd/Makefile.com b/usr/src/cmd/iscsi/iscsitgtd/Makefile.com index 226a1b90ae..60b8584fb9 100644 --- a/usr/src/cmd/iscsi/iscsitgtd/Makefile.com +++ b/usr/src/cmd/iscsi/iscsitgtd/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -52,7 +52,7 @@ CLEANFILES += $(OBJS) all: $(PROG) LDLIBS += -lumem -luuid -lxml2 -lsocket -lnsl -ldoor -lavl -lmd5 -ladm -lefi -LDLIBS += -liscsitgt -lzfs +LDLIBS += -liscsitgt -lzfs -ldlpi $(PROG): $(OBJS) $(COMMON_OBJS) $(LINK.c) $(OBJS) $(COMMON_OBJS) -o $@ $(LDLIBS) diff --git a/usr/src/cmd/iscsi/iscsitgtd/target.h b/usr/src/cmd/iscsi/iscsitgtd/target.h index c852337948..6c4ed53c1b 100644 --- a/usr/src/cmd/iscsi/iscsitgtd/target.h +++ b/usr/src/cmd/iscsi/iscsitgtd/target.h @@ -190,7 +190,7 @@ extern char *target_log; extern char *config_file; extern tgt_node_t *targets_config; extern tgt_node_t *main_config; -extern uchar_t *mac_addr; +extern uchar_t mac_addr[]; extern size_t mac_len; extern int main_vers_maj, main_vers_min, diff --git a/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c b/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c index 76ea64f469..d1c3b15d19 100644 --- a/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c +++ b/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c @@ -20,18 +20,18 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/types.h> -#include <sys/dlpi.h> #include <libdlpi.h> #include <ctype.h> #include <sys/sysmacros.h> #include <net/if_types.h> +#include <net/if.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> @@ -59,18 +59,13 @@ * at this given time will have the same MAC address and as time moves along * well, time will change. */ -uchar_t *mac_addr; -size_t mac_len; - -#define PATH_PART "/dev/" +uchar_t mac_addr[DLPI_PHYSADDR_MAX]; +size_t mac_len; static struct lifreq *if_setup(int *n); static void dump_addr_to_ascii(struct sockaddr *addr, char *buf, size_t len); -static int strputmsg(int fd, uint8_t *ctl_buf, size_t ctl_len, int flags); -static int strgetmsg(int fd, char *ctl_buf, size_t *ctl_lenp, char *data_buf, - size_t *data_lenp); -static Boolean_t grab_address(char *ifname, uchar_t **addr, size_t *lp); +static Boolean_t grab_address(char *ifname, uchar_t *addrp, size_t *addrlenp); /* * []---- @@ -89,13 +84,15 @@ if_find_mac(target_queue_t *mgmt) { struct lifreq *lifrp, *first; int n; - char *str = NULL; + char *str; + + mac_len = DLPI_PHYSADDR_MAX; first = if_setup(&n); for (lifrp = first; n > 0; n--, lifrp++) { - if (grab_address(lifrp->lifr_name, &mac_addr, + if (grab_address(lifrp->lifr_name, mac_addr, &mac_len) == True) { - str = _link_ntoa(mac_addr, str, mac_len, IFT_OTHER); + str = _link_ntoa(mac_addr, NULL, mac_len, IFT_OTHER); if ((str != NULL) && (mgmt != NULL)) { queue_prt(mgmt, Q_GEN_DETAILS, "MAIN %s: %s \n", lifrp->lifr_name, str); @@ -338,171 +335,18 @@ if_setup(int *n) return (lifc.lifc_req); } -static int -strputmsg(int fd, uint8_t *ctl_buf, size_t ctl_len, int flags) -{ - struct strbuf ctl; - - bzero(&ctl, sizeof (ctl)); - ctl.buf = (char *)ctl_buf; - ctl.len = ctl_len; - - return (putmsg(fd, &ctl, NULL, flags)); -} - -static int -strgetmsg(int fd, char *ctl_buf, size_t *ctl_lenp, char *data_buf, - size_t *data_lenp) -{ - struct strbuf ctl; - struct strbuf data; - int flags = 0, - res; - - bzero(&ctl, sizeof (ctl)); - ctl.buf = ctl_buf; - ctl.len = 0; - ctl.maxlen = (ctl_lenp != NULL) ? *ctl_lenp : 0; - - bzero(&data, sizeof (data)); - data.buf = data_buf; - data.len = 0; - data.maxlen = (data_lenp != NULL) ? *data_lenp : 0; - - res = getmsg(fd, &ctl, &data, &flags); - if (ctl_lenp != NULL) - *ctl_lenp = ctl.len; - if (data_lenp != NULL) - *data_lenp = data.len; - - return (res); -} - static Boolean_t -ppa_attach(int fd, int ppa) +grab_address(char *ifname, uchar_t *addrp, size_t *addrlenp) { - union DL_primitives *buf = NULL; - dl_attach_req_t dlar; - size_t size; - Boolean_t rval = False; - - size = 0; - size = MAX(sizeof (dl_ok_ack_t), size); - size = MAX(sizeof (dl_error_ack_t), size); + int retval; + dlpi_handle_t dh; - if ((buf = malloc(size)) == NULL) + if (dlpi_open(ifname, &dh, 0) != DLPI_SUCCESS) return (False); - dlar.dl_primitive = DL_ATTACH_REQ; - dlar.dl_ppa = ppa; + retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, addrp, addrlenp); - if (strputmsg(fd, (uint8_t *)&dlar, DL_ATTACH_REQ_SIZE, 0) == -1) - goto error; + dlpi_close(dh); - if (strgetmsg(fd, (char *)buf, &size, NULL, NULL) == -1) - goto error; - - if (size < sizeof (t_uscalar_t)) - goto error; - - switch (buf->dl_primitive) { - case DL_OK_ACK: - if (size == DL_OK_ACK_SIZE) - rval = True; - break; - } - -error: - if (buf != NULL) - free(buf); - - return (rval); -} - -static Boolean_t -grab_address(char *ifname, uchar_t **addr, size_t *lp) -{ - char *dev_name = NULL, - *p; - size_t len; - int ppa, - fd = -1; - union DL_primitives *buf = NULL; - dl_phys_addr_req_t dlpar; - dl_phys_addr_ack_t *dlpaap; - Boolean_t rval = False; - - if (strcmp(ifname, LOCAL_LOOPBACK) == 0) - return (False); - - bzero(&dlpar, sizeof (dlpar)); - len = strlen(PATH_PART) + strlen(ifname) + 1; - if ((dev_name = (char *)malloc(len)) == NULL) { - goto error; - } - (void) snprintf(dev_name, len, "%s%s", PATH_PART, ifname); - - if ((fd = open(dev_name, O_RDWR)) < 0) { - for (p = dev_name; *p; p++) { - if (isdigit(*p)) { - ppa = atoi(p); - *p = '\0'; - if (((fd = open(dev_name, O_RDWR)) < 0) || - (ppa_attach(fd, ppa) == False)) { - goto error; - } - break; - } - } - if (fd == -1) - goto error; - } - - len = 0; - len = MAX(sizeof (dl_phys_addr_ack_t) + MAXADDRLEN, len); - len = MAX(sizeof (dl_error_ack_t), len); - - if ((buf = calloc(len, 1)) == NULL) - goto error; - dlpar.dl_primitive = DL_PHYS_ADDR_REQ; - dlpar.dl_addr_type = DL_CURR_PHYS_ADDR; - - if (strputmsg(fd, (uint8_t *)&dlpar, DL_PHYS_ADDR_REQ_SIZE, 0) == -1) { - goto error; - } - - if (strgetmsg(fd, (char *)buf, &len, NULL, NULL) == -1) { - goto error; - } - - switch (buf->dl_primitive) { - case DL_PHYS_ADDR_ACK: - if (len < DL_PHYS_ADDR_ACK_SIZE) { - goto error; - } - - dlpaap = (dl_phys_addr_ack_t *)buf; - if (dlpaap->dl_addr_offset != 0) { - if (dlpaap->dl_addr_length == 0) { - goto error; - } - *addr = malloc(dlpaap->dl_addr_length); - if (*addr == NULL) - goto error; - bcopy((char *)buf + dlpaap->dl_addr_offset, *addr, - dlpaap->dl_addr_length); - *lp = dlpaap->dl_addr_length; - rval = True; - } - break; - } - -error: - if (fd != -1) - (void) close(fd); - if (dev_name != NULL) - free(dev_name); - if (buf != NULL) - free(buf); - return (rval); + return (retval == DLPI_SUCCESS); } diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index f0e102ed89..4fc879cad9 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -473,6 +473,7 @@ libdevinfo: libnvpair libsec libdhcpagent: libsocket libdhcputil libuuid libdlpi libdhcpsvc: libinetutil libdhcputil: libnsl libgen libinetutil libdlpi +libdlpi: libinetutil libdladm: libdlpi libdevinfo libwladm libinetutil libdtrace: libproc libgen libctf libdtrace_jni: libuutil libdtrace diff --git a/usr/src/lib/libdhcpagent/common/dhcp_stable.c b/usr/src/lib/libdhcpagent/common/dhcp_stable.c index 7ae11346f6..e240164549 100644 --- a/usr/src/lib/libdhcpagent/common/dhcp_stable.c +++ b/usr/src/lib/libdhcpagent/common/dhcp_stable.c @@ -131,9 +131,10 @@ write_stable_duid(const uchar_t *duid, size_t duidlen) uchar_t * make_stable_duid(const char *physintf, size_t *duidlen) { - int fd, len; - dl_info_ack_t dl_info; - dlpi_if_attr_t dia; + int len; + dlpi_info_t dlinfo; + dlpi_handle_t dh = NULL; + uint_t arptype; duid_en_t *den; /* @@ -141,35 +142,29 @@ make_stable_duid(const char *physintf, size_t *duidlen) * provided as a hint. If that works, we can use a DUID-LLT. */ - fd = dlpi_if_open(physintf, &dia, B_FALSE); - if (fd != -1 && - dlpi_info(fd, -1, &dl_info, NULL, NULL, NULL, NULL, NULL, - NULL) != -1 && - (len = dl_info.dl_addr_length - abs(dl_info.dl_sap_length)) > 0) { + if (dlpi_open(physintf, &dh, 0) == DLPI_SUCCESS && + dlpi_info(dh, &dlinfo, 0) == DLPI_SUCCESS && + (len = dlinfo.di_physaddrlen) > 0 && + (arptype = dlpi_to_arp(dlinfo.di_mactype) != 0)) { duid_llt_t *dllt; - uint_t arptype; - - arptype = dlpi_to_arp(dl_info.dl_mac_type); + time_t now; if ((dllt = malloc(sizeof (*dllt) + len)) == NULL) { - (void) dlpi_close(fd); + dlpi_close(dh); return (NULL); } - if (arptype != 0 && dlpi_phys_addr(fd, -1, DL_CURR_PHYS_ADDR, - (uint8_t *)(dllt + 1), NULL) == 0) { - time_t now; - dllt->dllt_dutype = htons(DHCPV6_DUID_LLT); - dllt->dllt_hwtype = htons(arptype); - now = time(NULL) - DUID_TIME_BASE; - dllt->dllt_time = htonl(now); - *duidlen = sizeof (*dllt) + len; - return ((uchar_t *)dllt); - } - free(dllt); + (void) memcpy((dllt + 1), dlinfo.di_physaddr, len); + dllt->dllt_dutype = htons(DHCPV6_DUID_LLT); + dllt->dllt_hwtype = htons(arptype); + now = time(NULL) - DUID_TIME_BASE; + dllt->dllt_time = htonl(now); + *duidlen = sizeof (*dllt) + len; + dlpi_close(dh); + return ((uchar_t *)dllt); } - if (fd != -1) - (void) dlpi_close(fd); + if (dh != NULL) + dlpi_close(dh); /* * If we weren't able to create a DUID based on the network interface diff --git a/usr/src/lib/libdhcputil/common/dhcp_inittab.c b/usr/src/lib/libdhcputil/common/dhcp_inittab.c index e16b241f23..861dbc3f57 100644 --- a/usr/src/lib/libdhcputil/common/dhcp_inittab.c +++ b/usr/src/lib/libdhcputil/common/dhcp_inittab.c @@ -526,17 +526,16 @@ static int get_mac_addr(const char *str, int *ierrnop, uint16_t *hwret, int hwtype, uchar_t *outbuf) { - int fd = -1; int maclen; int dig, val; - dlpi_if_attr_t dia; - dl_info_ack_t dl_info; + dlpi_handle_t dh; + dlpi_info_t dlinfo; char chr; if (*str != '\0') { if (*str++ != ',') goto failed; - if ((fd = dlpi_if_open(str, &dia, B_FALSE)) == -1) { + if (dlpi_open(str, &dh, 0) != DLPI_SUCCESS) { maclen = 0; dig = val = 0; /* @@ -564,19 +563,15 @@ get_mac_addr(const char *str, int *ierrnop, uint16_t *hwret, int hwtype, } } } else { - if (dlpi_info(fd, -1, &dl_info, NULL, NULL, NULL, - NULL, NULL, NULL) == -1) + if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) { + dlpi_close(dh); goto failed; - maclen = dl_info.dl_addr_length - - abs(dl_info.dl_sap_length); - if (maclen > MAXADDRLEN) - goto failed; - if (dlpi_phys_addr(fd, -1, DL_CURR_PHYS_ADDR, outbuf, - NULL) == -1) - goto failed; - (void) dlpi_close(fd); + } + maclen = dlinfo.di_physaddrlen; + (void) memcpy(outbuf, dlinfo.di_physaddr, maclen); + dlpi_close(dh); if (hwtype == -1) - hwtype = dlpi_to_arp(dl_info.dl_mac_type); + hwtype = dlpi_to_arp(dlinfo.di_mactype); } } if (hwtype == -1) @@ -585,8 +580,6 @@ get_mac_addr(const char *str, int *ierrnop, uint16_t *hwret, int hwtype, return (maclen); failed: - if (fd != -1) - (void) dlpi_close(fd); *ierrnop = ITAB_BAD_NUMBER; return (-1); } @@ -651,8 +644,8 @@ inittab_encode_e(const dhcp_symbol_t *ie, const char *value, uint16_t *lengthp, case DSYM_DUID: /* Worst case is ":::::" */ n_entries = strlen(value); - if (n_entries < MAXADDRLEN) - n_entries = MAXADDRLEN; + if (n_entries < DLPI_PHYSADDR_MAX) + n_entries = DLPI_PHYSADDR_MAX; n_entries += sizeof (duid_llt_t); break; diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c index 2a62bb8232..5a5c06c464 100644 --- a/usr/src/lib/libdladm/common/libdladm.c +++ b/usr/src/lib/libdladm/common/libdladm.c @@ -129,37 +129,17 @@ i_dladm_nt_net_add(void *arg, char *name) static int i_dladm_nt_net_walk(di_node_t node, di_minor_t minor, void *arg) { - dl_info_ack_t dlia; - char name[IFNAMSIZ]; - int fd; - char *provider; - uint_t ppa; - - provider = di_minor_name(minor); - - if ((fd = dlpi_open(provider)) < 0) - return (DI_WALK_CONTINUE); - - if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) < 0) { - (void) dlpi_close(fd); - return (DI_WALK_CONTINUE); - } + char linkname[DLPI_LINKNAME_MAX]; + dlpi_handle_t dh; - if (dlia.dl_provider_style == DL_STYLE1) { - i_dladm_nt_net_add(arg, provider); - (void) dlpi_close(fd); + if (dlpi_makelink(linkname, di_minor_name(minor), + di_instance(node)) != DLPI_SUCCESS) return (DI_WALK_CONTINUE); - } - ppa = di_instance(node); - - if (dlpi_attach(fd, -1, ppa) < 0) { - (void) dlpi_close(fd); - return (DI_WALK_CONTINUE); + if (dlpi_open(linkname, &dh, 0) == DLPI_SUCCESS) { + i_dladm_nt_net_add(arg, linkname); + dlpi_close(dh); } - (void) snprintf(name, IFNAMSIZ - 1, "%s%d", provider, ppa); - i_dladm_nt_net_add(arg, name); - (void) dlpi_close(fd); return (DI_WALK_CONTINUE); } diff --git a/usr/src/lib/libdlpi/Makefile b/usr/src/lib/libdlpi/Makefile index a354d4de53..1f0a03b675 100644 --- a/usr/src/lib/libdlpi/Makefile +++ b/usr/src/lib/libdlpi/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -31,6 +31,7 @@ HDRS = libdlpi.h HDRDIR = common SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) POFILE = libdlpi.po MSGFILES = common/libdlpi.c diff --git a/usr/src/lib/libdlpi/Makefile.com b/usr/src/lib/libdlpi/Makefile.com index 2ce8d412af..a8b5e6be1f 100644 --- a/usr/src/lib/libdlpi/Makefile.com +++ b/usr/src/lib/libdlpi/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -36,7 +36,7 @@ include ../../Makefile.rootfs LIBS = $(DYNLIB) $(LINTLIB) -LDLIBS += -lc +LDLIBS += -lc -linetutil SRCDIR = ../common $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) diff --git a/usr/src/lib/libdlpi/amd64/Makefile b/usr/src/lib/libdlpi/amd64/Makefile new file mode 100644 index 0000000000..a76ebb70e3 --- /dev/null +++ b/usr/src/lib/libdlpi/amd64/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libdlpi/common/libdlpi.c b/usr/src/lib/libdlpi/common/libdlpi.c index fc6dbe0f83..42ac808382 100644 --- a/usr/src/lib/libdlpi/common/libdlpi.c +++ b/usr/src/lib/libdlpi/common/libdlpi.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,7 +28,6 @@ /* * Data-Link Provider Interface (Version 2) */ - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -40,1285 +39,1408 @@ #include <stropts.h> #include <sys/dlpi.h> #include <errno.h> +#include <alloca.h> #include <sys/sysmacros.h> #include <ctype.h> #include <libdlpi.h> -#include <libdladm.h> - -typedef enum dlpi_multi_op { - DLPI_MULTI_DISABLE = 0, - DLPI_MULTI_ENABLE -} dlpi_multi_op_t; - -typedef enum dlpi_promisc_op { - DLPI_PROMISC_OFF = 0, - DLPI_PROMISC_ON -} dlpi_promisc_op_t; - -const char *i_dlpi_mac_type[] = { - "CSMA/CD", /* 0x00 */ - "Token Bus", /* 0x01 */ - "Token Ring", /* 0x02 */ - "Metro Net", /* 0x03 */ - "Ethernet", /* 0x04 */ - "HDLC", /* 0x05 */ - "Sync Character", /* 0x06 */ - "CTCA", /* 0x07 */ - "FDDI", /* 0x08 */ - "unknown", /* 0x09 */ - "Frame Relay (LAPF)", /* 0x0a */ - "MP Frame Relay", /* 0x0b */ - "Async Character", /* 0x0c */ - "X.25 (Classic IP)", /* 0x0d */ - "Software Loopback", /* 0x0e */ - "undefined", /* 0x0f */ - "Fiber Channel", /* 0x10 */ - "ATM", /* 0x11 */ - "ATM (Classic IP)", /* 0x12 */ - "X.25 (LAPB)", /* 0x13 */ - "ISDN", /* 0x14 */ - "HIPPI", /* 0x15 */ - "100BaseVG Ethernet", /* 0x16 */ - "100BaseVG Token Ring", /* 0x17 */ - "Ethernet/IEEE 802.3", /* 0x18 */ - "100BaseT", /* 0x19 */ - "Infiniband" /* 0x1a */ -}; - -static int i_dlpi_ifrm_num(char *, unsigned int *); - -const char * -dlpi_mac_type(uint_t type) -{ - if (type >= sizeof (i_dlpi_mac_type) / sizeof (i_dlpi_mac_type[0])) - return ("ERROR"); - - return (i_dlpi_mac_type[type]); -} - -static int -strputmsg(int fd, uint8_t *ctl_buf, size_t ctl_len, int flags) -{ - struct strbuf ctl; - - ctl.buf = (char *)ctl_buf; - ctl.len = ctl_len; - - return (putmsg(fd, &ctl, NULL, flags)); -} +#include <libintl.h> +#include <libinetutil.h> + +#include "libdlpi_impl.h" + +static int i_dlpi_open(const char *, int *, uint_t); +static int i_dlpi_style1_open(dlpi_impl_t *); +static int i_dlpi_style2_open(dlpi_impl_t *); +static int i_dlpi_checkstyle(dlpi_impl_t *, t_uscalar_t); +static int i_dlpi_remove_ppa(char *); +static int i_dlpi_attach(dlpi_impl_t *); +static void i_dlpi_passive(dlpi_impl_t *); + +static int i_dlpi_strputmsg(int, const dlpi_msg_t *, const void *, size_t, int); +static int i_dlpi_strgetmsg(int, int, dlpi_msg_t *, t_uscalar_t, t_uscalar_t, + size_t, void *, size_t *, size_t *); +static int i_dlpi_msg_common(dlpi_impl_t *, const dlpi_msg_t *, dlpi_msg_t *, + size_t, int); + +static size_t i_dlpi_getprimsize(t_uscalar_t); +static int i_dlpi_multi(dlpi_handle_t, t_uscalar_t, const uint8_t *, size_t); +static int i_dlpi_promisc(dlpi_handle_t, t_uscalar_t, uint_t); +static uint_t i_dlpi_buildsap(uint8_t *, uint_t); +static void i_dlpi_writesap(void *, uint_t, uint_t); -static int -strgetmsg(int fd, int timeout, char *ctl_buf, - size_t *ctl_lenp, char *data_buf, size_t *data_lenp) +int +dlpi_open(const char *linkname, dlpi_handle_t *dhp, uint_t flags) { - struct strbuf ctl; - struct strbuf data; - int res; - struct pollfd pfd; - int flags = 0; - - pfd.fd = fd; - pfd.events = POLLIN | POLLPRI; - - switch (poll(&pfd, 1, timeout)) { - default: - ctl.buf = ctl_buf; - ctl.len = 0; - ctl.maxlen = (ctl_lenp != NULL) ? *ctl_lenp : 0; + int retval; + int cnt; + ifspec_t ifsp; + dlpi_impl_t *dip; - data.buf = data_buf; - data.len = 0; - data.maxlen = (data_lenp != NULL) ? *data_lenp : 0; + /* + * Validate linkname, fail if logical unit number (lun) is specified, + * otherwise decompose the contents into ifsp. + */ + if (linkname == NULL || (strchr(linkname, ':') != NULL) || + !ifparse_ifspec(linkname, &ifsp)) + return (DLPI_ELINKNAMEINVAL); + + /* Allocate a new dlpi_impl_t. */ + if ((dip = calloc(1, sizeof (dlpi_impl_t))) == NULL) + return (DL_SYSERR); + + /* Fill in known/default libdlpi handle values. */ + dip->dli_timeout = DLPI_DEF_TIMEOUT; + dip->dli_ppa = ifsp.ifsp_ppa; + dip->dli_mod_cnt = ifsp.ifsp_modcnt; + dip->dli_oflags = flags; + + for (cnt = 0; cnt != dip->dli_mod_cnt; cnt++) { + (void) strlcpy(dip->dli_modlist[cnt], ifsp.ifsp_mods[cnt], + DLPI_LINKNAME_MAX); + } - if ((res = getmsg(fd, &ctl, &data, &flags)) < 0) - goto failed; + /* Copy linkname provided to the function. */ + if (strlcpy(dip->dli_linkname, linkname, sizeof (dip->dli_linkname)) >= + sizeof (dip->dli_linkname)) { + free(dip); + return (DLPI_ELINKNAMEINVAL); + } - if (ctl_buf != NULL) { - if (res & MORECTL) { - errno = E2BIG; - goto failed; - } + /* Copy provider name. */ + (void) strlcpy(dip->dli_provider, ifsp.ifsp_devnm, + sizeof (dip->dli_provider)); - *ctl_lenp = ctl.len; + /* + * Special case: DLPI_SERIAL flag is set to indicate a synchronous + * serial line interface (see syncinit(1M), syncstat(1M), + * syncloop(1M)), which is not a DLPI link. + */ + if (dip->dli_oflags & DLPI_SERIAL) { + if ((retval = i_dlpi_style2_open(dip)) != DLPI_SUCCESS) { + free(dip); + return (retval); } - if (data_buf != NULL) { - if (res & MOREDATA) { - errno = E2BIG; - goto failed; - } + *dhp = (dlpi_handle_t)dip; + return (retval); + } - *data_lenp = data.len; + if (i_dlpi_style1_open(dip) != DLPI_SUCCESS) { + if ((retval = i_dlpi_style2_open(dip)) != DLPI_SUCCESS) { + free(dip); + return (retval); } - - break; - case 0: - errno = ETIME; - /*FALLTHRU*/ - case -1: - goto failed; } - return (0); -failed: - return (-1); -} - -int -dlpi_open(const char *provider) -{ - char devname[MAXPATHLEN]; - char path[MAXPATHLEN]; - int fd; - struct stat st; + if (dip->dli_oflags & DLPI_PASSIVE) + i_dlpi_passive(dip); - (void) snprintf(devname, MAXPATHLEN, "/dev/%s", provider); - - if ((fd = open(devname, O_RDWR)) != -1) - return (fd); - - (void) snprintf(path, MAXPATHLEN, "/devices/pseudo/clone@0:%s", - provider); + if ((dip->dli_oflags & DLPI_RAW) && + ioctl(dip->dli_fd, DLIOCRAW, 0) < 0) { + dlpi_close((dlpi_handle_t)dip); + return (DLPI_ERAWNOTSUP); + } - if (stat(path, &st) == 0) { - (void) strlcpy(devname, path, sizeof (devname)); - if ((fd = open(devname, O_RDWR)) != -1) - return (fd); + /* + * We intentionally do not care if this request fails, as this + * indicates the underlying DLPI device does not support Native mode + * (pre-GLDV3 device drivers). + */ + if (dip->dli_oflags & DLPI_NATIVE) { + if ((retval = ioctl(dip->dli_fd, DLIOCNATIVE, 0)) > 0) + dip->dli_mactype = retval; } - return (-1); + *dhp = (dlpi_handle_t)dip; + return (DLPI_SUCCESS); } -int -dlpi_close(int fd) +void +dlpi_close(dlpi_handle_t dh) { - return (close(fd)); + dlpi_impl_t *dip = (dlpi_impl_t *)dh; + + if (dip != NULL) { + (void) close(dip->dli_fd); + free(dip); + } } +/* + * NOTE: The opt argument must be zero and is reserved for future use to extend + * fields to the dlpi_info_t structure (see dlpi_info(3DLPI)). + */ int -dlpi_info(int fd, int timeout, dl_info_ack_t *ackp, - union DL_qos_types *selp, union DL_qos_types *rangep, - uint8_t *addrp, size_t *addrlenp, uint8_t *brdcst_addrp, - size_t *brdcst_addrlenp) +dlpi_info(dlpi_handle_t dh, dlpi_info_t *infop, uint_t opt) { - int rc = -1; - size_t size; - dl_info_ack_t *buf; - dl_info_req_t dlir; - dl_info_ack_t *dliap; - union DL_qos_types *uqtp; - - size = sizeof (dl_info_ack_t); /* DL_INFO_ACK */ - size += sizeof (union DL_qos_types); /* QoS selections */ - size += sizeof (union DL_qos_types); /* QoS ranges */ - size += MAXADDRLEN + MAXSAPLEN; /* DLSAP Address */ - size += MAXADDRLEN; /* Broadcast Address */ - - if ((buf = malloc(size)) == NULL) - return (-1); - - dlir.dl_primitive = DL_INFO_REQ; - - if (strputmsg(fd, (uint8_t *)&dlir, DL_INFO_REQ_SIZE, RS_HIPRI) == -1) - goto done; - - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; - - if (size < DL_INFO_ACK_SIZE) { - errno = EBADMSG; - goto done; + int retval; + dlpi_msg_t req, ack; + dl_info_ack_t *infoackp; + uint8_t *sapp, *addrp; + caddr_t ackendp, datap; + t_uscalar_t dataoff, datalen; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; + + if (dip == NULL) + return (DLPI_EINHANDLE); + + if (infop == NULL || opt != 0) + return (DLPI_EINVAL); + + (void) memset(infop, 0, sizeof (dlpi_info_t)); + + /* Set QoS range parameters to default unsupported value. */ + infop->di_qos_range.dl_qos_type = (t_uscalar_t)DL_UNKNOWN; + infop->di_qos_range.dl_trans_delay.dl_target_value = DL_UNKNOWN; + infop->di_qos_range.dl_trans_delay.dl_accept_value = DL_UNKNOWN; + infop->di_qos_range.dl_priority.dl_min = DL_UNKNOWN; + infop->di_qos_range.dl_priority.dl_max = DL_UNKNOWN; + infop->di_qos_range.dl_protection.dl_min = DL_UNKNOWN; + infop->di_qos_range.dl_protection.dl_max = DL_UNKNOWN; + infop->di_qos_range.dl_residual_error = DL_UNKNOWN; + + /* Set QoS parameters to default unsupported value. */ + infop->di_qos_sel.dl_qos_type = (t_uscalar_t)DL_UNKNOWN; + infop->di_qos_sel.dl_trans_delay = DL_UNKNOWN; + infop->di_qos_sel.dl_priority = DL_UNKNOWN; + infop->di_qos_sel.dl_protection = DL_UNKNOWN; + infop->di_qos_sel.dl_residual_error = DL_UNKNOWN; + + DLPI_MSG_CREATE(req, DL_INFO_REQ); + DLPI_MSG_CREATE(ack, DL_INFO_ACK); + + retval = i_dlpi_msg_common(dip, &req, &ack, DL_INFO_ACK_SIZE, RS_HIPRI); + if (retval != DLPI_SUCCESS) + return (retval); + + infoackp = &(ack.dlm_msg->info_ack); + if (infoackp->dl_version != DL_VERSION_2) + return (DLPI_EVERNOTSUP); + + if (infoackp->dl_service_mode != DL_CLDLS) + return (DLPI_EMODENOTSUP); + + dip->dli_style = infoackp->dl_provider_style; + dip->dli_mactype = infoackp->dl_mac_type; + + ackendp = (caddr_t)ack.dlm_msg + ack.dlm_msgsz; + + /* Check and save QoS selection information, if any. */ + datalen = infoackp->dl_qos_length; + dataoff = infoackp->dl_qos_offset; + if (dataoff != 0 && datalen != 0) { + datap = (caddr_t)infoackp + dataoff; + if (datalen > sizeof (dl_qos_cl_sel1_t) || + dataoff < DL_INFO_ACK_SIZE || datap + datalen > ackendp) + return (DLPI_EBADMSG); + + (void) memcpy(&infop->di_qos_sel, datap, datalen); + if (infop->di_qos_sel.dl_qos_type != DL_QOS_CL_SEL1) + return (DLPI_EMODENOTSUP); } - dliap = (dl_info_ack_t *)buf; - if (dliap->dl_primitive != DL_INFO_ACK || - dliap->dl_version != DL_VERSION_2) { - errno = EPROTO; - goto done; + /* Check and save QoS range information, if any. */ + datalen = infoackp->dl_qos_range_length; + dataoff = infoackp->dl_qos_range_offset; + if (dataoff != 0 && datalen != 0) { + datap = (caddr_t)infoackp + dataoff; + if (datalen > sizeof (dl_qos_cl_range1_t) || + dataoff < DL_INFO_ACK_SIZE || datap + datalen > ackendp) + return (DLPI_EBADMSG); + + (void) memcpy(&infop->di_qos_range, datap, datalen); + if (infop->di_qos_range.dl_qos_type != DL_QOS_CL_RANGE1) + return (DLPI_EMODENOTSUP); } - (void) memcpy(ackp, buf, DL_INFO_ACK_SIZE); - - if (dliap->dl_qos_offset != 0) { - if (dliap->dl_qos_length < sizeof (t_uscalar_t)) { - errno = EPROTO; - goto done; - } - - uqtp = (union DL_qos_types *) - ((uintptr_t)buf + dliap->dl_qos_offset); - if (uqtp->dl_qos_type != DL_QOS_CO_SEL1 && - uqtp->dl_qos_type != DL_QOS_CL_SEL1) { - errno = EPROTO; - goto done; - } - - if (selp != NULL) - (void) memcpy(selp, (char *)buf + dliap->dl_qos_offset, - dliap->dl_qos_length); - } - - if (dliap->dl_qos_range_offset != 0) { - if (dliap->dl_qos_range_length < sizeof (t_uscalar_t)) { - errno = EPROTO; - goto done; - } - - uqtp = (union DL_qos_types *) - ((uintptr_t)buf + dliap->dl_qos_range_offset); - if (uqtp->dl_qos_type != DL_QOS_CO_RANGE1 && - uqtp->dl_qos_type != DL_QOS_CL_RANGE1) { - errno = EPROTO; - goto done; - } - - if (rangep != NULL) - (void) memcpy(rangep, - (char *)buf + dliap->dl_qos_range_offset, - dliap->dl_qos_range_length); + /* Check and save physical address and SAP information. */ + dip->dli_saplen = abs(infoackp->dl_sap_length); + dip->dli_sapbefore = (infoackp->dl_sap_length > 0); + infop->di_physaddrlen = infoackp->dl_addr_length - dip->dli_saplen; + + if (infop->di_physaddrlen > DLPI_PHYSADDR_MAX || + dip->dli_saplen > DLPI_SAPLEN_MAX) + return (DL_BADADDR); + + dataoff = infoackp->dl_addr_offset; + datalen = infoackp->dl_addr_length; + if (dataoff != 0 && datalen != 0) { + datap = (caddr_t)infoackp + dataoff; + if (dataoff < DL_INFO_ACK_SIZE || datap + datalen > ackendp) + return (DLPI_EBADMSG); + + sapp = addrp = (uint8_t *)datap; + if (dip->dli_sapbefore) + addrp += dip->dli_saplen; + else + sapp += infop->di_physaddrlen; + + (void) memcpy(infop->di_physaddr, addrp, infop->di_physaddrlen); + infop->di_sap = i_dlpi_buildsap(sapp, dip->dli_saplen); } - if (dliap->dl_addr_offset != 0) { - if (dliap->dl_addr_length == 0) { - errno = EPROTO; - goto done; - } - - if (addrlenp != NULL) - *addrlenp = dliap->dl_addr_length; - if (addrp != NULL) - (void) memcpy(addrp, - (char *)buf + dliap->dl_addr_offset, - dliap->dl_addr_length); + /* Check and save broadcast address information, if any. */ + datalen = infoackp->dl_brdcst_addr_length; + dataoff = infoackp->dl_brdcst_addr_offset; + if (dataoff != 0 && datalen != 0) { + datap = (caddr_t)infoackp + dataoff; + if (dataoff < DL_INFO_ACK_SIZE || datap + datalen > ackendp) + return (DLPI_EBADMSG); + if (datalen != infop->di_physaddrlen) + return (DL_BADADDR); + + infop->di_bcastaddrlen = datalen; + (void) memcpy(infop->di_bcastaddr, datap, datalen); } - if (dliap->dl_brdcst_addr_offset != 0) { - if (dliap->dl_brdcst_addr_length == 0) { - errno = EPROTO; - goto done; - } + infop->di_max_sdu = infoackp->dl_max_sdu; + infop->di_min_sdu = infoackp->dl_min_sdu; + infop->di_state = infoackp->dl_current_state; + infop->di_mactype = infoackp->dl_mac_type; - if (brdcst_addrlenp != NULL) - *brdcst_addrlenp = dliap->dl_brdcst_addr_length; - if (brdcst_addrp != NULL) - (void) memcpy(brdcst_addrp, - (char *)buf + dliap->dl_brdcst_addr_offset, - dliap->dl_brdcst_addr_length); - } + /* Information retrieved from the handle. */ + (void) strlcpy(infop->di_linkname, dip->dli_linkname, + sizeof (infop->di_linkname)); + infop->di_timeout = dip->dli_timeout; - rc = 0; /* success */ -done: - free(buf); - return (rc); + return (DLPI_SUCCESS); } +/* + * This function parses 'linkname' and stores the 'provider' name and 'PPA'. + */ int -dlpi_attach(int fd, int timeout, uint_t ppa) +dlpi_parselink(const char *linkname, char *provider, uint_t *ppa) { - int rc = -1; - size_t size; - dl_attach_req_t dlar; - dl_error_ack_t *dleap; - union DL_primitives *buf; - union DL_primitives *udlp; + ifspec_t ifsp; - size = 0; - size = MAX(sizeof (dl_ok_ack_t), size); - size = MAX(sizeof (dl_error_ack_t), size); + if (linkname == NULL || !ifparse_ifspec(linkname, &ifsp)) + return (DLPI_ELINKNAMEINVAL); - if ((buf = malloc(size)) == NULL) - return (-1); + if (provider != NULL) + (void) strlcpy(provider, ifsp.ifsp_devnm, DLPI_LINKNAME_MAX); - dlar.dl_primitive = DL_ATTACH_REQ; - dlar.dl_ppa = ppa; + if (ppa != NULL) + *ppa = ifsp.ifsp_ppa; - if (strputmsg(fd, (uint8_t *)&dlar, DL_ATTACH_REQ_SIZE, 0) == -1) - goto done; + return (DLPI_SUCCESS); +} + +/* + * This function takes a provider name and a PPA and stores a full linkname + * as 'linkname'. If 'provider' already is a full linkname 'provider' name + * is stored in 'linkname'. + */ +int +dlpi_makelink(char *linkname, const char *provider, uint_t ppa) +{ + int provlen = strlen(provider); - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; + if (linkname == NULL || provlen == 0 || provlen >= DLPI_LINKNAME_MAX) + return (DLPI_ELINKNAMEINVAL); - if (size < sizeof (t_uscalar_t)) { - errno = EBADMSG; - goto done; + if (!isdigit(provider[provlen - 1])) { + (void) snprintf(linkname, DLPI_LINKNAME_MAX, "%s%d", provider, + ppa); + } else { + (void) strlcpy(linkname, provider, DLPI_LINKNAME_MAX); } - udlp = (union DL_primitives *)buf; - switch (udlp->dl_primitive) { - case DL_OK_ACK: - if (size < DL_OK_ACK_SIZE) { - errno = EBADMSG; - goto done; - } - break; + return (DLPI_SUCCESS); +} - case DL_ERROR_ACK: - if (size < DL_ERROR_ACK_SIZE) { - errno = EBADMSG; - goto done; - } +int +dlpi_bind(dlpi_handle_t dh, uint_t sap, uint_t *boundsap) +{ + int retval; + dlpi_msg_t req, ack; + dl_bind_req_t *bindreqp; + dl_bind_ack_t *bindackp; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; - dleap = (dl_error_ack_t *)buf; - switch (dleap->dl_errno) { - case DL_BADPPA: - errno = EINVAL; - break; + if (dip == NULL) + return (DLPI_EINHANDLE); - case DL_ACCESS: - errno = EPERM; - break; + DLPI_MSG_CREATE(req, DL_BIND_REQ); + DLPI_MSG_CREATE(ack, DL_BIND_ACK); + bindreqp = &(req.dlm_msg->bind_req); - case DL_SYSERR: - errno = dleap->dl_unix_errno; - break; + /* + * If 'sap' is DLPI_ANY_SAP, bind to SAP 2 on token ring, else 0 on + * other interface types (SAP 0 has special significance on token ring). + */ + if (sap == DLPI_ANY_SAP) + bindreqp->dl_sap = ((dip->dli_mactype == DL_TPR) ? 2 : 0); + else + bindreqp->dl_sap = sap; - default: - errno = EPROTO; - break; - } + bindreqp->dl_service_mode = DL_CLDLS; + bindreqp->dl_conn_mgmt = 0; + bindreqp->dl_max_conind = 0; + bindreqp->dl_xidtest_flg = 0; - goto done; + retval = i_dlpi_msg_common(dip, &req, &ack, DL_BIND_ACK_SIZE, 0); + if (retval != DLPI_SUCCESS) + return (retval); - default: - errno = EBADMSG; - goto done; + bindackp = &(ack.dlm_msg->bind_ack); + /* + * Received a DLPI_BIND_ACK, now verify that the bound SAP + * is equal to the SAP requested. Some DLPI MAC type may bind + * to a different SAP than requested, in this case 'boundsap' + * returns the actual bound SAP. For the case where 'boundsap' + * is NULL and 'sap' is not DLPI_ANY_SAP, dlpi_bind fails. + */ + if (boundsap != NULL) { + *boundsap = bindackp->dl_sap; + } else if (sap != DLPI_ANY_SAP && bindackp->dl_sap != sap) { + if (dlpi_unbind(dh) != DLPI_SUCCESS) + return (DLPI_FAILURE); + else + return (DLPI_EUNAVAILSAP); } - rc = 0; /* success */ -done: - free(buf); - return (rc); + dip->dli_sap = bindackp->dl_sap; /* save sap value in handle */ + return (DLPI_SUCCESS); } int -dlpi_detach(int fd, int timeout) +dlpi_unbind(dlpi_handle_t dh) { - int rc = -1; - size_t size; - dl_detach_req_t dldr; - dl_error_ack_t *dleap; - union DL_primitives *buf; - union DL_primitives *udlp; + dlpi_msg_t req, ack; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; - size = 0; - size = MAX(sizeof (dl_ok_ack_t), size); - size = MAX(sizeof (dl_error_ack_t), size); + if (dip == NULL) + return (DLPI_EINHANDLE); - if ((buf = malloc(size)) == NULL) - return (-1); + DLPI_MSG_CREATE(req, DL_UNBIND_REQ); + DLPI_MSG_CREATE(ack, DL_OK_ACK); - dldr.dl_primitive = DL_DETACH_REQ; - - if (strputmsg(fd, (uint8_t *)&dldr, DL_DETACH_REQ_SIZE, 0) == -1) - goto done; - - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; + return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); +} - if (size < sizeof (t_uscalar_t)) { - errno = EBADMSG; - goto done; - } +/* + * This function is invoked by dlpi_enabmulti() or dlpi_disabmulti() and + * based on the "op" value, multicast address is enabled/disabled. + */ +static int +i_dlpi_multi(dlpi_handle_t dh, t_uscalar_t op, const uint8_t *addrp, + size_t addrlen) +{ + dlpi_msg_t req, ack; + dl_enabmulti_req_t *multireqp; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; - udlp = (union DL_primitives *)buf; - switch (udlp->dl_primitive) { - case DL_OK_ACK: - if (size < DL_OK_ACK_SIZE) { - errno = EBADMSG; - goto done; - } - break; + if (dip == NULL) + return (DLPI_EINHANDLE); - case DL_ERROR_ACK: - if (size < DL_ERROR_ACK_SIZE) { - errno = EBADMSG; - goto done; - } + if (addrlen > DLPI_PHYSADDR_MAX) + return (DLPI_EINVAL); - dleap = (dl_error_ack_t *)buf; - switch (dleap->dl_errno) { - case DL_SYSERR: - errno = dleap->dl_unix_errno; - break; + DLPI_MSG_CREATE(req, op); + DLPI_MSG_CREATE(ack, DL_OK_ACK); - default: - errno = EPROTO; - break; - } - goto done; + multireqp = &(req.dlm_msg->enabmulti_req); + multireqp->dl_addr_length = addrlen; + multireqp->dl_addr_offset = sizeof (dl_enabmulti_req_t); + (void) memcpy(&multireqp[1], addrp, addrlen); - default: - errno = EBADMSG; - goto done; - } + return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); +} - rc = 0; /* success */ -done: - free(buf); - return (rc); +int +dlpi_enabmulti(dlpi_handle_t dh, const void *addrp, size_t addrlen) +{ + return (i_dlpi_multi(dh, DL_ENABMULTI_REQ, addrp, addrlen)); } int -dlpi_bind(int fd, int timeout, uint_t sap, uint16_t mode, - boolean_t conn_mgmt, uint32_t *max_conn_ind, - uint32_t *xid_test, uint8_t *addrp, size_t *addrlenp) +dlpi_disabmulti(dlpi_handle_t dh, const void *addrp, size_t addrlen) { - int rc = -1; - size_t size; - dl_bind_req_t dlbr; - dl_bind_ack_t *dlbap; - dl_error_ack_t *dleap; - union DL_primitives *buf; - union DL_primitives *udlp; - - size = 0; - size = MAX(sizeof (dl_bind_ack_t) + MAXADDRLEN + MAXSAPLEN, size); - size = MAX(sizeof (dl_error_ack_t), size); - - if ((buf = malloc(size)) == NULL) - return (-1); - - dlbr.dl_primitive = DL_BIND_REQ; - dlbr.dl_sap = sap; - dlbr.dl_service_mode = mode; - dlbr.dl_conn_mgmt = (conn_mgmt) ? 1 : 0; - dlbr.dl_max_conind = (max_conn_ind != NULL) ? *max_conn_ind : 0; - dlbr.dl_xidtest_flg = (xid_test != NULL) ? *xid_test : 0; - - if (strputmsg(fd, (uint8_t *)&dlbr, DL_BIND_REQ_SIZE, 0) == -1) - goto done; - - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; - - if (size < sizeof (t_uscalar_t)) { - errno = EBADMSG; - goto done; - } + return (i_dlpi_multi(dh, DL_DISABMULTI_REQ, addrp, addrlen)); +} - udlp = (union DL_primitives *)buf; - switch (udlp->dl_primitive) { - case DL_BIND_ACK: - if (size < DL_BIND_ACK_SIZE) { - errno = EBADMSG; - goto done; - } +/* + * This function is invoked by dlpi_promiscon() or dlpi_promiscoff(). Based + * on the value of 'op', promiscuous mode is turned on/off at the specified + * 'level'. + */ +static int +i_dlpi_promisc(dlpi_handle_t dh, t_uscalar_t op, uint_t level) +{ + dlpi_msg_t req, ack; + dl_promiscon_req_t *promiscreqp; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; - dlbap = (dl_bind_ack_t *)buf; - if (max_conn_ind != NULL) - *max_conn_ind = dlbap->dl_max_conind; - if (xid_test != NULL) - *xid_test = dlbap->dl_xidtest_flg; + if (dip == NULL) + return (DLPI_EINHANDLE); - if (dlbap->dl_addr_offset != 0) { - if (dlbap->dl_addr_length == 0) { - errno = EPROTO; - goto done; - } + DLPI_MSG_CREATE(req, op); + DLPI_MSG_CREATE(ack, DL_OK_ACK); - if (addrlenp != NULL) - *addrlenp = dlbap->dl_addr_length; - if (addrp != NULL) - (void) memcpy(addrp, - (char *)buf + dlbap->dl_addr_offset, - dlbap->dl_addr_length); - } + promiscreqp = &(req.dlm_msg->promiscon_req); + promiscreqp->dl_level = level; - break; + return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); +} - case DL_ERROR_ACK: - if (size < DL_ERROR_ACK_SIZE) { - errno = EBADMSG; - goto done; - } +int +dlpi_promiscon(dlpi_handle_t dh, uint_t level) +{ + return (i_dlpi_promisc(dh, DL_PROMISCON_REQ, level)); +} - dleap = (dl_error_ack_t *)buf; - switch (dleap->dl_errno) { - case DL_BADADDR: - errno = EINVAL; - break; - - case DL_INITFAILED: - case DL_NOTINIT: - errno = EIO; - break; - - case DL_ACCESS: - errno = EACCES; - break; - - case DL_NOADDR: - errno = EFAULT; - break; - - case DL_UNSUPPORTED: - case DL_NOAUTO: - case DL_NOXIDAUTO: - case DL_NOTESTAUTO: - errno = ENOTSUP; - break; - - case DL_SYSERR: - errno = dleap->dl_unix_errno; - break; - - default: - errno = EPROTO; - break; - } - goto done; +int +dlpi_promiscoff(dlpi_handle_t dh, uint_t level) +{ + return (i_dlpi_promisc(dh, DL_PROMISCOFF_REQ, level)); +} - default: - errno = EBADMSG; - goto done; +int +dlpi_get_physaddr(dlpi_handle_t dh, uint_t type, void *addrp, size_t *addrlenp) +{ + int retval; + dlpi_msg_t req, ack; + dl_phys_addr_req_t *physreqp; + dl_phys_addr_ack_t *physackp; + t_uscalar_t dataoff, datalen; + caddr_t datap, physackendp; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; + + if (dip == NULL) + return (DLPI_EINHANDLE); + + if (addrlenp == NULL || addrp == NULL || *addrlenp < DLPI_PHYSADDR_MAX) + return (DLPI_EINVAL); + + DLPI_MSG_CREATE(req, DL_PHYS_ADDR_REQ); + DLPI_MSG_CREATE(ack, DL_PHYS_ADDR_ACK); + + physreqp = &(req.dlm_msg->physaddr_req); + physreqp->dl_addr_type = type; + + retval = i_dlpi_msg_common(dip, &req, &ack, DL_PHYS_ADDR_ACK_SIZE, 0); + if (retval != DLPI_SUCCESS) + return (retval); + + /* Received DL_PHYS_ADDR_ACK, store the physical address and length. */ + physackp = &(ack.dlm_msg->physaddr_ack); + physackendp = (caddr_t)ack.dlm_msg + ack.dlm_msgsz; + dataoff = physackp->dl_addr_offset; + datalen = physackp->dl_addr_length; + if (dataoff != 0 && datalen != 0) { + datap = (caddr_t)physackp + dataoff; + if (datalen > DLPI_PHYSADDR_MAX) + return (DL_BADADDR); + if (dataoff < DL_PHYS_ADDR_ACK_SIZE || + datap + datalen > physackendp) + return (DLPI_EBADMSG); + + *addrlenp = physackp->dl_addr_length; + (void) memcpy(addrp, datap, datalen); + } else { + *addrlenp = datalen; } - rc = 0; /* success */ -done: - free(buf); - return (rc); + return (DLPI_SUCCESS); } int -dlpi_unbind(int fd, int timeout) +dlpi_set_physaddr(dlpi_handle_t dh, uint_t type, const void *addrp, + size_t addrlen) { - int rc = -1; - size_t size; - dl_unbind_req_t dlubr; - dl_error_ack_t *dleap; - union DL_primitives *buf; - union DL_primitives *udlp; + dlpi_msg_t req, ack; + dl_set_phys_addr_req_t *setphysreqp; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; - size = 0; - size = MAX(sizeof (dl_ok_ack_t), size); - size = MAX(sizeof (dl_error_ack_t), size); + if (dip == NULL) + return (DLPI_EINHANDLE); - if ((buf = malloc(size)) == NULL) - return (-1); + if (addrp == NULL || type != DL_CURR_PHYS_ADDR || + addrlen > DLPI_PHYSADDR_MAX) + return (DLPI_EINVAL); - dlubr.dl_primitive = DL_UNBIND_REQ; + DLPI_MSG_CREATE(req, DL_SET_PHYS_ADDR_REQ); + DLPI_MSG_CREATE(ack, DL_OK_ACK); - if (strputmsg(fd, (uint8_t *)&dlubr, DL_UNBIND_REQ_SIZE, 0) == -1) - goto done; + setphysreqp = &(req.dlm_msg->set_physaddr_req); + setphysreqp->dl_addr_length = addrlen; + setphysreqp->dl_addr_offset = sizeof (dl_set_phys_addr_req_t); + (void) memcpy(&setphysreqp[1], addrp, addrlen); - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; + return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); +} - if (size < sizeof (t_uscalar_t)) { - errno = EBADMSG; - goto done; +int +dlpi_send(dlpi_handle_t dh, const void *daddrp, size_t daddrlen, + const void *msgbuf, size_t msglen, const dlpi_sendinfo_t *sendp) +{ + dlpi_msg_t req; + dl_unitdata_req_t *udatareqp; + uint_t sap; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; + + if (dip == NULL) + return (DLPI_EINHANDLE); + + if (dip->dli_oflags & DLPI_RAW) + return (i_dlpi_strputmsg(dip->dli_fd, NULL, msgbuf, msglen, 0)); + + if (daddrp == NULL || daddrlen > DLPI_PHYSADDR_MAX) + return (DLPI_EINVAL); + + DLPI_MSG_CREATE(req, DL_UNITDATA_REQ); + udatareqp = &(req.dlm_msg->unitdata_req); + + /* Set priority to default priority range. */ + udatareqp->dl_priority.dl_min = 0; + udatareqp->dl_priority.dl_max = 0; + + /* Use SAP value if specified otherwise use bound SAP value. */ + if (sendp != NULL) { + sap = sendp->dsi_sap; + if (sendp->dsi_prio.dl_min != DL_QOS_DONT_CARE) + udatareqp->dl_priority.dl_min = sendp->dsi_prio.dl_min; + if (sendp->dsi_prio.dl_max != DL_QOS_DONT_CARE) + udatareqp->dl_priority.dl_max = sendp->dsi_prio.dl_max; + } else { + sap = dip->dli_sap; } - udlp = (union DL_primitives *)buf; - switch (udlp->dl_primitive) { - case DL_OK_ACK: - if (size < DL_OK_ACK_SIZE) { - errno = EBADMSG; - goto done; - } - break; - - case DL_ERROR_ACK: - if (size < DL_ERROR_ACK_SIZE) { - errno = EBADMSG; - goto done; - } - - dleap = (dl_error_ack_t *)buf; - switch (dleap->dl_errno) { - case DL_SYSERR: - errno = dleap->dl_unix_errno; - break; + udatareqp->dl_dest_addr_length = daddrlen + dip->dli_saplen; + udatareqp->dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE; - default: - errno = EPROTO; - break; - } - goto done; - - default: - errno = EBADMSG; - goto done; + /* + * Since `daddrp' only has the link-layer destination address, + * we must prepend or append the SAP (according to dli_sapbefore) + * to make a full DLPI address. + */ + if (dip->dli_sapbefore) { + i_dlpi_writesap(&udatareqp[1], sap, dip->dli_saplen); + (void) memcpy((caddr_t)&udatareqp[1] + dip->dli_saplen, + daddrp, daddrlen); + } else { + (void) memcpy(&udatareqp[1], daddrp, daddrlen); + i_dlpi_writesap((caddr_t)&udatareqp[1] + daddrlen, sap, + dip->dli_saplen); } - rc = 0; /* success */ -done: - free(buf); - return (rc); + return (i_dlpi_strputmsg(dip->dli_fd, &req, msgbuf, msglen, 0)); } -static int -i_dlpi_multi(int fd, int timeout, dlpi_multi_op_t op, - uint8_t *addrp, size_t addr_length) +int +dlpi_recv(dlpi_handle_t dh, void *saddrp, size_t *saddrlenp, void *msgbuf, + size_t *msglenp, int msec, dlpi_recvinfo_t *recvp) { - int rc = -1; - size_t opsize; - size_t size; - dl_enabmulti_req_t *dlemrp; - dl_disabmulti_req_t *dldmrp; - dl_error_ack_t *dleap; - union DL_primitives *buf; - union DL_primitives *udlp; - - opsize = (op == DLPI_MULTI_ENABLE) ? sizeof (dl_enabmulti_req_t) : - sizeof (dl_disabmulti_req_t); - opsize += addr_length; - - size = 0; - size = MAX(opsize, size); - size = MAX(sizeof (dl_ok_ack_t), size); - size = MAX(sizeof (dl_error_ack_t), size); - - if ((buf = malloc(size)) == NULL) - return (-1); - - if (op == DLPI_MULTI_ENABLE) { - dlemrp = (dl_enabmulti_req_t *)buf; - dlemrp->dl_primitive = DL_ENABMULTI_REQ; - dlemrp->dl_addr_length = addr_length; - dlemrp->dl_addr_offset = sizeof (dl_enabmulti_req_t); - (void) memcpy(&dlemrp[1], addrp, addr_length); - } else { - dldmrp = (dl_disabmulti_req_t *)buf; - dldmrp->dl_primitive = DL_DISABMULTI_REQ; - dldmrp->dl_addr_length = addr_length; - dldmrp->dl_addr_offset = sizeof (dl_disabmulti_req_t); - (void) memcpy(&dldmrp[1], addrp, addr_length); - } + int retval; + dlpi_msg_t ind; + size_t totmsglen; + dl_unitdata_ind_t *udatap; + t_uscalar_t dataoff, datalen; + caddr_t datap, indendp; + dlpi_impl_t *dip = (dlpi_impl_t *)dh; + + if (dip == NULL) + return (DLPI_EINHANDLE); + /* + * If handle is in raw mode ignore everything except total message + * length. + */ + if (dip->dli_oflags & DLPI_RAW) { + retval = i_dlpi_strgetmsg(dip->dli_fd, msec, NULL, 0, 0, 0, + msgbuf, msglenp, &totmsglen); - if (strputmsg(fd, (uint8_t *)buf, opsize, 0) == -1) - goto done; + if (retval == DLPI_SUCCESS && recvp != NULL) + recvp->dri_totmsglen = totmsglen; + return (retval); + } - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; + DLPI_MSG_CREATE(ind, DL_UNITDATA_IND); + udatap = &(ind.dlm_msg->unitdata_ind); + indendp = (caddr_t)ind.dlm_msg + ind.dlm_msgsz; - if (size < sizeof (t_uscalar_t)) { - errno = EBADMSG; - goto done; - } + if ((retval = i_dlpi_strgetmsg(dip->dli_fd, msec, &ind, + DL_UNITDATA_IND, DL_UNITDATA_IND, DL_UNITDATA_IND_SIZE, + msgbuf, msglenp, &totmsglen)) != DLPI_SUCCESS) + return (retval); - udlp = (union DL_primitives *)buf; - switch (udlp->dl_primitive) { - case DL_OK_ACK: - if (size < DL_OK_ACK_SIZE) { - errno = EBADMSG; - goto done; + /* + * If DLPI link provides source address, store source address in + * 'saddrp' and source length in 'saddrlenp', else set saddrlenp to 0. + */ + if (saddrp != NULL && saddrlenp != NULL) { + if (*saddrlenp < DLPI_PHYSADDR_MAX) + return (DLPI_EINVAL); + + dataoff = udatap->dl_src_addr_offset; + datalen = udatap->dl_src_addr_length; + if (dataoff != 0 && datalen != 0) { + datap = (caddr_t)udatap + dataoff; + if (dataoff < DL_UNITDATA_IND_SIZE || + datap + datalen > indendp) + return (DLPI_EBADMSG); + + *saddrlenp = datalen - dip->dli_saplen; + if (*saddrlenp > DLPI_PHYSADDR_MAX) + return (DL_BADADDR); + + if (dip->dli_sapbefore) + datap += dip->dli_saplen; + (void) memcpy(saddrp, datap, *saddrlenp); + } else { + *saddrlenp = 0; } - break; + } - case DL_ERROR_ACK: - if (size < DL_ERROR_ACK_SIZE) { - errno = EBADMSG; - goto done; + /* + * If destination address requested, check and save destination + * address, if any. + */ + if (recvp != NULL) { + dataoff = udatap->dl_dest_addr_offset; + datalen = udatap->dl_dest_addr_length; + if (dataoff != 0 && datalen != 0) { + datap = (caddr_t)udatap + dataoff; + if (dataoff < DL_UNITDATA_IND_SIZE || + datap + datalen > indendp) + return (DLPI_EBADMSG); + + recvp->dri_destaddrlen = datalen - dip->dli_saplen; + if (recvp->dri_destaddrlen > DLPI_PHYSADDR_MAX) + return (DL_BADADDR); + + if (dip->dli_sapbefore) + datap += dip->dli_saplen; + (void) memcpy(recvp->dri_destaddr, datap, + recvp->dri_destaddrlen); + } else { + recvp->dri_destaddrlen = 0; } - dleap = (dl_error_ack_t *)buf; - switch (dleap->dl_errno) { - case DL_BADADDR: - errno = EINVAL; - break; - - case DL_TOOMANY: - errno = ENOSPC; - break; + recvp->dri_dstaddrtype = udatap->dl_group_address; + recvp->dri_totmsglen = totmsglen; + } - case DL_NOTSUPPORTED: - errno = ENOTSUP; - break; + return (DLPI_SUCCESS); +} - case DL_NOTENAB: - errno = EINVAL; - break; +int +dlpi_fd(dlpi_handle_t dh) +{ + dlpi_impl_t *dip = (dlpi_impl_t *)dh; - case DL_SYSERR: - errno = dleap->dl_unix_errno; - break; + return (dip != NULL ? dip->dli_fd : -1); +} - default: - errno = EPROTO; - break; - } - goto done; +int +dlpi_set_timeout(dlpi_handle_t dh, int sec) +{ + dlpi_impl_t *dip = (dlpi_impl_t *)dh; - default: - errno = EBADMSG; - goto done; - } + if (dip == NULL) + return (DLPI_EINHANDLE); - rc = 0; /* success */ -done: - free(buf); - return (rc); + dip->dli_timeout = sec; + return (DLPI_SUCCESS); } -int -dlpi_enabmulti(int fd, int timeout, uint8_t *addrp, - size_t addr_length) +const char * +dlpi_linkname(dlpi_handle_t dh) { - return (i_dlpi_multi(fd, timeout, DLPI_MULTI_ENABLE, addrp, - addr_length)); + dlpi_impl_t *dip = (dlpi_impl_t *)dh; + + return (dip != NULL ? dip->dli_linkname : NULL); } -int -dlpi_disabmulti(int fd, int timeout, uint8_t *addrp, - size_t addr_length) +/* + * Returns DLPI style stored in the handle. + * Note: This function is used for test purposes only. Do not remove without + * fixing the DLPI testsuite. + */ +uint_t +dlpi_style(dlpi_handle_t dh) { - return (i_dlpi_multi(fd, timeout, DLPI_MULTI_DISABLE, addrp, - addr_length)); + dlpi_impl_t *dip = (dlpi_impl_t *)dh; + + return (dip->dli_style); } +/* + * This function attempts to open linkname under the following namespaces: + * - /dev + * - /devices + * If open doesn't succeed and link doesn't exist (ENOENT), this function + * returns DLPI_ENOLINK, otherwise returns DL_SYSERR. + */ static int -i_dlpi_promisc(int fd, int timeout, dlpi_promisc_op_t op, - uint_t level) +i_dlpi_open(const char *provider, int *fd, uint_t flags) { - int rc = -1; - size_t opsize; - size_t size; - dl_promiscon_req_t *dlpnrp; - dl_promiscoff_req_t *dlpfrp; - dl_error_ack_t *dleap; - union DL_primitives *buf; - union DL_primitives *udlp; - - opsize = (op == DLPI_PROMISC_ON) ? sizeof (dl_promiscon_req_t) : - sizeof (dl_promiscoff_req_t); - - size = 0; - size = MAX(opsize, size); - size = MAX(sizeof (dl_ok_ack_t), size); - size = MAX(sizeof (dl_error_ack_t), size); - - if ((buf = malloc(size)) == NULL) - return (-1); - - if (op == DLPI_PROMISC_ON) { - dlpnrp = (dl_promiscon_req_t *)buf; - dlpnrp->dl_primitive = DL_PROMISCON_REQ; - dlpnrp->dl_level = level; - - if (strputmsg(fd, (uint8_t *)dlpnrp, opsize, 0) == -1) - goto done; - } else { - dlpfrp = (dl_promiscoff_req_t *)buf; - dlpfrp->dl_primitive = DL_PROMISCOFF_REQ; - dlpfrp->dl_level = level; - - if (strputmsg(fd, (uint8_t *)dlpfrp, opsize, 0) == -1) - goto done; - } + char path[MAXPATHLEN]; + int oflags; - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; + oflags = O_RDWR; + if (flags & DLPI_EXCL) + oflags |= O_EXCL; - if (size < sizeof (t_uscalar_t)) { - errno = EBADMSG; - goto done; - } + (void) snprintf(path, sizeof (path), "/dev/%s", provider); - udlp = (union DL_primitives *)buf; - switch (udlp->dl_primitive) { - case DL_OK_ACK: - if (size < DL_OK_ACK_SIZE) { - errno = EBADMSG; - goto done; - } - break; + if ((*fd = open(path, oflags)) != -1) + return (DLPI_SUCCESS); - case DL_ERROR_ACK: - if (size < DL_ERROR_ACK_SIZE) { - errno = EBADMSG; - goto done; - } + /* + * On diskless boot, it's possible the /dev links have not yet + * been created; fallback to /devices. When /dev links are + * created on demand, this code can be removed. + */ + (void) snprintf(path, sizeof (path), "/devices/pseudo/clone@0:%s", + provider); - dleap = (dl_error_ack_t *)buf; - switch (dleap->dl_errno) { - case DL_NOTSUPPORTED: - case DL_UNSUPPORTED: - errno = ENOTSUP; - break; + if ((*fd = open(path, oflags)) != -1) + return (DLPI_SUCCESS); - case DL_NOTENAB: - errno = EINVAL; - break; + return (errno == ENOENT ? DLPI_ENOLINK : DL_SYSERR); +} - case DL_SYSERR: - errno = dleap->dl_unix_errno; - break; +/* + * Open a style 1 link. PPA is implicitly attached. + */ +static int +i_dlpi_style1_open(dlpi_impl_t *dip) +{ + int retval, save_errno; + int fd; - default: - errno = EPROTO; - break; - } - goto done; + /* + * In order to support open of syntax like device[.module[.module...]] + * where modules need to be pushed onto the device stream, open only + * device name, otherwise open the full linkname. + */ + retval = i_dlpi_open((dip->dli_mod_cnt != 0) ? dip->dli_provider : + dip->dli_linkname, &fd, dip->dli_oflags); - default: - errno = EBADMSG; - goto done; + if (retval != DLPI_SUCCESS) { + dip->dli_mod_pushed = 0; + return (retval); } + dip->dli_fd = fd; - rc = 0; /* success */ -done: - free(buf); - return (rc); -} + /* + * Try to push modules (if any) onto the device stream. If I_PUSH + * fails, we increment count of modules pushed (dli_mod_pushed) + * expecting it is last module to be pushed and thus will be pushed + * in i_dlpi_style2_open(). + */ + for (dip->dli_mod_pushed = 0; dip->dli_mod_pushed < dip->dli_mod_cnt; + dip->dli_mod_pushed++) { + if (ioctl(fd, I_PUSH, + dip->dli_modlist[dip->dli_mod_pushed]) == -1) { + dip->dli_mod_pushed++; + return (DLPI_FAILURE); + } + } -int -dlpi_promiscon(int fd, int timeout, uint_t level) -{ - return (i_dlpi_promisc(fd, timeout, DLPI_PROMISC_ON, level)); -} + if ((retval = i_dlpi_checkstyle(dip, DL_STYLE1)) != DLPI_SUCCESS) { + save_errno = errno; + (void) close(dip->dli_fd); + errno = save_errno; + dip->dli_mod_pushed = 0; + return (retval); + } -int -dlpi_promiscoff(int fd, int timeout, uint_t level) -{ - return (i_dlpi_promisc(fd, timeout, DLPI_PROMISC_OFF, level)); + return (DLPI_SUCCESS); } -int -dlpi_phys_addr(int fd, int timeout, uint_t type, uint8_t *addrp, - size_t *addrlenp) +/* + * Open a style 2 link. PPA must be explicitly attached. + */ +static int +i_dlpi_style2_open(dlpi_impl_t *dip) { - int rc = -1; - size_t size; - dl_phys_addr_req_t dlpar; - dl_phys_addr_ack_t *dlpaap; - dl_error_ack_t *dleap; - union DL_primitives *buf; - union DL_primitives *udlp; + int fd; + int retval, save_errno; - size = 0; - size = MAX(sizeof (dl_phys_addr_ack_t) + MAXADDRLEN, size); - size = MAX(sizeof (dl_error_ack_t), size); + /* + * If style 1 open failed, we need to determine how far it got and + * finish up the open() call as a style 2 open. + * + * If no modules were pushed (mod_pushed == 0), then we need to + * open it as a style 2 link. + * + * If the pushing of the last module failed, we need to + * try pushing it as a style 2 module. Decrement dli_mod_pushed + * count so it can be pushed onto the stream. + * + * Otherwise we failed during the push of an intermediate module and + * must fail out and close the link. + */ + if (dip->dli_mod_pushed == 0) { + if ((retval = i_dlpi_open(dip->dli_provider, &fd, + dip->dli_oflags)) != DLPI_SUCCESS) + return (retval); + + dip->dli_fd = fd; + } else if (dip->dli_mod_pushed == dip->dli_mod_cnt) { + if (i_dlpi_remove_ppa(dip->dli_modlist[dip->dli_mod_cnt - 1]) + != DLPI_SUCCESS) + return (DLPI_ELINKNAMEINVAL); + + dip->dli_mod_pushed--; + fd = dip->dli_fd; + } else { + return (DLPI_ELINKNAMEINVAL); + } - if ((buf = malloc(size)) == NULL) - return (-1); + /* Try and push modules (if any) onto the device stream. */ + for (; dip->dli_mod_pushed < dip->dli_mod_cnt; dip->dli_mod_pushed++) { + if (ioctl(fd, I_PUSH, + dip->dli_modlist[dip->dli_mod_pushed]) == -1) { + retval = DL_SYSERR; + goto failure; + } + } - dlpar.dl_primitive = DL_PHYS_ADDR_REQ; - dlpar.dl_addr_type = type; + /* + * Special case: DLPI_SERIAL flag (synchronous serial lines) is not a + * DLPI link so attach and ignore rest. + */ + if (dip->dli_oflags & DLPI_SERIAL) + goto attach; - if (strputmsg(fd, (uint8_t *)&dlpar, DL_PHYS_ADDR_REQ_SIZE, 0) == -1) - goto done; + if ((retval = i_dlpi_checkstyle(dip, DL_STYLE2)) != DLPI_SUCCESS) + goto failure; - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; + /* + * Succeeded opening the link and verified it is style2. Now attach to + * PPA only if DLPI_NOATTACH is not set. + */ + if (dip->dli_oflags & DLPI_NOATTACH) + return (DLPI_SUCCESS); - if (size < sizeof (t_uscalar_t)) { - errno = EBADMSG; - goto done; - } +attach: + if ((retval = i_dlpi_attach(dip)) != DLPI_SUCCESS) + goto failure; - udlp = (union DL_primitives *)buf; - switch (udlp->dl_primitive) { - case DL_PHYS_ADDR_ACK: - if (size < DL_PHYS_ADDR_ACK_SIZE) { - errno = EBADMSG; - goto done; - } + return (DLPI_SUCCESS); - dlpaap = (dl_phys_addr_ack_t *)buf; - if (dlpaap->dl_addr_offset != 0) { - if (dlpaap->dl_addr_length == 0) { - errno = EPROTO; - goto done; - } +failure: + save_errno = errno; + (void) close(dip->dli_fd); + errno = save_errno; + return (retval); +} - if (addrlenp != NULL) - *addrlenp = dlpaap->dl_addr_length; +/* + * Verify with DLPI that the link is the expected DLPI 'style' device, + * dlpi_info sets the DLPI style in the DLPI handle. + */ +static int +i_dlpi_checkstyle(dlpi_impl_t *dip, t_uscalar_t style) +{ + int retval; + dlpi_info_t dlinfo; - if (addrp != NULL) - (void) memcpy(addrp, - (char *)buf + dlpaap->dl_addr_offset, - dlpaap->dl_addr_length); - } - break; + retval = dlpi_info((dlpi_handle_t)dip, &dlinfo, 0); + if (retval == DLPI_SUCCESS && dip->dli_style != style) + retval = DLPI_EBADLINK; - case DL_ERROR_ACK: - if (size < DL_ERROR_ACK_SIZE) { - errno = EBADMSG; - goto done; - } + return (retval); +} - dleap = (dl_error_ack_t *)buf; - switch (dleap->dl_errno) { - case DL_SYSERR: - errno = dleap->dl_unix_errno; - break; +/* + * Remove PPA from end of linkname. + * Return DLPI_SUCCESS if found, else return DLPI_FAILURE. + */ +static int +i_dlpi_remove_ppa(char *linkname) +{ + int i = strlen(linkname) - 1; - default: - errno = EPROTO; - break; - } - goto done; + if (i == -1 || !isdigit(linkname[i--])) + return (DLPI_FAILURE); - default: - errno = EBADMSG; - goto done; - } + while (i >= 0 && isdigit(linkname[i])) + i--; - rc = 0; /* success */ -done: - free(buf); - return (rc); + linkname[i + 1] = '\0'; + return (DLPI_SUCCESS); } -int -dlpi_set_phys_addr(int fd, int timeout, uint8_t *addrp, - size_t addr_length) +/* + * For DLPI style 2 providers, an explicit attach of PPA is required. + */ +static int +i_dlpi_attach(dlpi_impl_t *dip) { - int rc = -1; - size_t opsize; - size_t size; - dl_set_phys_addr_req_t *dlspap; - dl_error_ack_t *dleap; - union DL_primitives *buf; - union DL_primitives *udlp; - - opsize = sizeof (dl_set_phys_addr_req_t) + addr_length; - - size = 0; - size = MAX(opsize, size); - size = MAX(sizeof (dl_ok_ack_t), size); - size = MAX(sizeof (dl_error_ack_t), size); - - if ((buf = malloc(size)) == NULL) - return (-1); - - dlspap = (dl_set_phys_addr_req_t *)buf; - dlspap->dl_primitive = DL_SET_PHYS_ADDR_REQ; - dlspap->dl_addr_length = addr_length; - dlspap->dl_addr_offset = sizeof (dl_set_phys_addr_req_t); - (void) memcpy(&dlspap[1], addrp, addr_length); - - if (strputmsg(fd, (uint8_t *)dlspap, opsize, 0) == -1) - goto done; - - if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) - goto done; - - if (size < sizeof (t_uscalar_t)) { - errno = EBADMSG; - goto done; - } - - udlp = (union DL_primitives *)buf; - switch (udlp->dl_primitive) { - case DL_OK_ACK: - if (size < DL_OK_ACK_SIZE) { - errno = EBADMSG; - goto done; - } - break; + dlpi_msg_t req, ack; + dl_attach_req_t *attachreqp; - case DL_ERROR_ACK: - if (size < DL_ERROR_ACK_SIZE) { - errno = EBADMSG; - goto done; - } + /* + * Special case: DLPI_SERIAL flag (synchronous serial lines) + * is not a DLPI link so ignore DLPI style. + */ + if (dip->dli_style != DL_STYLE2 && !(dip->dli_oflags & DLPI_SERIAL)) + return (DLPI_ENOTSTYLE2); - dleap = (dl_error_ack_t *)buf; - switch (dleap->dl_errno) { - case DL_BADADDR: - errno = EINVAL; - break; + DLPI_MSG_CREATE(req, DL_ATTACH_REQ); + DLPI_MSG_CREATE(ack, DL_OK_ACK); - case DL_NOTSUPPORTED: - errno = ENOTSUP; - break; + attachreqp = &(req.dlm_msg->attach_req); + attachreqp->dl_ppa = dip->dli_ppa; - case DL_SYSERR: - errno = dleap->dl_unix_errno; - break; + return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); +} - default: - errno = EPROTO; - break; - } - goto done; +/* + * Enable DLPI passive mode on a DLPI handle. We intentionally do not care + * if this request fails, as this indicates the underlying DLPI device does + * not support link aggregation (pre-GLDV3 device drivers), and thus will + * see the expected behavior without failing with DL_SYSERR/EBUSY when issuing + * DLPI primitives like DL_BIND_REQ. For further info see dlpi(7p). + */ +static void +i_dlpi_passive(dlpi_impl_t *dip) +{ + dlpi_msg_t req, ack; - default: - errno = EBADMSG; - goto done; - } + DLPI_MSG_CREATE(req, DL_PASSIVE_REQ); + DLPI_MSG_CREATE(ack, DL_OK_ACK); - rc = 0; /* success */ -done: - free(buf); - return (rc); + (void) i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0); } -void -dlpi_passive(int fd, int timeout) +/* + * Send a dlpi control message and/or data message on a stream. The inputs + * for this function are: + * int fd: file descriptor of open stream to send message + * const dlpi_msg_t *dlreqp: request message structure + * void *databuf: data buffer + * size_t datalen: data buffer len + * int flags: flags to set for putmsg() + * Returns DLPI_SUCCESS if putmsg() succeeds, otherwise DL_SYSERR on failure. + */ +static int +i_dlpi_strputmsg(int fd, const dlpi_msg_t *dlreqp, + const void *databuf, size_t datalen, int flags) { - size_t size; - dl_passive_req_t dlpr; - union DL_primitives *buf; + int retval; + struct strbuf ctl; + struct strbuf data; - size = MAX(sizeof (dl_ok_ack_t), sizeof (dl_error_ack_t)); + if (dlreqp != NULL) { + ctl.buf = (void *)dlreqp->dlm_msg; + ctl.len = dlreqp->dlm_msgsz; + } - if ((buf = malloc(size)) == NULL) - return; + data.buf = (void *)databuf; + data.len = datalen; - dlpr.dl_primitive = DL_PASSIVE_REQ; + retval = putmsg(fd, (dlreqp == NULL ? NULL: &ctl), + (databuf == NULL ? NULL : &data), flags); - /* - * We don't care about the outcome of this operation. We at least - * don't want to return until the operation completes or the - * timeout expires. - */ - if (strputmsg(fd, (uint8_t *)&dlpr, DL_PASSIVE_REQ_SIZE, 0) == 0) - (void) strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL); - free(buf); + return ((retval == 0) ? DLPI_SUCCESS : DL_SYSERR); } +/* + * Get a DLPI control message and/or data message from a stream. The inputs + * for this function are: + * int fd: file descriptor of open stream + * int msec: timeout to wait for message + * dlpi_msg_t *dlreplyp: reply message structure, the message size + * member on return stores actual size received + * t_uscalar_t dlreqprim: requested primitive + * t_uscalar_t dlreplyprim:acknowledged primitive in response to request + * size_t dlreplyminsz: minimum size of acknowledged primitive size + * void *databuf: data buffer + * size_t *datalenp: data buffer len + * size_t *totdatalenp: total data received. Greater than 'datalenp' if + * actual data received is larger than 'databuf' + * Function returns DLPI_SUCCESS if requested message is retrieved + * otherwise returns error code or timeouts. + */ static int -i_dlpi_style1_open(dlpi_if_attr_t *diap) +i_dlpi_strgetmsg(int fd, int msec, dlpi_msg_t *dlreplyp, t_uscalar_t dlreqprim, + t_uscalar_t dlreplyprim, size_t dlreplyminsz, void *databuf, + size_t *datalenp, size_t *totdatalenp) { - int fd; - int cnt; - dl_info_ack_t dlia; + int retval; + int flags = 0; + struct strbuf ctl, data; + struct pollfd pfd; + hrtime_t start, current; + long bufc[DLPI_CHUNKSIZE / sizeof (long)]; + long bufd[DLPI_CHUNKSIZE / sizeof (long)]; + union DL_primitives *dlprim; + boolean_t infinite = (msec < 0); /* infinite timeout */ + + if ((dlreplyp == NULL && databuf == NULL) || + (databuf == NULL && datalenp != NULL) || + (databuf != NULL && datalenp == NULL)) + return (DLPI_EINVAL); - /* Open device */ - if ((fd = dlpi_open(diap->devname)) == -1) { - diap->style1_failed = B_TRUE; - diap->mod_pushed = 0; - return (-1); - } else { - diap->style1_fd = fd; - } + pfd.fd = fd; + pfd.events = POLLIN | POLLPRI; - /* - * Try to push modules (if any) onto the device stream - */ - for (cnt = 0; cnt < diap->mod_cnt; cnt++) { - if (ioctl(fd, I_PUSH, diap->modlist[cnt]) == -1) { - diap->mod_pushed = cnt+1; - return (-1); + ctl.buf = (dlreplyp == NULL) ? bufc : (void *)dlreplyp->dlm_msg; + ctl.len = 0; + ctl.maxlen = (dlreplyp == NULL) ? sizeof (bufc) : dlreplyp->dlm_msgsz; + + data.buf = (databuf == NULL) ? bufd : databuf; + data.len = 0; + data.maxlen = (databuf == NULL) ? sizeof (bufd): *datalenp; + + for (;;) { + if (!infinite) + start = gethrtime() / (NANOSEC / MILLISEC); + + switch (poll(&pfd, 1, msec)) { + default: + break; + case 0: + return (DLPI_ETIMEDOUT); + case -1: + return (DL_SYSERR); } - } - if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) == -1) - goto failed; + if ((retval = getmsg(fd, &ctl, &data, &flags)) < 0) + return (DL_SYSERR); + + if (totdatalenp != NULL) + *totdatalenp = data.len; + + /* + * The supplied DLPI_CHUNKSIZE sized buffers are large enough + * to retrieve all valid DLPI responses in one iteration. + * If MORECTL or MOREDATA is set, we are not interested in the + * remainder of the message. Temporary buffers are used to + * drain the remainder of this message. + * The special case we have to account for is if + * a higher priority messages is enqueued whilst handling + * this condition. We use a change in the flags parameter + * returned by getmsg() to indicate the message has changed. + */ + while (retval & (MORECTL | MOREDATA)) { + struct strbuf cscratch, dscratch; + int oflags = flags; + + cscratch.buf = (char *)bufc; + dscratch.buf = (char *)bufd; + cscratch.len = dscratch.len = 0; + cscratch.maxlen = dscratch.maxlen = + sizeof (bufc); + + if ((retval = getmsg(fd, &cscratch, &dscratch, + &flags)) < 0) + return (DL_SYSERR); + + if (totdatalenp != NULL) + *totdatalenp += dscratch.len; + /* + * In the special case of higher priority + * message received, the low priority message + * received earlier is discarded, if no data + * or control message is left. + */ + if ((flags != oflags) && + !(retval & (MORECTL | MOREDATA)) && + (cscratch.len != 0)) { + ctl.len = MIN(cscratch.len, DLPI_CHUNKSIZE); + if (dlreplyp != NULL) + (void) memcpy(dlreplyp->dlm_msg, bufc, + ctl.len); + break; + } + } + + /* + * If we were expecting a data message, and we got one, set + * *datalenp. If we aren't waiting on a control message, then + * we're done. + */ + if (databuf != NULL && data.len >= 0) { + *datalenp = data.len; + if (dlreplyp == NULL) + break; + } + + /* + * If we were expecting a control message, and the message + * we received is at least big enough to be a DLPI message, + * then verify it's a reply to something we sent. If it + * is a reply to something we sent, also verify its size. + */ + if (dlreplyp != NULL && ctl.len >= sizeof (t_uscalar_t)) { + dlprim = dlreplyp->dlm_msg; + if (dlprim->dl_primitive == dlreplyprim) { + if (ctl.len < dlreplyminsz) + return (DLPI_EBADMSG); + dlreplyp->dlm_msgsz = ctl.len; + break; + } else if (dlprim->dl_primitive == DL_ERROR_ACK) { + if (ctl.len < DL_ERROR_ACK_SIZE) + return (DLPI_EBADMSG); + + /* Is it ours? */ + if (dlprim->error_ack.dl_error_primitive == + dlreqprim) + break; + } + } - if (dlia.dl_provider_style != DL_STYLE1) - goto failed; + if (!infinite) { + current = gethrtime() / (NANOSEC / MILLISEC); + msec -= (current - start); - diap->style = DL_STYLE1; - diap->style1_failed = B_FALSE; + if (msec <= 0) + return (DLPI_ETIMEDOUT); + } + } - return (fd); -failed: - diap->style1_failed = B_TRUE; - (void) dlpi_close(fd); - return (-1); + return (DLPI_SUCCESS); } +/* + * Common routine invoked by all DLPI control routines. The inputs for this + * function are: + * dlpi_impl_t *dip: internal dlpi handle + * const dlpi_msg_t *dlreqp: request message structure + * dlpi_msg_t *dlreplyp: reply message structure + * size_t dlreplyminsz: minimum size of reply primitive + * int flags: flags to be set to send a message + * This routine succeeds if the message is an expected request/acknowledged + * message. Unexpected asynchronous messages (e.g. unexpected DL_NOTIFY_IND + * messages) will be discarded. + */ static int -i_dlpi_style2_open(dlpi_if_attr_t *diap) +i_dlpi_msg_common(dlpi_impl_t *dip, const dlpi_msg_t *dlreqp, + dlpi_msg_t *dlreplyp, size_t dlreplyminsz, int flags) { - int fd; - uint_t ppa; - dl_info_ack_t dlia; + int retval; + t_uscalar_t dlreqprim = dlreqp->dlm_msg->dl_primitive; + t_uscalar_t dlreplyprim = dlreplyp->dlm_msg->dl_primitive; - /* - * If style 1 open failed, we need to determine how far it got and - * finish up the open() call as a style 2 open - * - * If no modules were pushed (mod_pushed == 0), then we need to - * strip off the ppa off the device name and open it as a style 2 - * device - * - * If the pushing of the last module failed, we need to strip off the - * ppa from that module and try pushing it as a style 2 module - * - * Otherwise we failed during the push of an intermediate module and - * must fail out and close the device. - * - * And if style1 did not fail (i.e. we called style2 open directly), - * just open the device - */ - if (diap->style1_failed) { - if (!diap->mod_pushed) { - if (i_dlpi_ifrm_num(diap->devname, &ppa) < 0) - return (-1); - if ((fd = dlpi_open(diap->devname)) == -1) - return (-1); - } else if (diap->mod_pushed == diap->mod_cnt) { - if (i_dlpi_ifrm_num( - diap->modlist[diap->mod_cnt - 1], &ppa) < 0) - return (-1); - diap->mod_pushed--; - fd = diap->style1_fd; - } else { - return (-1); - } - } else { - if ((fd = dlpi_open(diap->devname)) == -1) - return (-1); - } + /* Put the requested primitive on the stream. */ + retval = i_dlpi_strputmsg(dip->dli_fd, dlreqp, NULL, 0, flags); + if (retval != DLPI_SUCCESS) + return (retval); + + /* Retrieve acknowledged message for requested primitive. */ + retval = i_dlpi_strgetmsg(dip->dli_fd, (dip->dli_timeout * MILLISEC), + dlreplyp, dlreqprim, dlreplyprim, dlreplyminsz, NULL, NULL, NULL); + if (retval != DLPI_SUCCESS) + return (retval); /* - * Try and push modules (if any) onto the device stream + * If primitive is DL_ERROR_ACK, set errno. */ - for (; diap->mod_pushed < diap->mod_cnt; diap->mod_pushed++) { - if (ioctl(fd, I_PUSH, - diap->modlist[diap->mod_pushed]) == -1) - goto failed; + if (dlreplyp->dlm_msg->dl_primitive == DL_ERROR_ACK) { + errno = dlreplyp->dlm_msg->error_ack.dl_unix_errno; + retval = dlreplyp->dlm_msg->error_ack.dl_errno; } - if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, - NULL) == -1) - goto failed; - - if (dlia.dl_provider_style != DL_STYLE2) - goto failed; + return (retval); +} - diap->style = DL_STYLE2; +/* + * DLPI error codes. + */ +static const char *dlpi_errlist[] = { + "bad LSAP selector", /* DL_BADSAP 0x00 */ + "DLSAP address in improper format or invalid", /* DL_BADADDR 0x01 */ + "improper permissions for request", /* DL_ACCESS 0x02 */ + "primitive issued in improper state", /* DL_OUTSTATE 0x03 */ + NULL, /* DL_SYSERR 0x04 */ + "sequence number not from outstanding DL_CONN_IND", + /* DL_BADCORR 0x05 */ + "user data exceeded provider limit", /* DL_BADDATA 0x06 */ + "requested service not supplied by provider", + /* DL_UNSUPPORTED 0x07 */ + "specified PPA was invalid", /* DL_BADPPA 0x08 */ + "primitive received not known by provider", /* DL_BADPRIM 0x09 */ + "QoS parameters contained invalid values", + /* DL_BADQOSPARAM 0x0a */ + "QoS structure type is unknown/unsupported", /* DL_BADQOSTYPE 0x0b */ + "token used not an active stream", /* DL_BADTOKEN 0x0c */ + "attempted second bind with dl_max_conind", /* DL_BOUND 0x0d */ + "physical link initialization failed", /* DL_INITFAILED 0x0e */ + "provider couldn't allocate alternate address", /* DL_NOADDR 0x0f */ + "physical link not initialized", /* DL_NOTINIT 0x10 */ + "previous data unit could not be delivered", + /* DL_UNDELIVERABLE 0x11 */ + "primitive is known but unsupported", + /* DL_NOTSUPPORTED 0x12 */ + "limit exceeded", /* DL_TOOMANY 0x13 */ + "promiscuous mode not enabled", /* DL_NOTENAB 0x14 */ + "other streams for PPA in post-attached", /* DL_BUSY 0x15 */ + "automatic handling XID&TEST unsupported", /* DL_NOAUTO 0x16 */ + "automatic handling of XID unsupported", /* DL_NOXIDAUTO 0x17 */ + "automatic handling of TEST unsupported", /* DL_NOTESTAUTO 0x18 */ + "automatic handling of XID response", /* DL_XIDAUTO 0x19 */ + "automatic handling of TEST response", /* DL_TESTAUTO 0x1a */ + "pending outstanding connect indications" /* DL_PENDING 0x1b */ +}; - if (dlpi_attach(fd, -1, diap->ppa) < 0) - goto failed; +/* + * libdlpi error codes. + */ +static const char *libdlpi_errlist[] = { + "DLPI operation succeeded", /* DLPI_SUCCESS */ + "invalid argument", /* DLPI_EINVAL */ + "invalid DLPI linkname", /* DLPI_ELINKNAMEINVAL */ + "DLPI link does not exist", /* DLPI_ENOLINK */ + "bad DLPI link", /* DLPI_EBADLINK */ + "invalid DLPI handle", /* DLPI_EINHANDLE */ + "DLPI operation timed out", /* DLPI_ETIMEDOUT */ + "unsupported DLPI version", /* DLPI_EVERNOTSUP */ + "unsupported DLPI connection mode", /* DLPI_EMODENOTSUP */ + "unavailable DLPI SAP", /* DLPI_EUNAVAILSAP */ + "DLPI operation failed", /* DLPI_FAILURE */ + "DLPI style-2 node reports style-1", /* DLPI_ENOTSTYLE2 */ + "bad DLPI message", /* DLPI_EBADMSG */ + "DLPI raw mode not supported" /* DLPI_ERAWNOTSUP */ +}; - return (fd); -failed: - (void) dlpi_close(fd); - return (-1); +const char * +dlpi_strerror(int err) +{ + if (err == DL_SYSERR) + return (strerror(errno)); + else if (err >= 0 && err < NELEMS(dlpi_errlist)) + return (dgettext(TEXT_DOMAIN, dlpi_errlist[err])); + else if (err > DLPI_SUCCESS && err < DLPI_ERRMAX) + return (dgettext(TEXT_DOMAIN, libdlpi_errlist[err - + DLPI_SUCCESS])); + else + return (dgettext(TEXT_DOMAIN, "Unknown DLPI error")); } -static int -i_dlpi_ifname_parse(const char *ifname, dlpi_if_attr_t *diap) +/* + * Each table entry comprises a DLPI/Private mactype and the description. + */ +static const dlpi_mactype_t dlpi_mactypes[] = { + { DL_CSMACD, "CSMA/CD" }, + { DL_TPB, "Token Bus" }, + { DL_TPR, "Token Ring" }, + { DL_METRO, "Metro Net" }, + { DL_ETHER, "Ethernet" }, + { DL_HDLC, "HDLC" }, + { DL_CHAR, "Sync Character" }, + { DL_CTCA, "CTCA" }, + { DL_FDDI, "FDDI" }, + { DL_FRAME, "Frame Relay (LAPF)" }, + { DL_MPFRAME, "MP Frame Relay" }, + { DL_ASYNC, "Async Character" }, + { DL_IPX25, "X.25 (Classic IP)" }, + { DL_LOOP, "Software Loopback" }, + { DL_FC, "Fiber Channel" }, + { DL_ATM, "ATM" }, + { DL_IPATM, "ATM (Classic IP)" }, + { DL_X25, "X.25 (LAPB)" }, + { DL_ISDN, "ISDN" }, + { DL_HIPPI, "HIPPI" }, + { DL_100VG, "100BaseVG Ethernet" }, + { DL_100VGTPR, "100BaseVG Token Ring" }, + { DL_ETH_CSMA, "Ethernet/IEEE 802.3" }, + { DL_100BT, "100BaseT" }, + { DL_IB, "Infiniband" }, + { DL_IPV4, "IPv4 Tunnel" }, + { DL_IPV6, "IPv6 Tunnel" }, + { DL_WIFI, "IEEE 802.11" } +}; + +const char * +dlpi_mactype(uint_t mactype) { - char *modlist = NULL; /* list of modules to push */ - int cnt = 0; /* number of modules to push */ - char modbuf[LIFNAMSIZ + 32]; - char *nxtmod; - char *p; - int len; - - /* if lun is specified fail (backwards compat) */ - if (strchr(ifname, ':') != NULL) - return (-1); - - /* save copy of original device name */ - if (strlcpy(diap->ifname, ifname, sizeof (diap->ifname)) >= - sizeof (diap->ifname)) - return (-1); - - /* initialize ppa */ - diap->ppa = -1; - - /* get provider name and ppa from ifname */ - len = strlen(ifname); - for (p = (char *)ifname + len; --p != ifname; len--) { - if (!isdigit(*p)) { - (void) strlcpy(diap->provider, ifname, len + 1); - diap->ppa = atoi(p + 1); - break; - } - } + int i; - if (strlcpy(modbuf, diap->ifname, sizeof (modbuf)) >= - sizeof (modbuf)) - return (-1); - - /* parse '.' delimited module list */ - modlist = strchr(modbuf, '.'); - if (modlist != NULL) { - /* null-terminate interface name (device) */ - *modlist = '\0'; - modlist++; - while (modlist && cnt < MAX_MODS) { - if (*modlist == '\0') - return (-1); - - nxtmod = strchr(modlist, '.'); - if (nxtmod) { - *nxtmod = '\0'; - nxtmod++; - } - if (strlcpy(diap->modlist[cnt], modlist, - sizeof (diap->modlist[cnt])) >= - sizeof (diap->modlist[cnt])) - return (-1); - cnt++; - modlist = nxtmod; - } + for (i = 0; i < NELEMS(dlpi_mactypes); i++) { + if (dlpi_mactypes[i].dm_mactype == mactype) + return (dlpi_mactypes[i].dm_desc); } - diap->mod_cnt = cnt; - if (strlcpy(diap->devname, modbuf, sizeof (diap->devname)) >= - sizeof (diap->devname)) - return (-1); - - return (0); + return ("Unknown MAC Type"); } -int -dlpi_if_open(const char *ifname, dlpi_if_attr_t *diap, - boolean_t force_style2) -{ - int fd; - - if (i_dlpi_ifname_parse(ifname, diap) == -1) { - errno = EINVAL; - return (-1); - } +/* + * Each table entry comprises a DLPI primitive and the maximum buffer + * size needed, in bytes, for the DLPI message (see <sys/dlpi.h> for details). + */ +static const dlpi_primsz_t dlpi_primsizes[] = { +{ DL_INFO_REQ, DL_INFO_REQ_SIZE }, +{ DL_INFO_ACK, DL_INFO_ACK_SIZE + (2 * DLPI_PHYSADDR_MAX) + + DLPI_SAPLEN_MAX + (2 * sizeof (union DL_qos_types))}, +{ DL_ATTACH_REQ, DL_ATTACH_REQ_SIZE }, +{ DL_BIND_REQ, DL_BIND_REQ_SIZE }, +{ DL_BIND_ACK, DL_BIND_ACK_SIZE + DLPI_PHYSADDR_MAX + + DLPI_SAPLEN_MAX }, +{ DL_UNBIND_REQ, DL_UNBIND_REQ_SIZE }, +{ DL_ENABMULTI_REQ, DL_ENABMULTI_REQ_SIZE + DLPI_PHYSADDR_MAX }, +{ DL_DISABMULTI_REQ, DL_DISABMULTI_REQ_SIZE + DLPI_PHYSADDR_MAX }, +{ DL_PROMISCON_REQ, DL_PROMISCON_REQ_SIZE }, +{ DL_PROMISCOFF_REQ, DL_PROMISCOFF_REQ_SIZE }, +{ DL_PASSIVE_REQ, DL_PASSIVE_REQ_SIZE }, +{ DL_UNITDATA_REQ, DL_UNITDATA_REQ_SIZE + DLPI_PHYSADDR_MAX + + DLPI_SAPLEN_MAX }, +{ DL_UNITDATA_IND, DL_UNITDATA_IND_SIZE + (2 * (DLPI_PHYSADDR_MAX + + DLPI_SAPLEN_MAX)) }, +{ DL_PHYS_ADDR_REQ, DL_PHYS_ADDR_REQ_SIZE }, +{ DL_PHYS_ADDR_ACK, DL_PHYS_ADDR_ACK_SIZE + DLPI_PHYSADDR_MAX }, +{ DL_SET_PHYS_ADDR_REQ, DL_SET_PHYS_ADDR_REQ_SIZE + DLPI_PHYSADDR_MAX }, +{ DL_OK_ACK, MAX(DL_ERROR_ACK_SIZE, DL_OK_ACK_SIZE) } +}; - diap->style1_failed = B_TRUE; +/* + * Refers to the dlpi_primsizes[] table to return corresponding maximum + * buffer size. + */ +static size_t +i_dlpi_getprimsize(t_uscalar_t prim) +{ + int i; - if (!force_style2) { - if ((fd = i_dlpi_style1_open(diap)) != -1) - return (fd); + for (i = 0; i < NELEMS(dlpi_primsizes); i++) { + if (dlpi_primsizes[i].dp_prim == prim) + return (dlpi_primsizes[i].dp_primsz); } - if ((fd = i_dlpi_style2_open(diap)) == -1) - return (-1); - - return (fd); + return (sizeof (t_uscalar_t)); } -int -dlpi_if_parse(const char *ifname, char *provider, int *ppap) +/* + * sap values vary in length and are in host byte order, build sap value + * by writing saplen bytes, so that the sap value is left aligned. + */ +static uint_t +i_dlpi_buildsap(uint8_t *sapp, uint_t saplen) { - dlpi_if_attr_t diap; - - if (i_dlpi_ifname_parse(ifname, &diap) == -1) { - errno = EINVAL; - return (-1); + int i; + uint_t sap = 0; + +#ifdef _LITTLE_ENDIAN + for (i = saplen - 1; i >= 0; i--) { +#else + for (i = 0; i < saplen; i++) { +#endif + sap <<= 8; + sap |= sapp[i]; } - if (strlcpy(provider, diap.provider, LIFNAMSIZ) > LIFNAMSIZ) - return (-1); - - if (ppap != NULL) - *ppap = diap.ppa; - - return (0); + return (sap); } /* - * attempt to remove ppa from end of file name - * return -1 if none found - * return ppa if found and remove the ppa from the filename + * Copy sap value to a buffer in host byte order. saplen is the number of + * bytes to copy. */ -static int -i_dlpi_ifrm_num(char *fname, unsigned int *ppa) +static void +i_dlpi_writesap(void *dstbuf, uint_t sap, uint_t saplen) { - int i; - uint_t p = 0; - unsigned int m = 1; + uint8_t *sapp; - i = strlen(fname) - 1; - - while (i >= 0 && isdigit(fname[i])) { - p += (fname[i] - '0')*m; - m *= 10; - i--; - } - - if (m == 1) { - return (-1); - } +#ifdef _LITTLE_ENDIAN + sapp = (uint8_t *)&sap; +#else + sapp = (uint8_t *)&sap + (sizeof (sap) - saplen); +#endif - fname[i + 1] = '\0'; - *ppa = p; - return (0); + (void) memcpy(dstbuf, sapp, saplen); } diff --git a/usr/src/lib/libdlpi/common/libdlpi.h b/usr/src/lib/libdlpi/common/libdlpi.h index e8c6f80207..0099727cc5 100644 --- a/usr/src/lib/libdlpi/common/libdlpi.h +++ b/usr/src/lib/libdlpi/common/libdlpi.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,56 +30,143 @@ #include <sys/types.h> #include <sys/dlpi.h> -#include <net/if.h> #ifdef __cplusplus extern "C" { #endif -#define MAXADDRLEN 64 -#define MAXSAPLEN 64 -#define MAX_MODS 9 - -typedef struct dlpi_if_attr { - char ifname[LIFNAMSIZ]; - int style; - int ppa; - int mod_cnt; - int mod_pushed; - boolean_t style1_failed; - int style1_fd; - char devname[LIFNAMSIZ + 32]; /* added space for /dev path */ - char modlist[MAX_MODS][LIFNAMSIZ]; - char provider[LIFNAMSIZ]; -} dlpi_if_attr_t; - -extern const char *dlpi_mac_type(uint_t); - -extern int dlpi_open(const char *); -extern int dlpi_close(int); -extern int dlpi_info(int, int, dl_info_ack_t *, union DL_qos_types *, - union DL_qos_types *, uint8_t *, size_t *, uint8_t *, size_t *); -extern int dlpi_attach(int, int, uint_t); -extern int dlpi_detach(int, int); -extern int dlpi_bind(int, int, uint_t, uint16_t, boolean_t, uint32_t *, - uint32_t *, uint8_t *, size_t *); -extern int dlpi_unbind(int, int); -extern int dlpi_enabmulti(int, int, uint8_t *, size_t); -extern int dlpi_disabmulti(int, int, uint8_t *, size_t); -extern int dlpi_promiscon(int, int, uint_t); -extern int dlpi_promiscoff(int, int, uint_t); -extern int dlpi_phys_addr(int, int, uint_t, uint8_t *, size_t *); -extern int dlpi_set_phys_addr(int, int, uint8_t *, size_t); -extern void dlpi_passive(int, int); +/* + * Maximum Physical (hardware) address length, in bytes. + * Must be as large as MAXMACADDRLEN (see <sys/mac.h>). + */ +#define DLPI_PHYSADDR_MAX 64 + +/* + * Maximum link name length, including terminating NUL, in bytes. + */ +#define DLPI_LINKNAME_MAX 32 + +/* + * Constant used to indicate bind to any SAP value + */ +#define DLPI_ANY_SAP (uint_t)-1 + +/* + * Flag values for dlpi_open(); those not documented in dlpi_open(3DLPI) + * are Consolidation Private and subject to change or removal. + */ +#define DLPI_EXCL 0x0001 /* Exclusive open */ +#define DLPI_PASSIVE 0x0002 /* Open DLPI link in passive mode */ +#define DLPI_RAW 0x0004 /* Open DLPI link in raw mode */ +#define DLPI_SERIAL 0x0008 /* Synchronous serial line interface */ +#define DLPI_NOATTACH 0x0010 /* Do not attach PPA */ +#define DLPI_NATIVE 0x0020 /* Open DLPI link in Native mode */ + +/* + * Timeout to be used in DLPI-related operations, in seconds. + */ +#define DLPI_DEF_TIMEOUT 5 + +/* + * Since this library returns error codes defined in either <sys/dlpi.h> or + * <libdlpi.h>, libdlpi specific error codes will start at value 10000 to + * avoid overlap. DLPI_SUCCESS cannot be 0 because 0 is already DL_BADSAP in + * <sys/dlpi.h>. + */ +enum { + DLPI_SUCCESS = 10000, /* DLPI operation succeeded */ + DLPI_EINVAL, /* invalid argument */ + DLPI_ELINKNAMEINVAL, /* invalid DLPI linkname */ + DLPI_ENOLINK, /* DLPI link does not exist */ + DLPI_EBADLINK, /* bad DLPI link */ + DLPI_EINHANDLE, /* invalid DLPI handle */ + DLPI_ETIMEDOUT, /* DLPI operation timed out */ + DLPI_EVERNOTSUP, /* unsupported DLPI Version */ + DLPI_EMODENOTSUP, /* unsupported DLPI connection mode */ + DLPI_EUNAVAILSAP, /* unavailable DLPI SAP */ + DLPI_FAILURE, /* DLPI operation failed */ + DLPI_ENOTSTYLE2, /* DLPI style-2 node reports style-1 */ + DLPI_EBADMSG, /* bad DLPI message */ + DLPI_ERAWNOTSUP, /* DLPI raw mode not supported */ + DLPI_ERRMAX /* Highest + 1 libdlpi error code */ +}; + +/* + * DLPI information; see dlpi_info(3DLPI). + */ +typedef struct { + uint_t di_opts; + uint_t di_max_sdu; + uint_t di_min_sdu; + uint_t di_state; + uint_t di_mactype; + char di_linkname[DLPI_LINKNAME_MAX]; + uchar_t di_physaddr[DLPI_PHYSADDR_MAX]; + uchar_t di_physaddrlen; + uchar_t di_bcastaddr[DLPI_PHYSADDR_MAX]; + uchar_t di_bcastaddrlen; + uint_t di_sap; + int di_timeout; + dl_qos_cl_sel1_t di_qos_sel; + dl_qos_cl_range1_t di_qos_range; +} dlpi_info_t; + +/* + * DLPI send information; see dlpi_send(3DLPI). + */ +typedef struct { + uint_t dsi_sap; + dl_priority_t dsi_prio; +} dlpi_sendinfo_t; + +/* + * Destination DLPI address type; see dlpi_recv(3DLPI). + */ +typedef enum { + DLPI_ADDRTYPE_UNICAST, + DLPI_ADDRTYPE_GROUP +} dlpi_addrtype_t; + +/* + * DLPI receive information; see dlpi_recv(3DLPI). + */ +typedef struct { + uchar_t dri_destaddr[DLPI_PHYSADDR_MAX]; + uchar_t dri_destaddrlen; + dlpi_addrtype_t dri_dstaddrtype; + size_t dri_totmsglen; +} dlpi_recvinfo_t; + +typedef struct __dlpi_handle *dlpi_handle_t; + +extern const char *dlpi_mactype(uint_t); +extern const char *dlpi_strerror(int); +extern const char *dlpi_linkname(dlpi_handle_t); + +extern int dlpi_open(const char *, dlpi_handle_t *, uint_t); +extern void dlpi_close(dlpi_handle_t); +extern int dlpi_info(dlpi_handle_t, dlpi_info_t *, uint_t); +extern int dlpi_bind(dlpi_handle_t, uint_t, uint_t *); +extern int dlpi_unbind(dlpi_handle_t); +extern int dlpi_enabmulti(dlpi_handle_t, const void *, size_t); +extern int dlpi_disabmulti(dlpi_handle_t, const void *, size_t); +extern int dlpi_promiscon(dlpi_handle_t, uint_t); +extern int dlpi_promiscoff(dlpi_handle_t, uint_t); +extern int dlpi_get_physaddr(dlpi_handle_t, uint_t, void *, size_t *); +extern int dlpi_set_physaddr(dlpi_handle_t, uint_t, const void *, size_t); +extern int dlpi_recv(dlpi_handle_t, void *, size_t *, void *, size_t *, + int, dlpi_recvinfo_t *); +extern int dlpi_send(dlpi_handle_t, const void *, size_t, const void *, size_t, + const dlpi_sendinfo_t *); +extern int dlpi_fd(dlpi_handle_t); +extern int dlpi_set_timeout(dlpi_handle_t, int); /* - * dlpi_if_open() - * Takes interface name in the following formats - * o Specific physical unit (ex. "bge0" or "ce0") - * o Tunnels (ex. "ip.tun0" or "ip6.tun0") + * These are Consolidation Private interfaces and are subject to change. */ -extern int dlpi_if_open(const char *, dlpi_if_attr_t *, boolean_t); -extern int dlpi_if_parse(const char *, char *, int *); +extern int dlpi_parselink(const char *, char *, uint_t *); +extern int dlpi_makelink(char *, const char *, uint_t); +extern uint_t dlpi_style(dlpi_handle_t); #ifdef __cplusplus } diff --git a/usr/src/lib/libdlpi/common/libdlpi_impl.h b/usr/src/lib/libdlpi/common/libdlpi_impl.h new file mode 100644 index 0000000000..313a37127c --- /dev/null +++ b/usr/src/lib/libdlpi/common/libdlpi_impl.h @@ -0,0 +1,120 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LIBDLPI_IMPL_H +#define _LIBDLPI_IMPL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libdlpi.h> +#include <sys/sysmacros.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Maximum DLPI response size, in bytes. + */ +#define DLPI_CHUNKSIZE 8192 + +/* + * Maximum SAP length, in bytes. + */ +#define DLPI_SAPLEN_MAX 4 + +/* + * Maximum number of modules that can be pushed onto a device stream. + */ +#define DLPI_MODS_MAX 9 + +/* + * Number of elements in 'arr'. + */ +#define NELEMS(arr) (sizeof (arr) / sizeof ((arr)[0])) + +/* + * Allocate buffer size for DLPI message, in bytes and set DLPI primitive. + */ +#define DLPI_MSG_CREATE(dlmsg, dlprimitive) \ + (dlmsg).dlm_msgsz = i_dlpi_getprimsize((dlprimitive)); \ + (dlmsg).dlm_msg = alloca((dlmsg).dlm_msgsz); \ + (dlmsg).dlm_msg->dl_primitive = (dlprimitive); + +/* + * Used in a mactype lookup table. + */ +typedef struct dlpi_mactype_s { + uint_t dm_mactype; /* DLPI/Private mactype */ + char *dm_desc; /* Description of mactype */ +} dlpi_mactype_t; + +/* + * Used to get the maximum DLPI message buffer size, in bytes. + */ +typedef struct dlpi_primsz { + t_uscalar_t dp_prim; /* store DLPI primitive */ + size_t dp_primsz; + /* max. message size, in bytes, for dp_prim */ +} dlpi_primsz_t; + +/* + * Used to create DLPI message. + */ +typedef struct dlpi_msg { + union DL_primitives *dlm_msg; + /* store DLPI primitive message */ + size_t dlm_msgsz; + /* provide buffer size for dlm_msg */ +} dlpi_msg_t; + +/* + * Private libdlpi structure associated with each DLPI handle. + */ +typedef struct dlpi_impl_s { + int dli_fd; /* fd attached to stream */ + int dli_timeout; /* timeout for operations, in sec */ + char dli_linkname[DLPI_LINKNAME_MAX]; + /* full linkname including PPA */ + char dli_provider[DLPI_LINKNAME_MAX]; + /* only provider name */ + t_uscalar_t dli_style; /* style 1 or 2 */ + uint_t dli_saplen; /* bound SAP length */ + uint_t dli_sap; /* bound SAP value */ + boolean_t dli_sapbefore; /* true if SAP precedes address */ + uint_t dli_ppa; /* physical point of attachment */ + uint_t dli_mod_cnt; /* number of modules to be pushed */ + uint_t dli_mod_pushed; /* number of modules pushed */ + char dli_modlist[DLPI_MODS_MAX][DLPI_LINKNAME_MAX]; + /* array of mods */ + uint_t dli_mactype; /* mac type */ + uint_t dli_oflags; /* flags set at open */ +} dlpi_impl_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBDLPI_IMPL_H */ diff --git a/usr/src/lib/libdlpi/common/mapfile-vers b/usr/src/lib/libdlpi/common/mapfile-vers index 8a263e2d5c..31ae2a5aa1 100644 --- a/usr/src/lib/libdlpi/common/mapfile-vers +++ b/usr/src/lib/libdlpi/common/mapfile-vers @@ -19,31 +19,38 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # -SUNWprivate_1.1 { +SUNW_1.1 { # first release of libdlpi, Solaris 11 global: - dlpi_attach; - dlpi_bind; - dlpi_close; - dlpi_detach; - dlpi_disabmulti; - dlpi_enabmulti; - dlpi_if_open; - dlpi_if_parse; - dlpi_info; - dlpi_mac_type; - dlpi_open; - dlpi_passive; - dlpi_phys_addr; - dlpi_promiscoff; - dlpi_promiscon; - dlpi_set_phys_addr; - dlpi_unbind; + dlpi_bind; + dlpi_close; + dlpi_disabmulti; + dlpi_enabmulti; + dlpi_fd; + dlpi_get_physaddr; + dlpi_info; + dlpi_linkname; + dlpi_mactype; + dlpi_open; + dlpi_promiscoff; + dlpi_promiscon; + dlpi_recv; + dlpi_send; + dlpi_set_physaddr; + dlpi_set_timeout; + dlpi_strerror; + dlpi_unbind; +}; +SUNWprivate { + global: + dlpi_parselink; + dlpi_makelink; + dlpi_style; local: *; }; diff --git a/usr/src/lib/libdlpi/sparcv9/Makefile b/usr/src/lib/libdlpi/sparcv9/Makefile new file mode 100644 index 0000000000..600ff73f12 --- /dev/null +++ b/usr/src/lib/libdlpi/sparcv9/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libinetutil/common/ifspec.c b/usr/src/lib/libinetutil/common/ifspec.c index 58f7c5ae71..157b497efd 100644 --- a/usr/src/lib/libinetutil/common/ifspec.c +++ b/usr/src/lib/libinetutil/common/ifspec.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -85,7 +84,7 @@ getppa(const char *bp, int bpsize, uint_t *ppa) char *ep = (char *)&bp[bpsize - 1]; char *tp; - if (isdigit(*bp) || !isdigit(*ep)) { + if (!isdigit(*ep)) { errno = EINVAL; return (-1); } @@ -104,8 +103,8 @@ getppa(const char *bp, int bpsize, uint_t *ppa) /* * Given an ifconfig-style inet relative-path interface specification - * (e.g: hme0.foo.ip.udp:2), validate its form and decompose the contents - * into a dynamically allocated ifspec_t. + * (e.g: hme.[module].[module][PPA]:2), validate its form and decompose the + * contents into a dynamically allocated ifspec_t. * * Returns ifspec_t for success, NULL pointer if spec is malformed. */ @@ -131,9 +130,10 @@ ifparse_ifspec(const char *ifname, ifspec_t *ifsp) /* * An interface name must have the format of: - * dev[ppa][.module[.module...][ppa]][:lun] + * dev[.module[.module...]][ppa][:lun] * - * where only one ppa may be specified e.g. ip0.foo.tun or ip.foo.tun0 + * where the ppa must be specified at the end of the interface name. + * e.g. ip.foo.tun0 * * lun - logical unit number. * @@ -180,27 +180,25 @@ ifparse_ifspec(const char *ifname, ifspec_t *ifsp) (void) strlcpy(ifsp->ifsp_devnm, ifnamecp, LIFNAMSIZ); - /* Find ppa - has to be part of devname or part of last module name */ - /* This should be changed to require the latter of the two */ - if (getppa(ifsp->ifsp_devnm, strlen(ifsp->ifsp_devnm), - &ifsp->ifsp_ppa) == 0) - have_ppa = B_TRUE; + /* + * Find ppa - has to be part of devname or if modules exist part of + * last module name. + */ if (ifsp->ifsp_modcnt != 0 && getppa(ifsp->ifsp_mods[ifsp->ifsp_modcnt - 1], strlen(ifsp->ifsp_mods[ifsp->ifsp_modcnt - 1]), &ifsp->ifsp_ppa) == 0) { - if (!have_ppa) - have_ppa = B_TRUE; - else - return (B_FALSE); /* only one please */ - } - if (!have_ppa) - return (B_FALSE); + have_ppa = B_TRUE; + } else if (ifsp->ifsp_modcnt == 0 && + getppa(ifsp->ifsp_devnm, strlen(ifsp->ifsp_devnm), + &ifsp->ifsp_ppa) == 0) { + have_ppa = B_TRUE; - /* strip the ppa off of the device name if present */ - for (tp = &ifsp->ifsp_devnm[strlen(ifsp->ifsp_devnm) - 1]; - tp >= ifsp->ifsp_devnm && isdigit(*tp); tp--) - *tp = '\0'; + /* strip the ppa off of the device name if present */ + for (tp = &ifsp->ifsp_devnm[strlen(ifsp->ifsp_devnm) - 1]; + tp >= ifsp->ifsp_devnm && isdigit(*tp); tp--) + *tp = '\0'; + } - return (B_TRUE); + return (have_ppa); } diff --git a/usr/src/pkgdefs/SUNWarcr/prototype_i386 b/usr/src/pkgdefs/SUNWarcr/prototype_i386 index f02fab5d83..c05a6a50fd 100644 --- a/usr/src/pkgdefs/SUNWarcr/prototype_i386 +++ b/usr/src/pkgdefs/SUNWarcr/prototype_i386 @@ -21,7 +21,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -64,6 +64,7 @@ f none lib/amd64/llib-ldevice.ln 644 root bin f none lib/amd64/llib-ldevid.ln 644 root bin f none lib/amd64/llib-ldevinfo.ln 644 root bin f none lib/amd64/llib-ldl.ln 644 root bin +f none lib/amd64/llib-ldlpi.ln 644 root bin f none lib/amd64/llib-ldoor.ln 644 root bin f none lib/amd64/llib-lefi.ln 644 root bin f none lib/amd64/llib-lelf.ln 644 root bin diff --git a/usr/src/pkgdefs/SUNWarcr/prototype_sparc b/usr/src/pkgdefs/SUNWarcr/prototype_sparc index 9cee1f2ca2..e0635d7204 100644 --- a/usr/src/pkgdefs/SUNWarcr/prototype_sparc +++ b/usr/src/pkgdefs/SUNWarcr/prototype_sparc @@ -21,7 +21,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -64,6 +64,7 @@ f none lib/sparcv9/llib-ldevice.ln 644 root bin f none lib/sparcv9/llib-ldevid.ln 644 root bin f none lib/sparcv9/llib-ldevinfo.ln 644 root bin f none lib/sparcv9/llib-ldl.ln 644 root bin +f none lib/sparcv9/llib-ldlpi.ln 644 root bin f none lib/sparcv9/llib-ldoor.ln 644 root bin f none lib/sparcv9/llib-lefi.ln 644 root bin f none lib/sparcv9/llib-lelf.ln 644 root bin diff --git a/usr/src/pkgdefs/SUNWcslr/prototype_i386 b/usr/src/pkgdefs/SUNWcslr/prototype_i386 index d7ab2182f3..94057d2a78 100644 --- a/usr/src/pkgdefs/SUNWcslr/prototype_i386 +++ b/usr/src/pkgdefs/SUNWcslr/prototype_i386 @@ -21,7 +21,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -78,6 +78,8 @@ s none lib/amd64/libdevinfo.so=libdevinfo.so.1 f none lib/amd64/libdevinfo.so.1 755 root bin s none lib/amd64/libdl.so=libdl.so.1 f none lib/amd64/libdl.so.1 755 root bin +s none lib/amd64/libdlpi.so=libdlpi.so.1 +f none lib/amd64/libdlpi.so.1 755 root bin s none lib/amd64/libdoor.so=libdoor.so.1 f none lib/amd64/libdoor.so.1 755 root bin s none lib/amd64/libefi.so=libefi.so.1 diff --git a/usr/src/pkgdefs/SUNWcslr/prototype_sparc b/usr/src/pkgdefs/SUNWcslr/prototype_sparc index be4f18ddb5..c902bf36f4 100644 --- a/usr/src/pkgdefs/SUNWcslr/prototype_sparc +++ b/usr/src/pkgdefs/SUNWcslr/prototype_sparc @@ -79,6 +79,8 @@ s none lib/sparcv9/libdevinfo.so=libdevinfo.so.1 f none lib/sparcv9/libdevinfo.so.1 755 root bin s none lib/sparcv9/libdl.so=libdl.so.1 f none lib/sparcv9/libdl.so.1 755 root bin +s none lib/sparcv9/libdlpi.so=libdlpi.so.1 +f none lib/sparcv9/libdlpi.so.1 755 root bin s none lib/sparcv9/libdoor.so=libdoor.so.1 f none lib/sparcv9/libdoor.so.1 755 root bin s none lib/sparcv9/libefi.so=libefi.so.1 diff --git a/usr/src/tools/abi/etc/exceptions b/usr/src/tools/abi/etc/exceptions index edf114334a..8f97028267 100644 --- a/usr/src/tools/abi/etc/exceptions +++ b/usr/src/tools/abi/etc/exceptions @@ -409,7 +409,6 @@ PSARC 2002/762: RULE W3: usr/lib/amd64/libtsol.so.2 PSARC 2002/762: RULE W3: lib/libtsol.so.2 PSARC 2002/762: RULE W3: lib/sparcv9/libtsol.so.2 PSARC 2002/762: RULE W3: lib/amd64/libtsol.so.2 -6289029: RULE W3: lib/libdlpi.so.1 PSARC 2005/204: RULE W3: usr/lib/libraidcfg.so.1 PSARC 2005/204: RULE W3: usr/lib/amd64/libraidcfg.so.1 PSARC 2005/204: RULE W3: usr/lib/sparcv9/libraidcfg.so.1 |