Revision: 14779
Author: adrian.chadd
Date: Sat Sep  4 05:33:15 2010
Log: Merge r13331 from /playpen/ipv6_acl

* Fix a bug in the splay tree IP acl walk function - print out mask when
  needed, not just addr2 again! tsk adrian.

* Hack together a basic IPv6 address parsing and IP ACL list builder
  function; there's a bit of code copying going on which needs to be
  looked at -and- the code doesn't yet do host lookups for IP ACLs.
  That can all come later.

* Implement src6/myip6 ACL types using the above.

The ACLs load and dump out right in mgr:config; they're just not yet used
anywhere!


http://code.google.com/p/lusca-cache/source/detail?r=14779

Modified:
 /playpen/LUSCA_HEAD_ipv6/src/acl.c
 /playpen/LUSCA_HEAD_ipv6/src/cf.data.pre
 /playpen/LUSCA_HEAD_ipv6/src/enums.h

=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/acl.c  Sat Sep  4 05:24:18 2010
+++ /playpen/LUSCA_HEAD_ipv6/src/acl.c  Sat Sep  4 05:33:15 2010
@@ -42,7 +42,7 @@

 static void aclParseDomainList(void *curlist);
 static void aclParseUserList(void **current);
-static void aclParseIpList(void *curlist);
+static void aclParseIpList(void *curlist, int family);
 static void aclParseIntlist(void *curlist);
 static void aclParseWordList(void *curlist);
 static void aclParseProtoList(void *curlist);
@@ -153,6 +153,10 @@
        return ACL_DST_IP;
     if (!strcmp(s, "myip"))
        return ACL_MY_IP;
+    if (!strcmp(s, "src6"))
+       return ACL_SRC_IP6;
+    if (!strcmp(s, "myip6"))
+       return ACL_MY_IP6;
     if (!strcmp(s, "domain"))
        return ACL_DST_DOMAIN;
     if (!strcmp(s, "dstdomain"))
@@ -259,6 +263,10 @@
        return "dst";
     if (type == ACL_MY_IP)
        return "myip";
+    if (type == ACL_SRC_IP6)
+       return "src6";
+    if (type == ACL_MY_IP6)
+       return "myip6";
     if (type == ACL_DST_DOMAIN)
        return "dstdomain";
     if (type == ACL_SRC_DOMAIN)
@@ -483,14 +491,123 @@
     return 1;
 }

