commit 8fa17a5a554aaeb85d3ec4118b45a31f1efd6808 Author: guy Date: Wed Nov 19 08:20:39 2008 +0000 Fix the handling of the "any" device, including making it reject attempts to open it in monitor mode. diff --git a/pcap-linux.c b/pcap-linux.c index 2a92d30..b18c4d2 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -297,6 +297,12 @@ pcap_create(const char *device, char *ebuf) { pcap_t *handle; + /* + * A null device name is equivalent to the "any" device. + */ + if (device == NULL) + device = "any"; + #ifdef HAVE_DAG_API if (strstr(device, "dag")) { return dag_create(device, ebuf); @@ -338,10 +344,9 @@ pcap_can_set_rfmon_linux(pcap_t *p) struct iwreq ireq; #endif - if (p->opt.source == NULL) { + if (strcmp(p->opt.source, "any") == 0) { /* - * This is equivalent to the "any" device, and we don't - * support monitor mode on it. + * Monitor mode makes no sense on the "any" device. */ return 0; } @@ -518,12 +523,11 @@ pcap_activate_linux(pcap_t *handle) handle->stats_op = pcap_stats_linux; /* - * NULL and "any" are special devices which give us the hint to - * monitor all devices. + * The "any" device is a special device which causes us not + * to bind to a particular device and thus to look at all + * devices. */ - if (!device || strcmp(device, "any") == 0) { - device = NULL; - handle->md.device = strdup("any"); + if (strcmp(device, "any") == 0) { if (handle->opt.promisc) { handle->opt.promisc = 0; /* Just a warning. */ @@ -531,10 +535,9 @@ pcap_activate_linux(pcap_t *handle) "Promiscuous mode not supported on the \"any\" device"); status = PCAP_WARNING_PROMISC_NOTSUP; } + } - } else - handle->md.device = strdup(device); - + handle->md.device = strdup(device); if (handle->md.device == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s", pcap_strerror(errno) ); @@ -1657,19 +1660,21 @@ static int activate_new(pcap_t *handle) { #ifdef HAVE_PF_PACKET_SOCKETS + const char *device = handle->opt.source; + int is_any_device = (strcmp(device, "any") == 0); int sock_fd = -1, arptype, val; int err = 0; struct packet_mreq mr; - const char* device = handle->opt.source; /* - * Open a socket with protocol family packet. If a device is - * given we try to open it in raw mode otherwise we use - * the cooked interface. + * Open a socket with protocol family packet. If the + * "any" device was specified, we open a SOCK_DGRAM + * socket for the cooked interface, otherwise we first + * try a SOCK_RAW socket for the raw interface. */ - sock_fd = device ? - socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) - : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); + sock_fd = is_any_device ? + socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) : + socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock_fd == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s", @@ -1704,7 +1709,7 @@ activate_new(pcap_t *handle) * to cooked mode if we have an unknown interface type * or a type we know doesn't work well in raw mode. */ - if (device) { + if (!is_any_device) { /* Assume for now we don't need cooked mode. */ handle->md.cooked = 0; @@ -1819,15 +1824,23 @@ activate_new(pcap_t *handle) } } else { /* - * This is cooked mode. + * The "any" device. + */ + if (handle->opt.rfmon) { + /* + * It doesn't support monitor mode. + */ + return PCAP_ERROR_RFMON_NOTSUP; + } + + /* + * It uses cooked mode. */ handle->md.cooked = 1; handle->linktype = DLT_LINUX_SLL; /* * We're not bound to a device. - * XXX - true? Or true only if we're using - * the "any" device? * For now, we're using this as an indication * that we can't transmit; stop doing that only * if we figure out how to transmit in cooked @@ -1852,10 +1865,13 @@ activate_new(pcap_t *handle) /* * Hmm, how can we set promiscuous mode on all interfaces? - * I am not sure if that is possible at all. + * I am not sure if that is possible at all. For now, we + * silently ignore attempts to turn promiscuous mode on + * for the "any" device (so you don't have to explicitly + * disable it in programs such as tcpdump). */ - if (device && handle->opt.promisc) { + if (!is_any_device && handle->opt.promisc) { memset(&mr, 0, sizeof(mr)); mr.mr_ifindex = handle->md.ifindex; mr.mr_type = PACKET_MR_PROMISC; @@ -3118,7 +3134,7 @@ activate_old(pcap_t *handle) /* Bind to the given device */ - if (!device) { + if (strcmp(device, "any") == 0) { strncpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems", PCAP_ERRBUF_SIZE); return PCAP_ERROR;