static int monitor_mode(pcap_t *p, int set) { int sock; struct ifmediareq req; int *media_list; int i; int can_do; struct ifreq ifr; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s", pcap_strerror(errno)); return (PCAP_ERROR); } memset(&req, 0, sizeof req); (void)strlcpy(req.ifm_name, p->opt.source, sizeof req.ifm_name); /* * Find out how many media types we have. */ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { /* * Can't get the media types. */ switch (errno) { case ENXIO: /* * There's no such device. */ close(sock); return (PCAP_ERROR_NO_SUCH_DEVICE); case EINVAL: /* * Interface doesn't support SIOC{G,S}IFMEDIA. */ close(sock); return (PCAP_ERROR_RFMON_NOTSUP); default: snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA 1: %s", pcap_strerror(errno)); close(sock); return (PCAP_ERROR); } } if (req.ifm_count == 0) { /* * No media types. */ close(sock); return (PCAP_ERROR_RFMON_NOTSUP); } /* * Allocate a buffer to hold all the media types, and * get the media types. */ media_list = (int *) calloc(req.ifm_count, sizeof(int)); if (media_list == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); close(sock); return (PCAP_ERROR); } req.ifm_ulist = media_list; if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s", pcap_strerror(errno)); free(media_list); close(sock); return (PCAP_ERROR); } /* * Look for an 802.11 "automatic" media type. * We assume that all 802.11 adapters have that media type, * and that it will carry the monitor mode supported flag. */ can_do = 0; for (i = 0; i < req.ifm_count; i++) { if (IFM_TYPE(media_list[i]) == IFM_IEEE80211 && IFM_SUBTYPE(media_list[i]) == IFM_AUTO) { /* OK, does it do monitor mode? */ if (media_list[i] & IFM_IEEE80211_MONITOR) { can_do = 1; break; } } } free(media_list); if (!can_do) { /* * This adapter doesn't support monitor mode. */ close(sock); return (PCAP_ERROR_RFMON_NOTSUP); } if (set) { /* * Don't just check whether we can enable monitor mode, * do so, if it's not already enabled. */ if ((req.ifm_current & IFM_IEEE80211_MONITOR) == 0) { /* * Monitor mode isn't currently on, so turn it on, * and remember that we should turn it off when the * pcap_t is closed. */ /* * If we haven't already done so, arrange to have * "pcap_close_all()" called when we exit. */ if (!pcap_do_addexit(p)) { /* * "atexit()" failed; don't put the interface * in monitor mode, just give up. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "atexit failed"); close(sock); return (PCAP_ERROR); } memset(&ifr, 0, sizeof(ifr)); (void)strlcpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR; if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSIFMEDIA: %s", pcap_strerror(errno)); close(sock); return (PCAP_ERROR); } p->md.must_do_on_close |= MUST_CLEAR_RFMON; /* * Add this to the list of pcaps to close when we exit. */ pcap_add_to_pcaps_to_close(p); } } return (0); }
static int pfq_activate_linux(pcap_t *handle) { char *device = NULL, *config = NULL; const int maxlen = 1514; const int queue = Q_ANY_QUEUE; char *first_dev; handle->opt.pfq = pfq_opt_default(handle); handle->linktype = DLT_EN10MB; config = pfq_get_config_file(handle->opt.source); device = pfq_get_devname(handle->opt.source); fprintf(stdout, "[PFQ] running on device %s...\n", device); fprintf(stdout, "[PFQ] configuration file %s...\n", config); if (config == NULL) { char *conf = getenv("PFQ_CONFIG"); if (conf) config = strdup(conf); } if (config != NULL) { if (pfq_parse_config(&handle->opt.pfq, config) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pfq: config error"); return PCAP_ERROR; } free(config); } if (pfq_parse_env(&handle->opt.pfq) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pfq: env error!"); return PCAP_ERROR; } if (handle->opt.pfq.caplen > maxlen || handle->opt.pfq.caplen == 0) { fprintf(stdout, "[PFQ] capture length forced to %d\n", maxlen); handle->opt.pfq.caplen = maxlen; } if (handle->opt.buffer_size/handle->opt.pfq.caplen > handle->opt.pfq.rx_slots) handle->opt.pfq.rx_slots = handle->opt.buffer_size/handle->opt.pfq.caplen; fprintf(stdout, "[PFQ] buffer_size = %d caplen = %d, rx_slots = %d, tx_slots = %d, tx_fhint = %d\n", handle->opt.buffer_size, handle->opt.pfq.caplen, handle->opt.pfq.rx_slots, handle->opt.pfq.tx_slots, handle->opt.pfq.tx_fhint); handle->read_op = pfq_read_linux; handle->inject_op = pfq_inject_linux; handle->setfilter_op = pfq_setfilter_linux; handle->setdirection_op = pfq_setdirection_linux; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = pfq_stats_linux; handle->cleanup_op = pfq_cleanup_linux; handle->set_datalink_op = NULL; /* can't change data link type */ handle->md.pfq.q = NULL; handle->md.pfq.current = NULL; pfq_net_queue_init(&handle->md.pfq.nq); handle->md.pfq.ifs_promisc = 0; handle->fd = socket(AF_INET, SOCK_DGRAM, 0); if (handle->fd == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", pcap_strerror(errno)); if (errno == EPERM || errno == EACCES) { /* * You don't have permission to open the * socket. */ return PCAP_ERROR_PERM_DENIED; } else { /* * Other error. */ return PCAP_ERROR; } } /* * The "any" device is a special device which causes us not * to bind to a particular device and thus to look at all * devices of a given group. */ /* handle promisc */ if (handle->opt.promisc) { /* put all devic(es) in promisc mode */ int n = 0; int set_promisc(const char *dev) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFFLAGS: %s", pcap_strerror(errno)); return PCAP_ERROR; } if ((ifr.ifr_flags & IFF_PROMISC) == 0) { /* * Promiscuous mode isn't currently on, * so turn it on, and remember that * we should turn it off when the * pcap_t is closed. */ /* * If we haven't already done so, arrange * to have "pcap_close_all()" called when * we exit. */ if (!pcap_do_addexit(handle)) { /* * "atexit()" failed; don't put * the interface in promiscuous * mode, just give up. */ return PCAP_ERROR; } fprintf(stdout, "[PFQ] set promisc on dev %s...\n", dev); ifr.ifr_flags |= IFF_PROMISC; if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SIOCSIFFLAGS: %s", pcap_strerror(errno)); return PCAP_ERROR; } handle->md.pfq.ifs_promisc |= (1 << n); handle->md.must_do_on_close |= MUST_CLEAR_PROMISC; } n++; return 0; } if (strcmp(device, "any") != 0) { if (string_for_each_token(device, ":", set_promisc) < 0) { goto fail; } } }