]> mj.ucw.cz Git - libucw.git/blob - lib/ipaccess.c
conf2: insert a node into a list as soon as possible instead of at the end
[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/conf2.h"
13 #include "lib/chartype.h"
14 #include "lib/ipaccess.h"
15
16 #include <string.h>
17 #include <stdlib.h>
18 #include <errno.h>
19
20 struct ipaccess_list {
21   list l;
22 };
23
24 struct ipaccess_entry {
25   node n;
26   uns allow;
27   u32 addr, mask;
28 };
29
30 struct ipaccess_list *
31 ipaccess_init(void)
32 {
33   /* Cannot use cfg_malloc() here as the pool can be uninitialized now */
34   struct ipaccess_list *l = xmalloc(sizeof(*l));
35
36   init_list(&l->l);
37   return l;
38 }
39
40 // FIXME: replace by cf_parse_ip()
41 static byte *
42 parse_ip(byte **p, u32 *varp)
43 {
44   while (Cspace(**p))
45     (*p)++;
46   if (!**p)
47     return "Missing IP address";
48   uns x = 0;
49   if (**p == '0' && *(*p + 1) | 32 == 'X')
50     {
51       errno = 0;
52       x = strtoul(*p + 2, (char **)p, 16);
53       if (errno == ERANGE || x > 0xffffffff)
54         goto error;
55     }
56   else
57     for (uns i = 0; i < 4; i++)
58       {
59         if (i)
60           {
61             while (Cspace(**p))
62               (*p)++;
63             if (*(*p)++ != '.')
64               goto error;
65           }
66         while (Cspace(**p))
67           (*p)++;
68         errno = 0;
69         uns y = strtoul(*p, (char **)p, 10);
70         if (errno == ERANGE || y > 255)
71           goto error;
72         x = (x << 8) + y;
73       }
74   *varp = x;
75   return NULL;
76 error:
77   return "Invalid IP address";
78 }
79
80 byte *
81 ipaccess_parse(struct ipaccess_list *l, byte *c, int is_allow)
82 {
83   byte *p = strchr(c, '/');
84   char *q;
85   struct ipaccess_entry *a = cf_malloc(sizeof(struct ipaccess_entry));
86   unsigned long pxlen;
87
88   a->allow = is_allow;
89   a->mask = ~0U;
90   if (p)
91     {
92       *p++ = 0;
93       pxlen = strtoul(p, &q, 10);
94       if ((!q || !*q) && pxlen <= 32)
95         {
96           if (pxlen != 32)
97             a->mask = ~(~0U >> (uns) pxlen);
98         }
99       else if (q = parse_ip(&p, &a->mask))
100         return q;
101     }
102   add_tail(&l->l, &a->n);
103   return parse_ip(&c, &a->addr);
104 }
105
106 int
107 ipaccess_check(struct ipaccess_list *l, u32 ip)
108 {
109   struct ipaccess_entry *a;
110
111   DO_FOR_ALL(a, l->l)
112     if (! ((ip ^ a->addr) & a->mask))
113       return a->allow;
114   return 0;
115 }