+/*
+ * Decode a v6 address and/or cidr mask assignment
+ *
+ * The passed-in sqaddr_t -must- be init'ed and set to the correct family.
+ */
+static int
+decode_v6_addr(const char *asc, sqaddr_t *A)
+{
+       int a, r;
+
+       /* Is it a CIDR netmask? Store it away */
+       r = sscanf(asc, "%d", &a);
+       if (r > 0) {
+               return sqinet_set_mask_addr(A, a);
+       }
+
+       /* Try to parse an IPv6 address */
+       return sqinet_aton(A, asc, SQATON_NONE);
+}
+
+/* Stolen shamelessly from Squid-3; thanks Amos! */
+
+#define SCAN_ACL1_6 "%[0123456789ABCDEFabcdef:]-%[0123456789ABCDEFabcdef:]/%[0123456789]" +#define SCAN_ACL2_6 "%[0123456789ABCDEFabcdef:]-%[0123456789ABCDEFabcdef:]%c"
+#define SCAN_ACL3_6       "%[0123456789ABCDEFabcdef:]/%[0123456789]"
+#define SCAN_ACL4_6       "%[0123456789ABCDEFabcdef:]/%c"
+
+acl_ip_data *
+aclParseIpData6(const char *t)
+{
+       LOCAL_ARRAY(char, addr1, MAX_IPSTRLEN);
+       LOCAL_ARRAY(char, addr2, MAX_IPSTRLEN);
+       LOCAL_ARRAY(char, mask, MAX_IPSTRLEN);
+       LOCAL_ARRAY(char, buf, MAX_IPSTRLEN);
+
+       acl_ip_data *q;
+       char c;
+
+       q = memPoolAlloc(acl_ip_data_pool);
+       sqinet_init(&q->addr1);
+       sqinet_init(&q->addr2);
+       sqinet_init(&q->mask);
+       sqinet_set_family(&q->addr1, AF_INET6);
+       sqinet_set_family(&q->addr2, AF_INET6);
+       sqinet_set_family(&q->mask, AF_INET6);
+
+       /* "all" matches entire ipv6 internet */
+       if ((strcasecmp(t, "all") == 0) || (strcasecmp(t, "ipv6") == 0)) {
+               sqinet_set_anyaddr(&q->addr1);
+               sqinet_set_anyaddr(&q->addr2);
+               sqinet_set_anyaddr(&q->mask);
+               return q;
+       }
+
+       /* start matching on the available formats */
+       if (sscanf(t, SCAN_ACL1_6, addr1, addr2, mask) == 3) {
+               (void) 0;
+       } else if (sscanf(t, SCAN_ACL2_6, addr1, addr2, &c) >= 2) {
+               mask[0] = '\0';
+       } else if (sscanf(t, SCAN_ACL3_6, addr1, mask) == 2) {
+               addr2[0] = '\0';
+       } else if (sscanf(t, SCAN_ACL4_6, addr1, &c) == 2) {
+               addr2[0] = '\0';
+               mask[0] = '\0';
+       } else {
+               debug(28, 0) ("aclParseIpData6: Entry '%s' can't be parsed!\n", 
t);
+               memPoolFree(acl_ip_data_pool, q);
+               return NULL;
+       }
+
+       /*
+ * XXX - The rest of this is a blatant copy from aclParseIpData(); yes these
+        * XXX - two functions should be merged!
+        */
+    /* Decode addr1 */
+    if (!decode_v6_addr(addr1, &q->addr1)) {
+       debug(28, 0) ("%s line %d: %s\n",
+           cfg_filename, config_lineno, config_input_line);
+ debug(28, 0) ("aclParseIpData6: Ignoring invalid IP acl entry: unknown first address '%s'\n", addr1);
+       safe_free(q);
+       return NULL;
+    }
+    /* Decode addr2 */
+    if (*addr2 && !decode_v6_addr(addr2, &q->addr2)) {
+       debug(28, 0) ("%s line %d: %s\n",
+           cfg_filename, config_lineno, config_input_line);
+ debug(28, 0) ("aclParseIpData6: Ignoring invalid IP acl entry: unknown second address '%s'\n", addr2);
+       safe_free(q);
+       return NULL;
+    }
+    /* Decode mask */
+    if (*mask && !decode_v6_addr(mask, &q->mask)) {
+       debug(28, 0) ("%s line %d: %s\n",
+           cfg_filename, config_lineno, config_input_line);
+ debug(28, 0) ("aclParseIpData6: Ignoring invalid IP acl entry: unknown netmask '%s'\n", mask);
+       safe_free(q);
+       return NULL;
+    }
+    sqinet_ntoa(&q->mask, buf, sizeof(buf), SQADDR_NONE);
+
+ if (sqinet_host_is_netaddr(&q->addr1, &q->mask) || sqinet_host_is_netaddr(&q->addr2, &q->mask)) + debug(28, 0) ("aclParseIpData6: WARNING: Netmask masks away part of the specified IP in '%s'\n", t);
+    /* Store the masked version of the IP address */
+    sqinet_mask_addr(&q->addr1, &q->mask);
+    sqinet_mask_addr(&q->addr2, &q->mask);
+    /* 1.2.3.4/255.255.255.0  --> 1.2.3.0 */
+    return q;
+
+}

 #define SCAN_ACL1       "%[0123456789.]-%[0123456789.]/%[0123456789.]"
 #define SCAN_ACL2       "%[0123456789.]-%[0123456789.]%c"
 #define SCAN_ACL3       "%[0123456789.]/%[0123456789.]"
 #define SCAN_ACL4       "%[0123456789.]%c"

