]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
splay trees for IP acls (Ed Knowles)
authorwessels <>
Sat, 1 Feb 1997 07:28:07 +0000 (07:28 +0000)
committerwessels <>
Sat, 1 Feb 1997 07:28:07 +0000 (07:28 +0000)
src/acl.cc

index 6105243c46ca832367f2b26634987752ac067c7b..3680deedb85819672c4bc70f8ee5c11271c7f76a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: acl.cc,v 1.77 1997/01/23 18:33:40 wessels Exp $
+ * $Id: acl.cc,v 1.78 1997/02/01 00:28:07 wessels Exp $
  *
  * DEBUG: section 28    Access Control
  * AUTHOR: Duane Wessels
@@ -52,6 +52,8 @@ static const char *const w_space = " \t\n\r"; /* Jasper sez so */
 
 static void aclDestroyAclList _PARAMS((struct _acl_list * list));
 static void aclDestroyIpList _PARAMS((struct _acl_ip_data * data));
+static struct _acl_ip_data *aclSplayInsertIp _PARAMS((struct in_addr, struct in_addr, struct in_addr, struct _acl_ip_data *));
+static struct _acl_ip_data *aclSplayIp _PARAMS((struct in_addr, struct _acl_ip_data *));
 static void aclDestroyTimeList _PARAMS((struct _acl_time_data * data));
 static int aclMatchDomainList _PARAMS((wordlist *, const char *));
 static int aclMatchAclList _PARAMS((const struct _acl_list *, aclCheck_t *));
@@ -265,9 +267,6 @@ aclParseIpData(const char *t)
        q->mask.s_addr = 0;
        return q;
     }
-    memset(addr1, 0, 256);
-    memset(addr2, 0, 256);
-    memset(mask, 0, 256);
     if (sscanf(t, "%[0-9.]-%[0-9.]/%[0-9.]", addr1, addr2, mask) == 3) {
        (void) 0;
     } else if (sscanf(t, "%[0-9.]-%[0-9.]", addr1, addr2) == 2) {
@@ -321,15 +320,94 @@ static void
 aclParseIpList(void *curlist)
 {
     char *t = NULL;
-    struct _acl_ip_data **Tail;
+    struct _acl_ip_data **ip_data = curlist;
     struct _acl_ip_data *q = NULL;
-    for (Tail = curlist; *Tail; Tail = &((*Tail)->next));
     while ((t = strtokFile())) {
        if ((q = aclParseIpData(t)) == NULL)
            continue;
-       *(Tail) = q;
-       Tail = &q->next;
+       *ip_data = aclSplayInsertIp(q->addr1, q->addr2, q->mask, *ip_data);
+    }
+
+}
+
+static struct _acl_ip_data *
+aclSplayInsertIp(struct in_addr addr1, struct in_addr addr2, struct in_addr mask, struct _acl_ip_data * t)
+{
+    struct _acl_ip_data *new;
+
+    new = xmalloc(sizeof(struct _acl_ip_data));
+    new->addr1 = addr1;
+    new->addr2 = addr2;
+    new->mask = mask;
+    if (t == NULL) {
+       new->left = new->right = NULL;
+       return new;
+    }
+    t = aclSplayIp(addr1, t);
+    if (addr1.s_addr < t->addr1.s_addr) {
+       new->left = t->left;
+       new->right = t;
+       t->left = NULL;
+       return new;
+    } else if (addr1.s_addr > t->addr1.s_addr) {
+       new->right = t->right;
+       new->left = t;
+       t->right = NULL;
+       return new;
+    } else {
+       debug(28, 0, "aclSplayInsertIp: Address is already in the tree, is this going to be a problem?");
+       safe_free(new);
+       return t;
+    }
+}
+
+static struct _acl_ip_data *
+aclSplayIp(struct in_addr addr1, struct _acl_ip_data * t)
+{
+    struct _acl_ip_data N, *l, *r, *y;
+    if (t == NULL)
+       return t;
+    N.left = N.right = NULL;
+    l = r = &N;
+
+    for (;;) {
+       if (addr1.s_addr < t->addr1.s_addr) {
+           if (t->left == NULL)
+               break;
+           if (addr1.s_addr < t->left->addr1.s_addr) {
+               y = t->left;    /* rotate right */
+               t->left = y->right;
+               y->right = t;
+               t = y;
+               if (t->left == NULL)
+                   break;
+           }
+           r->left = t;        /* link right */
+           r = t;
+           t = t->left;
+       } else if (addr1.s_addr > t->addr1.s_addr) {
+           if (t->right == NULL)
+               break;
+           if (addr1.s_addr > t->right->addr1.s_addr) {
+               y = t->right;   /* rotate left */
+               t->right = y->left;
+               y->left = t;
+               t = y;
+               if (t->right == NULL)
+                   break;
+           }
+           l->right = t;       /* link left */
+           l = t;
+           t = t->right;
+       } else {
+           break;
+       }
     }
+    l->right = t->left;                /* assemble */
+    r->left = t->right;
+    t->left = N.right;
+    t->right = N.left;
+    return t;
 }
 
 static void
@@ -502,7 +580,7 @@ aclParseAclLine(void)
        return;
     }
     if ((A = aclFindByName(aclname)) == NULL) {
-       debug(28, 3, "aclParseAclLine: Creating ACL '%s'\n", aclname);
+       debug(28, 3, "aclParseAclLine: Creating ACL '%s'\n", aclname);
        A = xcalloc(1, sizeof(struct _acl));
        xstrncpy(A->name, aclname, ACL_NAME_SZ);
        A->type = acltype;
@@ -695,31 +773,21 @@ aclParseAccessLine(struct _acl_access **head)
 }
 
 static int
