4 * Copyright (C) 2007-2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: iptable.c,v 1.15 2009/02/18 23:47:48 tbox Exp */
24 #include <isc/radix.h>
28 static void destroy_iptable(dns_iptable_t
*dtab
);
31 * Create a new IP table and the underlying radix structure
34 dns_iptable_create(isc_mem_t
*mctx
, dns_iptable_t
**target
) {
38 tab
= isc_mem_get(mctx
, sizeof(*tab
));
40 return (ISC_R_NOMEMORY
);
42 isc_refcount_init(&tab
->refcount
, 1);
44 tab
->magic
= DNS_IPTABLE_MAGIC
;
46 result
= isc_radix_create(mctx
, &tab
->radix
, RADIX_MAXBITS
);
47 if (result
!= ISC_R_SUCCESS
)
51 return (ISC_R_SUCCESS
);
54 dns_iptable_detach(&tab
);
58 isc_boolean_t dns_iptable_neg
= ISC_FALSE
;
59 isc_boolean_t dns_iptable_pos
= ISC_TRUE
;
62 * Add an IP prefix to an existing IP table
65 dns_iptable_addprefix(dns_iptable_t
*tab
, isc_netaddr_t
*addr
,
66 isc_uint16_t bitlen
, isc_boolean_t pos
)
70 isc_radix_node_t
*node
= NULL
;
73 INSIST(DNS_IPTABLE_VALID(tab
));
76 NETADDR_TO_PREFIX_T(addr
, pfx
, bitlen
);
78 result
= isc_radix_insert(tab
->radix
, &node
, NULL
, &pfx
);
79 if (result
!= ISC_R_SUCCESS
) {
80 isc_refcount_destroy(&pfx
.refcount
);
84 /* If a node already contains data, don't overwrite it */
86 if (family
== AF_UNSPEC
) {
88 INSIST(pfx
.bitlen
== 0);
90 if (node
->data
[0] == NULL
)
91 node
->data
[0] = &dns_iptable_pos
;
92 if (node
->data
[1] == NULL
)
93 node
->data
[1] = &dns_iptable_pos
;
95 if (node
->data
[0] == NULL
)
96 node
->data
[0] = &dns_iptable_neg
;
97 if (node
->data
[1] == NULL
)
98 node
->data
[1] = &dns_iptable_neg
;
101 /* any other prefix */
102 if (node
->data
[ISC_IS6(family
)] == NULL
) {
104 node
->data
[ISC_IS6(family
)] = &dns_iptable_pos
;
106 node
->data
[ISC_IS6(family
)] = &dns_iptable_neg
;
110 isc_refcount_destroy(&pfx
.refcount
);
111 return (ISC_R_SUCCESS
);
115 * Merge one IP table into another one.
118 dns_iptable_merge(dns_iptable_t
*tab
, dns_iptable_t
*source
, isc_boolean_t pos
)
121 isc_radix_node_t
*node
, *new_node
;
124 RADIX_WALK (source
->radix
->head
, node
) {
126 result
= isc_radix_insert (tab
->radix
, &new_node
, node
, NULL
);
128 if (result
!= ISC_R_SUCCESS
)
132 * If we're negating a nested ACL, then we should
133 * reverse the sense of every node. However, this
134 * could lead to a negative node in a nested ACL
135 * becoming a positive match in the parent, which
136 * could be a security risk. To prevent this, we
137 * just leave the negative nodes negative.
141 *(isc_boolean_t
*) node
->data
[0] == ISC_TRUE
)
142 new_node
->data
[0] = &dns_iptable_neg
;
145 *(isc_boolean_t
*) node
->data
[1] == ISC_TRUE
)
146 new_node
->data
[1] = &dns_iptable_neg
;
149 if (node
->node_num
[0] > max_node
)
150 max_node
= node
->node_num
[0];
151 if (node
->node_num
[1] > max_node
)
152 max_node
= node
->node_num
[1];
155 tab
->radix
->num_added_node
+= max_node
;
156 return (ISC_R_SUCCESS
);
160 dns_iptable_attach(dns_iptable_t
*source
, dns_iptable_t
**target
) {
161 REQUIRE(DNS_IPTABLE_VALID(source
));
162 isc_refcount_increment(&source
->refcount
, NULL
);
167 dns_iptable_detach(dns_iptable_t
**tabp
) {
168 dns_iptable_t
*tab
= *tabp
;
170 REQUIRE(DNS_IPTABLE_VALID(tab
));
171 isc_refcount_decrement(&tab
->refcount
, &refs
);
173 destroy_iptable(tab
);
178 destroy_iptable(dns_iptable_t
*dtab
) {
180 REQUIRE(DNS_IPTABLE_VALID(dtab
));
182 if (dtab
->radix
!= NULL
) {
183 isc_radix_destroy(dtab
->radix
, NULL
);
187 isc_refcount_destroy(&dtab
->refcount
);
189 isc_mem_put(dtab
->mctx
, dtab
, sizeof(*dtab
));