]> mj.ucw.cz Git - libucw.git/blob - lib/ipaccess.c
Free thread context structure on thread termination.
[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/conf.h"
13 #include "lib/getopt.h"
14 #include "lib/fastbuf.h"
15 #include "lib/ipaccess.h"
16
17 #include <string.h>
18
19 struct addrmask {
20   u32 addr;
21   u32 mask;
22 };
23
24 struct ipaccess_entry {
25   cnode n;
26   int allow;
27   struct addrmask addr;
28 };
29
30 static byte *
31 addrmask_parser(byte *c, void *ptr)
32 {
33   /*
34    * This is tricky: addrmasks will be compared by memcmp(), so we must ensure
35    * that even the padding between structure members is zeroed out.
36    */
37   struct addrmask *am = ptr;
38   bzero(am, sizeof(*am));
39
40   byte *p = strchr(c, '/');
41   if (p)
42     *p++ = 0;
43   byte *err = cf_parse_ip(c, &am->addr);
44   if (err)
45     return err;
46   if (p)
47     {
48       uns len;
49       if (!cf_parse_int(p, &len) && len <= 32)
50         am->mask = ~(len == 32 ? 0 : ~0U >> len);
51       else if (cf_parse_ip(p, &am->mask))
52         return "Invalid prefix length or netmask";
53     }
54   else
55     am->mask = ~0U;
56   return NULL;
57 }
58
59 static void
60 addrmask_dumper(struct fastbuf *fb, void *ptr)
61 {
62   struct addrmask *am = ptr;
63   bprintf(fb, "%08x/%08x ", am->addr, am->mask);
64 }
65
66 static struct cf_user_type addrmask_type = {
67   .size = sizeof(struct addrmask),
68   .name = "addrmask",
69   .parser = addrmask_parser,
70   .dumper = addrmask_dumper
71 };
72
73 struct cf_section ipaccess_cf = {
74   CF_TYPE(struct ipaccess_entry),
75   CF_ITEMS {
76     CF_LOOKUP("Mode", PTR_TO(struct ipaccess_entry, allow), ((byte*[]) { "deny", "allow", NULL })),
77     CF_USER("IP", PTR_TO(struct ipaccess_entry, addr), &addrmask_type),
78     CF_END
79   }
80 };
81
82 int
83 ipaccess_check(clist *l, u32 ip)
84 {
85   CLIST_FOR_EACH(struct ipaccess_entry *, a, *l)
86     if (! ((ip ^ a->addr.addr) & a->addr.mask))
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       byte *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