]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 2795: pt 2: ARP lookups require IPv4-only socket on Linux/Solaris
authorAmos Jeffries <squid3@treenet.co.nz>
Wed, 4 Nov 2009 04:43:47 +0000 (17:43 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Wed, 4 Nov 2009 04:43:47 +0000 (17:43 +1300)
src/acl/Arp.cc

index 49eaade5c39b576617ae0bc2d0136ed7157482d3..dd4e971cd80da6ec178a1d57dd374789eb40211e 100644 (file)
@@ -259,6 +259,10 @@ aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
     int offset;
 
     SplayNode<acl_arp_data*> **Top = dataptr;
+
+    /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */
+    int tmpSocket = socket(AF_INET,SOCK_STREAM,0);
+
     /*
      * The linux kernel 2.2 maintains per interface ARP caches and
      * thus requires an interface name when doing ARP queries.
@@ -280,8 +284,9 @@ aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
     ipAddr.GetSockAddr(*sa);
     /* Query ARP table */
 
-    if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) {
+    if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
         /* Skip non-ethernet interfaces */
+        close(tmpSocket);
 
         if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
             return 0;
@@ -308,13 +313,15 @@ aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
 
     ifc.ifc_buf = (char *)ifbuffer;
 
-    if (ioctl(HttpSockets[0], SIOCGIFCONF, &ifc) < 0) {
+    if (ioctl(tmpSocket, SIOCGIFCONF, &ifc) < 0) {
         debugs(28, 1, "Attempt to retrieve interface list failed: " << xstrerror());
+        close(tmpSocket);
         return 0;
     }
 
     if (ifc.ifc_len > (int)sizeof(ifbuffer)) {
         debugs(28, 1, "Interface list too long - " << ifc.ifc_len);
+        close(tmpSocket);
         return 0;
     }
 
@@ -347,7 +354,7 @@ aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
         arpReq.arp_dev[sizeof(arpReq.arp_dev) - 1] = '\0';
 
         /* Query ARP table */
-        if (-1 == ioctl(HttpSockets[0], SIOCGARP, &arpReq)) {
+        if (-1 == ioctl(tmpSocket, SIOCGARP, &arpReq)) {
             /*
              * Query failed.  Do not log failed lookups or "device
              * not supported"
@@ -386,6 +393,7 @@ aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
         /* Return if match, otherwise continue to other interfaces */
         if (0 == splayLastResult) {
             debugs(28, 3, "aclMatchArp: " << ipAddr << " found on " << ifr->ifr_name);
+            close(tmpSocket);
             return 1;
         }
 
@@ -395,10 +403,15 @@ aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
          */
     }
 
+    close(tmpSocket);
+
 #elif defined(_SQUID_SOLARIS_)
 
     SplayNode<acl_arp_data *> **Top = dataptr;
 
+    /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */
+    int tmpSocket = socket(AF_INET,SOCK_STREAM,0);
+
     /*
     * Set up structures for ARP lookup with blank interface name
     */
@@ -409,11 +422,12 @@ aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
     ipAddr.GetSockAddr(*sa);
 
     /* Query ARP table */
-    if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) {
+    if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
         /*
         *  Solaris (at least 2.6/x86) does not use arp_ha.sa_family -
         * it returns 00:00:00:00:00:00 for non-ethernet media
         */
+        close(tmpSocket);
 
         if (arpReq.arp_ha.sa_data[0] == 0 &&
                 arpReq.arp_ha.sa_data[1] == 0 &&
@@ -438,6 +452,8 @@ aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
         return (0 == splayLastResult);
     }
 
+    close(tmpSocket);
+
 #elif defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) || defined(_SQUID_DRAGONFLY_) || defined(_SQUID_KFREEBSD_)
 
     SplayNode<acl_arp_data *> **Top = dataptr;