int pcap_activate(pcap_t *p) { int status = 0; int fd; struct ifreq ifr; struct bpf_version bv; struct bpf_dltlist bdl; int new_dlt; u_int v; fd = bpf_open(p); if (fd < 0) { status = fd; goto bad; } p->fd = fd; if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "kernel bpf filter out of date"); status = PCAP_ERROR; goto bad; } #if 0 /* Just use the kernel default */ v = 32768; /* XXX this should be a user-accessible hook */ /* Ignore the return value - this is because the call fails on * BPF systems that don't have kernel malloc. And if the call * fails, it's no big deal, we just continue to use the standard * buffer size. */ (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v); #endif /* * Set the buffer size. */ if (p->opt.buffer_size != 0) { /* * A buffer size was explicitly specified; use it. */ if (ioctl(fd, BIOCSBLEN, (caddr_t)&p->opt.buffer_size) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSBLEN: %s: %s", p->opt.source, pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } } /* * Now bind to the device. */ (void)strlcpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { status = check_setif_failure(p, errno); goto bad; } /* Get the data link layer type. */ if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } #if _BSDI_VERSION - 0 >= 199510 /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */ switch (v) { case DLT_SLIP: v = DLT_SLIP_BSDOS; break; case DLT_PPP: v = DLT_PPP_BSDOS; break; case 11: /*DLT_FR*/ v = DLT_FRELAY; break; case 12: /*DLT_C_HDLC*/ v = DLT_CHDLC; break; } #endif /* * We know the default link type -- now determine all the DLTs * this interface supports. If this fails with EINVAL, it's * not fatal; we just don't get to use the feature later. */ if (get_dlt_list(fd, v, &bdl, p->errbuf) == -1) { status = PCAP_ERROR; goto bad; } p->dlt_count = bdl.bfl_len; p->dlt_list = bdl.bfl_list; /* * *BSD with the new 802.11 ioctls. * Do we want monitor mode? */ if (p->opt.rfmon) { /* * Try to put the interface into monitor mode. */ status = monitor_mode(p, 1); if (status != 0) { /* * We failed. */ goto bad; } /* * We're in monitor mode. * Try to find the best 802.11 DLT_ value and, if we * succeed, try to switch to that mode if we're not * already in that mode. */ new_dlt = find_802_11(&bdl); if (new_dlt != -1) { /* * We have at least one 802.11 DLT_ value. * new_dlt is the best of the 802.11 * DLT_ values in the list. * * If the new mode we want isn't the default mode, * attempt to select the new mode. */ if (new_dlt != v) { if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) { /* * We succeeded; make this the * new DLT_ value. */ v = new_dlt; } } } } p->linktype = v; /* set timeout */ if (p->md.timeout) { struct timeval to; to.tv_sec = p->md.timeout / 1000; to.tv_usec = (p->md.timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } } if (p->opt.promisc) { /* set promiscuous mode, just warn if it fails */ if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s", pcap_strerror(errno)); status = PCAP_WARNING_PROMISC_NOTSUP; } } if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } p->bufsize = v; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); status = PCAP_ERROR; goto bad; } if (status < 0) goto bad; p->activated = 1; return (status); bad: pcap_cleanup_bpf(p); if (p->errbuf[0] == '\0') { /* * No error message supplied by the activate routine; * for the benefit of programs that don't specially * handle errors other than PCAP_ERROR, return the * error message corresponding to the status. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_statustostr(status)); } return (status); }
#ifdef BIOCSETLIF if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0) #else if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) #endif { status = check_setif_failure(p, errno); goto bad; }