]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/eui/Eui48.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / eui / Eui48.cc
index 91d86d948795b4a156747a556cc4cef2d7101f04..de50ac701aaa99027dfe9ad199264b6eeba1ab89 100644 (file)
@@ -1,37 +1,13 @@
 /*
- * DEBUG: section 89    EUI-48 Lookup
- * AUTHOR: Duane Wessels
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
  *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- *
- * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
+/* DEBUG: section 89    EUI-48 Lookup */
+
 #include "squid.h"
 
 #if USE_SQUID_EUI
 #include "globals.h"
 #include "ip/Address.h"
 
-
-#if _SQUID_CYGWIN_
-#include <squid_windows.h>
-#endif
+#include <cerrno>
 
 /* START Legacy includes pattern */
-/* TODO: clean this up so we dont have per-OS requirements.
+/* TODO: clean this up so we do not have per-OS requirements.
          The files are checked for existence individually
          and can be wrapped
  */
@@ -60,13 +33,11 @@ struct arpreq {
     struct sockaddr arp_ha;   /* hardware address */
     int arp_flags;            /* flags */
 };
-
-#include <Iphlpapi.h>
+#if HAVE_IPHLPAPI_H
+#include <iphlpapi.h>
 #endif
-
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
 #endif
+
 #if HAVE_SYS_PARAM_H
 #include <sys/param.h>
 #endif
@@ -108,7 +79,7 @@ struct arpreq {
  * Working on setting up a proper firewall for a network containing some
  * Win'95 computers at our Univ, I've discovered that some smart students
  * avoid the restrictions easily just changing their IP addresses in Win'95
- * Contol Panel... It has been getting boring, so I took Squid-1.1.18
+ * Control Panel... It has been getting boring, so I took Squid-1.1.18
  * sources and added a new acl type for hard-wired access control:
  *
  * acl <name> arp <Ethernet address> ...
@@ -128,9 +99,9 @@ Eui::Eui48::decode(const char *asc)
     int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0;
 
     if (sscanf(asc, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) {
-        debugs(28, 0, "Decode EUI-48: Invalid ethernet address '" << asc << "'");
+        debugs(28, DBG_CRITICAL, "Decode EUI-48: Invalid ethernet address '" << asc << "'");
         clear();
-        return false;          /* This is not valid address */
+        return false;       /* This is not valid address */
     }
 
     eui[0] = (u_char) a1;
@@ -139,18 +110,23 @@ Eui::Eui48::decode(const char *asc)
     eui[3] = (u_char) a4;
     eui[4] = (u_char) a5;
     eui[5] = (u_char) a6;
+
+    debugs(28, 4, "id=" << (void*)this << " decoded " << asc);
     return true;
 }
 
 bool
-Eui::Eui48::encode(char *buf, const int len)
+Eui::Eui48::encode(char *buf, const int len) const
 {
-    if (len < SZ_EUI48_BUF) return false;
+    if (len < SZ_EUI48_BUF)
+        return false;
 
     snprintf(buf, len, "%02x:%02x:%02x:%02x:%02x:%02x",
              eui[0] & 0xff, eui[1] & 0xff,
              eui[2] & 0xff, eui[3] & 0xff,
              eui[4] & 0xff, eui[5] & 0xff);
+
+    debugs(28, 4, "id=" << (void*)this << " encoded " << buf);
     return true;
 }
 
@@ -158,11 +134,8 @@ Eui::Eui48::encode(char *buf, const int len)
 bool
 Eui::Eui48::lookup(const Ip::Address &c)
 {
-#if !_SQUID_WINDOWS_
-#endif /* !_SQUID_WINDOWS_ */
-
     Ip::Address ipAddr = c;
-    ipAddr.SetPort(0);
+    ipAddr.port(0);
 
 #if _SQUID_LINUX_
 
@@ -174,6 +147,12 @@ Eui::Eui48::lookup(const Ip::Address &c)
 
     /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */
     int tmpSocket = socket(AF_INET,SOCK_STREAM,0);
+    if (tmpSocket < 0) {
+        int xerrno = errno;
+        debugs(28, DBG_IMPORTANT, "Attempt to open socket for EUI retrieval failed: " << xstrerr(xerrno));
+        clear();
+        return false;
+    }
 
     /*
      * The linux kernel 2.2 maintains per interface ARP caches and
@@ -194,19 +173,21 @@ Eui::Eui48::lookup(const Ip::Address &c)
     memset(&arpReq, '\0', sizeof(arpReq));
 
     struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa;
-    ipAddr.GetSockAddr(*sa);
+    ipAddr.getSockAddr(*sa);
 
     /* Query ARP table */
+    debugs(28, 4, "id=" << (void*)this << " query ARP table");
     if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
         /* Skip non-ethernet interfaces */
         close(tmpSocket);
 
         if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
+            debugs(28, 4, "id=" << (void*)this << " ... not an Ethernet interface: " << arpReq.arp_ha.sa_data);
             clear();
             return false;
         }
 
-        debugs(28, 4, "Got address "<< std::setfill('0') << std::hex <<
+        debugs(28, 4, "id=" << (void*)this << " got address "<< std::setfill('0') << std::hex <<
                std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff)  << ":" <<
                std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff)  << ":" <<
                std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff)  << ":" <<
