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