]> git.ipfire.org Git - thirdparty/chrony.git/blob - addrfilt.c
ntp: fix log message for replaced source
[thirdparty/chrony.git] / addrfilt.c
1 /*
2 chronyd/chronyc - Programs for keeping computer clocks accurate.
3
4 **********************************************************************
5 * Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
6 * Copyright (C) Miroslav Lichvar 2009, 2015
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 **********************************************************************
22
23 =======================================================================
24
25 This module provides a set of routines for checking IP addresses
26 against a set of rules and deciding whether they are allowed or
27 disallowed.
28
29 */
30
31 #include "config.h"
32
33 #include "sysincl.h"
34
35 #include "addrfilt.h"
36 #include "memory.h"
37
38 /* Define the number of bits which are stripped off per level of
39 indirection in the tables */
40 #define NBITS 4
41
42 /* Define the table size */
43 #define TABLE_SIZE (1UL<<NBITS)
44
45 typedef enum {DENY, ALLOW, AS_PARENT} State;
46
47 typedef struct _TableNode {
48 State state;
49 struct _TableNode *extended;
50 } TableNode;
51
52 struct ADF_AuthTableInst {
53 TableNode base4; /* IPv4 node */
54 TableNode base6; /* IPv6 node */
55 };
56
57 /* ================================================== */
58
59 static void
60 split_ip6(IPAddr *ip, uint32_t *dst)
61 {
62 int i;
63
64 for (i = 0; i < 4; i++)
65 dst[i] = (uint32_t)ip->addr.in6[i * 4 + 0] << 24 |
66 ip->addr.in6[i * 4 + 1] << 16 |
67 ip->addr.in6[i * 4 + 2] << 8 |
68 ip->addr.in6[i * 4 + 3];
69 }
70
71 /* ================================================== */
72
73 inline static uint32_t
74 get_subnet(uint32_t *addr, unsigned int where)
75 {
76 int off;
77
78 off = where / 32;
79 where %= 32;
80
81 return (addr[off] >> (32 - NBITS - where)) & ((1UL << NBITS) - 1);
82 }
83
84 /* ================================================== */
85
86 ADF_AuthTable
87 ADF_CreateTable(void)
88 {
89 ADF_AuthTable result;
90 result = MallocNew(struct ADF_AuthTableInst);
91
92 /* Default is that nothing is allowed */
93 result->base4.state = DENY;
94 result->base4.extended = NULL;
95 result->base6.state = DENY;
96 result->base6.extended = NULL;
97
98 return result;
99 }
100
101 /* ================================================== */
102 /* This function deletes all definitions of child nodes, in effect
103 pruning a whole subnet definition back to a single parent
104 record. */
105 static void
106 close_node(TableNode *node)
107 {
108 int i;
109 TableNode *child_node;
110
111 if (node->extended != NULL) {
112 for (i=0; i<TABLE_SIZE; i++) {
113 child_node = &(node->extended[i]);
114 close_node(child_node);
115 }
116 Free(node->extended);
117 node->extended = NULL;
118 }
119 }
120
121
122 /* ================================================== */
123 /* Allocate the extension field in a node, and set all the children's
124 states to default to that of the node being extended */
125
126 static void
127 open_node(TableNode *node)
128 {
129 int i;
130 TableNode *child_node;
131
132 if (node->extended == NULL) {
133
134 node->extended = MallocArray(struct _TableNode, TABLE_SIZE);
135
136 for (i=0; i<TABLE_SIZE; i++) {
137 child_node = &(node->extended[i]);
138 child_node->state = AS_PARENT;
139 child_node->extended = NULL;
140 }
141 }
142 }
143
144 /* ================================================== */
145
146 static ADF_Status
147 set_subnet(TableNode *start_node,
148 uint32_t *ip,
149 int ip_len,
150 int subnet_bits,
151 State new_state,
152 int delete_children)
153 {
154 int bits_to_go, bits_consumed;
155 uint32_t subnet;
156 TableNode *node;
157
158 bits_consumed = 0;
159 bits_to_go = subnet_bits;
160 node = start_node;
161
162 if ((subnet_bits < 0) ||
163 (subnet_bits > 32 * ip_len)) {
164
165 return ADF_BADSUBNET;
166
167 } else {
168
169 if ((bits_to_go & (NBITS-1)) == 0) {
170
171 while (bits_to_go > 0) {
172 subnet = get_subnet(ip, bits_consumed);
173 if (!(node->extended)) {
174 open_node(node);
175 }
176 node = &(node->extended[subnet]);
177 bits_to_go -= NBITS;
178 bits_consumed += NBITS;
179 }
180
181 if (delete_children) {
182 close_node(node);
183 }
184 node->state = new_state;
185
186 } else { /* Have to set multiple entries */
187 int N, i, j;
188 TableNode *this_node;
189
190 while (bits_to_go >= NBITS) {
191 subnet = get_subnet(ip, bits_consumed);
192 if (!(node->extended)) {
193 open_node(node);
194 }
195 node = &(node->extended[subnet]);
196 bits_to_go -= NBITS;
197 bits_consumed += NBITS;
198 }
199
200 /* How many subnet entries to set : 1->8, 2->4, 3->2 */
201 N = 1 << (NBITS-bits_to_go);
202
203 subnet = get_subnet(ip, bits_consumed) & ~(N - 1);
204 assert(subnet + N <= TABLE_SIZE);
205
206 if (!(node->extended)) {
207 open_node(node);
208 }
209
210 for (i=subnet, j=0; j<N; i++, j++) {
211 this_node = &(node->extended[i]);
212 if (delete_children) {
213 close_node(this_node);
214 }
215 this_node->state = new_state;
216 }
217 }
218
219 return ADF_SUCCESS;
220 }
221
222 }
223
224 /* ================================================== */
225
226 static ADF_Status
227 set_subnet_(ADF_AuthTable table,
228 IPAddr *ip_addr,
229 int subnet_bits,
230 State new_state,
231 int delete_children)
232 {
233 uint32_t ip6[4];
234
235 switch (ip_addr->family) {
236 case IPADDR_INET4:
237 return set_subnet(&table->base4, &ip_addr->addr.in4, 1, subnet_bits, new_state, delete_children);
238 case IPADDR_INET6:
239 split_ip6(ip_addr, ip6);
240 return set_subnet(&table->base6, ip6, 4, subnet_bits, new_state, delete_children);
241 case IPADDR_UNSPEC:
242 /* Apply to both, subnet_bits has to be 0 */
243 if (subnet_bits != 0)
244 return ADF_BADSUBNET;
245 memset(ip6, 0, sizeof (ip6));
246 if (set_subnet(&table->base4, ip6, 1, 0, new_state, delete_children) == ADF_SUCCESS &&
247 set_subnet(&table->base6, ip6, 4, 0, new_state, delete_children) == ADF_SUCCESS)
248 return ADF_SUCCESS;
249 break;
250 default:
251 break;
252 }
253
254 return ADF_BADSUBNET;
255 }
256
257 ADF_Status
258 ADF_Allow(ADF_AuthTable table,
259 IPAddr *ip,
260 int subnet_bits)
261 {
262 return set_subnet_(table, ip, subnet_bits, ALLOW, 0);
263 }
264
265 /* ================================================== */
266
267
268 ADF_Status
269 ADF_AllowAll(ADF_AuthTable table,
270 IPAddr *ip,
271 int subnet_bits)
272 {
273 return set_subnet_(table, ip, subnet_bits, ALLOW, 1);
274 }
275
276 /* ================================================== */
277
278 ADF_Status
279 ADF_Deny(ADF_AuthTable table,
280 IPAddr *ip,
281 int subnet_bits)
282 {
283 return set_subnet_(table, ip, subnet_bits, DENY, 0);
284 }
285
286 /* ================================================== */
287
288 ADF_Status
289 ADF_DenyAll(ADF_AuthTable table,
290 IPAddr *ip,
291 int subnet_bits)
292 {
293 return set_subnet_(table, ip, subnet_bits, DENY, 1);
294 }
295
296 /* ================================================== */
297
298 void
299 ADF_DestroyTable(ADF_AuthTable table)
300 {
301 close_node(&table->base4);
302 close_node(&table->base6);
303 Free(table);
304 }
305
306 /* ================================================== */
307
308 static int
309 check_ip_in_node(TableNode *start_node, uint32_t *ip)
310 {
311 uint32_t subnet;
312 int bits_consumed = 0;
313 int result = 0;
314 int finished = 0;
315 TableNode *node;
316 State state=DENY;
317
318 node = start_node;
319
320 do {
321 if (node->state != AS_PARENT) {
322 state = node->state;
323 }
324 if (node->extended) {
325 subnet = get_subnet(ip, bits_consumed);
326 node = &(node->extended[subnet]);
327 bits_consumed += NBITS;
328 } else {
329 /* Make decision on this node */
330 finished = 1;
331 }
332 } while (!finished);
333
334 switch (state) {
335 case ALLOW:
336 result = 1;
337 break;
338 case DENY:
339 result = 0;
340 break;
341 case AS_PARENT:
342 assert(0);
343 break;
344 }
345
346 return result;
347 }
348
349
350 /* ================================================== */
351
352 int
353 ADF_IsAllowed(ADF_AuthTable table,
354 IPAddr *ip_addr)
355 {
356 uint32_t ip6[4];
357
358 switch (ip_addr->family) {
359 case IPADDR_INET4:
360 return check_ip_in_node(&table->base4, &ip_addr->addr.in4);
361 case IPADDR_INET6:
362 split_ip6(ip_addr, ip6);
363 return check_ip_in_node(&table->base6, ip6);
364 default:
365 return 0;
366 }
367 }
368
369 /* ================================================== */
370
371 static int
372 is_any_allowed(TableNode *node, State parent)
373 {
374 State state;
375 int i;
376
377 state = node->state != AS_PARENT ? node->state : parent;
378 assert(state != AS_PARENT);
379
380 if (node->extended) {
381 for (i = 0; i < TABLE_SIZE; i++) {
382 if (is_any_allowed(&node->extended[i], state))
383 return 1;
384 }
385 } else if (state == ALLOW) {
386 return 1;
387 }
388
389 return 0;
390 }
391
392 /* ================================================== */
393
394 int
395 ADF_IsAnyAllowed(ADF_AuthTable table, int family)
396 {
397 switch (family) {
398 case IPADDR_INET4:
399 return is_any_allowed(&table->base4, AS_PARENT);
400 case IPADDR_INET6:
401 return is_any_allowed(&table->base6, AS_PARENT);
402 default:
403 return 0;
404 }
405 }