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