/*
- * 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.
*/
-#include "config.h"
+/* 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
*/
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
* 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> ...
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;
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;
}
bool
Eui::Eui48::lookup(const Ip::Address &c)
{
- struct arpreq arpReq;
-#if !_SQUID_WINDOWS_
- struct sockaddr_in *sa = NULL;
-#endif /* !_SQUID_WINDOWS_ */
-
Ip::Address ipAddr = c;
- ipAddr.SetPort(0);
+ ipAddr.port(0);
#if _SQUID_LINUX_
/* 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
/*
* Set up structures for ARP lookup with blank interface name
*/
+ struct arpreq arpReq;
memset(&arpReq, '\0', sizeof(arpReq));
- sa = (sockaddr_in*)&arpReq.arp_pa;
- ipAddr.GetSockAddr(*sa);
+ struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa;
+ 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) << ":" <<
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;
/* 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);
/* 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) << ":" <<
/* 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));
- sa = (sockaddr_in*)&arpReq.arp_pa;
- ipAddr.GetSockAddr(*sa);
+ struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa;
+ ipAddr.getSockAddr(*sa);
/* Query ARP table */
if (ioctl(tmpSocket, SIOCGARP, &arpReq) != -1) {
set(arpReq.arp_ha.sa_data, 6);
return true;
+ } else {
+ close(tmpSocket);
}
#elif _SQUID_FREEBSD_ || _SQUID_NETBSD_ || _SQUID_OPENBSD_ || _SQUID_DRAGONFLY_ || _SQUID_KFREEBSD_
/*
* Set up structures for ARP lookup with blank interface name
*/
-
+ struct arpreq arpReq;
memset(&arpReq, '\0', sizeof(arpReq));
- sa = (struct sockaddr_in*) &arpReq.arp_pa;
- ipAddr.GetSockAddr(*sa);
+ struct sockaddr_in *sa = (struct sockaddr_in*)&arpReq.arp_pa;
+ ipAddr.getSockAddr(*sa);
/* Query ARP table */
mib[0] = CTL_NET;
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;
DWORD i;
+ struct arpreq arpReq;
memset(&arpReq, '\0', sizeof(arpReq));
/* 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;
}
/* Find MAC address from net table */
- for (i = 0 ; i < NetTable->dwNumEntries ; i++) {
+ for (i = 0 ; i < NetTable->dwNumEntries ; ++i) {
in_addr a;
a.s_addr = NetTable->table[i].dwAddr;
if (c == a && (NetTable->table[i].dwType > 2)) {
#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;
/* ==== END EUI LOOKUP SUPPORT =============================================== */
#endif /* USE_SQUID_EUI */
+