--------------------- PatchSet 7446 Date: 2008/03/04 10:15:53 Author: amosjeffries Branch: ayjwork Tag: (none) Log: WORK in Progress: * Experimental work adding ACLEth - for EUI-48 / EUI-64 validation alongside ARP Members: NOTES:1.1.4.2->1.1.4.3 configure.in:1.130.2.11->1.130.2.12 src/ACLARP.cc:1.18.4.5->1.18.4.6 src/ACLEth.cc:1.1->1.1.2.1 src/ACLEth.h:1.1->1.1.2.1 src/ACLEth_ARP.cc:1.1->1.1.2.1 src/Makefile.am:1.116.2.14->1.116.2.15 Index: squid3/NOTES =================================================================== RCS file: /cvsroot/squid-sf//squid3/Attic/NOTES,v retrieving revision 1.1.4.2 retrieving revision 1.1.4.3 diff -u -r1.1.4.2 -r1.1.4.3 --- squid3/NOTES 4 Mar 2008 10:12:26 -0000 1.1.4.2 +++ squid3/NOTES 4 Mar 2008 10:15:53 -0000 1.1.4.3 @@ -6,3 +6,6 @@ * Adding EUI-48/64 to IPAddress API. - using it to add ACLEther for MAC-based IPv6 tests. + + * Experimental work adding ACLEth + - for EUI-48 / EUI-64 validation alongside ARP Index: squid3/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid3/configure.in,v retrieving revision 1.130.2.11 retrieving revision 1.130.2.12 diff -u -r1.130.2.11 -r1.130.2.12 --- squid3/configure.in 22 Jan 2008 22:34:06 -0000 1.130.2.11 +++ squid3/configure.in 4 Mar 2008 10:15:53 -0000 1.130.2.12 @@ -1,7 +1,7 @@ dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.130.2.11 2008/01/22 22:34:06 amosjeffries Exp $ +dnl $Id: configure.in,v 1.130.2.12 2008/03/04 10:15:53 amosjeffries Exp $ dnl dnl dnl @@ -11,7 +11,7 @@ AC_CONFIG_AUX_DIR(cfgaux) AC_CONFIG_SRCDIR([src/main.cc]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_REVISION($Revision: 1.130.2.11 $)dnl +AC_REVISION($Revision: 1.130.2.12 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -808,11 +808,11 @@ esac ]) -AM_CONDITIONAL(ENABLE_ARP_ACL, false) -AC_ARG_ENABLE(arp-acl, -[ --enable-arp-acl Enable use of ARP ACL lists (ether address)], +AM_CONDITIONAL(ENABLE_ETHERNET_ACL, false) +AC_ARG_ENABLE(eth-acl, +[ --enable-eth-acl Enable use of Ethernet Address ACL lists (ARP, EUI-48, EUI-64)], [ if test "$enableval" = "yes" ; then - echo "ARP ACL lists enabled (ether address)" + echo "Ethernet ACL lists enabled (ARP, EUI-48, EUI-64)" case "$host" in *-linux-*) ;; @@ -831,12 +831,12 @@ LIBS="$LIBS -liphlpapi" ;; *) - echo "WARNING: ARP ACL support probably won't work on $host." + echo "WARNING: Ethernet ACL support probably won't work on $host for IPv4 Traffic." sleep 10 ;; esac - AC_DEFINE(USE_ARP_ACL,1,[Define this to include code which lets you specify access control elements based on ethernet hardware addresses. This code uses functions found in 4.4 BSD derviations (e.g. FreeBSD, ?).]) - AM_CONDITIONAL(ENABLE_ARP_ACL, true) + AC_DEFINE(USE_ETHERNET_ACL,1,[Define this to include code which lets you specify access control elements based on ethernet hardware addresses.]) + AM_CONDITIONAL(ENABLE_ETHERNET_ACL, true) fi ]) @@ -1927,7 +1927,9 @@ math.h \ memory.h \ mount.h \ + net/ethernet.h \ net/if.h \ + net/if_arp.h \ net/pfvar.h \ netdb.h \ netinet/in.h \ Index: squid3/src/ACLARP.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ACLARP.cc,v retrieving revision 1.18.4.5 retrieving revision 1.18.4.6 diff -u -r1.18.4.5 -r1.18.4.6 --- squid3/src/ACLARP.cc 5 Feb 2008 13:01:05 -0000 1.18.4.5 +++ squid3/src/ACLARP.cc 4 Mar 2008 10:15:53 -0000 1.18.4.6 @@ -1,6 +1,6 @@ /* - * $Id: ACLARP.cc,v 1.18.4.5 2008/02/05 13:01:05 amosjeffries Exp $ + * $Id: ACLARP.cc,v 1.18.4.6 2008/03/04 10:15:53 amosjeffries Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -80,8 +80,8 @@ #include "ACLARP.h" #include "wordlist.h" -#if !USE_ARP_ACL -#error USE_ARP_ACL Not defined +#if !USE_ETHERNET_ACL +#error USE_ETHERNET_ACL Not defined #endif static void aclParseArpList(SplayNode **curlist); static int decode_eth(const char *asc, char *eth); --- /dev/null Sun Mar 23 01:25:13 2008 +++ squid3/src/ACLEth.cc Sun Mar 23 01:25:13 2008 @@ -0,0 +1,235 @@ +/* + * $Id: ACLEth.cc,v 1.1.2.1 2008/03/04 10:15:53 amosjeffries Exp $ + * + * DEBUG: section 28 Access Control + * AUTHOR: Amos Jeffries + * + * 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. + * + */ + +#include "config.h" + +#if !USE_ETHERNET_ACL +#error USE_ETHERNET_ACL Not defined +#endif + +#include "ACLEth.h" + + +#ifdef _SQUID_CYGWIN_ +#include +#endif +#include "squid.h" +#include "IPAddress.h" +#include "wordlist.h" + +static void aclParseArpList(SplayNode **curlist); +static int decode_eth(const char *asc, char *eth); +static int aclMatchEth(SplayNode **dataptr, IPAddress &c); +static SplayNode::SPLAYCMP aclEthCompare; + +ACL::Prototype ACLEth::RegistryPrototype(&ACLEth::RegistryEntry_, "eth"); + +ACLEth ACLEth::RegistryEntry_("eth"); + +ACL * +ACLEth::clone() const +{ + return new ACLEth(*this); +} + +ACLEth::ACLEth (char const *theClass) : data (NULL), class_ (theClass) +{} + +ACLEth::ACLEth (ACLEth const & old) : data (NULL), class_ (old.class_) +{ + /* we don't have copy constructors for the data yet */ + assert (!old.data); +} + +ACLEth::~ACLEth() +{ + if (data) + data->destroy(SplayNode::DefaultFree); +} + +char const * +ACLEth::typeString() const +{ + return class_; +} + +bool +ACLEth::empty () const +{ + return data->empty(); +} + +/** + * Decode an ascii representation (asc) of an ethernet address. + * + \param asc[in] ASCII representation of an ethernet (MAC) address + \param eth[out] 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_eth_data * +aclParseEthData(const char *t) +{ + LOCAL_ARRAY(char, eth, 256); + acl_eth_data *q = new acl_eth_data; + debugs(28, 5, "aclParseArpData: " << t); + +// TODO improve this to detech only actual MAC address format +// also accept IPv6 format, but handle that seperately. + +/* decode_eth hould be able to do that properly. :-P + if (sscanf(t, "%[0-9a-fA-F:]", eth) != 1) { + debugs(28, 0, "aclParseArpData: Bad ethernet address: '" << t << "'"); + safe_free(q); + return NULL; + } +*/ + + if (!decode_eth(eth, q->eth.e_addr8)) { + debugs(28, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line); + debugs(28, 0, "aclParseArpData: Ignoring invalid Ethernet acl entry: can't parse '" << eth << "'"); + safe_free(q); + return NULL; + } + + return q; +} + + +/*******************/ +/* aclParseEthList */ +/*******************/ +void +ACLEth::parse() +{ + aclParseEthList(&data); +} + +void +aclParseEthList(SplayNode **curlist) +{ + char *t = NULL; + SplayNode **Top = curlist; + acl_eth_data *q = NULL; + + while ((t = strtokFile())) { + if ((q = aclParseEthData(t)) == NULL) + continue; + + *Top = (*Top)->insert(q, ACLEthCompare); + } +} + +/** + * Match the checklist Source ethernet (MAC) address against the ACL + * Looks up ARP (IPv4) or EUI-64 (IPv6) as needed to perform the match. + * + \param checklist Connection details for ACL to check. Only src_addr field is used here. + \retval 1 Match found. + \retval 0 Match not found. + \retval 0 Match not possible on this Source address + * May occur if the IPv6 contains no EUI-64 data or Source is beyond ARP range. + */ +int +ACLEth::match(ACLChecklist *checklist) +{ + int result = 0; + + /* IPv6 does not do ARP */ + if(checklist->src_addr.IsIPv4()) { + result = aclMatchEthArp(&data, checklist->src_addr); + } + /* IPv4 does not do EUI-64 */ + else if(checklist->src_addr.IsIPv6()) { + result = aclMatchEthEui(SplayNode **dataptr, IPAddress &c) + } + else { + debugs(14, 3, "ACLEth::match: IPv4 Required for ARP Lookups. Skipping " << checklist->src_addr ); + return 0; + } + + return result; +} + +static int +ACLEthCompare(acl_eth_data * const &a, acl_eth_data * const &b) +{ + return memcmp(a->e_addr, b->e_addr, sizeof(eth_acl_data) ); +} + +/** \ingroup ACLEthAPI + * Function passed by address to splay library for walking the splay tree + * and displaying its content. + */ +static void +aclDumpEthListWalkee(acl_eth_data * const &node, void *state) +{ + acl_eth_data *p = node; + static char buf[24]; + snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", + p->e_addr8[0] & 0xff, p->e_addr8[1] & 0xff, + p->e_addr8[2] & 0xff, p->e_addr8[3] & 0xff, + p->e_addr8[4] & 0xff, p->e_addr8[5] & 0xff); + wordlistAdd((wordlist **)state, buf); +} + +/** + * Kick off a walk of the ACL splay tree producing + */ +wordlist * +ACLEth::dump() const +{ + wordlist *w = NULL; + data->walk(aclDumpEthListWalkee, &w); + return w; +} --- /dev/null Sun Mar 23 01:25:13 2008 +++ squid3/src/ACLEth.h Sun Mar 23 01:25:13 2008 @@ -0,0 +1,77 @@ +/* + * $Id: ACLEth.h,v 1.1.2.1 2008/03/04 10:15:53 amosjeffries Exp $ + * + * AUTHOR: Amos Jeffries + * + * 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. + * + */ +#ifndef SQUID_ACLETH_H +#define SQUID_ACLETH_H + +#include "ACL.h" +#include "splay.h" + +struct acl_eth_data +{ + union { + uint8_t e_addr8[6]; + uint16_t e_addr16[3]; + uint32_t e_addr32[2]; + }; +}; + +class ACLChecklist; + +class ACLEth : public ACL +{ + +public: + MEMPROXY_CLASS(ACLEth); + + ACLEth(char const *); + ACLEth(ACLEth const &); + ~ACLEth(); + ACLEth & operator =(ACLEth const &); + + virtual ACL *clone() const; + virtual char const *typeString() const; + virtual void parse(); + virtual int match(ACLChecklist *checklist); + virtual wordlist *dump() const; + virtual bool empty() const; + +protected: + static Prototype RegistryPrototype; + static ACLEth RegistryEntry_; + SplayNode *data; + char const *class_; +}; + +MEMPROXY_CLASS_INLINE(ACLEth); + +#endif /* SQUID_ACLETH_H */ --- /dev/null Sun Mar 23 01:25:13 2008 +++ squid3/src/ACLEth_ARP.cc Sun Mar 23 01:25:13 2008 @@ -0,0 +1,477 @@ +/* + * $Id: ACLEth_ARP.cc,v 1.1.2.1 2008/03/04 10:15:53 amosjeffries Exp $ + * + * DEBUG: section 28 Access Control + * AUTHOR: Duane Wessels + * + * 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 + */ + +#include "config.h" + +#include "ACLEth.h" + +#include "squid.h" +#include "IPAddress.h" + +#ifdef _SQUID_CYGWIN_ +#include +#endif + +#ifdef _SQUID_WIN32_ +struct arpreq +{ + IPAddress arp_pa; /**< protocol address */ + struct sockaddr arp_ha; /**< hardware address */ + int arp_flags; /**< flags */ +}; +#include +#else +#include +#include +#endif + +#ifdef _SQUID_SOLARIS_ +#include +#else +#include +#endif + +#ifdef _SQUID_LINUX_ +//#include +#include +#else +#include +#endif + +// #if defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) +#if HAVE_NET_IF_ARP_H +#include +#endif + +#include "wordlist.h" + +/* + * From: dale@server.ctam.bitmcnit.bryansk.su (Dale) + * To: wessels@nlanr.net + * Subject: Another Squid patch... :) + * Date: Thu, 04 Dec 1997 19:55:01 +0300 + * ============================================================================ + * + * 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 + * sources and added a new acl type for hard-wired access control: + * + * acl arp ... + * + * For example, + * + * acl students arp 00:00:21:55:ed:22 00:00:21:ff:55:38 + * + * NOTE: Linux code by David Luyer . + * Original (BSD-specific) code no longer works. + * Solaris code by R. Gancarz + */ + +static int aclMatchArp(SplayNode **dataptr, IPAddress &c); + +int +aclMatchArp(SplayNode **dataptr, IPAddress &c) +{ + struct arpreq arpReq; + + IPAddress ipAddr = c; + +#if defined(_SQUID_LINUX_) + + unsigned char ifbuffer[sizeof(struct ifreq) * 64]; + struct ifconf ifc; + struct sockaddr_in *sa = NULL; + + struct ifreq *ifr; + int offset; + + SplayNode **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 */ + ether_addr 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 **Top = dataptr; + + /* + * Set up structures for ARP lookup with blank interface name + */ + + memset(&arpReq, '\0', sizeof(arpReq)); + + ipAddr.GetSockAddr(arpReq.arp_pa); + + /* 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); + + debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found")); + + return (0 == splayLastResult); + } + +#elif defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) + + SplayNode **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)); + + ipAddr.GetSockAddr(arpReq.arp_pa); + + /* 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 **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; +} Index: squid3/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v retrieving revision 1.116.2.14 retrieving revision 1.116.2.15 diff -u -r1.116.2.14 -r1.116.2.15 --- squid3/src/Makefile.am 11 Feb 2008 23:19:15 -0000 1.116.2.14 +++ squid3/src/Makefile.am 4 Mar 2008 10:15:54 -0000 1.116.2.15 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.116.2.14 2008/02/11 23:19:15 amosjeffries Exp $ +# $Id: Makefile.am,v 1.116.2.15 2008/03/04 10:15:54 amosjeffries Exp $ # # Uncomment and customize the following to suit your needs: # @@ -192,11 +192,11 @@ IDENT_SOURCE = endif -ARP_ACL_ALL_SOURCE = ACLARP.cc ACLARP.h -if ENABLE_ARP_ACL -ARP_ACL_SOURCE = $(ARP_ACL_ALL_SOURCE) +ETH_ACL_ALL_SOURCE = ACLARP.cc ACLARP.h ACLEth.h ACLEth.cc ACLEth_ARP.cc ACLEth_EUI64.cc +if ENABLE_ETHERNET_ACL +ETH_ACL_SOURCE = $(ETH_ACL_ALL_SOURCE) else -ARP_ACL_SOURCE = +ETH_ACL_SOURCE = endif AM_CFLAGS = @SQUID_CFLAGS@ @@ -282,7 +282,7 @@ $(all_DISKIOMODULES) \ $(AIO_WIN32_ALL_SOURCES) \ $(all_AUTHMODULES) \ - $(ARP_ACL_ALL_SOURCE) \ + $(ETH_ACL_ALL_SOURCE) \ ConfigOption.h \ $(DELAY_POOL_ALL_SOURCE) \ dns.cc \ @@ -305,7 +305,7 @@ DiskIO/DiskThreads/aiops_win32.cc squid_ACLSOURCES = \ - $(ARP_ACL_SOURCE) \ + $(ETH_ACL_SOURCE) \ ACLASN.cc \ ACLASN.h \ ACLDestinationASN.h \