]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
move ARP support into acl.c
authorwessels <>
Sat, 6 Dec 1997 04:02:06 +0000 (04:02 +0000)
committerwessels <>
Sat, 6 Dec 1997 04:02:06 +0000 (04:02 +0000)
src/acl.cc
src/protos.h

index 03a8846983a4ebdf46bd31324a98db1fc51eebcc..2595061f9c4e03200c93723b5f8d2108ec5c342c 100644 (file)
@@ -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 <name> arp <Ethernet address> ...
+ * 
+ * For example,
+ * 
+ * acl students arp 00:00:21:55:ed:22 00:00:21:ff:55:38
+ */
+
+#include "squid.h"
+
+#include <sys/sysctl.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <netinet/if_ether.h>
+
+/*
+ * 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(&eth, *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 */
index 73478254242b85da5b9038499edb938fdfdb5001..7e3fff753addba012846ffb7136023cd09ca5a3f 100644 (file)
@@ -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 *);