--- embedaddon/libnet/src/libnet_link_dlpi.c 2012/02/21 22:14:23 1.1.1.1 +++ embedaddon/libnet/src/libnet_link_dlpi.c 2023/09/27 11:11:38 1.1.1.3 @@ -1,5 +1,5 @@ /* - * $Id: libnet_link_dlpi.c,v 1.1.1.1 2012/02/21 22:14:23 misho Exp $ + * $Id: libnet_link_dlpi.c,v 1.1.1.3 2023/09/27 11:11:38 misho Exp $ * * libnet * libnet_dlpi.c - dlpi routines @@ -31,9 +31,8 @@ */ -#if (HAVE_CONFIG_H) -#include "../include/config.h" -#endif +#include "common.h" + #include #include #ifdef HAVE_SYS_BUFMOD_H @@ -100,7 +99,7 @@ static int send_request(int, int8_t *, int, int8_t *, static int strioctl(int, int, int, int8_t *); #endif #ifdef HAVE_HPUX9 -static int dlpi_kread(int, off_t, void *, u_int, int8_t *); +static int dlpi_kread(int, off_t, void *, uint, int8_t *); #endif #ifdef HAVE_DEV_DLPI static int get_dlpi_ppa(int, const int8_t *, int, int8_t *); @@ -109,54 +108,129 @@ static int get_dlpi_ppa(int, const int8_t *, int, int8 /* XXX Needed by HP-UX (at least) */ static bpf_u_int32 ctlbuf[MAXDLBUF]; +/* Return a pointer to the last character in 'in' that is not in 's', + * or NULL if no such character exists. */ +static char *find_last_not_of(char *in, const char *s) +{ + char* cur; + cur = in + strlen(in); + for(; cur != in; cur--) { + if (!strchr(s, *cur)) { + break; + } + } + return cur == in ? NULL : cur; +} +/* Split device into device type and unit number. + * Return >0 on success. */ +static int +dlpi_unit(const char *dev, int *namelen, int *unit) +{ + char *p; + char *eos; + if (!*dev) { + return 0; + } + p = find_last_not_of(dev, "0123456789"); + if (!p) { + return 0; + } + p++; + if (!*p) { + return 0; + } + *unit = strtol(p, NULL, 10); + *namelen = p - dev; + return 1; +} + +/* Sometimes the network device is at /dev/, and sometimes at + * /dev/net/. Sometimes both. Sometimes with unit number, sometimes + * without. + * This function tries to find the device, and won't be stopped just because + * it tried to open a directory. (e.g. interface net0 would try to open + * /dev/net). + */ +static int +try_open_dev(libnet_t *l, const char *dev, int unit) +{ + const char *prefixes[] = { + DLPI_DEV_PREFIX, + "/dev", + "/dev/net", + "", + NULL + }; + int ret; + char fullpath[MAXPATHLEN]; + int cur_prefix; + + for (cur_prefix = 0; prefixes[cur_prefix]; cur_prefix++) { + snprintf(fullpath, sizeof(fullpath), + "%s/%s", prefixes[cur_prefix], dev); + if (0 <= (ret = open(fullpath, O_RDWR))) { + return ret; + } + if (errno != ENOENT && errno != EISDIR) { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s", + __func__, fullpath, strerror(errno)); + return -1; + } + snprintf(fullpath, sizeof(fullpath), + "%s/%s%d", prefixes[cur_prefix], dev, unit); + if (0 <= (ret = open(fullpath, O_RDWR))) { + return ret; + } + if (errno != ENOENT && errno != EISDIR) { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s", + __func__, fullpath, strerror(errno)); + return -1; + } + } + return -1; +} + int libnet_open_link(libnet_t *l) { register int8_t *cp; int8_t *eos; - register int ppa; + int ppa; register dl_info_ack_t *infop; bpf_u_int32 buf[MAXDLBUF]; - int8_t dname[100]; -#ifndef HAVE_DEV_DLPI - int8_t dname2[100]; -#endif + int namelen; + int8_t dname[MAXPATHLEN]; if (l == NULL) { return (-1); } + memset(&dname, 0, sizeof(dname)); + /* * Determine device and ppa */ - cp = strpbrk(l->device, "0123456789"); - if (cp == NULL) - { + if (!dlpi_unit(l->device, &namelen, &ppa)) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, - "%s(): %s is missing unit number\n", __func__, l->device); + "%s(): %s has bad device type or unit number", + __func__, l->device); goto bad; } - ppa = strtol(cp, &eos, 10); - if (*eos != '\0') - { - snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, - "%s(): %s bad unit number\n", __func__, l->device); - goto bad; - } + strncpy(dname, l->device, namelen); +#ifdef HAVE_DEV_DLPI if (*(l->device) == '/') { - memset(&dname, 0, sizeof(dname)); strncpy(dname, l->device, sizeof(dname) - 1); dname[sizeof(dname) - 1] = '\0'; } else { - sprintf(dname, "%s/%s", DLPI_DEV_PREFIX, l->device); + snprintf(dname, sizeof(dname), "%s/%s", DLPI_DEV_PREFIX, l->device); } -#ifdef HAVE_DEV_DLPI + /* * Map network device to /dev/dlpi unit */ @@ -165,8 +239,6 @@ libnet_open_link(libnet_t *l) l->fd = open(cp, O_RDWR); if (l->fd == -1) { - snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s\n", - __func__, cp, strerror(errno)); goto bad; } @@ -182,45 +254,9 @@ libnet_open_link(libnet_t *l) /* * Try device without unit number */ - strcpy(dname2, dname); - cp = strchr(dname, *cp); - *cp = '\0'; - - l->fd = open(dname, O_RDWR); - if (l->fd == -1) - { - if (errno != ENOENT) - { - snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s\n", - __func__, dname, strerror(errno)); - goto bad; - } - - /* - * Try again with unit number - */ - l->fd = open(dname2, O_RDWR); - if (l->fd == -1) - { - snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): %s: %s\n", - __func__, dname2, strerror(errno)); - goto bad; - } - - cp = dname2; - while (*cp && !isdigit((int)*cp)) - { - cp++; - } - if (*cp) - { - ppa = atoi(cp); - } - else - /* - * XXX Assume unit zero - */ - ppa = 0; + l->fd = try_open_dev(l, dname, ppa); + if (l->fd == -1) { + goto bad; } #endif /* @@ -276,8 +312,9 @@ libnet_open_link(libnet_t *l) l->link_offset = 0x16; break; default: - sprintf(l->err_buf, "%s(): unknown mac type 0x%lu\n", __func__, - (u_int32_t) infop->dl_mac_type); + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): unknown mac type 0x%lu", __func__, + (uint32_t) infop->dl_mac_type); goto bad; } @@ -287,7 +324,8 @@ libnet_open_link(libnet_t *l) */ if (strioctl(l->fd, DLIOCRAW, 0, NULL) < 0) { - sprintf(l->err_buf, "%s(): DLIOCRAW: %s\n", __func__, strerror(errno)); + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): DLIOCRAW: %s", __func__, strerror(errno)); goto bad; } #endif @@ -314,7 +352,8 @@ int flags) if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { - sprintf(ebuf, "%s(): putmsg \"%s\": %s\n", __func__, what, + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "%s(): putmsg \"%s\": %s", __func__, what, strerror(errno)); return (-1); } @@ -335,7 +374,8 @@ recv_ack(int fd, int size, const int8_t *what, int8_t flags = 0; if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { - sprintf(ebuf, "%s(): %s getmsg: %s\n", __func__, what, strerror(errno)); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "%s(): %s getmsg: %s", __func__, what, strerror(errno)); return (-1); } @@ -358,32 +398,37 @@ recv_ack(int fd, int size, const int8_t *what, int8_t switch (dlp->error_ack.dl_errno) { case DL_BADPPA: - sprintf(ebuf, "recv_ack: %s bad ppa (device unit)", what); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "recv_ack: %s bad ppa (device unit)", what); break; case DL_SYSERR: - sprintf(ebuf, "recv_ack: %s: %s", + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "recv_ack: %s: %s", what, strerror(dlp->error_ack.dl_unix_errno)); break; case DL_UNSUPPORTED: - sprintf(ebuf, + snprintf(ebuf, LIBNET_ERRBUF_SIZE, "recv_ack: %s: Service not supplied by provider", what); break; default: - sprintf(ebuf, "recv_ack: %s error 0x%x", what, + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "recv_ack: %s error 0x%x", what, (bpf_u_int32)dlp->error_ack.dl_errno); break; } return (-1); default: - sprintf(ebuf, "recv_ack: %s unexpected primitive ack 0x%x ", + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "recv_ack: %s unexpected primitive ack 0x%x ", what, (bpf_u_int32)dlp->dl_primitive); return (-1); } if (ctl.len < size) { - sprintf(ebuf, "recv_ack: %s ack too small (%d < %d)", + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "recv_ack: %s ack too small (%d < %d)", what, ctl.len, size); return (-1); } @@ -491,14 +536,15 @@ register int8_t *ebuf) register dl_hp_ppa_ack_t *ap; register dl_hp_ppa_info_t *ip; register int i; - register u_int32_t majdev; + register uint32_t majdev; dl_hp_ppa_req_t req; struct stat statbuf; bpf_u_int32 buf[MAXDLBUF]; if (stat(device, &statbuf) < 0) { - sprintf(ebuf, "stat: %s: %s", device, strerror(errno)); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "stat: %s: %s", device, strerror(errno)); return (-1); } majdev = major(statbuf.st_rdev); @@ -514,25 +560,27 @@ register int8_t *ebuf) } ap = (dl_hp_ppa_ack_t *)buf; - ip = (dl_hp_ppa_info_t *)((u_int8_t *)ap + ap->dl_offset); + ip = (dl_hp_ppa_info_t *)((uint8_t *)ap + ap->dl_offset); for (i = 0; i < ap->dl_count; i++) { if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit) break; - ip = (dl_hp_ppa_info_t *)((u_int8_t *)ip + ip->dl_next_offset); + ip = (dl_hp_ppa_info_t *)((uint8_t *)ip + ip->dl_next_offset); } if (i == ap->dl_count) { - sprintf(ebuf, "can't find PPA for %s", device); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "can't find PPA for %s", device); return (-1); } if (ip->dl_hdw_state == HDW_DEAD) { - sprintf(ebuf, "%s: hardware state: DOWN\n", device); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "%s: hardware state: DOWN", device); return (-1); } return ((int)ip->dl_ppa); @@ -573,20 +621,23 @@ get_dlpi_ppa(register int fd, register const int8_t *i } if (nlist(path_vmunix, &nl) < 0) { - sprintf(ebuf, "nlist %s failed", path_vmunix); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "nlist %s failed", path_vmunix); return (-1); } if (nl[NL_IFNET].n_value == 0) { - sprintf(ebuf, "could't find %s kernel symbol", nl[NL_IFNET].n_name); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "could't find %s kernel symbol", nl[NL_IFNET].n_name); return (-1); } kd = open("/dev/kmem", O_RDONLY); if (kd < 0) { - sprintf(ebuf, "kmem open: %s", strerror(errno)); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "kmem open: %s", strerror(errno)); return (-1); } @@ -604,7 +655,7 @@ get_dlpi_ppa(register int fd, register const int8_t *i close(kd); return (-1); } - sprintf(tifname, "%.*s%d", + snprintf(tifname, sizeof(tifname), "%.*s%d", (int)sizeof(if_name), if_name, ifnet.if_unit); if (strcmp(tifname, ifname) == 0) { @@ -612,30 +663,34 @@ get_dlpi_ppa(register int fd, register const int8_t *i } } - sprintf(ebuf, "Can't find %s", ifname); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "Can't find %s", ifname); return (-1); } static int dlpi_kread(register int fd, register off_t addr, register void *buf, -register u_int len, register int8_t *ebuf) +register uint len, register int8_t *ebuf) { register int cc; if (lseek(fd, addr, SEEK_SET) < 0) { - sprintf(ebuf, "lseek: %s", strerror(errno)); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "lseek: %s", strerror(errno)); return (-1); } cc = read(fd, buf, len); if (cc < 0) { - sprintf(ebuf, "read: %s", strerror(errno)); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "read: %s", strerror(errno)); return (-1); } else if (cc != len) { - sprintf(ebuf, "int16_t read (%d != %d)", cc, len); + snprintf(ebuf, LIBNET_ERRBUF_SIZE, + "int16_t read (%d != %d)", cc, len); return (-1); } return (cc); @@ -646,7 +701,7 @@ register u_int len, register int8_t *ebuf) struct EnetHeaderInfo { struct libnet_ether_addr DestEtherAddr; - u_int16_t EtherFrameType; + uint16_t EtherFrameType; }; @@ -655,19 +710,17 @@ libnet_close_link(libnet_t *l) { if (close(l->fd) == 0) { - free(l); return (1); } else { - free(l); return (-1); } } #ifdef HAVE_HPUX11 int -libnet_write_link(libnet_t *l, u_int8_t *packet, u_int32_t size) +libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size) { struct strbuf data, ctl; dl_hp_rawdata_req_t *rdata; @@ -694,7 +747,7 @@ libnet_write_link(libnet_t *l, u_int8_t *packet, u_int if (c == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, - "libnet_write_link(): %d bytes written (%s)\n", c, + "libnet_write_link(): %d bytes written (%s)", c, strerror(errno)); return (-1); } @@ -705,7 +758,7 @@ libnet_write_link(libnet_t *l, u_int8_t *packet, u_int } #else int -libnet_write_link(libnet_t *l, u_int8_t *packet, u_int32_t size) +libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size) { int c; struct strbuf data; @@ -723,7 +776,7 @@ libnet_write_link(libnet_t *l, u_int8_t *packet, u_int if (c == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, - "libnet_write_link: %d bytes written (%s)\n", c, + "libnet_write_link: %d bytes written (%s)", c, strerror(errno)); return (-1); } @@ -737,15 +790,23 @@ libnet_write_link(libnet_t *l, u_int8_t *packet, u_int struct libnet_ether_addr * libnet_get_hwaddr(libnet_t *l) { - int8_t buf[2048]; union DL_primitives *dlp; - struct libnet_ether_addr *eap; + int8_t *buf; + int8_t *mac; if (l == NULL) { return (NULL); } + buf = (int8_t *)malloc(2048); + if (buf == NULL) + { + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s", + __func__, strerror(errno)); + return (NULL); + } + dlp = (union DL_primitives *)buf; dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ; @@ -754,17 +815,26 @@ libnet_get_hwaddr(libnet_t *l) if (send_request(l->fd, (int8_t *)dlp, DL_PHYS_ADDR_REQ_SIZE, "physaddr", l->err_buf, 0) < 0) { + free(buf); return (NULL); } if (recv_ack(l->fd, DL_PHYS_ADDR_ACK_SIZE, "physaddr", (int8_t *)dlp, l->err_buf) < 0) { + free(buf); return (NULL); } - eap = (struct libnet_ether_addr *) - ((int8_t *) dlp + dlp->physaddr_ack.dl_addr_offset); - return (eap); + mac = (int8_t *)dlp + dlp->physaddr_ack.dl_addr_offset; + memcpy(l->link_addr.ether_addr_octet, mac, ETHER_ADDR_LEN); + free(buf); + + return (&l->link_addr); } -/* EOF */ +/** + * Local Variables: + * indent-tabs-mode: nil + * c-file-style: "stroustrup" + * End: + */