📄 rbtdb.c
字号:
* If we have to set foundname, we do it before anything else. * If we were to set foundname after we had set nodep or bound the * rdataset, then we'd have to undo that work if dns_name_copy() * failed. By setting foundname first, there's nothing to undo if * we have trouble. */ if (foundname != NULL && search->copy_name) { zcname = dns_fixedname_name(&search->zonecut_name); result = dns_name_copy(zcname, foundname, NULL); if (result != ISC_R_SUCCESS) return (result); } if (nodep != NULL) { /* * Note that we don't have to increment the node's reference * count here because we're going to use the reference we * already have in the search block. */ *nodep = node; search->need_cleanup = ISC_FALSE; } if (rdataset != NULL) { LOCK(&(search->rbtdb->node_locks[node->locknum].lock)); bind_rdataset(search->rbtdb, node, search->zonecut_rdataset, search->now, rdataset); if (sigrdataset != NULL && search->zonecut_sigrdataset != NULL) bind_rdataset(search->rbtdb, node, search->zonecut_sigrdataset, search->now, sigrdataset); UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock)); } if (type == dns_rdatatype_dname) return (DNS_R_DNAME); return (DNS_R_DELEGATION);}static inline isc_boolean_tvalid_glue(rbtdb_search_t *search, dns_name_t *name, rbtdb_rdatatype_t type, dns_rbtnode_t *node){ unsigned char *raw; unsigned int count, size; dns_name_t ns_name; isc_boolean_t valid = ISC_FALSE; dns_offsets_t offsets; isc_region_t region; rdatasetheader_t *header; /* * No additional locking is required. */ /* * Valid glue types are A, AAAA, A6. NS is also a valid glue type * if it occurs at a zone cut, but is not valid below it. */ if (type == dns_rdatatype_ns) { if (node != search->zonecut) { return (ISC_FALSE); } } else if (type != dns_rdatatype_a && type != dns_rdatatype_aaaa && type != dns_rdatatype_a6) { return (ISC_FALSE); } header = search->zonecut_rdataset; raw = (unsigned char *)header + sizeof(*header); count = raw[0] * 256 + raw[1]; raw += 2; while (count > 0) { count--; size = raw[0] * 256 + raw[1]; raw += 2; region.base = raw; region.length = size; raw += size; /* * XXX Until we have rdata structures, we have no choice but * to directly access the rdata format. */ dns_name_init(&ns_name, offsets); dns_name_fromregion(&ns_name, ®ion); if (dns_name_compare(&ns_name, name) == 0) { valid = ISC_TRUE; break; } } return (valid);}static inline isc_boolean_tactiveempty(rbtdb_search_t *search, dns_rbtnodechain_t *chain, dns_name_t *name){ dns_fixedname_t fnext; dns_fixedname_t forigin; dns_name_t *next; dns_name_t *origin; dns_name_t prefix; dns_rbtdb_t *rbtdb; dns_rbtnode_t *node; isc_result_t result; isc_boolean_t answer = ISC_FALSE; rdatasetheader_t *header; rbtdb = search->rbtdb; dns_name_init(&prefix, NULL); dns_fixedname_init(&fnext); next = dns_fixedname_name(&fnext); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); result = dns_rbtnodechain_next(chain, NULL, NULL); while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) { node = NULL; result = dns_rbtnodechain_current(chain, &prefix, origin, &node); if (result != ISC_R_SUCCESS) break; LOCK(&(rbtdb->node_locks[node->locknum].lock)); for (header = node->data; header != NULL; header = header->next) { if (header->serial <= search->serial && !IGNORE(header) && EXISTS(header)) break; } UNLOCK(&(rbtdb->node_locks[node->locknum].lock)); if (header != NULL) break; result = dns_rbtnodechain_next(chain, NULL, NULL); } if (result == ISC_R_SUCCESS) result = dns_name_concatenate(&prefix, origin, next, NULL); if (result == ISC_R_SUCCESS && dns_name_issubdomain(next, name)) answer = ISC_TRUE; return (answer);}static inline isc_boolean_tactiveemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) { dns_fixedname_t fnext; dns_fixedname_t forigin; dns_fixedname_t fprev; dns_name_t *next; dns_name_t *origin; dns_name_t *prev; dns_name_t name; dns_name_t rname; dns_name_t tname; dns_rbtdb_t *rbtdb; dns_rbtnode_t *node; dns_rbtnodechain_t chain; isc_boolean_t check_next = ISC_TRUE; isc_boolean_t check_prev = ISC_TRUE; isc_boolean_t answer = ISC_FALSE; isc_result_t result; rdatasetheader_t *header; unsigned int n; rbtdb = search->rbtdb; dns_name_init(&name, NULL); dns_name_init(&tname, NULL); dns_name_init(&rname, NULL); dns_fixedname_init(&fnext); next = dns_fixedname_name(&fnext); dns_fixedname_init(&fprev); prev = dns_fixedname_name(&fprev); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); /* * Find if qname is at or below a empty node. * Use our own copy of the chain. */ chain = search->chain; do { node = NULL; result = dns_rbtnodechain_current(&chain, &name, origin, &node); if (result != ISC_R_SUCCESS) break; LOCK(&(rbtdb->node_locks[node->locknum].lock)); for (header = node->data; header != NULL; header = header->next) { if (header->serial <= search->serial && !IGNORE(header) && EXISTS(header)) break; } UNLOCK(&(rbtdb->node_locks[node->locknum].lock)); if (header != NULL) break; result = dns_rbtnodechain_prev(&chain, NULL, NULL); } while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN); if (result == ISC_R_SUCCESS) result = dns_name_concatenate(&name, origin, prev, NULL); if (result != ISC_R_SUCCESS) check_prev = ISC_FALSE; result = dns_rbtnodechain_next(&chain, NULL, NULL); while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) { node = NULL; result = dns_rbtnodechain_current(&chain, &name, origin, &node); if (result != ISC_R_SUCCESS) break; LOCK(&(rbtdb->node_locks[node->locknum].lock)); for (header = node->data; header != NULL; header = header->next) { if (header->serial <= search->serial && !IGNORE(header) && EXISTS(header)) break; } UNLOCK(&(rbtdb->node_locks[node->locknum].lock)); if (header != NULL) break; result = dns_rbtnodechain_next(&chain, NULL, NULL); } if (result == ISC_R_SUCCESS) result = dns_name_concatenate(&name, origin, next, NULL); if (result != ISC_R_SUCCESS) check_next = ISC_FALSE; dns_name_clone(qname, &rname); /* * Remove the wildcard label to find the terminal name. */ n = dns_name_countlabels(wname); dns_name_getlabelsequence(wname, 1, n - 1, &tname); do { if ((check_prev && dns_name_issubdomain(prev, &rname)) || (check_next && dns_name_issubdomain(next, &rname))) { answer = ISC_TRUE; break; } /* * Remove the left hand label. */ n = dns_name_countlabels(&rname); dns_name_getlabelsequence(&rname, 1, n - 1, &rname); } while (!dns_name_equal(&rname, &tname)); return (answer);}static inline isc_result_tfind_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep, dns_name_t *qname){ unsigned int i, j; dns_rbtnode_t *node, *level_node, *wnode; rdatasetheader_t *header; isc_result_t result = ISC_R_NOTFOUND; dns_name_t name; dns_name_t *wname; dns_fixedname_t fwname; dns_rbtdb_t *rbtdb; isc_boolean_t done, wild, active; dns_rbtnodechain_t wchain; /* * Caller must be holding the tree lock and MUST NOT be holding * any node locks. */ /* * Examine each ancestor level. If the level's wild bit * is set, then construct the corresponding wildcard name and * search for it. If the wildcard node exists, and is active in * this version, we're done. If not, then we next check to see * if the ancestor is active in this version. If so, then there * can be no possible wildcard match and again we're done. If not, * continue the search. */ rbtdb = search->rbtdb; i = search->chain.level_matches; done = ISC_FALSE; node = *nodep; do { LOCK(&(rbtdb->node_locks[node->locknum].lock)); /* * First we try to figure out if this node is active in * the search's version. We do this now, even though we * may not need the information, because it simplifies the * locking and code flow. */ for (header = node->data; header != NULL; header = header->next) { if (header->serial <= search->serial && !IGNORE(header) && EXISTS(header)) break; } if (header != NULL) active = ISC_TRUE; else active = ISC_FALSE; if (node->wild) wild = ISC_TRUE; else wild = ISC_FALSE; UNLOCK(&(rbtdb->node_locks[node->locknum].lock)); if (wild) { /* * Construct the wildcard name for this level. */ dns_name_init(&name, NULL); dns_rbt_namefromnode(node, &name); dns_fixedname_init(&fwname); wname = dns_fixedname_name(&fwname); result = dns_name_concatenate(dns_wildcardname, &name, wname, NULL); j = i; while (result == ISC_R_SUCCESS && j != 0) { j--; level_node = search->chain.levels[j]; dns_name_init(&name, NULL); dns_rbt_namefromnode(level_node, &name); result = dns_name_concatenate(wname, &name, wname, NULL); } if (result != ISC_R_SUCCESS) break; wnode = NULL; dns_rbtnodechain_init(&wchain, NULL); result = dns_rbt_findnode(rbtdb->tree, wname, NULL, &wnode, &wchain, DNS_RBTFIND_EMPTYDATA, NULL, NULL); if (result == ISC_R_SUCCESS) { /* * We have found the wildcard node. If it * is active in the search's version, we're * done. */ LOCK(&(rbtdb->node_locks[wnode->locknum].lock)); for (header = wnode->data; header != NULL; header = header->next) { if (header->serial <= search->serial && !IGNORE(header) && EXISTS(header)) break; } UNLOCK(&(rbtdb->node_locks[wnode->locknum].lock)); if (header != NULL || activeempty(search, &wchain, wname)) { if (activeemtpynode(search, qname, wname)) return (ISC_R_NOTFOUND); /* * The wildcard node is active! * * Note: result is still ISC_R_SUCCESS * so we don't have to set it. */ *nodep = wnode; break; } } else if (result != ISC_R_NOTFOUND && result != DNS_R_PARTIALMATCH) { /* * An error has occurred. Bail out. */ break; } } if (active) { /* * The level node is active. Any wildcarding * present at higher levels has no * effect and we're done. */ result = ISC_R_NOTFOUND; break; } if (i > 0) { i--; node = search->chain.levels[i]; } else done = ISC_TRUE; } while (!done); return (result);}static inline isc_result_tfind_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, isc_boolean_t need_sig){ dns_rbtnode_t *node; rdatasetheader_t *header, *header_next, *found, *foundsig; isc_boolean_t empty_node; isc_result_t result; dns_fixedname_t fname, forigin; dns_name_t *name, *origin; do { node = NULL; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); result = dns_rbtnodechain_current(&search->chain, name, origin, &node); if (result != ISC_R_SUCCESS) return (result); LOCK(&(search->rbtdb->node_locks[node->locknum].lock)); found = NULL; foundsig = NULL; empty_node = ISC_TRUE; for (header = node->data; header != NULL; header = header_next) { header_next = header->next; /* * Look for an active, extant NSEC or RRSIG NSEC. */ do { if (header->serial <= search->serial && !IGNORE(header)) { /* * Is this a "this rdataset doesn't * exist" record? */ if (NONEXISTENT(header)) header = NULL; break; } else header = header->down; } while (header != NULL); if (header != NULL) { /* * We now know that there is at least one * active rdataset at this node. */ empty_node = ISC_FALSE; if (header->type == dns_rdatatype_nsec) { found = header; if (foundsig != NULL) break; } else if (header->type == RBTDB_RDATATYPE_SIGNSEC) { foundsig = header; if (found != NULL) break; } } } if (!empty_node) { if (found != NULL && (foundsig != NULL || !need_sig)) { /* * We've found the right NSEC record. * * Note: for this to really be the right * NSEC record, it's essential that the NSEC * records of any nodes obscured by a zone * cut have been removed; we assume this is * the case. */ result = dns_name_concatenate(name, origin, foundname, NULL); if (result == ISC_R_SUCCESS) { if (nodep != NULL) { new_reference(search->rbtdb, node); *nodep = node; } bind_rdataset(search->rbtdb, node, found, search->now, rdataset); if (foundsig != NULL) bind_rdataset(search->rbtdb, node, foundsig, search->now, sigrdataset); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -