X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fipaccess.c;h=5dd388ccd36ee0a5a68c71c47656650458629d13;hb=1a3cd3005f2a5cda8dbdaaf8f153ae5703845876;hp=2116f71d9b6193815a947c6653b1a8440601e437;hpb=b1fbf9e3292eab73fa448dd6c937e70eb66dc4a7;p=libucw.git diff --git a/lib/ipaccess.c b/lib/ipaccess.c index 2116f71d..5dd388cc 100644 --- a/lib/ipaccess.c +++ b/lib/ipaccess.c @@ -1,7 +1,7 @@ /* * UCW Library -- IP address access lists * - * (c) 1997--2006 Martin Mares + * (c) 1997--2007 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -9,72 +9,81 @@ #include "lib/lib.h" #include "lib/clists.h" -#include "lib/conf2.h" +#include "lib/conf.h" +#include "lib/getopt.h" +#include "lib/fastbuf.h" #include "lib/ipaccess.h" -#undef ipaccess_check /* FIXME */ - #include struct ipaccess_entry { cnode n; - uns allow; - u32 addr, mask; + int allow; + struct ip_addrmask addr; }; -static byte * -ipaccess_cf_ip(uns n UNUSED, byte **pars, struct ipaccess_entry *a) +static char * +addrmask_parser(char *c, void *ptr) { - byte *c = pars[0]; - CF_JOURNAL_VAR(a->addr); - CF_JOURNAL_VAR(a->mask); - - byte *p = strchr(c, '/'); + /* + * This is tricky: addrmasks will be compared by memcmp(), so we must ensure + * that even the padding between structure members is zeroed out. + */ + struct ip_addrmask *am = ptr; + bzero(am, sizeof(*am)); + + char *p = strchr(c, '/'); if (p) *p++ = 0; - byte *err = cf_parse_ip(c, &a->addr); + char *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 byte * -ipaccess_cf_mode(uns n UNUSED, byte **pars, struct ipaccess_entry *a) +static void +addrmask_dumper(struct fastbuf *fb, void *ptr) { - CF_JOURNAL_VAR(a->allow); - if (!strcasecmp(pars[0], "allow")) - a->allow = 1; - else if (!strcasecmp(pars[0], "deny")) - a->allow = 0; - else - return "Either `allow' or `deny' expected"; - return NULL; + struct ip_addrmask *am = ptr; + bprintf(fb, "%08x/%08x ", am->addr, am->mask); } +struct cf_user_type ip_addrmask_type = { + .size = sizeof(struct ip_addrmask), + .name = "ip_addrmask", + .parser = addrmask_parser, + .dumper = addrmask_dumper +}; + struct cf_section ipaccess_cf = { CF_TYPE(struct ipaccess_entry), CF_ITEMS { - CF_PARSER("Mode", NULL, ipaccess_cf_mode, 1), - CF_PARSER("IP", NULL, ipaccess_cf_ip, 1), + CF_LOOKUP("Mode", PTR_TO(struct ipaccess_entry, allow), ((char*[]) { "deny", "allow", NULL })), + CF_USER("IP", PTR_TO(struct ipaccess_entry, addr), &ip_addrmask_type), CF_END } }; +int ip_addrmask_match(struct ip_addrmask *am, u32 ip) +{ + return !((ip ^ am->addr) & am->mask); +} + int ipaccess_check(clist *l, u32 ip) { CLIST_FOR_EACH(struct ipaccess_entry *, a, *l) - if (! ((ip ^ a->addr) & a->mask)) + if (ip_addrmask_match(&a->addr, ip)) return a->allow; return 0; } @@ -95,13 +104,13 @@ static struct cf_section test_cf = { int main(int argc, char **argv) { cf_declare_section("T", &test_cf, 0); - if (cf_get_opt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) != -1) + if (cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) != -1) die("Invalid arguments"); byte buf[256]; while (fgets(buf, sizeof(buf), stdin)) { - byte *c = strchr(buf, '\n'); + char *c = strchr(buf, '\n'); if (c) *c = 0; u32 ip;