]> mj.ucw.cz Git - libucw.git/blob - lib/ipaccess.c
shell/config: check the default value from the command-line
[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   .name = "addrmask",
68   .parser = addrmask_parser,
69   .dumper = addrmask_dumper
70 };
71
72 struct cf_section ipaccess_cf = {
73   CF_TYPE(struct ipaccess_entry),
74   CF_ITEMS {
75     CF_LOOKUP("Mode", PTR_TO(struct ipaccess_entry, allow), ((byte*[]) { "deny", "allow", NULL })),
76     CF_USER("IP", PTR_TO(struct ipaccess_entry, addr), &addrmask_type),
77     CF_END
78   }
79 };
80
81 int
82 ipaccess_check(clist *l, u32 ip)
83 {
84   CLIST_FOR_EACH(struct ipaccess_entry *, a, *l)
85     if (! ((ip ^ a->addr.addr) & a->addr.mask))
86       return a->allow;
87   return 0;
88 }
89
90 #ifdef TEST
91
92 #include <stdio.h>
93
94 static clist t;
95
96 static struct cf_section test_cf = {
97   CF_ITEMS {
98     CF_LIST("A", &t, &ipaccess_cf),
99     CF_END
100   }
101 };
102
103 int main(int argc, char **argv)
104 {
105   cf_declare_section("T", &test_cf, 0);
106   if (cf_get_opt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) != -1)
107     die("Invalid arguments");
108
109   byte buf[256];
110   while (fgets(buf, sizeof(buf), stdin))
111     {
112       byte *c = strchr(buf, '\n');
113       if (c)
114         *c = 0;
115       u32 ip;
116       if (cf_parse_ip(buf, &ip))
117         puts("Invalid IP address");
118       else if (ipaccess_check(&t, ip))
119         puts("Allowed");
120       else
121         puts("Denied");
122     }
123   return 0;
124 }
125
126 #endif