]> mj.ucw.cz Git - libucw.git/commitdiff
ipaccess filters now use CF_USER for (addr,mask) pairs, operations
authorMartin Mares <mj@ucw.cz>
Tue, 25 Apr 2006 22:03:13 +0000 (00:03 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 25 Apr 2006 22:03:13 +0000 (00:03 +0200)
on lists now work fine.

lib/ipaccess.c

index f1637c8554587a4b2b86af046ddfcc366773d873..f9cda623ca45ff2efeaa1ec04a5e99dc60afca9a 100644 (file)
 
 #include <string.h>
 
+struct addrmask {
+  u32 addr;
+  u32 mask;
+};
+
 struct ipaccess_entry {
   cnode n;
   int allow;
-  u32 addr, mask;
+  struct addrmask addr;
 };
 
-static byte *
-ipaccess_cf_ip(uns n UNUSED, byte **pars, struct ipaccess_entry *a)
+static byte *addrmask_parser(byte *c, void *ptr)
 {
-  byte *c = pars[0];
-  CF_JOURNAL_VAR(a->addr);
-  CF_JOURNAL_VAR(a->mask);
+  /*
+   * This is tricky: addrmasks will be compared by memcmp(), so we must ensure
+   * that even the padding between structure members is zeroed out.
+   */
+  struct addrmask *am = ptr;
+  bzero(am, sizeof(*am));
 
   byte *p = strchr(c, '/');
   if (p)
     *p++ = 0;
-  byte *err = cf_parse_ip(c, &a->addr);
+  byte *err = cf_parse_ip(c, &am->addr);
   if (err)
     return err;
   if (p)
     {
       uns len;
       if (!cf_parse_int(p, &len) && len <= 32)
-       a->mask = ~(len == 32 ? 0 : ~0U >> len);
-      else if (cf_parse_ip(p, &a->mask))
+       am->mask = ~(len == 32 ? 0 : ~0U >> len);
+      else if (cf_parse_ip(p, &am->mask))
        return "Invalid prefix length or netmask";
     }
   else
-    a->mask = ~0U;
+    am->mask = ~0U;
   return NULL;
 }
 
+static struct cf_user_type addrmask_type = {
+  .size = sizeof(struct addrmask),
+  .parser = addrmask_parser
+};
+
 struct cf_section ipaccess_cf = {
   CF_TYPE(struct ipaccess_entry),
   CF_ITEMS {
     CF_LOOKUP("Mode", PTR_TO(struct ipaccess_entry, allow), ((char*[]) { "deny", "allow" })),
-    CF_PARSER("IP", NULL, ipaccess_cf_ip, 1),
+    CF_USER("IP", PTR_TO(struct ipaccess_entry, addr), &addrmask_type),
     CF_END
   }
 };
@@ -59,7 +71,7 @@ int
 ipaccess_check(clist *l, u32 ip)
 {
   CLIST_FOR_EACH(struct ipaccess_entry *, a, *l)
-    if (! ((ip ^ a->addr) & a->mask))
+    if (! ((ip ^ a->addr.addr) & a->addr.mask))
       return a->allow;
   return 0;
 }