-aclMatchIp(struct _acl_ip_data *data, struct in_addr c)
+aclMatchIp(struct _acl_ip_data * data, struct in_addr c)
 {
     struct in_addr h;
     unsigned long lh, la1, la2;
-    struct _acl_ip_data *first, *prev;
+    struct _acl_ip_data *root;
 
-    first = data;              /* remember first element, this will never be moved */
-    prev = NULL;               /* previous element in the list */
-    while (data) {
-       h.s_addr = c.s_addr & data->mask.s_addr;
-       debug(28, 3, "aclMatchIp: h     = %s\n", inet_ntoa(h));
-       debug(28, 3, "aclMatchIp: addr1 = %s\n", inet_ntoa(data->addr1));
-       debug(28, 3, "aclMatchIp: addr2 = %s\n", inet_ntoa(data->addr2));
+    h.s_addr = c.s_addr & data->mask.s_addr;
+    debug(28, 3, "aclMatchIp: h     = %s\n", inet_ntoa(h));
+    debug(28, 3, "aclMatchIp: addr1 = %s\n", inet_ntoa(data->addr1));
+    debug(28, 3, "aclMatchIp: addr2 = %s\n", inet_ntoa(data->addr2));
+    root = aclSplayIp(h, data);
+    if (h.s_addr == root->addr1.s_addr) {
        if (!data->addr2.s_addr) {
-           if (h.s_addr == data->addr1.s_addr) {
-               debug(28, 3, "aclMatchIp: 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;
-           }
+           debug(28, 3, "aclMatchIp: returning 1\n");
+           return 1;
        } else {
            /* This is a range check */
            lh = ntohl(h.s_addr);
@@ -730,8 +798,6 @@ aclMatchIp(struct _acl_ip_data *data, struct in_addr c)
                return 1;
            }
        }
-       prev = data;
-       data = data->next;
     }
     debug(28, 3, "aclMatchIp: returning 0\n");
     return 0;
@@ -980,13 +1046,13 @@ aclCheck(const struct _acl_access *A, aclCheck_t * checklist)
 }
 
 static void
-aclDestroyIpList(struct _acl_ip_data *data)
+aclDestroyIpList(struct _acl_ip_data * data)
 {
-    struct _acl_ip_data *next = NULL;
-    for (; data; data = next) {
-       next = data->next;
-       safe_free(data);
-    }
+    if (data == NULL)
+       return;
+    aclDestroyIpList(data->left);
+    aclDestroyIpList(data->right);
+    safe_free(data);
 }
 
 static void