Commit 65e69031 65e690315175530ba12d03b614f6354fea27335d by Sergey Poznyakoff

Configuration and ACL routines.

1 parent 038ae343
1 /* Copyright (C) 1998,2001 Free Software Foundation, Inc.
2
3 This file is part of GNU Inetutils.
4
5 GNU Inetutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 GNU Inetutils is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU Inetutils; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20 #include "comsat.h"
21 #include <argcv.h>
22 #include <ctype.h>
23
24 typedef struct netdef netdef_t;
25
26 struct netdef
27 {
28 netdef_t *next;
29 unsigned int ipaddr;
30 unsigned int netmask;
31 };
32
33 #define ACT_ALLOW 0
34 #define ACT_DENY 1
35
36 typedef struct acl acl_t;
37
38 struct acl
39 {
40 acl_t *next;
41 netdef_t *netlist;
42 int action;
43 };
44
45
46 acl_t *acl_head, *acl_tail;
47
48 #define DOTTED_QUAD_LEN 16
49
50 static int
51 read_address (char **line_ptr, char *ptr)
52 {
53 char *startp = *line_ptr;
54 char *endp;
55 int dotcount = 0;
56
57 for (endp = startp; *endp; endp++, ptr++)
58 if (!(isdigit (*endp) || *endp == '.'))
59 break;
60 else if (endp < startp + DOTTED_QUAD_LEN)
61 {
62 if (*endp == '.')
63 dotcount++;
64 *ptr = *endp;
65 }
66 else
67 break;
68 *line_ptr = endp;
69 *ptr = 0;
70 return dotcount;
71 }
72
73 static netdef_t *
74 netdef_parse (char *str)
75 {
76 unsigned int ipaddr, netmask;
77 netdef_t *netdef;
78 char ipbuf[DOTTED_QUAD_LEN+1];
79
80 if (strcmp (str, "any") == 0)
81 {
82 ipaddr = 0;
83 netmask = 0;
84 }
85 else
86 {
87 read_address (&str, ipbuf);
88 ipaddr = inet_addr (ipbuf);
89 if (ipaddr == INADDR_NONE)
90 return NULL;
91 if (*str == 0)
92 netmask = 0xfffffffful;
93 else if (*str != '/')
94 return NULL;
95 else
96 {
97 str++;
98 if (read_address (&str, ipbuf) == 0)
99 {
100 /* netmask length */
101 unsigned int len = strtoul (ipbuf, NULL, 0);
102 if (len > 32)
103 return NULL;
104 netmask = 0xfffffffful >> (32-len);
105 netmask <<= (32-len);
106 /*FIXME: hostorder?*/
107 }
108 else
109 netmask = inet_network (ipbuf);
110 netmask = htonl (netmask);
111 }
112 }
113
114 netdef = malloc (sizeof *netdef);
115 if (!netdef)
116 {
117 syslog (LOG_ERR, "out of memory");
118 exit (1);
119 }
120
121 netdef->next = NULL;
122 netdef->ipaddr = ipaddr;
123 netdef->netmask = netmask;
124
125 return netdef;
126 }
127
128 void
129 read_config (char *config_file)
130 {
131 FILE *fp;
132 int line;
133 char buf[128];
134 char *ptr;
135
136 if (!config_file)
137 return;
138
139 fp = fopen (config_file, "r");
140 if (!fp)
141 {
142 syslog (LOG_ERR, "can't open config file %s: %m", config_file);
143 return;
144 }
145
146 line = 0;
147 while ((ptr = fgets (buf, sizeof buf, fp)))
148 {
149 int len, i;
150 int argc;
151 char **argv;
152 int action;
153 netdef_t *head, *tail;
154 acl_t *acl;
155
156 line++;
157 len = strlen (ptr);
158 if (len > 0 && ptr[len-1] == '\n')
159 ptr[--len] = 0;
160
161 while (*ptr && isspace (*ptr))
162 ptr++;
163 if (!*ptr || *ptr == '#')
164 continue;
165
166 argcv_get (ptr, "", &argc, &argv);
167 if (argc < 2)
168 {
169 syslog (LOG_ERR, "%s:%d: too few fields", config_file, line);
170 argcv_free (argc, argv);
171 continue;
172 }
173
174 if (strcmp (argv[0], "max-requests") == 0)
175 maxrequests = strtoul (argv[1], NULL, 0);
176 else if (strcmp (argv[0], "request-control-interval") == 0)
177 request_control_interval = strtoul (argv[1], NULL, 0);
178 else if (strcmp (argv[0], "overflow-control-interval") == 0)
179 overflow_control_interval = strtoul (argv[1], NULL, 0);
180 else if (strcmp (argv[0], "overflow-delay-time") == 0)
181 overflow_delay_time = strtoul (argv[1], NULL, 0);
182 else if (strcmp (argv[0], "max-lines") == 0)
183 maxlines = strtoul (argv[1], NULL, 0);
184 else if (strcmp (argv[0], "acl") == 0)
185 {
186 if (strcmp (argv[1], "allow") == 0)
187 action = ACT_ALLOW;
188 else if (strcmp (argv[1], "deny") == 0)
189 action = ACT_DENY;
190 else
191 {
192 syslog (LOG_ERR, "%s:%d: unknown keyword", config_file, line);
193 argcv_free (argc, argv);
194 continue;
195 }
196
197 head = tail = NULL;
198 for (i = 2; i < argc; i++)
199 {
200 netdef_t *cur = netdef_parse (argv[i]);
201 if (!cur)
202 {
203 syslog (LOG_ERR, "%s:%d: can't parse netdef: %s",
204 config_file, line, argv[i]);
205 continue;
206 }
207 if (!tail)
208 head = cur;
209 else
210 tail->next = cur;
211 tail = cur;
212 }
213
214 argcv_free (argc, argv);
215
216 acl = malloc (sizeof *acl);
217 if (!acl)
218 {
219 syslog (LOG_CRIT, "out of memory");
220 exit (1);
221 }
222 acl->next = NULL;
223 acl->action = action;
224 acl->netlist = head;
225
226 if (!acl_tail)
227 acl_head = acl;
228 else
229 acl_tail->next = acl;
230 acl_tail = acl;
231 }
232 }
233 fclose (fp);
234 }
235
236 static void
237 netdef_free (netdef_t *netdef)
238 {
239 netdef_t *next;
240
241 while (netdef)
242 {
243 next = netdef->next;
244 free (netdef);
245 netdef = next;
246 }
247 }
248
249 static void
250 acl_free (acl_t *acl)
251 {
252 acl_t *next;
253
254 while (acl)
255 {
256 next = acl->next;
257 netdef_free (acl->netlist);
258 free (acl);
259 acl = next;
260 }
261 }
262
263 /*NOTE: currently unused. */
264 void
265 discard_acl (acl_t *mark)
266 {
267 if (mark)
268 {
269 acl_free (mark->next);
270 acl_tail = mark;
271 acl_tail->next = NULL;
272 }
273 else
274 acl_head = acl_tail = NULL;
275 }
276
277 int
278 acl_match (struct sockaddr_in *sa_in)
279 {
280 acl_t *acl;
281 unsigned int ip;
282
283 ip = sa_in->sin_addr.s_addr;
284 for (acl = acl_head; acl; acl = acl->next)
285 {
286 netdef_t *net;
287
288 for (net = acl->netlist; net; net = net->next)
289 {
290 if (net->ipaddr == (ip & net->netmask))
291 return acl->action;
292 }
293 }
294 return ACT_ALLOW;
295 }