00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <config.h>
00018
00019 #include <isc/mem.h>
00020 #include <isc/radix.h>
00021
00022 #include <dns/acl.h>
00023
00024 static void destroy_iptable(dns_iptable_t *dtab);
00025
00026
00027
00028
00029 isc_result_t
00030 dns_iptable_create(isc_mem_t *mctx, dns_iptable_t **target) {
00031 isc_result_t result;
00032 dns_iptable_t *tab;
00033
00034 tab = isc_mem_get(mctx, sizeof(*tab));
00035 if (tab == NULL)
00036 return (ISC_R_NOMEMORY);
00037 tab->mctx = NULL;
00038 isc_mem_attach(mctx, &tab->mctx);
00039 isc_refcount_init(&tab->refcount, 1);
00040 tab->radix = NULL;
00041 tab->magic = DNS_IPTABLE_MAGIC;
00042
00043 result = isc_radix_create(mctx, &tab->radix, RADIX_MAXBITS);
00044 if (result != ISC_R_SUCCESS)
00045 goto cleanup;
00046
00047 *target = tab;
00048 return (ISC_R_SUCCESS);
00049
00050 cleanup:
00051 dns_iptable_detach(&tab);
00052 return (result);
00053 }
00054
00055 isc_boolean_t dns_iptable_neg = ISC_FALSE;
00056 isc_boolean_t dns_iptable_pos = ISC_TRUE;
00057
00058
00059
00060
00061 isc_result_t
00062 dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
00063 isc_uint16_t bitlen, isc_boolean_t pos)
00064 {
00065 return(dns_iptable_addprefix2(tab, addr, bitlen, pos, ISC_FALSE));
00066 }
00067
00068 isc_result_t
00069 dns_iptable_addprefix2(dns_iptable_t *tab, isc_netaddr_t *addr,
00070 isc_uint16_t bitlen, isc_boolean_t pos,
00071 isc_boolean_t is_ecs)
00072 {
00073 isc_result_t result;
00074 isc_prefix_t pfx;
00075 isc_radix_node_t *node = NULL;
00076 int i;
00077
00078 INSIST(DNS_IPTABLE_VALID(tab));
00079 INSIST(tab->radix);
00080
00081 NETADDR_TO_PREFIX_T(addr, pfx, bitlen, is_ecs);
00082
00083 result = isc_radix_insert(tab->radix, &node, NULL, &pfx);
00084 if (result != ISC_R_SUCCESS) {
00085 isc_refcount_destroy(&pfx.refcount);
00086 return(result);
00087 }
00088
00089
00090 if (pfx.family == AF_UNSPEC) {
00091
00092 INSIST(pfx.bitlen == 0);
00093 for (i = 0; i < 4; i++) {
00094 if (node->data[i] == NULL)
00095 node->data[i] = pos ? &dns_iptable_pos
00096 : &dns_iptable_neg;
00097 }
00098 } else {
00099
00100 int offset = ISC_RADIX_OFF(&pfx);
00101 if (node->data[offset] == NULL) {
00102 node->data[offset] = pos ? &dns_iptable_pos
00103 : &dns_iptable_neg;
00104 }
00105 }
00106
00107 isc_refcount_destroy(&pfx.refcount);
00108 return (ISC_R_SUCCESS);
00109 }
00110
00111
00112
00113
00114 isc_result_t
00115 dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos)
00116 {
00117 isc_result_t result;
00118 isc_radix_node_t *node, *new_node;
00119 int i, max_node = 0;
00120
00121 RADIX_WALK (source->radix->head, node) {
00122 new_node = NULL;
00123 result = isc_radix_insert (tab->radix, &new_node, node, NULL);
00124
00125 if (result != ISC_R_SUCCESS)
00126 return(result);
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 for (i = 0; i < 4; i++) {
00137 if (!pos) {
00138 if (node->data[i] &&
00139 *(isc_boolean_t *) node->data[i])
00140 new_node->data[i] = &dns_iptable_neg;
00141 }
00142 if (node->node_num[i] > max_node)
00143 max_node = node->node_num[i];
00144 }
00145 } RADIX_WALK_END;
00146
00147 tab->radix->num_added_node += max_node;
00148 return (ISC_R_SUCCESS);
00149 }
00150
00151 void
00152 dns_iptable_attach(dns_iptable_t *source, dns_iptable_t **target) {
00153 REQUIRE(DNS_IPTABLE_VALID(source));
00154 isc_refcount_increment(&source->refcount, NULL);
00155 *target = source;
00156 }
00157
00158 void
00159 dns_iptable_detach(dns_iptable_t **tabp) {
00160 dns_iptable_t *tab = *tabp;
00161 unsigned int refs;
00162 REQUIRE(DNS_IPTABLE_VALID(tab));
00163 isc_refcount_decrement(&tab->refcount, &refs);
00164 if (refs == 0)
00165 destroy_iptable(tab);
00166 *tabp = NULL;
00167 }
00168
00169 static void
00170 destroy_iptable(dns_iptable_t *dtab) {
00171
00172 REQUIRE(DNS_IPTABLE_VALID(dtab));
00173
00174 if (dtab->radix != NULL) {
00175 isc_radix_destroy(dtab->radix, NULL);
00176 dtab->radix = NULL;
00177 }
00178
00179 isc_refcount_destroy(&dtab->refcount);
00180 dtab->magic = 0;
00181 isc_mem_putanddetach(&dtab->mctx, dtab, sizeof(*dtab));
00182 }