📄 adb.c
字号:
*/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(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES"); if ((notify) != 0) { find->flags &= ~addrs; process = ISC_TRUE; } break; case DNS_EVENT_ADBNOMOREADDRESSES: DP(ISC_LOG_DEBUG(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; 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; f->fetch = NULL; f->namehook = new_adbnamehook(adb, NULL); if (f->namehook == NULL) goto err; f->entry = new_adbentry(adb); if (f->entry == NULL) goto err; dns_rdataset_init(&f->rdataset); f->magic = DNS_ADBFETCH_MAGIC; return (f); err: if (f->namehook != NULL) free_adbnamehook(adb, &f->namehook); if (f->entry != NULL) free_adbentry(adb, &f->entry); isc_mempool_put(adb->afmp, f); return (NULL);}static inline voidfree_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) { dns_adbfetch_t *f; INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch)); f = *fetch; *fetch = NULL; f->magic = 0; if (f->namehook != NULL) free_adbnamehook(adb, &f->namehook); if (f->entry != NULL) free_adbentry(adb, &f->entry); if (dns_rdataset_isassociated(&f->rdataset)) dns_rdataset_disassociate(&f->rdataset); isc_mempool_put(adb->afmp, f);}static inline isc_boolean_tfree_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) { dns_adbfind_t *find; INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp)); find = *findp; *findp = NULL; INSIST(!FIND_HAS_ADDRS(find)); INSIST(!ISC_LINK_LINKED(find, publink)); INSIST(!ISC_LINK_LINKED(find, plink)); INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET); INSIST(find->adbname == NULL); find->magic = 0; DESTROYLOCK(&find->lock); isc_mempool_put(adb->ahmp, find); return (dec_adb_irefcnt(adb));}/* * Copy bits from the entry into the newly allocated addrinfo. The entry * must be locked, and the reference count must be bumped up by one * if this function returns a valid pointer. */static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -