From: wessels <> Date: Sat, 1 Feb 1997 07:28:07 +0000 (+0000) Subject: splay trees for IP acls (Ed Knowles) X-Git-Tag: SQUID_3_0_PRE1~5152 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b1ef122090d745ad0eeaef2ea99941f73ab0ea86;p=thirdparty%2Fsquid.git splay trees for IP acls (Ed Knowles) --- diff --git a/src/acl.cc b/src/acl.cc index 6105243c46..3680deedb8 100644 --- a/src/acl.cc +++ b/src/acl.cc @@ -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