]> mj.ucw.cz Git - libucw.git/blob - lib/ipaccess.c
f1637c8554587a4b2b86af046ddfcc366773d873
[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 ipaccess_entry {
18   cnode n;
19   int allow;
20   u32 addr, mask;
21 };
22
23 static byte *
24 ipaccess_cf_ip(uns n UNUSED, byte **pars, struct ipaccess_entry *a)
25 {
26   byte *c = pars[0];
27   CF_JOURNAL_VAR(a->addr);
28   CF_JOURNAL_VAR(a->mask);
29
30   byte *p = strchr(c, '/');
31   if (p)
32     *p++ = 0;
33   byte *err = cf_parse_ip(c, &a->addr);
34   if (err)
35     return err;
36   if (p)
37     {
38       uns len;
39       if (!cf_parse_int(p, &len) && len <= 32)
40         a->mask = ~(len == 32 ? 0 : ~0U >> len);
41       else if (cf_parse_ip(p, &a->mask))
42         return "Invalid prefix length or netmask";
43     }
44   else
45     a->mask = ~0U;
46   return NULL;
47 }
48
49 struct cf_section ipaccess_cf = {
50   CF_TYPE(struct ipaccess_entry),
51   CF_ITEMS {
52     CF_LOOKUP("Mode", PTR_TO(struct ipaccess_entry, allow), ((char*[]) { "deny", "allow" })),
53     CF_PARSER("IP", NULL, ipaccess_cf_ip, 1),
54     CF_END
55   }
56 };
57
58 int
59 ipaccess_check(clist *l, u32 ip)
60 {
61   CLIST_FOR_EACH(struct ipaccess_entry *, a, *l)
62     if (! ((ip ^ a->addr) & a->mask))
63       return a->allow;
64   return 0;
65 }
66
67 #ifdef TEST
68
69 #include <stdio.h>
70
71 static clist t;
72
73 static struct cf_section test_cf = {
74   CF_ITEMS {
75     CF_LIST("A", &t, &ipaccess_cf),
76     CF_END
77   }
78 };
79
80 int main(int argc, char **argv)
81 {
82   cf_declare_section("T", &test_cf, 0);
83   if (cf_get_opt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) != -1)
84     die("Invalid arguments");
85
86   byte buf[256];
87   while (fgets(buf, sizeof(buf), stdin))
88     {
89       byte *c = strchr(buf, '\n');
90       if (c)
91         *c = 0;
92       u32 ip;
93       if (cf_parse_ip(buf, &ip))
94         puts("Invalid IP address");
95       else if (ipaccess_check(&t, ip))
96         puts("Allowed");
97       else
98         puts("Denied");
99     }
100   return 0;
101 }
102
103 #endif