summaryrefslogblamecommitdiffstats
path: root/source/n/tcpdump/libpcap.20-fix-any-intf.diff
blob: 84afa6822526517b9378e99f0d9f0af24759f586 (plain) (tree)






























































































































































                                                                                                                      
commit 8fa17a5a554aaeb85d3ec4118b45a31f1efd6808
Author: guy <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.
---
 pcap-linux.c |   68 ++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 42 insertions(+), 26 deletions(-)

--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -297,6 +297,12 @@
 {
 	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 @@
 	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 @@
 	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 @@
 			    "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 @@
 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.
-	 */
-	sock_fd = device ?
-		socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
-	      : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));
+	 * 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 = 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 @@
 	 * 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 @@
 		}
 	} 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 @@
 
 	/*
 	 * 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 @@
 
 	/* 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;