/*% * Allocates a key structure and fills in some of the fields. */ static dst_key_t * get_key_struct(dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, unsigned int bits, dns_rdataclass_t rdclass, isc_mem_t *mctx) { dst_key_t *key; isc_result_t result; int i; key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t)); if (key == NULL) return (NULL); memset(key, 0, sizeof(dst_key_t)); key->magic = KEY_MAGIC; result = isc_refcount_init(&key->refs, 1); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, key, sizeof(dst_key_t)); return (NULL); } key->key_name = isc_mem_get(mctx, sizeof(dns_name_t)); if (key->key_name == NULL) { isc_refcount_destroy(&key->refs); isc_mem_put(mctx, key, sizeof(dst_key_t)); return (NULL); } dns_name_init(key->key_name, NULL); result = dns_name_dup(name, mctx, key->key_name); if (result != ISC_R_SUCCESS) { isc_refcount_destroy(&key->refs); isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); isc_mem_put(mctx, key, sizeof(dst_key_t)); return (NULL); } key->key_alg = alg; key->key_flags = flags; key->key_proto = protocol; key->mctx = mctx; key->keydata.generic = NULL; key->key_size = bits; key->key_class = rdclass; key->func = dst_t_func[alg]; key->fmt_major = 0; key->fmt_minor = 0; for (i = 0; i < (DST_MAX_TIMES + 1); i++) { key->times[i] = 0; key->timeset[i] = ISC_FALSE; } return (key); }
static void destroy(isc_hash_t **hctxp) { isc_hash_t *hctx; isc_mem_t *mctx; REQUIRE(hctxp != NULL && *hctxp != NULL); hctx = *hctxp; *hctxp = NULL; LOCK(&hctx->lock); isc_refcount_destroy(&hctx->refcnt); mctx = hctx->mctx; if (hctx->entropy != NULL) isc_entropy_detach(&hctx->entropy); if (hctx->rndvector != NULL) isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen); UNLOCK(&hctx->lock); DESTROYLOCK(&hctx->lock); memset(hctx, 0, sizeof(isc_hash_t)); isc_mem_put(mctx, hctx, sizeof(isc_hash_t)); isc_mem_detach(&mctx); }
static void destroy(isc_hash_t **hctxp) { isc_hash_t *hctx; isc_mem_t *mctx; unsigned char canary0[4], canary1[4]; REQUIRE(hctxp != NULL && *hctxp != NULL); hctx = *hctxp; *hctxp = NULL; LOCK(&hctx->lock); isc_refcount_destroy(&hctx->refcnt); mctx = hctx->mctx; #ifdef BIND9 if (hctx->entropy != NULL) isc_entropy_detach(&hctx->entropy); #endif if (hctx->rndvector != NULL) isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen); UNLOCK(&hctx->lock); DESTROYLOCK(&hctx->lock); memcpy(canary0, hctx + 1, sizeof(canary0)); memset(hctx, 0, sizeof(isc_hash_t)); memcpy(canary1, hctx + 1, sizeof(canary1)); INSIST(memcmp(canary0, canary1, sizeof(canary0)) == 0); isc_mem_put(mctx, hctx, sizeof(isc_hash_t)); isc_mem_detach(&mctx); }
static void destroy(dns_acl_t *dacl) { unsigned int i; INSIST(!ISC_LINK_LINKED(dacl, nextincache)); for (i = 0; i < dacl->length; i++) { dns_aclelement_t *de = &dacl->elements[i]; if (de->type == dns_aclelementtype_keyname) { dns_name_free(&de->keyname, dacl->mctx); } else if (de->type == dns_aclelementtype_nestedacl) { dns_acl_detach(&de->nestedacl); } } if (dacl->elements != NULL) isc_mem_put(dacl->mctx, dacl->elements, dacl->alloc * sizeof(dns_aclelement_t)); if (dacl->name != NULL) isc_mem_free(dacl->mctx, dacl->name); if (dacl->iptable != NULL) dns_iptable_detach(&dacl->iptable); isc_refcount_destroy(&dacl->refcount); dacl->magic = 0; isc_mem_put(dacl->mctx, dacl, sizeof(*dacl)); }
void dst_key_free(dst_key_t **keyp) { isc_mem_t *mctx; dst_key_t *key; unsigned int refs; REQUIRE(dst_initialized == ISC_TRUE); REQUIRE(keyp != NULL && VALID_KEY(*keyp)); key = *keyp; mctx = key->mctx; isc_refcount_decrement(&key->refs, &refs); if (refs != 0) return; isc_refcount_destroy(&key->refs); if (key->keydata.generic != NULL) { INSIST(key->func->destroy != NULL); key->func->destroy(key); } if (key->engine != NULL) isc_mem_free(mctx, key->engine); if (key->label != NULL) isc_mem_free(mctx, key->label); dns_name_free(key->key_name, mctx); isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); if (key->key_tkeytoken) { isc_buffer_free(&key->key_tkeytoken); } memset(key, 0, sizeof(dst_key_t)); isc_mem_putanddetach(&mctx, key, sizeof(dst_key_t)); *keyp = NULL; }
static void destroy(dns_acl_t *dacl) { unsigned int i; for (i = 0; i < dacl->length; i++) { dns_aclelement_t *de = &dacl->elements[i]; switch (de->type) { case dns_aclelementtype_keyname: dns_name_free(&de->u.keyname, dacl->mctx); break; case dns_aclelementtype_nestedacl: dns_acl_detach(&de->u.nestedacl); break; default: break; } } if (dacl->elements != NULL) isc_mem_put(dacl->mctx, dacl->elements, dacl->alloc * sizeof(dns_aclelement_t)); if (dacl->name != NULL) isc_mem_free(dacl->mctx, dacl->name); isc_refcount_destroy(&dacl->refcount); dacl->magic = 0; isc_mem_put(dacl->mctx, dacl, sizeof(*dacl)); }
void dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) { unsigned int refs; dns_keynode_t *node = *keynode; REQUIRE(VALID_KEYNODE(node)); isc_refcount_decrement(&node->refcount, &refs); if (refs == 0) { if (node->key != NULL) dst_key_free(&node->key); isc_refcount_destroy(&node->refcount); isc_mem_put(mctx, node, sizeof(dns_keynode_t)); } *keynode = NULL; }
static void tsigkey_free(dns_tsigkey_t *key) { REQUIRE(VALID_TSIG_KEY(key)); key->magic = 0; dns_name_free(&key->name, key->mctx); if (algname_is_allocated(key->algorithm)) { dns_name_free(key->algorithm, key->mctx); isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t)); } if (key->key != NULL) dst_key_free(&key->key); if (key->creator != NULL) { dns_name_free(key->creator, key->mctx); isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t)); } isc_refcount_destroy(&key->refs); isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t)); }
void dns_portlist_detach(dns_portlist_t **portlistp) { dns_portlist_t *portlist; unsigned int count; REQUIRE(portlistp != NULL); portlist = *portlistp; REQUIRE(DNS_VALID_PORTLIST(portlist)); *portlistp = NULL; isc_refcount_decrement(&portlist->refcount, &count); if (count == 0) { portlist->magic = 0; isc_refcount_destroy(&portlist->refcount); if (portlist->list != NULL) isc_mem_put(portlist->mctx, portlist->list, portlist->allocated * sizeof(*portlist->list)); DESTROYLOCK(&portlist->lock); isc_mem_putanddetach(&portlist->mctx, portlist, sizeof(*portlist)); } }
void dns_order_detach(dns_order_t **orderp) { dns_order_t *order; dns_order_ent_t *ent; unsigned int references; REQUIRE(orderp != NULL); order = *orderp; REQUIRE(DNS_ORDER_VALID(order)); isc_refcount_decrement(&order->references, &references); *orderp = NULL; if (references != 0) return; order->magic = 0; while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) { ISC_LIST_UNLINK(order->ents, ent, link); isc_mem_put(order->mctx, ent, sizeof(*ent)); } isc_refcount_destroy(&order->references); isc_mem_putanddetach(&order->mctx, order, sizeof(*order)); }
isc_result_t dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name, dns_view_t **viewp) { dns_view_t *view; isc_result_t result; /* * Create a view. */ REQUIRE(name != NULL); REQUIRE(viewp != NULL && *viewp == NULL); view = isc_mem_get(mctx, sizeof(*view)); if (view == NULL) return (ISC_R_NOMEMORY); view->mctx = NULL; isc_mem_attach(mctx, &view->mctx); view->name = isc_mem_strdup(mctx, name); if (view->name == NULL) { result = ISC_R_NOMEMORY; goto cleanup_view; } result = isc_mutex_init(&view->lock); if (result != ISC_R_SUCCESS) goto cleanup_name; view->zonetable = NULL; if (isc_bind9) { result = dns_zt_create(mctx, rdclass, &view->zonetable); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "dns_zt_create() failed: %s", isc_result_totext(result)); result = ISC_R_UNEXPECTED; goto cleanup_mutex; } } view->secroots_priv = NULL; view->fwdtable = NULL; result = dns_fwdtable_create(mctx, &view->fwdtable); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "dns_fwdtable_create() failed: %s", isc_result_totext(result)); result = ISC_R_UNEXPECTED; goto cleanup_zt; } view->acache = NULL; view->cache = NULL; view->cachedb = NULL; ISC_LIST_INIT(view->dlz_searched); ISC_LIST_INIT(view->dlz_unsearched); view->hints = NULL; view->resolver = NULL; view->adb = NULL; view->requestmgr = NULL; view->rdclass = rdclass; view->frozen = ISC_FALSE; view->task = NULL; result = isc_refcount_init(&view->references, 1); if (result != ISC_R_SUCCESS) goto cleanup_fwdtable; view->weakrefs = 0; view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN| DNS_VIEWATTR_REQSHUTDOWN); view->statickeys = NULL; view->dynamickeys = NULL; view->matchclients = NULL; view->matchdestinations = NULL; view->matchrecursiveonly = ISC_FALSE; result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys); if (result != ISC_R_SUCCESS) goto cleanup_references; view->peers = NULL; view->order = NULL; view->delonly = NULL; view->rootdelonly = ISC_FALSE; view->rootexclude = NULL; view->adbstats = NULL; view->resstats = NULL; view->resquerystats = NULL; view->cacheshared = ISC_FALSE; ISC_LIST_INIT(view->dns64); view->dns64cnt = 0; /* * Initialize configuration data with default values. */ view->recursion = ISC_TRUE; view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ view->additionalfromcache = ISC_TRUE; view->additionalfromauth = ISC_TRUE; view->enablednssec = ISC_TRUE; view->enablevalidation = ISC_TRUE; view->acceptexpired = ISC_FALSE; view->minimalresponses = ISC_FALSE; view->transfer_format = dns_one_answer; view->cacheacl = NULL; view->cacheonacl = NULL; view->queryacl = NULL; view->queryonacl = NULL; view->recursionacl = NULL; view->recursiononacl = NULL; view->sortlist = NULL; view->transferacl = NULL; view->notifyacl = NULL; view->updateacl = NULL; view->upfwdacl = NULL; view->denyansweracl = NULL; view->nocasecompress = NULL; view->answeracl_exclude = NULL; view->denyanswernames = NULL; view->answernames_exclude = NULL; view->rrl = NULL; view->provideixfr = ISC_TRUE; view->maxcachettl = 7 * 24 * 3600; view->maxncachettl = 3 * 3600; view->dstport = 53; view->preferred_glue = 0; view->flush = ISC_FALSE; view->dlv = NULL; view->maxudp = 0; view->situdp = 0; view->maxbits = 0; view->v4_aaaa = dns_aaaa_ok; view->v6_aaaa = dns_aaaa_ok; view->aaaa_acl = NULL; view->rpzs = NULL; dns_fixedname_init(&view->dlv_fixed); view->managed_keys = NULL; view->redirect = NULL; view->requestnsid = ISC_FALSE; view->requestsit = ISC_TRUE; view->new_zone_file = NULL; view->new_zone_config = NULL; view->cfg_destroy = NULL; if (isc_bind9) { result = dns_order_create(view->mctx, &view->order); if (result != ISC_R_SUCCESS) goto cleanup_dynkeys; } result = dns_peerlist_new(view->mctx, &view->peers); if (result != ISC_R_SUCCESS) goto cleanup_order; result = dns_aclenv_init(view->mctx, &view->aclenv); if (result != ISC_R_SUCCESS) goto cleanup_peerlist; ISC_LINK_INIT(view, link); ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL, DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, view, NULL, NULL, NULL); ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL, DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, view, NULL, NULL, NULL); ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL, DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, view, NULL, NULL, NULL); view->viewlist = NULL; view->magic = DNS_VIEW_MAGIC; *viewp = view; return (ISC_R_SUCCESS); cleanup_peerlist: if (view->peers != NULL) dns_peerlist_detach(&view->peers); cleanup_order: if (view->order != NULL) dns_order_detach(&view->order); cleanup_dynkeys: if (view->dynamickeys != NULL) dns_tsigkeyring_detach(&view->dynamickeys); cleanup_references: isc_refcount_destroy(&view->references); cleanup_fwdtable: if (view->fwdtable != NULL) dns_fwdtable_destroy(&view->fwdtable); cleanup_zt: if (view->zonetable != NULL) dns_zt_detach(&view->zonetable); cleanup_mutex: DESTROYLOCK(&view->lock); cleanup_name: isc_mem_free(mctx, view->name); cleanup_view: isc_mem_putanddetach(&view->mctx, view, sizeof(*view)); return (result); }
isc_result_t dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, dst_key_t *dstkey, isc_boolean_t generated, dns_name_t *creator, isc_stdtime_t inception, isc_stdtime_t expire, isc_mem_t *mctx, dns_tsig_keyring_t *ring, dns_tsigkey_t **key) { dns_tsigkey_t *tkey; isc_result_t ret; unsigned int refs = 0; REQUIRE(key == NULL || *key == NULL); REQUIRE(name != NULL); REQUIRE(algorithm != NULL); REQUIRE(mctx != NULL); REQUIRE(key != NULL || ring != NULL); tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t)); if (tkey == NULL) return (ISC_R_NOMEMORY); dns_name_init(&tkey->name, NULL); ret = dns_name_dup(name, mctx, &tkey->name); if (ret != ISC_R_SUCCESS) goto cleanup_key; (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { tkey->algorithm = DNS_TSIG_HMACMD5_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA1_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA224_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA224) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA256_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA256) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA384_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA384) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA512_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA512) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) { tkey->algorithm = DNS_TSIG_GSSAPI_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { ret = DNS_R_BADALG; goto cleanup_name; } } else { if (dstkey != NULL) { ret = DNS_R_BADALG; goto cleanup_name; } tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t)); if (tkey->algorithm == NULL) { ret = ISC_R_NOMEMORY; goto cleanup_name; } dns_name_init(tkey->algorithm, NULL); ret = dns_name_dup(algorithm, mctx, tkey->algorithm); if (ret != ISC_R_SUCCESS) goto cleanup_algorithm; (void)dns_name_downcase(tkey->algorithm, tkey->algorithm, NULL); } if (creator != NULL) { tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t)); if (tkey->creator == NULL) { ret = ISC_R_NOMEMORY; goto cleanup_algorithm; } dns_name_init(tkey->creator, NULL); ret = dns_name_dup(creator, mctx, tkey->creator); if (ret != ISC_R_SUCCESS) { isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); goto cleanup_algorithm; } } else tkey->creator = NULL; tkey->key = NULL; if (dstkey != NULL) dst_key_attach(dstkey, &tkey->key); tkey->ring = ring; if (key != NULL) refs = 1; if (ring != NULL) refs++; ret = isc_refcount_init(&tkey->refs, refs); if (ret != ISC_R_SUCCESS) goto cleanup_creator; tkey->generated = generated; tkey->inception = inception; tkey->expire = expire; tkey->mctx = NULL; isc_mem_attach(mctx, &tkey->mctx); ISC_LINK_INIT(tkey, link); tkey->magic = TSIG_MAGIC; if (ring != NULL) { ret = keyring_add(ring, name, tkey); if (ret != ISC_R_SUCCESS) goto cleanup_refs; } /* * Ignore this if it's a GSS key, since the key size is meaningless. */ if (dstkey != NULL && dst_key_size(dstkey) < 64 && !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) && !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG, ISC_LOG_INFO, "the key '%s' is too short to be secure", namestr); } if (key != NULL) *key = tkey; return (ISC_R_SUCCESS); cleanup_refs: tkey->magic = 0; while (refs-- > 0) isc_refcount_decrement(&tkey->refs, NULL); isc_refcount_destroy(&tkey->refs); cleanup_creator: if (tkey->key != NULL) dst_key_free(&tkey->key); if (tkey->creator != NULL) { dns_name_free(tkey->creator, mctx); isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); } cleanup_algorithm: if (algname_is_allocated(tkey->algorithm)) { if (dns_name_dynamic(tkey->algorithm)) dns_name_free(tkey->algorithm, mctx); isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t)); } cleanup_name: dns_name_free(&tkey->name, mctx); cleanup_key: isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t)); return (ret); }
/* * Determine whether a given address or signer matches a given ACL. * For a match with a positive ACL element or iptable radix entry, * return with a positive value in match; for a match with a negated ACL * element or radix entry, return with a negative value in match. */ isc_result_t dns_acl_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner, const dns_acl_t *acl, const dns_aclenv_t *env, int *match, const dns_aclelement_t **matchelt) { isc_uint16_t bitlen, family; isc_prefix_t pfx; isc_radix_node_t *node = NULL; const isc_netaddr_t *addr; isc_netaddr_t v4addr; isc_result_t result; int match_num = -1; unsigned int i; REQUIRE(reqaddr != NULL); REQUIRE(matchelt == NULL || *matchelt == NULL); if (env == NULL || env->match_mapped == ISC_FALSE || reqaddr->family != AF_INET6 || !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6)) addr = reqaddr; else { isc_netaddr_fromv4mapped(&v4addr, reqaddr); addr = &v4addr; } /* Always match with host addresses. */ family = addr->family; bitlen = family == AF_INET6 ? 128 : 32; NETADDR_TO_PREFIX_T(addr, pfx, bitlen); /* Assume no match. */ *match = 0; /* Search radix. */ result = isc_radix_search(acl->iptable->radix, &node, &pfx); /* Found a match. */ if (result == ISC_R_SUCCESS && node != NULL) { match_num = node->node_num[ISC_IS6(family)]; if (*(isc_boolean_t *) node->data[ISC_IS6(family)] == ISC_TRUE) *match = match_num; else *match = -match_num; } /* Now search non-radix elements for a match with a lower node_num. */ for (i = 0; i < acl->length; i++) { dns_aclelement_t *e = &acl->elements[i]; /* Already found a better match? */ if (match_num != -1 && match_num < e->node_num) { isc_refcount_destroy(&pfx.refcount); return (ISC_R_SUCCESS); } if (dns_aclelement_match(reqaddr, reqsigner, e, env, matchelt)) { if (match_num == -1 || e->node_num < match_num) { if (e->negative == ISC_TRUE) *match = -e->node_num; else *match = e->node_num; } isc_refcount_destroy(&pfx.refcount); return (ISC_R_SUCCESS); } } isc_refcount_destroy(&pfx.refcount); return (ISC_R_SUCCESS); }
isc_result_t dns_acl_match2(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner, const isc_netaddr_t *ecs, isc_uint8_t ecslen, isc_uint8_t *scope, const dns_acl_t *acl, const dns_aclenv_t *env, int *match, const dns_aclelement_t **matchelt) { isc_uint16_t bitlen; isc_prefix_t pfx; isc_radix_node_t *node = NULL; const isc_netaddr_t *addr = reqaddr; isc_netaddr_t v4addr; isc_result_t result; int match_num = -1; unsigned int i; REQUIRE(reqaddr != NULL); REQUIRE(matchelt == NULL || *matchelt == NULL); REQUIRE(ecs != NULL || scope == NULL); if (env != NULL && env->match_mapped && addr->family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&addr->type.in6)) { isc_netaddr_fromv4mapped(&v4addr, addr); addr = &v4addr; } /* Always match with host addresses. */ bitlen = (addr->family == AF_INET6) ? 128 : 32; NETADDR_TO_PREFIX_T(addr, pfx, bitlen, ISC_FALSE); /* Assume no match. */ *match = 0; /* Search radix. */ result = isc_radix_search(acl->iptable->radix, &node, &pfx); /* Found a match. */ if (result == ISC_R_SUCCESS && node != NULL) { int off = ISC_RADIX_OFF(&pfx); match_num = node->node_num[off]; if (*(isc_boolean_t *) node->data[off]) *match = match_num; else *match = -match_num; } isc_refcount_destroy(&pfx.refcount); /* * If ecs is not NULL, we search the radix tree again to * see if we find a better match on an ECS node */ if (ecs != NULL) { node = NULL; addr = ecs; if (env != NULL && env->match_mapped && addr->family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&addr->type.in6)) { isc_netaddr_fromv4mapped(&v4addr, addr); addr = &v4addr; } NETADDR_TO_PREFIX_T(addr, pfx, ecslen, ISC_TRUE); result = isc_radix_search(acl->iptable->radix, &node, &pfx); if (result == ISC_R_SUCCESS && node != NULL) { int off = ISC_RADIX_OFF(&pfx); if (match_num == -1 || node->node_num[off] < match_num) { match_num = node->node_num[off]; if (scope != NULL) *scope = node->bit; if (*(isc_boolean_t *) node->data[off]) *match = match_num; else *match = -match_num; } } isc_refcount_destroy(&pfx.refcount); } /* Now search non-radix elements for a match with a lower node_num. */ for (i = 0; i < acl->length; i++) { dns_aclelement_t *e = &acl->elements[i]; /* Already found a better match? */ if (match_num != -1 && match_num < e->node_num) { break; } if (dns_aclelement_match2(reqaddr, reqsigner, ecs, ecslen, scope, e, env, matchelt)) { if (match_num == -1 || e->node_num < match_num) { if (e->negative) *match = -e->node_num; else *match = e->node_num; } break; } } return (ISC_R_SUCCESS); }