]> mj.ucw.cz Git - libucw.git/blob - ucw/ipaccess.c
tableprinter: code cleanup
[libucw.git] / ucw / ipaccess.c
1 /*
2  *      UCW Library -- IP address access lists
3  *
4  *      (c) 1997--2007 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/clists.h>
12 #include <ucw/conf.h>
13 #include <ucw/getopt.h>
14 #include <ucw/fastbuf.h>
15 #include <ucw/ipaccess.h>
16
17 #include <string.h>
18
19 struct ipaccess_entry {
20   cnode n;
21   int allow;
22   struct ip_addrmask addr;
23 };
24
25 static char *
26 addrmask_parser(char *c, void *ptr)
27 {
28   /*
29    * This is tricky: addrmasks will be compared by memcmp(), so we must ensure
30    * that even the padding between structure members is zeroed out.
31    */
32   struct ip_addrmask *am = ptr;
33   bzero(am, sizeof(*am));
34
35   char *p = strchr(c, '/');
36   if (p)
37     *p++ = 0;
38   char *err = cf_parse_ip(c, &am->addr);
39   if (err)
40     return err;
41   if (p)
42     {
43       uint len;
44       if (!cf_parse_int(p, &len) && len <= 32)
45         am->mask = ~(len == 32 ? 0 : ~0U >> len);
46       else if (cf_parse_ip(p, &am->mask))
47         return "Invalid prefix length or netmask";
48     }
49   else
50     am->mask = ~0U;
51   return NULL;
52 }
53
54 static void
55 addrmask_dumper(struct fastbuf *fb, void *ptr)
56 {
57   struct ip_addrmask *am = ptr;
58   bprintf(fb, "%08x/%08x ", am->addr, am->mask);
59 }
60
61 struct cf_user_type ip_addrmask_type = {
62   .size = sizeof(struct ip_addrmask),
63   .name = "ip_addrmask",
64   .parser = addrmask_parser,
65   .dumper = addrmask_dumper
66 };
67
68 struct cf_section ipaccess_cf = {
69   CF_TYPE(struct ipaccess_entry),
70   CF_ITEMS {
71     CF_LOOKUP("Mode", PTR_TO(struct ipaccess_entry, allow), ((const char* const []) { "deny", "allow", NULL })),
72     CF_USER("IP", PTR_TO(struct ipaccess_entry, addr), &ip_addrmask_type),
73     CF_END
74   }
75 };
76
77 int ip_addrmask_match(struct ip_addrmask *am, u32 ip)
78 {
79   return !((ip ^ am->addr) & am->mask);
80 }
81
82 int
83 ipaccess_check(clist *l, u32 ip)
84 {
85   CLIST_FOR_EACH(struct ipaccess_entry *, a, *l)
86     if (ip_addrmask_match(&a->addr, ip))
87       return a->allow;
88   return 0;
89 }
90
91 #ifdef TEST
92
93 #include <stdio.h>
94
95 static clist t;
96
97 static struct cf_section test_cf = {
98   CF_ITEMS {
99     CF_LIST("A", &t, &ipaccess_cf),
100     CF_END
101   }
102 };
103
104 int main(int argc, char **argv)
105 {
106   cf_declare_section("T", &test_cf, 0);
107   if (cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) != -1)
108     die("Invalid arguments");
109
110   byte buf[256];
111   while (fgets(buf, sizeof(buf), stdin))
112     {
113       char *c = strchr(buf, '\n');
114       if (c)
115         *c = 0;
116       u32 ip;
117       if (cf_parse_ip(buf, &ip))
118         puts("Invalid IP address");
119       else if (ipaccess_check(&t, ip))
120         puts("Allowed");
121       else
122         puts("Denied");
123     }
124   return 0;
125 }
126
127 #endif