📄 adb.c
字号:
static isc_result_tset_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname, dns_rdataset_t *rdataset, dns_name_t *target){ isc_result_t result; dns_namereln_t namereln; unsigned int nlabels, nbits; int order; dns_rdata_t rdata = DNS_RDATA_INIT; dns_fixedname_t fixed1, fixed2; dns_name_t *prefix, *new_target; REQUIRE(dns_name_countlabels(target) == 0); if (rdataset->type == dns_rdatatype_cname) { dns_rdata_cname_t cname; /* * Copy the CNAME's target into the target name. */ result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) return (result); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &cname, NULL); if (result != ISC_R_SUCCESS) return (result); result = dns_name_dup(&cname.cname, adb->mctx, target); dns_rdata_freestruct(&cname); if (result != ISC_R_SUCCESS) return (result); } else { dns_rdata_dname_t dname; INSIST(rdataset->type == dns_rdatatype_dname); namereln = dns_name_fullcompare(name, fname, &order, &nlabels, &nbits); INSIST(namereln == dns_namereln_subdomain); /* * Get the target name of the DNAME. */ result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) return (result); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &dname, NULL); if (result != ISC_R_SUCCESS) return (result); /* * Construct the new target name. */ dns_fixedname_init(&fixed1); prefix = dns_fixedname_name(&fixed1); dns_fixedname_init(&fixed2); new_target = dns_fixedname_name(&fixed2); result = dns_name_split(name, nlabels, nbits, prefix, NULL); if (result != ISC_R_SUCCESS) { dns_rdata_freestruct(&dname); return (result); } result = dns_name_concatenate(prefix, &dname.dname, new_target, NULL); dns_rdata_freestruct(&dname); if (result != ISC_R_SUCCESS) return (result); result = dns_name_dup(new_target, adb->mctx, target); if (result != ISC_R_SUCCESS) return (result); } return (ISC_R_SUCCESS);}/* * Assumes nothing is locked, since this is called by the client. */static voidevent_free(isc_event_t *event) { dns_adbfind_t *find; INSIST(event != NULL); find = event->ev_destroy_arg; INSIST(DNS_ADBFIND_VALID(find)); LOCK(&find->lock); find->flags |= FIND_EVENT_FREED; event->ev_destroy_arg = NULL; UNLOCK(&find->lock);}/* * Assumes the name bucket is locked. */static voidclean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype, unsigned int addrs){ isc_event_t *ev; isc_task_t *task; dns_adbfind_t *find; dns_adbfind_t *next_find; isc_boolean_t process; unsigned int wanted, notify; DP(ENTER_LEVEL, "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x", name, evtype, addrs); find = ISC_LIST_HEAD(name->finds); while (find != NULL) { LOCK(&find->lock); next_find = ISC_LIST_NEXT(find, plink); process = ISC_FALSE; wanted = find->flags & DNS_ADBFIND_ADDRESSMASK; notify = wanted & addrs; switch (evtype) { case DNS_EVENT_ADBMOREADDRESSES: DP(3, "DNS_EVENT_ADBMOREADDRESSES"); if ((notify) != 0) { find->flags &= ~addrs; process = ISC_TRUE; } break; case DNS_EVENT_ADBNOMOREADDRESSES: DP(3, "DNS_EVENT_ADBNOMOREADDRESSES"); find->flags &= ~addrs; wanted = find->flags & DNS_ADBFIND_ADDRESSMASK; if (wanted == 0) process = ISC_TRUE; break; default: find->flags &= ~addrs; process = ISC_TRUE; } if (process) { DP(DEF_LEVEL, "cfan: processing find %p", find); /* * Unlink the find from the name, letting the caller * call dns_adb_destroyfind() on it to clean it up * later. */ ISC_LIST_UNLINK(name->finds, find, plink); find->adbname = NULL; find->name_bucket = DNS_ADB_INVALIDBUCKET; INSIST(!FIND_EVENTSENT(find)); ev = &find->event; task = ev->ev_sender; ev->ev_sender = find; find->result_v4 = find_err_map[name->fetch_err]; find->result_v6 = find_err_map[name->fetch6_err]; ev->ev_type = evtype; ev->ev_destroy = event_free; ev->ev_destroy_arg = find; DP(DEF_LEVEL, "Sending event %p to task %p for find %p", ev, task, find); isc_task_sendanddetach(&task, (isc_event_t **)&ev); } else { DP(DEF_LEVEL, "cfan: skipping find %p", find); } UNLOCK(&find->lock); find = next_find; } DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);}static inline voidcheck_exit(dns_adb_t *adb) { isc_event_t *event; /* * The caller must be holding the adb lock. */ if (adb->shutting_down) { /* * If there aren't any external references either, we're * done. Send the control event to initiate shutdown. */ INSIST(!adb->cevent_sent); /* Sanity check. */ event = &adb->cevent; isc_task_send(adb->task, &event); adb->cevent_sent = ISC_TRUE; }}static inline isc_boolean_tdec_adb_irefcnt(dns_adb_t *adb) { isc_event_t *event; isc_task_t *etask; isc_boolean_t result = ISC_FALSE; LOCK(&adb->reflock); INSIST(adb->irefcnt > 0); adb->irefcnt--; if (adb->irefcnt == 0) { event = ISC_LIST_HEAD(adb->whenshutdown); while (event != NULL) { ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link); etask = event->ev_sender; event->ev_sender = adb; isc_task_sendanddetach(&etask, &event); event = ISC_LIST_HEAD(adb->whenshutdown); } } if (adb->irefcnt == 0 && adb->erefcnt == 0) result = ISC_TRUE; UNLOCK(&adb->reflock); return (result);}static inline voidinc_adb_irefcnt(dns_adb_t *adb) { LOCK(&adb->reflock); adb->irefcnt++; UNLOCK(&adb->reflock);}static inline voidinc_adb_erefcnt(dns_adb_t *adb) { LOCK(&adb->reflock); adb->erefcnt++; UNLOCK(&adb->reflock);}static inline voidinc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) { int bucket; bucket = entry->lock_bucket; if (lock) LOCK(&adb->entrylocks[bucket]); entry->refcnt++; if (lock) UNLOCK(&adb->entrylocks[bucket]);}static inline isc_boolean_tdec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) { int bucket; isc_boolean_t destroy_entry; isc_boolean_t result = ISC_FALSE; bucket = entry->lock_bucket; if (lock) LOCK(&adb->entrylocks[bucket]); INSIST(entry->refcnt > 0); entry->refcnt--; destroy_entry = ISC_FALSE; if (entry->refcnt == 0 && (adb->entry_sd[bucket] || entry->expires == 0)) { destroy_entry = ISC_TRUE; result = unlink_entry(adb, entry); } if (lock) UNLOCK(&adb->entrylocks[bucket]); if (!destroy_entry) return (result); entry->lock_bucket = DNS_ADB_INVALIDBUCKET; free_adbentry(adb, &entry); if (result) result =dec_adb_irefcnt(adb); return (result);}static inline dns_adbname_t *new_adbname(dns_adb_t *adb, dns_name_t *dnsname) { dns_adbname_t *name; name = isc_mempool_get(adb->nmp); if (name == NULL) return (NULL); dns_name_init(&name->name, NULL); if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) { isc_mempool_put(adb->nmp, name); return (NULL); } dns_name_init(&name->target, NULL); name->magic = DNS_ADBNAME_MAGIC; name->adb = adb; name->partial_result = 0; name->flags = 0; name->expire_v4 = INT_MAX; name->expire_v6 = INT_MAX; name->expire_target = INT_MAX; name->chains = 0; name->lock_bucket = DNS_ADB_INVALIDBUCKET; ISC_LIST_INIT(name->v4); ISC_LIST_INIT(name->v6); name->fetch_a = NULL; name->fetch_aaaa = NULL; ISC_LIST_INIT(name->fetches_a6); name->fetch_err = FIND_ERR_UNEXPECTED; name->fetch6_err = FIND_ERR_UNEXPECTED; ISC_LIST_INIT(name->finds); ISC_LINK_INIT(name, plink); return (name);}static inline voidfree_adbname(dns_adb_t *adb, dns_adbname_t **name) { dns_adbname_t *n; INSIST(name != NULL && DNS_ADBNAME_VALID(*name)); n = *name; *name = NULL; INSIST(!NAME_HAS_V4(n)); INSIST(!NAME_HAS_V6(n)); INSIST(!NAME_FETCH(n)); INSIST(ISC_LIST_EMPTY(n->finds)); INSIST(!ISC_LINK_LINKED(n, plink)); INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET); INSIST(n->adb == adb); n->magic = 0; dns_name_free(&n->name, adb->mctx); isc_mempool_put(adb->nmp, n);}static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) { dns_adbnamehook_t *nh; nh = isc_mempool_get(adb->nhmp); if (nh == NULL) return (NULL); nh->magic = DNS_ADBNAMEHOOK_MAGIC; nh->entry = entry; ISC_LINK_INIT(nh, plink); return (nh);}static inline voidfree_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) { dns_adbnamehook_t *nh; INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook)); nh = *namehook; *namehook = NULL; INSIST(nh->entry == NULL); INSIST(!ISC_LINK_LINKED(nh, plink)); nh->magic = 0; isc_mempool_put(adb->nhmp, nh);}static inline dns_adbzoneinfo_t *new_adbzoneinfo(dns_adb_t *adb, dns_name_t *zone) { dns_adbzoneinfo_t *zi; zi = isc_mempool_get(adb->zimp); if (zi == NULL) return (NULL); dns_name_init(&zi->zone, NULL); if (dns_name_dup(zone, adb->mctx, &zi->zone) != ISC_R_SUCCESS) { isc_mempool_put(adb->zimp, zi); return (NULL); } zi->magic = DNS_ADBZONEINFO_MAGIC; zi->lame_timer = 0; ISC_LINK_INIT(zi, plink); return (zi);}static inline voidfree_adbzoneinfo(dns_adb_t *adb, dns_adbzoneinfo_t **zoneinfo) { dns_adbzoneinfo_t *zi; INSIST(zoneinfo != NULL && DNS_ADBZONEINFO_VALID(*zoneinfo)); zi = *zoneinfo; *zoneinfo = NULL; INSIST(!ISC_LINK_LINKED(zi, plink)); dns_name_free(&zi->zone, adb->mctx); zi->magic = 0; isc_mempool_put(adb->zimp, zi);}static inline dns_adbentry_t *new_adbentry(dns_adb_t *adb) { dns_adbentry_t *e; isc_uint32_t r; e = isc_mempool_get(adb->emp); if (e == NULL) return (NULL); e->magic = DNS_ADBENTRY_MAGIC; e->lock_bucket = DNS_ADB_INVALIDBUCKET; e->refcnt = 0; e->flags = 0; isc_random_get(&r); e->srtt = (r & 0x1f) + 1; e->expires = 0; ISC_LIST_INIT(e->zoneinfo); ISC_LINK_INIT(e, plink); return (e);}static inline voidfree_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) { dns_adbentry_t *e; dns_adbzoneinfo_t *zi; INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry)); e = *entry; *entry = NULL; INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET); INSIST(e->refcnt == 0); INSIST(!ISC_LINK_LINKED(e, plink)); e->magic = 0; zi = ISC_LIST_HEAD(e->zoneinfo); while (zi != NULL) { ISC_LIST_UNLINK(e->zoneinfo, zi, plink); free_adbzoneinfo(adb, &zi); zi = ISC_LIST_HEAD(e->zoneinfo); } isc_mempool_put(adb->emp, e);}static inline dns_adbfind_t *new_adbfind(dns_adb_t *adb) { dns_adbfind_t *h; isc_result_t result; h = isc_mempool_get(adb->ahmp); if (h == NULL) return (NULL); /* * Public members. */ h->magic = 0; h->adb = adb; h->partial_result = 0; h->options = 0; h->flags = 0; h->result_v4 = ISC_R_UNEXPECTED; h->result_v6 = ISC_R_UNEXPECTED; ISC_LINK_INIT(h, publink); ISC_LINK_INIT(h, plink); ISC_LIST_INIT(h->list); h->adbname = NULL; h->name_bucket = DNS_ADB_INVALIDBUCKET; /* * private members */ result = isc_mutex_init(&h->lock); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_mutex_init failed in new_adbfind()"); isc_mempool_put(adb->ahmp, h); return (NULL); } ISC_EVENT_INIT(&h->event, sizeof (isc_event_t), 0, 0, 0, NULL, NULL, NULL, NULL, h); inc_adb_irefcnt(adb); h->magic = DNS_ADBFIND_MAGIC; return (h);}static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *adb) { dns_adbfetch_t *f; f = isc_mempool_get(adb->afmp); if (f == NULL) return (NULL); f->magic = 0; f->namehook = NULL; f->entry = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -