diff options
Diffstat (limited to 'pcap-bpf.c')
-rw-r--r-- | pcap-bpf.c | 417 |
1 files changed, 248 insertions, 169 deletions
diff --git a/pcap-bpf.c b/pcap-bpf.c index 2898e598d8e3..b9e84e65f634 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -19,9 +19,7 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifdef HAVE_CONFIG_H #include <config.h> -#endif #include <sys/param.h> /* optionally get BSD define */ #include <sys/socket.h> @@ -122,6 +120,7 @@ static int bpf_load(char *errbuf); #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <stddef.h> #ifdef SIOCGIFMEDIA # include <net/if_media.h> @@ -263,7 +262,7 @@ pcap_getnonblock_bpf(pcap_t *p) if (pb->zerocopy) return (pb->nonblock); #endif - return (pcap_getnonblock_fd(p)); + return (pcapint_getnonblock_fd(p)); } static int @@ -277,7 +276,7 @@ pcap_setnonblock_bpf(pcap_t *p, int nonblock) return (0); } #endif - return (pcap_setnonblock_fd(p, nonblock)); + return (pcapint_setnonblock_fd(p, nonblock)); } #ifdef HAVE_ZEROCOPY_BPF @@ -352,7 +351,7 @@ pcap_next_zbuf(pcap_t *p, int *cc) * sure that the timeout gets adjusted accordingly. This requires * that we analyze when the timeout should be been expired, and * subtract the current time from that. If after this operation, - * our timeout is less then or equal to zero, handle it like a + * our timeout is less than or equal to zero, handle it like a * regular timeout. */ tmout = p->opt.timeout; @@ -368,7 +367,7 @@ pcap_next_zbuf(pcap_t *p, int *cc) if (data) return (data); if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCROTZBUF"); return (PCAP_ERROR); } @@ -396,7 +395,7 @@ pcap_next_zbuf(pcap_t *p, int *cc) } return (0); } else if (r < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "select"); return (PCAP_ERROR); } @@ -415,7 +414,7 @@ pcap_next_zbuf(pcap_t *p, int *cc) * data. */ if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCROTZBUF"); return (PCAP_ERROR); } @@ -440,7 +439,7 @@ pcap_ack_zbuf(pcap_t *p) #endif /* HAVE_ZEROCOPY_BPF */ pcap_t * -pcap_create_interface(const char *device _U_, char *ebuf) +pcapint_create_interface(const char *device _U_, char *ebuf) { pcap_t *p; @@ -457,7 +456,7 @@ pcap_create_interface(const char *device _U_, char *ebuf) */ p->tstamp_precision_list = malloc(2 * sizeof(u_int)); if (p->tstamp_precision_list == NULL) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "malloc"); free(p); return (NULL); @@ -510,7 +509,7 @@ bpf_open(char *errbuf) cloning_device); } else { fd = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(errbuf, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "(cannot open device) %s", cloning_device); } @@ -554,13 +553,13 @@ bpf_open(char *errbuf) switch (errno) { case ENOENT: - fd = PCAP_ERROR; if (n == 1) { /* * /dev/bpf0 doesn't exist, which * means we probably have no BPF * devices. */ + fd = PCAP_ERROR_CAPTURE_NOTSUP; snprintf(errbuf, PCAP_ERRBUF_SIZE, "(there are no BPF devices)"); } else { @@ -570,6 +569,7 @@ bpf_open(char *errbuf) * devices, but all the ones * that exist are busy. */ + fd = PCAP_ERROR; snprintf(errbuf, PCAP_ERRBUF_SIZE, "(all BPF devices are busy)"); } @@ -592,7 +592,7 @@ bpf_open(char *errbuf) * Some other problem. */ fd = PCAP_ERROR; - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "(cannot open BPF device) %s", device); break; } @@ -606,7 +606,7 @@ bpf_open(char *errbuf) * BPF device and the name of the network adapter. * * Use BIOCSETLIF if available (meaning "on Solaris"), as it supports - * longer device names. + * longer device names and binding to devices in other zones. * * If the name is longer than will fit, return PCAP_ERROR_NO_SUCH_DEVICE * before trying to bind the interface, as there cannot be such a device. @@ -615,18 +615,13 @@ bpf_open(char *errbuf) * * If the attempt fails: * - * if it fails with ENXIO, return PCAP_ERROR_NO_SUCH_DEVICE, as - * the device doesn't exist; - * - * if it fails with ENETDOWN, return PCAP_ERROR_IFACE_NOT_UP, as - * the interface exists but isn't up and the OS doesn't allow - * binding to an interface that isn't up; - * * if it fails with ENOBUFS, return BPF_BIND_BUFFER_TOO_BIG, and * fill in an error message, as the buffer being requested is too - * large; + * large - our caller may try a smaller buffer if no buffer size + * was explicitly specified. * - * otherwise, return PCAP_ERROR and fill in an error message. + * otherwise, return the appropriate PCAP_ERROR_ code and + * fill in an error message. */ #define BPF_BIND_SUCCEEDED 0 #define BPF_BIND_BUFFER_TOO_BIG 1 @@ -637,12 +632,118 @@ bpf_bind(int fd, const char *name, char *errbuf) int status; #ifdef LIFNAMSIZ struct lifreq ifr; + const char *ifname = name; + + #if defined(ZONENAME_MAX) && defined(lifr_zoneid) + char *zonesep; + + /* + * We have support for zones. + * Retrieve the zoneid of the zone we are currently executing in. + */ + if ((ifr.lifr_zoneid = getzoneid()) == -1) { + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + errno, "getzoneid()"); + return (PCAP_ERROR); + } + + /* + * Check if the given source datalink name has a '/' separated + * zonename prefix string. The zonename prefixed source datalink can + * be used by pcap consumers in the Solaris global zone to capture + * traffic on datalinks in non-global zones. Non-global zones + * do not have access to datalinks outside of their own namespace. + */ + if ((zonesep = strchr(name, '/')) != NULL) { + char *zname; + ptrdiff_t znamelen; + + if (ifr.lifr_zoneid != GLOBAL_ZONEID) { + /* + * We treat this as a generic error rather + * than as "permission denied" because + * this isn't a case of "you don't have + * enough permission to capture on this + * device, so you'll have to do something + * to get that permission" (such as + * configuring the system to allow non-root + * users to capture traffic), it's a case + * of "nobody has permission to do this, + * so there's nothing to do to fix it + * other than running the capture program + * in the global zone or the zone containing + * the adapter". + * + * (And, yes, this is a real issue; for example, + * Wireshark might make platform-specific suggestions + * on how to fix a PCAP_ERROR_PERM_DENIED problem, + * none of which will help here.) + */ + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "zonename/linkname only valid in global zone."); + return (PCAP_ERROR); + } + znamelen = zonesep - name; + zname = malloc(znamelen + 1); + if (zname == NULL) { + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + errno, "malloc"); + return (PCAP_ERROR); + } + memcpy(zname, name, znamelen + 1); + zname[znamelen] = '\0'; + ifr.lifr_zoneid = getzoneidbyname(zname); + if (ifr.lifr_zoneid == -1) { + switch (errno) { + + case EINVAL: + case ENAMETOOLONG: + /* + * If the name's length exceeds + * ZONENAMEMAX, clearly there cannot + * be such a zone; it's not clear that + * "that name's too long for a zone" + * is more informative than "there's + * no such zone". + */ + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "There is no zone named \"%s\"", + zname); - if (strlen(name) >= sizeof(ifr.lifr_name)) { + /* + * No such zone means the name + * refers to a non-existent interface. + */ + status = PCAP_ERROR_NO_SUCH_DEVICE; + break; + + default: + pcapint_fmt_errmsg_for_errno(errbuf, + PCAP_ERRBUF_SIZE, errno, + "getzoneidbyname(%s)", zname); + status = PCAP_ERROR; + break; + } + free(zname); + return (status); + } + free(zname); + + /* + * To bind to this interface, we set the ifr.lifr_zoneid + * to the zone ID of its zone (done above), and we set + * ifr.lifr_name to the name of the interface within that + * zone (done below, using ifname). + */ + ifname = zonesep + 1; + } + #endif + + if (strlen(ifname) >= sizeof(ifr.lifr_name)) { /* The name is too long, so it can't possibly exist. */ return (PCAP_ERROR_NO_SUCH_DEVICE); } - (void)pcap_strlcpy(ifr.lifr_name, name, sizeof(ifr.lifr_name)); + (void)pcapint_strlcpy(ifr.lifr_name, ifname, sizeof(ifr.lifr_name)); status = ioctl(fd, BIOCSETLIF, (caddr_t)&ifr); #else struct ifreq ifr; @@ -651,14 +752,26 @@ bpf_bind(int fd, const char *name, char *errbuf) /* The name is too long, so it can't possibly exist. */ return (PCAP_ERROR_NO_SUCH_DEVICE); } - (void)pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + (void)pcapint_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); status = ioctl(fd, BIOCSETIF, (caddr_t)&ifr); #endif if (status < 0) { switch (errno) { +#if defined(HAVE_SOLARIS) + /* + * For some reason, Solaris 11 appears to return ESRCH + * for unknown devices. + */ + case ESRCH: +#else + /* + * The *BSDs (including CupertinoBSD a/k/a Darwin) + * return ENXIO for unknown devices. + */ case ENXIO: +#endif /* * There's no such device. * @@ -686,13 +799,13 @@ bpf_bind(int fd, const char *name, char *errbuf) * we have to continue; add an error message that * tells the user what needs to be fixed. */ - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "The requested buffer size for %s is too large", name); return (BPF_BIND_BUFFER_TOO_BIG); default: - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "Binding interface %s to BPF device failed", name); return (PCAP_ERROR); @@ -756,7 +869,7 @@ device_exists(int fd, const char *name, char *errbuf) /* The name is too long, so it can't possibly exist. */ return (PCAP_ERROR_NO_SUCH_DEVICE); } - (void)pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + (void)pcapint_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); status = ioctl(fd, SIOCGIFFLAGS, (caddr_t)&ifr); if (status < 0) { @@ -774,7 +887,7 @@ device_exists(int fd, const char *name, char *errbuf) * Some other error - provide a message for it, as * it's "unexpected". */ - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "Can't get interface flags on %s", name); return (PCAP_ERROR); } @@ -797,13 +910,13 @@ get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf) bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1)); if (bdlp->bfl_list == NULL) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "malloc"); return (PCAP_ERROR); } if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "BIOCGDLTLIST"); free(bdlp->bfl_list); return (PCAP_ERROR); @@ -858,7 +971,7 @@ get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf) * this device"; don't treat it as an error. */ if (errno != EINVAL) { - pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "BIOCGDLTLIST"); return (PCAP_ERROR); } @@ -928,12 +1041,12 @@ pcap_can_set_rfmon_bpf(pcap_t *p) } fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "socket"); return (PCAP_ERROR); } - if (pcap_asprintf(&wlt_name, "wlt%s", p->opt.device + 2) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + if (pcapint_asprintf(&wlt_name, "wlt%s", p->opt.device + 2) == -1) { + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "malloc"); close(fd); return (PCAP_ERROR); @@ -1046,13 +1159,17 @@ pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps) * by libpcap, and thus not yet seen by the application. */ if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCGSTATS"); return (PCAP_ERROR); } - ps->ps_recv = s.bs_recv; - ps->ps_drop = s.bs_drop; + /* + * On illumos, NetBSD and Solaris these values are 64-bit, but struct + * pcap_stat is what it is, so the integer precision loss is expected. + */ + ps->ps_recv = (u_int)s.bs_recv; + ps->ps_drop = (u_int)s.bs_drop; ps->ps_ifdrop = 0; return (0); } @@ -1061,7 +1178,7 @@ static int pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { struct pcap_bpf *pb = p->priv; - int cc; + ssize_t cc; int n = 0; register u_char *bp, *ep; u_char *datap; @@ -1107,7 +1224,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } else #endif { - cc = (int)read(p->fd, p->buffer, p->bufsize); + cc = read(p->fd, p->buffer, p->bufsize); } if (cc < 0) { /* Don't choke when we get ptraced */ @@ -1177,7 +1294,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* fall through */ #endif } - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "read"); return (PCAP_ERROR); } @@ -1255,7 +1372,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) #endif */ if (pb->filtering_in_kernel || - pcap_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) { + pcapint_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) { struct pcap_pkthdr pkthdr; #ifdef BIOCSTSTAMP struct bintime bt; @@ -1284,7 +1401,13 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) */ pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000; #else - pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec; + /* + * On NetBSD the former (timeval.tv_usec) is an int via + * suseconds_t and the latter (bpf_timeval.tv_usec) is + * a long. In any case, the value is supposed to be + * within the [0 .. 999999] interval. + */ + pkthdr.ts.tv_usec = (suseconds_t)bhp->bh_tstamp.tv_usec; #endif #endif /* BIOCSTSTAMP */ #ifdef PCAP_FDDIPAD @@ -1354,7 +1477,7 @@ pcap_inject_bpf(pcap_t *p, const void *buf, int size) u_int spoof_eth_src = 0; if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "send: can't turn off BIOCSHDRCMPLT"); return (PCAP_ERROR); } @@ -1366,7 +1489,7 @@ pcap_inject_bpf(pcap_t *p, const void *buf, int size) } #endif /* __APPLE__ */ if (ret == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "send"); return (PCAP_ERROR); } @@ -1455,7 +1578,7 @@ bpf_load(char *errbuf) major = genmajor(BPF_NAME); if (major == -1) { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "bpf_load: genmajor failed"); (void)bpf_odmcleanup(NULL); return (PCAP_ERROR); @@ -1465,7 +1588,7 @@ bpf_load(char *errbuf) if (!minors) { minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1); if (!minors) { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "bpf_load: genminor failed"); (void)bpf_odmcleanup(NULL); return (PCAP_ERROR); @@ -1477,7 +1600,7 @@ bpf_load(char *errbuf) rc = stat(BPF_NODE "0", &sbuf); if (rc == -1 && errno != ENOENT) { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "bpf_load: can't stat %s", BPF_NODE "0"); return (PCAP_ERROR); } @@ -1487,7 +1610,7 @@ bpf_load(char *errbuf) snprintf(buf, sizeof(buf), "%s%d", BPF_NODE, i); unlink(buf); if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) { - pcap_fmt_errmsg_for_errno(errbuf, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "bpf_load: can't mknod %s", buf); return (PCAP_ERROR); @@ -1503,7 +1626,7 @@ bpf_load(char *errbuf) (cfg_ld.kmid == 0)) { /* Driver isn't loaded, load it now */ if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "bpf_load: could not load driver"); return (PCAP_ERROR); } @@ -1517,7 +1640,7 @@ bpf_load(char *errbuf) for (i = 0; i < BPF_MINORS; i++) { cfg_bpf.devno = domakedev(major, i); if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "bpf_load: could not configure driver"); return (PCAP_ERROR); } @@ -1565,7 +1688,7 @@ pcap_cleanup_bpf(pcap_t *p) strerror(errno)); } else { memset(&req, 0, sizeof(req)); - pcap_strlcpy(req.ifm_name, pb->device, + pcapint_strlcpy(req.ifm_name, pb->device, sizeof(req.ifm_name)); if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { fprintf(stderr, @@ -1579,7 +1702,7 @@ pcap_cleanup_bpf(pcap_t *p) * turn it off. */ memset(&ifr, 0, sizeof(ifr)); - (void)pcap_strlcpy(ifr.ifr_name, + (void)pcapint_strlcpy(ifr.ifr_name, pb->device, sizeof(ifr.ifr_name)); ifr.ifr_media = @@ -1608,7 +1731,7 @@ pcap_cleanup_bpf(pcap_t *p) s = socket(AF_LOCAL, SOCK_DGRAM, 0); if (s >= 0) { - pcap_strlcpy(ifr.ifr_name, pb->device, + pcapint_strlcpy(ifr.ifr_name, pb->device, sizeof(ifr.ifr_name)); ioctl(s, SIOCIFDESTROY, &ifr); close(s); @@ -1620,7 +1743,7 @@ pcap_cleanup_bpf(pcap_t *p) * Take this pcap out of the list of pcaps for which we * have to take the interface out of some mode. */ - pcap_remove_from_pcaps_to_close(p); + pcapint_remove_from_pcaps_to_close(p); pb->must_do_on_close = 0; } @@ -1630,7 +1753,7 @@ pcap_cleanup_bpf(pcap_t *p) * Delete the mappings. Note that p->buffer gets * initialized to one of the mmapped regions in * this case, so do not try and free it directly; - * null it out so that pcap_cleanup_live_common() + * null it out so that pcapint_cleanup_live_common() * doesn't try to free it. */ if (pb->zbuf1 != MAP_FAILED && pb->zbuf1 != NULL) @@ -1644,7 +1767,7 @@ pcap_cleanup_bpf(pcap_t *p) free(pb->device); pb->device = NULL; } - pcap_cleanup_live_common(p); + pcapint_cleanup_live_common(p); } #ifdef __APPLE__ @@ -1670,14 +1793,14 @@ check_setif_failure(pcap_t *p, int error) if (fd != -1) { char *en_name; - if (pcap_asprintf(&en_name, "en%s", + if (pcapint_asprintf(&en_name, "en%s", p->opt.device + 3) == -1) { /* * We can't find out whether there's * an underlying "enN" device, so * just report "no such device". */ - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "malloc"); close(fd); @@ -1709,7 +1832,7 @@ check_setif_failure(pcap_t *p, int error) * just report "no such device". */ err = PCAP_ERROR_NO_SUCH_DEVICE; - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, errno, PCAP_ERRBUF_SIZE, "socket() failed"); } @@ -1764,10 +1887,6 @@ pcap_activate_bpf(pcap_t *p) int retv; #endif int fd; -#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid) - struct lifreq ifr; - char *zonesep; -#endif struct bpf_version bv; #ifdef __APPLE__ int sockfd; @@ -1801,7 +1920,7 @@ pcap_activate_bpf(pcap_t *p) p->fd = fd; if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCVERSION"); status = PCAP_ERROR; goto bad; @@ -1825,58 +1944,9 @@ pcap_activate_bpf(pcap_t *p) if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN) p->snapshot = MAXIMUM_SNAPLEN; -#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid) - /* - * Retrieve the zoneid of the zone we are currently executing in. - */ - if ((ifr.lifr_zoneid = getzoneid()) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, - errno, "getzoneid()"); - status = PCAP_ERROR; - goto bad; - } - /* - * Check if the given source datalink name has a '/' separated - * zonename prefix string. The zonename prefixed source datalink can - * be used by pcap consumers in the Solaris global zone to capture - * traffic on datalinks in non-global zones. Non-global zones - * do not have access to datalinks outside of their own namespace. - */ - if ((zonesep = strchr(p->opt.device, '/')) != NULL) { - char path_zname[ZONENAME_MAX]; - int znamelen; - char *lnamep; - - if (ifr.lifr_zoneid != GLOBAL_ZONEID) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, - "zonename/linkname only valid in global zone."); - status = PCAP_ERROR; - goto bad; - } - znamelen = zonesep - p->opt.device; - (void) pcap_strlcpy(path_zname, p->opt.device, znamelen + 1); - ifr.lifr_zoneid = getzoneidbyname(path_zname); - if (ifr.lifr_zoneid == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, - errno, "getzoneidbyname(%s)", path_zname); - status = PCAP_ERROR; - goto bad; - } - lnamep = strdup(zonesep + 1); - if (lnamep == NULL) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, - errno, "strdup"); - status = PCAP_ERROR; - goto bad; - } - free(p->opt.device); - p->opt.device = lnamep; - } -#endif - pb->device = strdup(p->opt.device); if (pb->device == NULL) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "strdup"); status = PCAP_ERROR; goto bad; @@ -1940,7 +2010,7 @@ pcap_activate_bpf(pcap_t *p) * report "no such device". */ status = PCAP_ERROR_NO_SUCH_DEVICE; - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "socket() failed"); } @@ -1948,7 +2018,7 @@ pcap_activate_bpf(pcap_t *p) } wltdev = malloc(strlen(p->opt.device) + 2); if (wltdev == NULL) { - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "malloc"); status = PCAP_ERROR; @@ -1991,7 +2061,7 @@ pcap_activate_bpf(pcap_t *p) */ s = socket(AF_LOCAL, SOCK_DGRAM, 0); if (s < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "Can't open socket"); status = PCAP_ERROR; @@ -2002,7 +2072,7 @@ pcap_activate_bpf(pcap_t *p) * If we haven't already done so, arrange to have * "pcap_close_all()" called when we exit. */ - if (!pcap_do_addexit(p)) { + if (!pcapint_do_addexit(p)) { /* * "atexit()" failed; don't create the * interface, just give up. @@ -2017,14 +2087,14 @@ pcap_activate_bpf(pcap_t *p) /* * Create the interface. */ - pcap_strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name)); + pcapint_strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name)); if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) { if (errno == EINVAL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Invalid USB bus interface %s", p->opt.device); } else { - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "Can't create interface for %s", p->opt.device); @@ -2042,7 +2112,7 @@ pcap_activate_bpf(pcap_t *p) /* * Add this to the list of pcaps to close when we exit. */ - pcap_add_to_pcaps_to_close(p); + pcapint_add_to_pcaps_to_close(p); } } #endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */ @@ -2070,7 +2140,7 @@ pcap_activate_bpf(pcap_t *p) * size. */ if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCGETZMAX"); status = PCAP_ERROR; goto bad; @@ -2097,7 +2167,7 @@ pcap_activate_bpf(pcap_t *p) pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "mmap"); status = PCAP_ERROR; goto bad; @@ -2107,7 +2177,7 @@ pcap_activate_bpf(pcap_t *p) bz.bz_bufb = pb->zbuf2; bz.bz_buflen = pb->zbufsize; if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCSETZBUF"); status = PCAP_ERROR; goto bad; @@ -2141,7 +2211,7 @@ pcap_activate_bpf(pcap_t *p) */ if (ioctl(fd, BIOCSBLEN, (caddr_t)&p->opt.buffer_size) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCSBLEN: %s", p->opt.device); status = PCAP_ERROR; @@ -2227,7 +2297,7 @@ pcap_activate_bpf(pcap_t *p) /* Get the data link layer type. */ if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCGDLT"); status = PCAP_ERROR; goto bad; @@ -2266,7 +2336,7 @@ pcap_activate_bpf(pcap_t *p) goto bad; } #endif -#if _BSDI_VERSION - 0 >= 199510 +#if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199510 /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */ switch (v) { @@ -2444,14 +2514,15 @@ pcap_activate_bpf(pcap_t *p) */ if (v == DLT_EN10MB && p->dlt_count == 0) { p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); - /* - * If that fails, just leave the list empty. - */ - if (p->dlt_list != NULL) { - p->dlt_list[0] = DLT_EN10MB; - p->dlt_list[1] = DLT_DOCSIS; - p->dlt_count = 2; + if (p->dlt_list == NULL) { + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + errno, "malloc"); + status = PCAP_ERROR; + goto bad; } + p->dlt_list[0] = DLT_EN10MB; + p->dlt_list[1] = DLT_DOCSIS; + p->dlt_count = 2; } #ifdef PCAP_FDDIPAD if (v == DLT_FDDI) @@ -2472,7 +2543,7 @@ pcap_activate_bpf(pcap_t *p) * BSDs - check CVS log for "bpf.c"? */ if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCSHDRCMPLT"); status = PCAP_ERROR; goto bad; @@ -2514,7 +2585,7 @@ pcap_activate_bpf(pcap_t *p) bpf_to.tv_sec = p->opt.timeout / 1000; bpf_to.tv_usec = (p->opt.timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, errno, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT"); status = PCAP_ERROR; goto bad; @@ -2524,7 +2595,7 @@ pcap_activate_bpf(pcap_t *p) to.tv_sec = p->opt.timeout / 1000; to.tv_usec = (p->opt.timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, errno, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT"); status = PCAP_ERROR; goto bad; @@ -2559,7 +2630,7 @@ pcap_activate_bpf(pcap_t *p) #endif /* _AIX */ v = 1; if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCIMMEDIATE"); status = PCAP_ERROR; goto bad; @@ -2581,7 +2652,7 @@ pcap_activate_bpf(pcap_t *p) if (p->opt.promisc) { /* set promiscuous mode, just warn if it fails */ if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCPROMISC"); status = PCAP_WARNING_PROMISC_NOTSUP; } @@ -2590,7 +2661,7 @@ pcap_activate_bpf(pcap_t *p) #ifdef BIOCSTSTAMP v = BPF_T_BINTIME; if (ioctl(p->fd, BIOCSTSTAMP, &v) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCSTSTAMP"); status = PCAP_ERROR; goto bad; @@ -2598,7 +2669,7 @@ pcap_activate_bpf(pcap_t *p) #endif /* BIOCSTSTAMP */ if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCGBLEN"); status = PCAP_ERROR; goto bad; @@ -2609,7 +2680,7 @@ pcap_activate_bpf(pcap_t *p) #endif p->buffer = malloc(p->bufsize); if (p->buffer == NULL) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "malloc"); status = PCAP_ERROR; goto bad; @@ -2640,7 +2711,7 @@ pcap_activate_bpf(pcap_t *p) total_prog.bf_len = 1; total_prog.bf_insns = &total_insn; if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCSETF"); status = PCAP_ERROR; goto bad; @@ -2731,7 +2802,7 @@ check_bpf_bindable(const char *name) * adapter, rather than by implementing the ioctls that * {Free,Net,Open,DragonFly}BSD provide. Opening that device * puts the adapter into monitor mode, which, at least for - * some adapters, causes them to deassociate from the network + * some adapters, causes them to disassociate from the network * with which they're associated. * * Instead, we try to open the corresponding "en" device (so @@ -2751,7 +2822,7 @@ check_bpf_bindable(const char *name) en_name_len = strlen(name) - 1; en_name = malloc(en_name_len + 1); if (en_name == NULL) { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "malloc"); return (-1); } @@ -2868,7 +2939,7 @@ finddevs_usb(pcap_if_list_t *devlistp, char *errbuf) * so we need to avoid adding multiple capture devices * for each bus. */ - if (find_or_add_dev(devlistp, name, PCAP_IF_UP, + if (pcapint_find_or_add_dev(devlistp, name, PCAP_IF_UP, get_usb_if_flags, NULL, errbuf) == NULL) { free(name); closedir(usbdir); @@ -2893,13 +2964,13 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) { - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "Can't create socket to get media information for %s", name); return (-1); } memset(&req, 0, sizeof(req)); - pcap_strlcpy(req.ifm_name, name, sizeof(req.ifm_name)); + pcapint_strlcpy(req.ifm_name, name, sizeof(req.ifm_name)); if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { if (errno == EOPNOTSUPP || errno == EINVAL || errno == ENOTTY || errno == ENODEV || errno == EPERM @@ -2938,7 +3009,7 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) close(sock); return (0); } - pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, + pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "SIOCGIFMEDIA on %s failed", name); close(sock); return (-1); @@ -3005,15 +3076,23 @@ get_if_flags(const char *name _U_, bpf_u_int32 *flags, char *errbuf _U_) #endif int -pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) +pcapint_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) { /* * Get the list of regular interfaces first. */ - if (pcap_findalldevs_interfaces(devlistp, errbuf, check_bpf_bindable, + if (pcapint_findalldevs_interfaces(devlistp, errbuf, check_bpf_bindable, get_if_flags) == -1) return (-1); /* failure */ +#if defined(HAVE_SOLARIS_ANY_DEVICE) + /* + * Add the "any" device. + */ + if (pcap_add_any_dev(devlistp, errbuf) == NULL) + return (-1); +#endif + #if defined(__FreeBSD__) && defined(SIOCIFCREATE2) if (finddevs_usb(devlistp, errbuf) == -1) return (-1); @@ -3036,13 +3115,13 @@ monitor_mode(pcap_t *p, int set) sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "can't open socket"); return (PCAP_ERROR); } memset(&req, 0, sizeof req); - pcap_strlcpy(req.ifm_name, p->opt.device, sizeof req.ifm_name); + pcapint_strlcpy(req.ifm_name, p->opt.device, sizeof req.ifm_name); /* * Find out how many media types we have. @@ -3072,7 +3151,7 @@ monitor_mode(pcap_t *p, int set) return (PCAP_ERROR_RFMON_NOTSUP); default: - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "SIOCGIFMEDIA"); close(sock); return (PCAP_ERROR); @@ -3092,14 +3171,14 @@ monitor_mode(pcap_t *p, int set) */ media_list = malloc(req.ifm_count * sizeof(*media_list)); if (media_list == NULL) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "malloc"); close(sock); return (PCAP_ERROR); } req.ifm_ulist = media_list; if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "SIOCGIFMEDIA"); free(media_list); close(sock); @@ -3147,7 +3226,7 @@ monitor_mode(pcap_t *p, int set) * If we haven't already done so, arrange to have * "pcap_close_all()" called when we exit. */ - if (!pcap_do_addexit(p)) { + if (!pcapint_do_addexit(p)) { /* * "atexit()" failed; don't put the interface * in monitor mode, just give up. @@ -3156,11 +3235,11 @@ monitor_mode(pcap_t *p, int set) return (PCAP_ERROR); } memset(&ifr, 0, sizeof(ifr)); - (void)pcap_strlcpy(ifr.ifr_name, p->opt.device, + (void)pcapint_strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name)); ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR; if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "SIOCSIFMEDIA"); close(sock); return (PCAP_ERROR); @@ -3171,7 +3250,7 @@ monitor_mode(pcap_t *p, int set) /* * Add this to the list of pcaps to close when we exit. */ - pcap_add_to_pcaps_to_close(p); + pcapint_add_to_pcaps_to_close(p); } } return (0); @@ -3397,17 +3476,17 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) * some kernels. */ if (errno != EINVAL) { - pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, + pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, errno, "BIOCSETF"); return (-1); } /* - * install_bpf_program() validates the program. + * pcapint_install_bpf_program() validates the program. * * XXX - what if we already have a filter in the kernel? */ - if (install_bpf_program(p, fp) < 0) + if (pcapint_install_bpf_program(p, fp) < 0) return (-1); pb->filtering_in_kernel = 0; /* filtering in userland */ return (0); @@ -3462,7 +3541,7 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d) } if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf), + pcapint_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf), errno, "Cannot set direction to %s", direction_name); return (-1); } @@ -3515,7 +3594,7 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d) break; } if (ioctl(p->fd, BIOCSDIRFILT, &dirfilt) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf), + pcapint_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf), errno, "Cannot set direction to %s", direction_name); return (-1); } @@ -3565,7 +3644,7 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d) } if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf), + pcapint_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf), errno, "Cannot set direction to %s", direction_name); return (-1); } @@ -3586,7 +3665,7 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt) { if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) { - pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf), + pcapint_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf), errno, "Cannot set DLT %d", dlt); return (-1); } |