]> mj.ucw.cz Git - libucw.git/blob - lib/ipaccess.c
Minor cleanup of KMP:
[libucw.git] / lib / ipaccess.c
1 /*
2  *      UCW Library -- IP address access lists
3  *
4  *      (c) 1997--2001 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/lists.h"
12 #include "lib/conf.h"
13 #include "lib/chartype.h"
14 #include "lib/ipaccess.h"
15
16 #include <string.h>
17 #include <stdlib.h>
18
19 struct ipaccess_list {
20   list l;
21 };
22
23 struct ipaccess_entry {
24   node n;
25   uns allow;
26   u32 addr, mask;
27 };
28
29 struct ipaccess_list *
30 ipaccess_init(void)
31 {
32   /* Cannot use cfg_malloc() here as the pool can be uninitialized now */
33   struct ipaccess_list *l = xmalloc(sizeof(*l));
34
35   init_list(&l->l);
36   return l;
37 }
38
39 static byte *
40 parse_ip(byte *x, u32 *a)
41 {
42   uns i, q;
43   u32 z = 0;
44
45   for(i=0; i<4; i++)
46     {
47       q = 0;
48       while (Cdigit(*x))
49         {
50           q = q*10 + *x++ - '0';
51           if (q > 255)
52             return "Invalid IP address";
53         }
54       if (*x++ != ((i == 3) ? 0 : '.'))
55         return "Invalid IP address";
56       z = (z << 8) | q;
57     }
58   *a = z;
59   return NULL;
60 }
61
62 byte *
63 ipaccess_parse(struct ipaccess_list *l, byte *c, int is_allow)
64 {
65   char *p = strchr(c, '/');
66   char *q;
67   struct ipaccess_entry *a = cfg_malloc(sizeof(struct ipaccess_entry));
68   unsigned long pxlen;
69
70   a->allow = is_allow;
71   a->mask = ~0U;
72   if (p)
73     {
74       *p++ = 0;
75       pxlen = strtoul(p, &q, 10);
76       if ((!q || !*q) && pxlen <= 32)
77         {
78           if (pxlen != 32)
79             a->mask = ~(~0U >> (uns) pxlen);
80         }
81       else if (q = parse_ip(p, &a->mask))
82         return q;
83     }
84   add_tail(&l->l, &a->n);
85   return parse_ip(c, &a->addr);
86 }
87
88 int
89 ipaccess_check(struct ipaccess_list *l, u32 ip)
90 {
91   struct ipaccess_entry *a;
92
93   DO_FOR_ALL(a, l->l)
94     if (! ((ip ^ a->addr) & a->mask))
95       return a->allow;
96   return 0;
97 }