From: wessels <> Date: Sat, 6 Dec 1997 04:02:06 +0000 (+0000) Subject: move ARP support into acl.c X-Git-Tag: SQUID_3_0_PRE1~4386 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=23351cb24c1f3928558815e7ecd8001255601b39;p=thirdparty%2Fsquid.git move ARP support into acl.c --- diff --git a/src/acl.cc b/src/acl.cc index 03a8846983..2595061f9c 100644 --- a/src/acl.cc +++ b/src/acl.cc @@ -1,6 +1,6 @@ /* - * $Id: acl.cc,v 1.121 1997/12/05 19:30:03 wessels Exp $ + * $Id: acl.cc,v 1.122 1997/12/05 21:02:06 wessels Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -59,10 +59,19 @@ static FQDNH aclLookupSrcFQDNDone; static FQDNH aclLookupDstFQDNDone; static int aclReadProxyAuth(struct _acl_proxy_auth *p); +#if USE_ARP_ACL +static int checkARP(u_long ip, char *eth); +static int decode_eth(const char *asc, char *eth); +static int aclMatchArp(void *dataptr, struct in_addr c); +#endif + #if defined(USE_SPLAY_TREE) static int aclIpNetworkCompare(const void *, splayNode *); static int aclHostDomainCompare(const void *, splayNode *); static int aclDomainCompare(const void *, splayNode *); +#if USE_ARP_ACL +static int aclArpNetworkCompare(const void *, splayNode *); +#endif #elif defined(USE_BIN_TREE) static int bintreeDomainCompare(void *, void *); @@ -71,6 +80,9 @@ static int bintreeNetworkCompare(void *, void *); static int bintreeIpNetworkCompare(void *, void *); static int aclDomainCompare(const char *d1, const char *d2); static void aclDestroyTree(tree **); +#if USE_ARP_ACL +static int bintreeArpNetworkCompare(void *, void *); +#endif #else /* LINKED LIST */ static void aclDestroyIpList(struct _acl_ip_data *data); @@ -80,9 +92,15 @@ static void aclDestroyIpList(struct _acl_ip_data *data); #if defined(USE_BIN_TREE) static void aclParseDomainList(void **curtree); static void aclParseIpList(void **curtree); +#if USE_ARP_ACL +static void aclParseArpList(void **curtree); +#endif #else static void aclParseDomainList(void *curlist); static void aclParseIpList(void *curlist); +#if USE_ARP_ACL +static void aclParseArpList(void *curlist); +#endif #endif static void aclParseIntlist(void *curlist); @@ -1914,3 +1932,240 @@ bintreeIpNetworkCompare(void *t1, void *t2) } #endif /* USE_BIN_TREE */ + + + + +#if USE_ARP_ACL +/* ==== BEGIN ARP ACL SUPPORT ============================================= */ + +/* + * 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 + */ + +#include "squid.h" + +#include +#include +#include +#include +#include + +/* + * Decode an ascii representation (asc) of an ethernet adress, and place + * it in eth[6]. + */ +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) { + debug(28, 0)("decode_eth: Invalid ethernet address '%s'\n", 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; +} + +static struct _acl_arp_data * +aclParseArpData(const char *t) +{ + LOCAL_ARRAY(char, eth, 256); /* addr1 ---> eth */ + struct _acl_arp_data *q = xcalloc(1, sizeof(struct _acl_arp_data)); + debug(28, 5)( "aclParseArpData: %s\n", t); + if (sscanf(t, "%[0-9a-f:]", eth) != 1) { + debug(28, 0)( "aclParseArpData: Bad ethernet address: '%s'\n", t); + safe_free(q); + return NULL; + } + if (!decode_eth(eth, q->eth)) { + debug(28, 0)( "%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0)( "aclParseArpData: Ignoring invalid ARP acl entry: can't parse '%s'\n", q); + safe_free(q); + return NULL; + } + return q; +} + + +/*******************/ +/* aclParseArpList */ +/*******************/ +#if defined(USE_SPLAY_TREE) +static void +aclParseArpList(void *curlist) +{ + char *t = NULL; + splayNode **Top = curlist; + struct _acl_arp_data *q = NULL; + while ((t = strtokFile())) { + if ((q = aclParseArpData(t)) == NULL) + continue; + *Top = splay_insert(q, *Top, aclArpNetworkCompare); + } +} +#elif defined(USE_BIN_TREE) +static void +aclParseArpList(void **curtree) +{ + tree **Tree; + char *t = NULL; + struct _acl_arp_data *q; + Tree = xmalloc(sizeof(tree *)); + *curtree = Tree; + tree_init(Tree); + while ((t = strtokFile())) { + if ((q = aclParseArpData(t)) == NULL) + continue; + tree_add(Tree, bintreeNetworkCompare, q, NULL); + } +} +#else +static void +aclParseArpList(void *curlist) +{ + char *t = NULL; + struct _acl_arp_data **Tail; + struct _acl_arp_data *q = NULL; + for (Tail = curlist; *Tail; Tail = &((*Tail)->next)); + while ((t = strtokFile())) { + if ((q = aclParseArpData(t)) == NULL) + continue; + *(Tail) = q; + Tail = &q->next; + } +} +#endif /* USE_SPLAY_TREE */ + + +/***************/ +/* aclMatchArp */ +/***************/ +#if defined(USE_SPLAY_TREE) +static int +aclMatchArp(void *dataptr, struct in_addr c) +{ + splayNode **Top = dataptr; + *Top = splay_splay(ð, *Top, aclArpNetworkCompare); + debug(28, 3)( "aclMatchArp: '%s' %s\n", + inet_ntoa(c), splayLastResult ? "NOT found" : "found"); + return !splayLastResult; +} +#elif defined(USE_BIN_TREE) +static int +aclMatchArp(void *dataptr, struct in_addr c) +{ + tree **data = dataptr; + if (tree_srch(data, bintreeArpNetworkCompare, &c)) { + debug(28, 3)( "aclMatchArp: '%s' found\n", inet_ntoa(c)); + return 1; + } + debug(28, 3)( "aclMatchArp: '%s' NOT found\n", inet_ntoa(c)); + return 0; +} +#else +static int +aclMatchArp(void *dataptr, struct in_addr c) +{ + struct _acl_arp_data **D = dataptr; + struct _acl_arp_data *data = *D; + struct _acl_arp_data *first, *prev; + first = data; /* remember first element, will never be moved */ + prev = NULL; /* previous element in the list */ + while (data) { + debug(28, 3)( "aclMatchArp: ip = %s\n", inet_ntoa(c)); + debug(28, 3)( "aclMatchArp: arp = %x:%x:%x:%x:%x:%x\n", + data->eth[0], data->eth[1], data->eth[2], data->eth[3], + data->eth[4], data->eth[5]); + if (checkARP(c.s_addr, data->eth)) { + debug(28, 3)( "aclMatchArp: returning 1\n"); + if (prev != NULL) { + /* shift the element just found to the second position + * in the list */ + prev->next = data->next; + data->next = first->next; + first->next = data; + } + return 1; + } + prev = data; + data = data->next; + } + debug(28, 3)( "aclMatchArp: returning 0\n"); + return 0; +} +#endif /* USE_SPLAY_TREE */ + +#if USE_BIN_TREE +static int +bintreeArpNetworkCompare(void *t1, void *t2) +{ + struct in_addr addr; + struct _acl_arp_data *data; + xmemcpy(&addr, t1, sizeof(addr)); + data = (struct _acl_arp_data *) t2; + return aclArpNetworkCompare(addr, data); +} +#endif + +static int +checkARP(u_long ip, char *eth) +{ + int mib[6] = + {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO}; + size_t needed; + char *buf, *next, *lim; + struct rt_msghdr *rtm; + struct sockaddr_inarp *sin; + struct sockaddr_dl *sdl; + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { + debug(28, 0)( "Can't estimate ARP table size!"); + return 0; + } + if ((buf = malloc(needed)) == NULL) { + debug(28, 0)( "Can't allocate temporary ARP table!"); + return 0; + } + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + debug(28, 0)( "Can't retrieve ARP table!"); + 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); + if (sin->sin_addr.s_addr == ip) { + if (sdl->sdl_alen) + if (!memcmp(LLADDR(sdl), eth, 6)) + return 1; + return 0; + } + } + return 0; +} + +/* ==== END ARP ACL SUPPORT =============================================== */ +#endif /* USE_ARP_ACL */ diff --git a/src/protos.h b/src/protos.h index 7347825424..7e3fff753a 100644 --- a/src/protos.h +++ b/src/protos.h @@ -28,20 +28,6 @@ extern void aclDestroyRegexList(struct _relist *data); extern int aclMatchRegex(relist * data, const char *word); extern void aclParseRegexList(void *curlist); -#if USE_ARP_ACL -extern int checkARP(u_long ip, char *eth); -extern int decode_eth(const char *asc, char *eth); -extern int aclMatchArp(void *dataptr, struct in_addr c); -#if USE_SPLAY_TREE -extern int aclArpNetworkCompare(const void *, splayNode *); -extern void aclParseArpList(void *curlist); -#elif USE_BIN_TREE -extern int bintreeArpNetworkCompare(void *, void *); -extern void aclParseArpList(void **curtree); -#endif -extern void aclParseArpList(void *curlist); -#endif - extern int aio_cancel(aio_result_t *); extern int aio_open(const char *, int, mode_t, aio_result_t *); extern int aio_read(int, char *, int, off_t, int, aio_result_t *);