* Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
*/
-#include "config.h"
-#ifdef _SQUID_CYGWIN_
-#include <squid_windows.h>
-#endif
#include "squid.h"
-#include "ip/IpAddress.h"
-#ifdef _SQUID_WIN32_
-
-struct arpreq {
-
- IpAddress arp_pa; /* protocol address */
-
- struct sockaddr arp_ha; /* hardware address */
- int arp_flags; /* flags */
-};
-
-#include <Iphlpapi.h>
-#else
-
-#ifdef _SQUID_SOLARIS_
-#include <sys/sockio.h>
-#else
-#include <sys/sysctl.h>
-#endif
-#ifdef _SQUID_LINUX_
-#include <net/if_arp.h>
-#include <sys/ioctl.h>
-#else
-#include <net/if_dl.h>
-#endif
-#include <net/route.h>
-#include <net/if.h>
-#if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) || defined(_SQUID_DRAGONFLY_)
-#include <net/if_arp.h>
-#endif
-#if HAVE_NETINET_IF_ETHER_H
-#include <netinet/if_ether.h>
-#endif
-#endif
+#if USE_SQUID_EUI
#include "acl/Arp.h"
#include "acl/FilledChecklist.h"
+#include "Debug.h"
+#include "eui/Eui48.h"
+#include "ip/Address.h"
+#include "protos.h"
#include "wordlist.h"
-#if !USE_ARP_ACL
-#error USE_ARP_ACL Not defined
-#endif
-static void aclParseArpList(SplayNode<acl_arp_data *> **curlist);
-static int decode_eth(const char *asc, char *eth);
-static int aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c);
-static SplayNode<acl_arp_data *>::SPLAYCMP aclArpCompare;
-static SplayNode<acl_arp_data *>::SPLAYWALKEE aclDumpArpListWalkee;
-
-
+static void aclParseArpList(SplayNode<Eui::Eui48 *> **curlist);
+static int aclMatchArp(SplayNode<Eui::Eui48 *> **dataptr, Ip::Address &c);
+static SplayNode<Eui::Eui48 *>::SPLAYCMP aclArpCompare;
+static SplayNode<Eui::Eui48 *>::SPLAYWALKEE aclDumpArpListWalkee;
ACL *
ACLARP::clone() const
ACLARP::~ACLARP()
{
if (data)
- data->destroy(SplayNode<acl_arp_data*>::DefaultFree);
+ data->destroy(SplayNode<Eui::Eui48*>::DefaultFree);
}
char const *
* Solaris code by R. Gancarz <radekg@solaris.elektrownia-lagisza.com.pl>
*/
-/**
- * Decode an ascii representation (asc) of an ethernet address.
- *
- * \param asc ASCII representation of an ethernet (MAC) address
- * \param eth Binary representation of the ethernet address
- * \retval 0 Conversion to binary failed. Invalid address
- * \retval 1 Conversion completed successfully
- */
-static int
-decode_eth(const char *asc, char *eth)
-{
- 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_eth: Invalid ethernet address '" << asc << "'");
- return 0; /* This is not valid address */
- }
-
- eth[0] = (u_char) a1;
- eth[1] = (u_char) a2;
- eth[2] = (u_char) a3;
- eth[3] = (u_char) a4;
- eth[4] = (u_char) a5;
- eth[5] = (u_char) a6;
- return 1;
-}
-
-acl_arp_data *
+Eui::Eui48 *
aclParseArpData(const char *t)
{
- LOCAL_ARRAY(char, eth, 256);
- acl_arp_data *q = new acl_arp_data;
+ char buf[256];
+ Eui::Eui48 *q = new Eui::Eui48;
debugs(28, 5, "aclParseArpData: " << t);
- if (sscanf(t, "%[0-9a-fA-F:]", eth) != 1) {
- debugs(28, 0, "aclParseArpData: Bad ethernet address: '" << t << "'");
+ if (sscanf(t, "%[0-9a-fA-F:]", buf) != 1) {
+ debugs(28, DBG_CRITICAL, "aclParseArpData: Bad ethernet address: '" << t << "'");
safe_free(q);
return NULL;
}
- if (!decode_eth(eth, q->eth)) {
- debugs(28, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
- debugs(28, 0, "aclParseArpData: Ignoring invalid ARP acl entry: can't parse '" << eth << "'");
+ if (!q->decode(buf)) {
+ debugs(28, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
+ debugs(28, DBG_CRITICAL, "aclParseArpData: Ignoring invalid ARP acl entry: can't parse '" << buf << "'");
safe_free(q);
return NULL;
}
return q;
}
-
/*******************/
/* aclParseArpList */
/*******************/
void
ACLARP::parse()
{
- aclParseArpList (&data);
+ aclParseArpList(&data);
}
void
-aclParseArpList(SplayNode<acl_arp_data *> **curlist)
+aclParseArpList(SplayNode<Eui::Eui48 *> **curlist)
{
char *t = NULL;
- SplayNode<acl_arp_data *> **Top = curlist;
- acl_arp_data *q = NULL;
+ SplayNode<Eui::Eui48*> **Top = curlist;
+ Eui::Eui48 *q = NULL;
while ((t = strtokFile())) {
if ((q = aclParseArpData(t)) == NULL)
/* aclMatchArp */
/***************/
int
-aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IpAddress &c)
+aclMatchArp(SplayNode<Eui::Eui48 *> **dataptr, Ip::Address &c)
{
- struct arpreq arpReq;
- struct sockaddr_in *sa = NULL;
-
- IpAddress ipAddr = c;
-
-#if defined(_SQUID_LINUX_)
-
- unsigned char ifbuffer[sizeof(struct ifreq) * 64];
- struct ifconf ifc;
-
- struct ifreq *ifr;
- int offset;
-
- SplayNode<acl_arp_data*> **Top = dataptr;
- /*
- * The linux kernel 2.2 maintains per interface ARP caches and
- * thus requires an interface name when doing ARP queries.
- *
- * The older 2.0 kernels appear to use a unified ARP cache,
- * and require an empty interface name
- *
- * To support both, we attempt the lookup with a blank interface
- * name first. If that does not succeed, the try each interface
- * in turn
- */
-
- /*
- * Set up structures for ARP lookup with blank interface name
- */
- memset(&arpReq, '\0', sizeof(arpReq));
-
- sa = (sockaddr_in*)&arpReq.arp_pa;
- ipAddr.GetSockAddr(*sa);
- /* Query ARP table */
-
- if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) {
- /* Skip non-ethernet interfaces */
-
- if (arpReq.arp_ha.sa_family != ARPHRD_ETHER) {
- return 0;
- }
-
- debugs(28, 4, "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) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
-
- /* Do lookup */
- acl_arp_data X;
- memcpy (X.eth, arpReq.arp_ha.sa_data, 6);
- *Top = (*Top)->splay(&X, aclArpCompare);
- debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
- return (0 == splayLastResult);
- }
-
- /* lookup list of interface names */
- ifc.ifc_len = sizeof(ifbuffer);
-
- ifc.ifc_buf = (char *)ifbuffer;
-
- if (ioctl(HttpSockets[0], SIOCGIFCONF, &ifc) < 0) {
- debugs(28, 1, "Attempt to retrieve interface list failed: " << xstrerror());
- return 0;
- }
-
- if (ifc.ifc_len > (int)sizeof(ifbuffer)) {
- debugs(28, 1, "Interface list too long - " << ifc.ifc_len);
- return 0;
- }
-
- /* Attempt ARP lookup on each interface */
- offset = 0;
-
- 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))
- continue;
-
- if (NULL != strchr(ifr->ifr_name, ':'))
- continue;
-
- debugs(28, 4, "Looking up ARP address for " << c << " on " << ifr->ifr_name);
-
- /* Set up structures for ARP lookup */
-
- memset(&arpReq, '\0', sizeof(arpReq));
-
- sa = (sockaddr_in*)&arpReq.arp_pa;
- ipAddr.GetSockAddr(*sa);
-
- strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1);
-
- arpReq.arp_dev[sizeof(arpReq.arp_dev) - 1] = '\0';
-
- /* Query ARP table */
- if (-1 == ioctl(HttpSockets[0], 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 failed: " << ifr->ifr_name << ": " << xstrerror());
-
- continue;
- }
-
- /* Skip non-ethernet interfaces */
- if (arpReq.arp_ha.sa_family != ARPHRD_ETHER)
- continue;
-
- debugs(28, 4, "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) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff) << " on "<<
- std::setfill(' ') << ifr->ifr_name);
-
- /* Do lookup */
- acl_arp_data X;
-
- memcpy (X.eth, arpReq.arp_ha.sa_data, 6);
-
- *Top = (*Top)->splay(&X, aclArpCompare);
-
- /* Return if match, otherwise continue to other interfaces */
- if (0 == splayLastResult) {
- debugs(28, 3, "aclMatchArp: " << c << " found on " << ifr->ifr_name);
- return 1;
- }
-
- /*
- * Should we stop looking here? Can the same IP address
- * exist on multiple interfaces?
- */
- }
-
-#elif defined(_SQUID_SOLARIS_)
-
- SplayNode<acl_arp_data *> **Top = dataptr;
-
- /*
- * Set up structures for ARP lookup with blank interface name
- */
-
- memset(&arpReq, '\0', sizeof(arpReq));
-
- sa = (sockaddr_in*)&arpReq.arp_pa;
- ipAddr.GetSockAddr(*sa);
-
- /* Query ARP table */
- if (ioctl(HttpSockets[0], 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
- */
-
- if (arpReq.arp_ha.sa_data[0] == 0 &&
- arpReq.arp_ha.sa_data[1] == 0 &&
- arpReq.arp_ha.sa_data[2] == 0 &&
- arpReq.arp_ha.sa_data[3] == 0 &&
- arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0)
- return 0;
-
- debugs(28, 4, "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) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
-
- /* Do lookup */
- *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare);
+ Eui::Eui48 result;
+ SplayNode<Eui::Eui48 *> **Top = dataptr;
+ if (result.lookup(c)) {
+ /* Do ACL match lookup */
+ *Top = (*Top)->splay(&result, aclArpCompare);
debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
-
return (0 == splayLastResult);
}
-#elif defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) || defined(_SQUID_DRAGONFLY_)
-
- SplayNode<acl_arp_data *> **Top = dataptr;
-
- int mib[6];
-
- size_t needed;
-
- char *lim, *buf, *next;
-
- struct rt_msghdr *rtm;
-
- struct sockaddr_inarp *sin;
-
- struct sockaddr_dl *sdl;
-
- /*
- * Set up structures for ARP lookup with blank interface name
- */
-
- memset(&arpReq, '\0', sizeof(arpReq));
-
- sa = (struct sockaddr_in*) &arpReq.arp_pa;
- ipAddr.GetSockAddr(*sa);
-
- /* Query ARP table */
- mib[0] = CTL_NET;
-
- mib[1] = PF_ROUTE;
-
- mib[2] = 0;
-
- mib[3] = AF_INET;
-
- mib[4] = NET_RT_FLAGS;
-
- mib[5] = RTF_LLINFO;
-
- if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
- debugs(28, 0, "Can't estimate ARP table size!");
- return 0;
- }
-
- if ((buf = (char *)xmalloc(needed)) == NULL) {
- debugs(28, 0, "Can't allocate temporary ARP table!");
- return 0;
- }
-
- if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
- debugs(28, 0, "Can't retrieve ARP table!");
- xfree(buf);
- return 0;
- }
-
- lim = buf + needed;
-
- for (next = buf; next < lim; next += rtm->rtm_msglen) {
-
- rtm = (struct rt_msghdr *) next;
-
- sin = (struct sockaddr_inarp *) (rtm + 1);
- /*sdl = (struct sockaddr_dl *) (sin + 1); */
-
-#define ROUNDUP(a) \
- ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
-
- sdl = (struct sockaddr_dl *)((char *) sin + ROUNDUP(sin->sin_len));
-
- if (c == sin->sin_addr) {
- if (sdl->sdl_alen) {
-
- arpReq.arp_ha.sa_len = sizeof(struct sockaddr);
- arpReq.arp_ha.sa_family = AF_UNSPEC;
- memcpy(arpReq.arp_ha.sa_data, LLADDR(sdl), sdl->sdl_alen);
- }
- }
- }
-
- xfree(buf);
-
- if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
- arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
- arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0)
- return 0;
-
- debugs(28, 4, "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) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
-
- /* Do lookup */
- *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare);
-
- debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
-
- return (0 == splayLastResult);
-
-#elif defined(_SQUID_WIN32_)
-
- DWORD dwNetTable = 0;
-
- DWORD ipNetTableLen = 0;
-
- PMIB_IPNETTABLE NetTable = NULL;
-
- DWORD i;
-
- SplayNode<acl_arp_data *> **Top = dataptr;
-
- 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!");
- return 0;
- }
-
- /* Allocate space for ARP table and assign pointers */
- if ((NetTable = (PMIB_IPNETTABLE)xmalloc(ipNetTableLen)) == NULL) {
- debugs(28, 0, "Can't allocate temporary ARP table!");
- return 0;
- }
-
- /* Get actual ARP table */
- if ((dwNetTable = GetIpNetTable(NetTable, &ipNetTableLen, FALSE)) != NO_ERROR) {
- debugs(28, 0, "Can't retrieve ARP table!");
- xfree(NetTable);
- return 0;
- }
-
- /* Find MAC address from net table */
- 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)) {
- arpReq.arp_ha.sa_family = AF_UNSPEC;
- memcpy(arpReq.arp_ha.sa_data, NetTable->table[i].bPhysAddr, NetTable->table[i].dwPhysAddrLen);
- }
- }
-
- xfree(NetTable);
-
- if (arpReq.arp_ha.sa_data[0] == 0 && arpReq.arp_ha.sa_data[1] == 0 &&
- arpReq.arp_ha.sa_data[2] == 0 && arpReq.arp_ha.sa_data[3] == 0 &&
- arpReq.arp_ha.sa_data[4] == 0 && arpReq.arp_ha.sa_data[5] == 0)
- return 0;
-
- debugs(28, 4, "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) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[3] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[4] & 0xff) << ":" <<
- std::setw(2) << (arpReq.arp_ha.sa_data[5] & 0xff));
-
- /* Do lookup */
- *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare);
-
- debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
-
- return (0 == splayLastResult);
-
-#else
-
-#error "ARP type ACL not supported on this operating system."
-
-#endif
/*
* Address was not found on any interface
*/
debugs(28, 3, "aclMatchArp: " << c << " NOT found");
-
return 0;
}
static int
-aclArpCompare(acl_arp_data * const &a, acl_arp_data * const &b)
+aclArpCompare(Eui::Eui48 * const &a, Eui::Eui48 * const &b)
{
- return memcmp(a->eth, b->eth, 6);
+ return memcmp(a, b, sizeof(Eui::Eui48));
}
static void
-aclDumpArpListWalkee(acl_arp_data * const &node, void *state)
+aclDumpArpListWalkee(Eui::Eui48 * const &node, void *state)
{
- acl_arp_data *arp = node;
- static char buf[24];
- snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
- arp->eth[0] & 0xff, arp->eth[1] & 0xff,
- arp->eth[2] & 0xff, arp->eth[3] & 0xff,
- arp->eth[4] & 0xff, arp->eth[5] & 0xff);
+ static char buf[48];
+ node->encode(buf, 48);
wordlistAdd((wordlist **)state, buf);
}
}
/* ==== END ARP ACL SUPPORT =============================================== */
+
+#endif /* USE_SQUID_EUI */