@@ -224,14 +205,15 @@ Eui::Eui48::lookup(const Ip::Address &c)
     ifc.ifc_buf = (char *)ifbuffer;
 
     if (ioctl(tmpSocket, SIOCGIFCONF, &ifc) < 0) {
-        debugs(28, 1, "Attempt to retrieve interface list failed: " << xstrerror());
+        int xerrno = errno;
+        debugs(28, DBG_IMPORTANT, "Attempt to retrieve interface list failed: " << xstrerr(xerrno));
         clear();
         close(tmpSocket);
         return false;
     }
 
     if (ifc.ifc_len > (int)sizeof(ifbuffer)) {
-        debugs(28, 1, "Interface list too long - " << ifc.ifc_len);
+        debugs(28, DBG_IMPORTANT, "Interface list too long - " << ifc.ifc_len);
         clear();
         close(tmpSocket);
         return false;
@@ -239,27 +221,29 @@ Eui::Eui48::lookup(const Ip::Address &c)
 
     /* Attempt ARP lookup on each interface */
     offset = 0;
-
+    debugs(28, 4, "id=" << (void*)this << " query ARP on each interface (" << ifc.ifc_len << " found)");
     while (offset < ifc.ifc_len) {
 
         ifr = (struct ifreq *) (ifbuffer + offset);
         offset += sizeof(*ifr);
-        /* Skip loopback and aliased interfaces */
 
-        if (0 == strncmp(ifr->ifr_name, "lo", 2))
+        debugs(28, 4, "id=" << (void*)this << " found interface " << ifr->ifr_name);
+
+        /* Skip loopback and aliased interfaces */
+        if (!strncmp(ifr->ifr_name, "lo", 2))
             continue;
 
-        if (NULL != strchr(ifr->ifr_name, ':'))
+        if (strchr(ifr->ifr_name, ':'))
             continue;
 
-        debugs(28, 4, "Looking up ARP address for " << ipAddr << " on " << ifr->ifr_name);
+        debugs(28, 4, "id=" << (void*)this << " looking up ARP address for " << ipAddr << " on " << ifr->ifr_name);
 
         /* Set up structures for ARP lookup */
 
         memset(&arpReq, '\0', sizeof(arpReq));
 
         sa = (sockaddr_in*)&arpReq.arp_pa;
-        ipAddr.GetSockAddr(*sa);
+        ipAddr.getSockAddr(*sa);
 
         strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1);
 
@@ -267,26 +251,21 @@ Eui::Eui48::lookup(const Ip::Address &c)
 
         /* Query ARP table */
         if (-1 == ioctl(tmpSocket, SIOCGARP, &arpReq)) {
-            /*
-             * Query failed.  Do not log failed lookups or "device
-             * not supported"
-             */
-
-            if (ENXIO == errno)
-                (void) 0;
-            else if (ENODEV == errno)
-                (void) 0;
-            else
-                debugs(28, 1, "ARP query " << ipAddr << " failed: " << ifr->ifr_name << ": " << xstrerror());
+            int xerrno = errno;
+            //  Query failed.  Do not log failed lookups or "device not supported"
+            if (ENXIO != xerrno && ENODEV != xerrno)
+                debugs(28, DBG_IMPORTANT, "ARP query " << ipAddr << " failed: " << ifr->ifr_name << ": " << xstrerr(xerrno));
 
             continue;
         }
 
         /* Skip non-ethernet interfaces */
-        if (arpReq.arp_ha.sa_family != ARPHRD_ETHER)
+        if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
+            debugs(28, 4, "id=" << (void*)this << "... not an Ethernet interface");
             continue;
+        }
 
