2 * Copyright (C) 2007-2009 Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
17 /* $Id: iptable.c,v 1.5.46.9 2009/02/18 23:46:34 tbox Exp $ */
22 #include <isc/radix.h>
26 static void destroy_iptable(dns_iptable_t
*dtab
);
29 * Create a new IP table and the underlying radix structure
32 dns_iptable_create(isc_mem_t
*mctx
, dns_iptable_t
**target
) {
36 tab
= isc_mem_get(mctx
, sizeof(*tab
));
38 return (ISC_R_NOMEMORY
);
40 isc_refcount_init(&tab
->refcount
, 1);
42 tab
->magic
= DNS_IPTABLE_MAGIC
;
44 result
= isc_radix_create(mctx
, &tab
->radix
, RADIX_MAXBITS
);
45 if (result
!= ISC_R_SUCCESS
)
49 return (ISC_R_SUCCESS
);
52 dns_iptable_detach(&tab
);
56 isc_boolean_t dns_iptable_neg
= ISC_FALSE
;
57 isc_boolean_t dns_iptable_pos
= ISC_TRUE
;
60 * Add an IP prefix to an existing IP table
63 dns_iptable_addprefix(dns_iptable_t
*tab
, isc_netaddr_t
*addr
,
64 isc_uint16_t bitlen
, isc_boolean_t pos
)
68 isc_radix_node_t
*node
= NULL
;
71 INSIST(DNS_IPTABLE_VALID(tab
));
74 NETADDR_TO_PREFIX_T(addr
, pfx
, bitlen
);
76 result
= isc_radix_insert(tab
->radix
, &node
, NULL
, &pfx
);
77 if (result
!= ISC_R_SUCCESS
) {
78 isc_refcount_destroy(&pfx
.refcount
);
82 /* If a node already contains data, don't overwrite it */
84 if (family
== AF_UNSPEC
) {
86 INSIST(pfx
.bitlen
== 0);
88 if (node
->data
[0] == NULL
)
89 node
->data
[0] = &dns_iptable_pos
;
90 if (node
->data
[1] == NULL
)
91 node
->data
[1] = &dns_iptable_pos
;
93 if (node
->data
[0] == NULL
)
94 node
->data
[0] = &dns_iptable_neg
;
95 if (node
->data
[1] == NULL
)
96 node
->data
[1] = &dns_iptable_neg
;
99 /* any other prefix */
100 if (node
->data
[ISC_IS6(family
)] == NULL
) {
102 node
->data
[ISC_IS6(family
)] = &dns_iptable_pos
;
104 node
->data
[ISC_IS6(family
)] = &dns_iptable_neg
;
108 isc_refcount_destroy(&pfx
.refcount
);
109 return (ISC_R_SUCCESS
);
113 * Merge one IP table into another one.
116 dns_iptable_merge(dns_iptable_t
*tab
, dns_iptable_t
*source
, isc_boolean_t pos
)
119 isc_radix_node_t
*node
, *new_node
;
122 RADIX_WALK (source
->radix
->head
, node
) {
124 result
= isc_radix_insert (tab
->radix
, &new_node
, node
, NULL
);
126 if (result
!= ISC_R_SUCCESS
)
130 * If we're negating a nested ACL, then we should
131 * reverse the sense of every node. However, this
132 * could lead to a negative node in a nested ACL
133 * becoming a positive match in the parent, which
134 * could be a security risk. To prevent this, we
135 * just leave the negative nodes negative.
139 *(isc_boolean_t
*) node
->data
[0] == ISC_TRUE
)
140 new_node
->data
[0] = &dns_iptable_neg
;
143 *(isc_boolean_t
*) node
->data
[1] == ISC_TRUE
)
144 new_node
->data
[1] = &dns_iptable_neg
;
147 if (node
->node_num
[0] > max_node
)
148 max_node
= node
->node_num
[0];
149 if (node
->node_num
[1] > max_node
)
150 max_node
= node
->node_num
[1];
153 tab
->radix
->num_added_node
+= max_node
;
154 return (ISC_R_SUCCESS
);
158 dns_iptable_attach(dns_iptable_t
*source
, dns_iptable_t
**target
) {
159 REQUIRE(DNS_IPTABLE_VALID(source
));
160 isc_refcount_increment(&source
->refcount
, NULL
);
165 dns_iptable_detach(dns_iptable_t
**tabp
) {
166 dns_iptable_t
*tab
= *tabp
;
168 REQUIRE(DNS_IPTABLE_VALID(tab
));
169 isc_refcount_decrement(&tab
->refcount
, &refs
);
171 destroy_iptable(tab
);
176 destroy_iptable(dns_iptable_t
*dtab
) {
178 REQUIRE(DNS_IPTABLE_VALID(dtab
));
180 if (dtab
->radix
!= NULL
) {
181 isc_radix_destroy(dtab
->radix
, NULL
);
185 isc_refcount_destroy(&dtab
->refcount
);
187 isc_mem_put(dtab
->mctx
, dtab
, sizeof(*dtab
));