-static int
-enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device)
-{
- int ret;
- char phydev_path[PATH_MAX+1];
- struct nl80211_state nlstate;
- struct ifreq ifr;
- u_int n;
-
- /*
- * Is this a mac80211 device?
- */
- ret = get_mac80211_phydev(handle, device, phydev_path, PATH_MAX);
- if (ret < 0)
- return ret; /* error */
- if (ret == 0)
- return 0; /* no error, but not mac80211 device */
-
- /*
- * XXX - is this already a monN device?
- * If so, we're done.
- * Is that determined by old Wireless Extensions ioctls?
- */
-
- /*
- * OK, it's apparently a mac80211 device.
- * Try to find an unused monN device for it.
- */
- ret = nl80211_init(handle, &nlstate, device);
- if (ret != 0)
- return ret;
- for (n = 0; n < UINT_MAX; n++) {
- /*
- * Try mon{n}.
- */
- char mondevice[3+10+1]; /* mon{UINT_MAX}\0 */
-
- snprintf(mondevice, sizeof mondevice, "mon%u", n);
- ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
- if (ret == 1) {
- handle->md.mondevice = strdup(mondevice);
- goto added;
- }
- if (ret < 0) {
- /*
- * Hard failure. Just return ret; handle->errbuf
- * has already been set.
- */
- nl80211_cleanup(&nlstate);
- return ret;
- }
- }
-
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "%s: No free monN interfaces", device);
- nl80211_cleanup(&nlstate);
- return PCAP_ERROR;
-
-added:
-
-#if 0
- /*
- * Sleep for .1 seconds.
- */
- delay.tv_sec = 0;
- delay.tv_nsec = 500000000;
- nanosleep(&delay, NULL);
-#endif
-
- /*
- * Now configure the monitor interface up.
- */
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, handle->md.mondevice, sizeof(ifr.ifr_name));
- if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "%s: Can't get flags for %s: %s", device,
- handle->md.mondevice, strerror(errno));
- del_mon_if(handle, sock_fd, &nlstate, device,
- handle->md.mondevice);
- nl80211_cleanup(&nlstate);
- return PCAP_ERROR;
- }
- ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
- if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
- snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "%s: Can't set flags for %s: %s", device,
- handle->md.mondevice, strerror(errno));
- del_mon_if(handle, sock_fd, &nlstate, device,
- handle->md.mondevice);
- nl80211_cleanup(&nlstate);
- return PCAP_ERROR;
- }
-
- /*
- * Success. Clean up the libnl state.
- */
- nl80211_cleanup(&nlstate);
-
- /*
- * Note that we have to delete the monitor device when we close
- * the handle.
- */
- handle->md.must_do_on_close |= MUST_DELETE_MONIF;
-
- /*
- * Add this to the list of pcaps to close when we exit.
- */
- pcap_add_to_pcaps_to_close(handle);
-
- return 1;
-}
-#endif /* HAVE_LIBNL */
-
-static int
-pcap_can_set_rfmon_linux(pcap_t *handle)
-{
-#ifdef HAVE_LIBNL
- char phydev_path[PATH_MAX+1];
- int ret;
-#endif
-#ifdef IW_MODE_MONITOR
- int sock_fd;
- struct iwreq ireq;
-#endif
-
- if (strcmp(handle->opt.source, "any") == 0) {
- /*
- * Monitor mode makes no sense on the "any" device.
- */
- return 0;
- }
-
-#ifdef HAVE_LIBNL
- /*
- * Bleah. There doesn't seem to be a way to ask a mac80211
- * device, through libnl, whether it supports monitor mode;
- * we'll just check whether the device appears to be a
- * mac80211 device and, if so, assume the device supports
- * monitor mode.
- *
- * wmaster devices don't appear to support the Wireless
- * Extensions, but we can create a mon device for a
- * wmaster device, so we don't bother checking whether
- * a mac80211 device supports the Wireless Extensions.
- */
- ret = get_mac80211_phydev(handle, handle->opt.source, phydev_path,
- PATH_MAX);
- if (ret < 0)
- return ret; /* error */
- if (ret == 1)
- return 1; /* mac80211 device */
-#endif
-
-#ifdef IW_MODE_MONITOR
- /*
- * Bleah. There doesn't appear to be an ioctl to use to ask
- * whether a device supports monitor mode; we'll just do
- * SIOCGIWMODE and, if it succeeds, assume the device supports
- * monitor mode.
- *
- * Open a socket on which to attempt to get the mode.
- * (We assume that if we have Wireless Extensions support
- * we also have PF_PACKET support.)
- */
- sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (sock_fd == -1) {
- (void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "socket: %s", pcap_strerror(errno));
- return PCAP_ERROR;
- }
-
- /*
- * Attempt to get the current mode.
- */
- strncpy(ireq.ifr_ifrn.ifrn_name, handle->opt.source,
- sizeof ireq.ifr_ifrn.ifrn_name);
- ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
- if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
- /*
- * Well, we got the mode; assume we can set it.
- */
- close(sock_fd);
- return 1;
- }
- if (errno == ENODEV) {
- /* The device doesn't even exist. */
- close(sock_fd);
- return PCAP_ERROR_NO_SUCH_DEVICE;
- }
- close(sock_fd);
-#endif
- return 0;
-}
-
-#ifdef HAVE_LIBNL
-