-static acl_ip_data *
-aclParseIpData(const char *t, int af_family)
+acl_ip_data *
+aclParseIpData(const char *t)
 {
     LOCAL_ARRAY(char, addr1, 256);
     LOCAL_ARRAY(char, addr2, 256);
@@ -500,9 +617,9 @@
     sqinet_init(&q->addr1);
     sqinet_init(&q->addr2);
     sqinet_init(&q->mask);
-    sqinet_set_family(&q->addr1, af_family);
-    sqinet_set_family(&q->addr2, af_family);
-    sqinet_set_family(&q->mask, af_family);
+    sqinet_set_family(&q->addr1, AF_INET);
+    sqinet_set_family(&q->addr2, AF_INET);
+    sqinet_set_family(&q->mask, AF_INET);
     acl_ip_data *r;
     acl_ip_data **Q;
     struct hostent *hp;
@@ -601,7 +718,7 @@
 /******************/

 static void
-aclParseIpList(void *curlist)
+aclParseIpList(void *curlist, int family)
 {
     char *t = NULL;
     splayNode **Top = curlist;
@@ -609,7 +726,7 @@
     while ((t = strtokFile())) {
        acl_ip_data *next;
         /* XXX how do we determine whether the AF is INET or INET6? */
-       for (q = aclParseIpData(t, AF_INET); q != NULL; q = next) {
+ for (q = (family == AF_INET ? aclParseIpData(t) : aclParseIpData6(t)); q != NULL; q = next) {
            next = q->next;
            *Top = splay_insert(q, *Top, aclIpNetworkCompare);
            if (splayLastResult == 0)
@@ -1048,7 +1165,11 @@
     case ACL_DST_IP:
     case ACL_MY_IP:
     case ACL_DSTFWD_IP:
-       aclParseIpList(&A->data);
+       aclParseIpList(&A->data, AF_INET);
+       break;
+    case ACL_SRC_IP6:
+    case ACL_MY_IP6:
+       aclParseIpList(&A->data, AF_INET6);
        break;
     case ACL_SRC_DOMAIN:
     case ACL_DST_DOMAIN:
@@ -1903,6 +2024,10 @@
            return 0;
        }
        /* NOTREACHED */
+    case ACL_SRC_IP6:
+       return 0;       /* XXX for now; no v6 address to compare! */
+    case ACL_MY_IP6:
+       return 0;       /* XXX for now; no v6 address to compare! */
     case ACL_DST_DOMAIN:
        if (aclMatchDomainList(&ae->data, r->host))
            return 1;
@@ -2621,6 +2746,8 @@
        case ACL_DST_IP:
        case ACL_MY_IP:
        case ACL_DSTFWD_IP:
+       case ACL_SRC_IP6:
+       case ACL_MY_IP6:
            splay_destroy(a->data, aclFreeIpData);
            break;
 #if USE_ARP_ACL
@@ -2947,7 +3074,7 @@
        memBufPrintf(&mb, "-%s", buf);
     }
     if (! sqinet_is_noaddr(&ip->mask)) {
-        (void) sqinet_ntoa(&ip->addr2, buf, sizeof(buf), SQATON_NONE);
+        (void) sqinet_ntoa(&ip->mask, buf, sizeof(buf), SQATON_NONE);
        memBufPrintf(&mb, "/%s", buf);
     }
     wordlistAdd(W, mb.buf);
@@ -3071,6 +3198,8 @@
     case ACL_DST_IP:
     case ACL_MY_IP:
     case ACL_DSTFWD_IP:
+    case ACL_SRC_IP6:
+    case ACL_MY_IP6:
        return aclDumpIpList(a->data);
     case ACL_SRC_DOMAIN:
     case ACL_DST_DOMAIN:
=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/cf.data.pre    Tue Aug 31 09:02:21 2010
+++ /playpen/LUSCA_HEAD_ipv6/src/cf.data.pre    Sat Sep  4 05:33:15 2010
@@ -688,6 +688,7 @@
 NOCOMMENT_START
 #Recommended minimum configuration:
 acl all src all
+acl all6 src6 ::0/0
 acl manager proto cache_object
 acl localhost src 127.0.0.1/32
 acl to_localhost dst 127.0.0.0/8
=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/enums.h        Sun Jul  4 06:56:53 2010
+++ /playpen/LUSCA_HEAD_ipv6/src/enums.h        Sat Sep  4 05:33:15 2010
@@ -105,6 +105,8 @@
     ACL_SRC_IP,
     ACL_DST_IP,
     ACL_MY_IP,
+    ACL_SRC_IP6,
+    ACL_MY_IP6,
     ACL_SRC_DOMAIN,
     ACL_DST_DOMAIN,
     ACL_SRC_DOM_REGEX,

--
You received this message because you are subscribed to the Google Groups 
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/lusca-commit?hl=en.

Reply via email to