aboutsummaryrefslogtreecommitdiffstats
path: root/pcap-linux.c
diff options
context:
space:
mode:
authorGuy Harris <gharris@steve.local>2009-06-01 13:04:55 -0700
committerGuy Harris <gharris@steve.local>2009-06-01 13:04:55 -0700
commit5d86a7c3b271e42374e5d9817838d491b7ba6681 (patch)
treee0d837a28f7a595a801a35d48e951ba56ea9870d /pcap-linux.c
parent9a4ef64d7627242371a17bd7fe96ae9725f3ab62 (diff)
Move some more stuff up before the first use.
Diffstat (limited to 'pcap-linux.c')
-rw-r--r--pcap-linux.c390
1 files changed, 193 insertions, 197 deletions
diff --git a/pcap-linux.c b/pcap-linux.c
index 455077b..0e23fd0 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -469,203 +469,6 @@ get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
return 1;
}
-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
-
struct nl80211_state {
struct nl_handle *nl_handle;
struct nl_cache *nl_cache;
@@ -881,8 +684,201 @@ nla_put_failure:
return PCAP_ERROR;
}
+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;
+}
+
/*
* With older kernels promiscuous mode is kind of interesting because we
* have to reset the interface before exiting. The problem can't really