fix missing parts of r19997.
[openwrt/svn-archive/archive.git] / package / libpcap / patches / 200-debian_fix_any_intf.patch
diff --git a/package/libpcap/patches/200-debian_fix_any_intf.patch b/package/libpcap/patches/200-debian_fix_any_intf.patch
new file mode 100644 (file)
index 0000000..8da6ef2
--- /dev/null
@@ -0,0 +1,149 @@
+--- a/pcap-linux.c
++++ b/pcap-linux.c
+@@ -297,6 +297,12 @@ pcap_create(const char *device, char *eb
+ {
+       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.
+-       */
+-      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 @@ 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;