]> 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>
Fri, 30 Oct 2009 04:47:33 +0000 (17:47 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 30 Oct 2009 04:47:33 +0000 (17:47 +1300)
src/eui/Eui48.cc

index 3c2777fac2aeed0964966f7666a1efd4161bc54a..52de1b24cbfc79367b4fe5758137ca52c3014983 100644 (file)
@@ -157,7 +157,7 @@ Eui48::lookup(IpAddress &c)
     struct arpreq arpReq;
 #if !defined(_SQUID_WIN32_)
     struct sockaddr_in *sa = NULL;
-#endif
+#endif /* !_SQUID_WIN32_ */
 
     IpAddress ipAddr = c;
     ipAddr.SetPort(0);
@@ -170,6 +170,9 @@ Eui48::lookup(IpAddress &c)
     struct ifreq *ifr;
     int offset;
 
+    /* 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.
@@ -191,8 +194,9 @@ Eui48::lookup(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) {
             clear();
@@ -216,15 +220,17 @@ Eui48::lookup(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());
         clear();
+        close(tmpSocket);
         return false;
     }
 
     if (ifc.ifc_len > (int)sizeof(ifbuffer)) {
         debugs(28, 1, "Interface list too long - " << ifc.ifc_len);
         clear();
+        close(tmpSocket);
         return false;
     }
 
@@ -257,7 +263,7 @@ Eui48::lookup(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"
@@ -294,11 +300,17 @@ Eui48::lookup(IpAddress &c)
          */
 
         /* AYJ: 2009-10-06: for now we have to. We can only store one EUI at a time. */
+        close(tmpSocket);
         return true;
     }
 
+    close(tmpSocket);
+
 #elif defined(_SQUID_SOLARIS_)
 
+    /* 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 */
 
     memset(&arpReq, '\0', sizeof(arpReq));
@@ -307,11 +319,12 @@ Eui48::lookup(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 &&