]>
git.ipfire.org Git - thirdparty/chrony.git/blob - addrfilt.c
2 chronyd/chronyc - Programs for keeping computer clocks accurate.
4 **********************************************************************
5 * Copyright (C) Richard P. Curnow 1997,1998,1999,2000,2001,2002,2005
6 * Copyright (C) Miroslav Lichvar 2009, 2015
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.
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.
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.
21 **********************************************************************
23 =======================================================================
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
38 /* Define the number of bits which are stripped off per level of
39 indirection in the tables */
42 /* Define the table size */
43 #define TABLE_SIZE (1UL<<NBITS)
45 typedef enum {DENY
, ALLOW
, AS_PARENT
} State
;
47 typedef struct _TableNode
{
49 struct _TableNode
*extended
;
52 struct ADF_AuthTableInst
{
53 TableNode base4
; /* IPv4 node */
54 TableNode base6
; /* IPv6 node */
57 /* ================================================== */
60 split_ip6(IPAddr
*ip
, uint32_t *dst
)
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];
71 /* ================================================== */
73 inline static uint32_t
74 get_subnet(uint32_t *addr
, unsigned int where
)
81 return (addr
[off
] >> (32 - NBITS
- where
)) & ((1UL << NBITS
) - 1);
84 /* ================================================== */
90 result
= MallocNew(struct ADF_AuthTableInst
);
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
;
101 /* ================================================== */
102 /* This function deletes all definitions of child nodes, in effect
103 pruning a whole subnet definition back to a single parent
106 close_node(TableNode
*node
)
109 TableNode
*child_node
;
111 if (node
->extended
!= NULL
) {
112 for (i
=0; i
<TABLE_SIZE
; i
++) {
113 child_node
= &(node
->extended
[i
]);
114 close_node(child_node
);
116 Free(node
->extended
);
117 node
->extended
= NULL
;
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 */
127 open_node(TableNode
*node
)
130 TableNode
*child_node
;
132 if (node
->extended
== NULL
) {
134 node
->extended
= MallocArray(struct _TableNode
, TABLE_SIZE
);
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
;
144 /* ================================================== */
147 set_subnet(TableNode
*start_node
,
154 int bits_to_go
, bits_consumed
;
159 bits_to_go
= subnet_bits
;
162 if ((subnet_bits
< 0) ||
163 (subnet_bits
> 32 * ip_len
)) {
165 return ADF_BADSUBNET
;
169 if ((bits_to_go
& (NBITS
-1)) == 0) {
171 while (bits_to_go
> 0) {
172 subnet
= get_subnet(ip
, bits_consumed
);
173 if (!(node
->extended
)) {
176 node
= &(node
->extended
[subnet
]);
178 bits_consumed
+= NBITS
;
181 if (delete_children
) {
184 node
->state
= new_state
;
186 } else { /* Have to set multiple entries */
188 TableNode
*this_node
;
190 while (bits_to_go
>= NBITS
) {
191 subnet
= get_subnet(ip
, bits_consumed
);
192 if (!(node
->extended
)) {
195 node
= &(node
->extended
[subnet
]);
197 bits_consumed
+= NBITS
;
200 /* How many subnet entries to set : 1->8, 2->4, 3->2 */
201 N
= 1 << (NBITS
-bits_to_go
);
203 subnet
= get_subnet(ip
, bits_consumed
) & ~(N
- 1);
204 assert(subnet
+ N
<= TABLE_SIZE
);
206 if (!(node
->extended
)) {
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
);
215 this_node
->state
= new_state
;
224 /* ================================================== */
227 set_subnet_(ADF_AuthTable table
,
235 switch (ip_addr
->family
) {
237 return set_subnet(&table
->base4
, &ip_addr
->addr
.in4
, 1, subnet_bits
, new_state
, delete_children
);
239 split_ip6(ip_addr
, ip6
);
240 return set_subnet(&table
->base6
, ip6
, 4, subnet_bits
, new_state
, delete_children
);
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
)
254 return ADF_BADSUBNET
;
258 ADF_Allow(ADF_AuthTable table
,
262 return set_subnet_(table
, ip
, subnet_bits
, ALLOW
, 0);
265 /* ================================================== */
269 ADF_AllowAll(ADF_AuthTable table
,
273 return set_subnet_(table
, ip
, subnet_bits
, ALLOW
, 1);
276 /* ================================================== */
279 ADF_Deny(ADF_AuthTable table
,
283 return set_subnet_(table
, ip
, subnet_bits
, DENY
, 0);
286 /* ================================================== */
289 ADF_DenyAll(ADF_AuthTable table
,
293 return set_subnet_(table
, ip
, subnet_bits
, DENY
, 1);
296 /* ================================================== */
299 ADF_DestroyTable(ADF_AuthTable table
)
301 close_node(&table
->base4
);
302 close_node(&table
->base6
);
306 /* ================================================== */
309 check_ip_in_node(TableNode
*start_node
, uint32_t *ip
)
312 int bits_consumed
= 0;
321 if (node
->state
!= AS_PARENT
) {
324 if (node
->extended
) {
325 subnet
= get_subnet(ip
, bits_consumed
);
326 node
= &(node
->extended
[subnet
]);
327 bits_consumed
+= NBITS
;
329 /* Make decision on this node */
350 /* ================================================== */
353 ADF_IsAllowed(ADF_AuthTable table
,
358 switch (ip_addr
->family
) {
360 return check_ip_in_node(&table
->base4
, &ip_addr
->addr
.in4
);
362 split_ip6(ip_addr
, ip6
);
363 return check_ip_in_node(&table
->base6
, ip6
);
369 /* ================================================== */
372 is_any_allowed(TableNode
*node
, State parent
)
377 state
= node
->state
!= AS_PARENT
? node
->state
: parent
;
378 assert(state
!= AS_PARENT
);
380 if (node
->extended
) {
381 for (i
= 0; i
< TABLE_SIZE
; i
++) {
382 if (is_any_allowed(&node
->extended
[i
], state
))
385 } else if (state
== ALLOW
) {
392 /* ================================================== */
395 ADF_IsAnyAllowed(ADF_AuthTable table
, int family
)
399 return is_any_allowed(&table
->base4
, AS_PARENT
);
401 return is_any_allowed(&table
->base6
, AS_PARENT
);