-        debugs(28, 4, "Got address "<< std::setfill('0') << std::hex <<
+        debugs(28, 4, "id=" << (void*)this << " got address "<< std::setfill('0') << std::hex <<
                std::setw(2) << (arpReq.arp_ha.sa_data[0] & 0xff)  << ":" <<
                std::setw(2) << (arpReq.arp_ha.sa_data[1] & 0xff)  << ":" <<
                std::setw(2) << (arpReq.arp_ha.sa_data[2] & 0xff)  << ":" <<
@@ -313,13 +292,19 @@ Eui::Eui48::lookup(const Ip::Address &c)
 
     /* IPv6 builds do not provide the first http_port as an IPv4 socket for ARP */
     int tmpSocket = socket(AF_INET,SOCK_STREAM,0);
+    if (tmpSocket < 0) {
+        int xerrno = errno;
+        debugs(28, DBG_IMPORTANT, "Attempt to open socket for EUI retrieval failed: " << xstrerr(xerrno));
+        clear();
+        return false;
+    }
 
     /* Set up structures for ARP lookup with blank interface name */
     struct arpreq arpReq;
     memset(&arpReq, '\0', sizeof(arpReq));
 
     struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa;
-    ipAddr.GetSockAddr(*sa);
+    ipAddr.getSockAddr(*sa);
 
     /* Query ARP table */
     if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
@@ -348,6 +333,8 @@ Eui::Eui48::lookup(const Ip::Address &c)
 
         set(arpReq.arp_ha.sa_data, 6);
         return true;
+    } else {
+        close(tmpSocket);
     }
 
 #elif _SQUID_FREEBSD_ || _SQUID_NETBSD_ || _SQUID_OPENBSD_ || _SQUID_DRAGONFLY_ || _SQUID_KFREEBSD_
@@ -371,7 +358,7 @@ Eui::Eui48::lookup(const Ip::Address &c)
     memset(&arpReq, '\0', sizeof(arpReq));
 
     struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa;
-    ipAddr.GetSockAddr(*sa);
+    ipAddr.getSockAddr(*sa);
 
     /* Query ARP table */
     mib[0] = CTL_NET;
@@ -384,22 +371,26 @@ Eui::Eui48::lookup(const Ip::Address &c)
 
     mib[4] = NET_RT_FLAGS;
 
+#if defined(RTF_LLDATA)
+    mib[5] = RTF_LLDATA;
+#else
     mib[5] = RTF_LLINFO;
+#endif
 
     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
-        debugs(28, 0, "Can't estimate ARP table size!");
+        debugs(28, DBG_CRITICAL, "Can't estimate ARP table size!");
         clear();
         return false;
     }
 
     if ((buf = (char *)xmalloc(needed)) == NULL) {
-        debugs(28, 0, "Can't allocate temporary ARP table!");
+        debugs(28, DBG_CRITICAL, "Can't allocate temporary ARP table!");
         clear();
         return false;
     }
 
     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
-        debugs(28, 0, "Can't retrieve ARP table!");
+        debugs(28, DBG_CRITICAL, "Can't retrieve ARP table!");
         xfree(buf);
         clear();
         return false;
@@ -464,21 +455,21 @@ Eui::Eui48::lookup(const Ip::Address &c)
 
     /* Get size of Windows ARP table */
     if (GetIpNetTable(NetTable, &ipNetTableLen, FALSE) != ERROR_INSUFFICIENT_BUFFER) {
-        debugs(28, 0, "Can't estimate ARP table size!");
+        debugs(28, DBG_CRITICAL, "Can't estimate ARP table size!");
         clear();
         return false;
     }
 
     /* Allocate space for ARP table and assign pointers */
     if ((NetTable = (PMIB_IPNETTABLE)xmalloc(ipNetTableLen)) == NULL) {
-        debugs(28, 0, "Can't allocate temporary ARP table!");
+        debugs(28, DBG_CRITICAL, "Can't allocate temporary ARP table!");
         clear();
         return false;
     }
 
     /* Get actual ARP table */
     if ((dwNetTable = GetIpNetTable(NetTable, &ipNetTableLen, FALSE)) != NO_ERROR) {
-        debugs(28, 0, "Can't retrieve ARP table!");
+        debugs(28, DBG_CRITICAL, "Can't retrieve ARP table!");
         xfree(NetTable);
         clear();
         return false;
@@ -516,13 +507,13 @@ Eui::Eui48::lookup(const Ip::Address &c)
 
 #else
 
-    debugs(28, 0, "ERROR: ARP / MAC / EUI-* operations not supported on this operating system.");
+    debugs(28, DBG_CRITICAL, "ERROR: ARP / MAC / EUI-* operations not supported on this operating system.");
 
 #endif
     /*
      * Address was not found on any interface
      */
-    debugs(28, 3, HERE << ipAddr << " NOT found");
+    debugs(28, 3, "id=" << (void*)this << ' ' << ipAddr << " NOT found");
 
     clear();
     return false;
@@ -531,3 +522,4 @@ Eui::Eui48::lookup(const Ip::Address &c)
 /* ==== END EUI LOOKUP SUPPORT =============================================== */
 
 #endif /* USE_SQUID_EUI */
+