ISC_TASKFUNC_SCOPE void isc__task_setprivilege(isc_task_t *task0, isc_boolean_t priv) { isc__task_t *task = (isc__task_t *)task0; isc__taskmgr_t *manager = task->manager; isc_boolean_t oldpriv; LOCK(&task->lock); oldpriv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0); if (priv) task->flags |= TASK_F_PRIVILEGED; else task->flags &= ~TASK_F_PRIVILEGED; UNLOCK(&task->lock); if (priv == oldpriv) return; LOCK(&manager->lock); if (priv && ISC_LINK_LINKED(task, ready_link)) ENQUEUE(manager->ready_priority_tasks, task, ready_priority_link); else if (!priv && ISC_LINK_LINKED(task, ready_priority_link)) DEQUEUE(manager->ready_priority_tasks, task, ready_priority_link); UNLOCK(&manager->lock); }
static void flush_lookup_list (void) { dig_lookup_t *l, *lp; dig_query_t *q, *qp; dig_server_t *s, *sp; lookup_counter = 0; l = ISC_LIST_HEAD (lookup_list); while (l != NULL) { q = ISC_LIST_HEAD (l->q); while (q != NULL) { if (q->sock != NULL) { isc_socket_cancel (q->sock, NULL, ISC_SOCKCANCEL_ALL); isc_socket_detach (&q->sock); } if (ISC_LINK_LINKED (&q->recvbuf, link)) ISC_LIST_DEQUEUE (q->recvlist, &q->recvbuf, link); if (ISC_LINK_LINKED (&q->lengthbuf, link)) ISC_LIST_DEQUEUE (q->lengthlist, &q->lengthbuf, link); isc_buffer_invalidate (&q->recvbuf); isc_buffer_invalidate (&q->lengthbuf); qp = q; q = ISC_LIST_NEXT (q, link); ISC_LIST_DEQUEUE (l->q, qp, link); isc_mem_free (mctx, qp); } s = ISC_LIST_HEAD (l->my_server_list); while (s != NULL) { sp = s; s = ISC_LIST_NEXT (s, link); ISC_LIST_DEQUEUE (l->my_server_list, sp, link); isc_mem_free (mctx, sp); } if (l->sendmsg != NULL) dns_message_destroy (&l->sendmsg); if (l->timer != NULL) isc_timer_detach (&l->timer); lp = l; l = ISC_LIST_NEXT (l, link); ISC_LIST_DEQUEUE (lookup_list, lp, link); isc_mem_free (mctx, lp); } }
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)); }
static inline isc_result_t generic_tostruct_ds(ARGS_TOSTRUCT) { dns_rdata_ds_t *ds = target; isc_region_t region; REQUIRE(target != NULL); REQUIRE(rdata->length != 0); REQUIRE(ds->common.rdtype == rdata->type); REQUIRE(ds->common.rdclass == rdata->rdclass); REQUIRE(!ISC_LINK_LINKED(&ds->common, link)); dns_rdata_toregion(rdata, ®ion); ds->key_tag = uint16_fromregion(®ion); isc_region_consume(®ion, 2); ds->algorithm = uint8_fromregion(®ion); isc_region_consume(®ion, 1); ds->digest_type = uint8_fromregion(®ion); isc_region_consume(®ion, 1); ds->length = region.length; ds->digest = mem_maybedup(mctx, region.base, region.length); if (ds->digest == NULL) return (ISC_R_NOMEMORY); ds->mctx = mctx; return (ISC_R_SUCCESS); }
static isc_result_t add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl, dns_namelist_t *namelist) { isc_result_t result; isc_region_t r, newr; dns_rdata_t *newrdata = NULL; dns_name_t *newname = NULL; dns_rdatalist_t *newlist = NULL; dns_rdataset_t *newset = NULL; isc_buffer_t *tmprdatabuf = NULL; RETERR(dns_message_gettemprdata(msg, &newrdata)); dns_rdata_toregion(rdata, &r); RETERR(isc_buffer_allocate(msg->mctx, &tmprdatabuf, r.length)); isc_buffer_availableregion(tmprdatabuf, &newr); memcpy(newr.base, r.base, r.length); dns_rdata_fromregion(newrdata, rdata->rdclass, rdata->type, &newr); dns_message_takebuffer(msg, &tmprdatabuf); RETERR(dns_message_gettempname(msg, &newname)); dns_name_init(newname, NULL); RETERR(dns_name_dup(name, msg->mctx, newname)); RETERR(dns_message_gettemprdatalist(msg, &newlist)); newlist->rdclass = newrdata->rdclass; newlist->type = newrdata->type; newlist->covers = 0; newlist->ttl = ttl; ISC_LIST_INIT(newlist->rdata); ISC_LIST_APPEND(newlist->rdata, newrdata, link); RETERR(dns_message_gettemprdataset(msg, &newset)); dns_rdataset_init(newset); RETERR(dns_rdatalist_tordataset(newlist, newset)); ISC_LIST_INIT(newname->list); ISC_LIST_APPEND(newname->list, newset, link); ISC_LIST_APPEND(*namelist, newname, link); return (ISC_R_SUCCESS); failure: if (newrdata != NULL) { if (ISC_LINK_LINKED(newrdata, link)) ISC_LIST_UNLINK(newlist->rdata, newrdata, link); dns_message_puttemprdata(msg, &newrdata); } if (newname != NULL) dns_message_puttempname(msg, &newname); if (newset != NULL) { dns_rdataset_disassociate(newset); dns_message_puttemprdataset(msg, &newset); } if (newlist != NULL) dns_message_puttemprdatalist(msg, &newlist); return (result); }
static inline void set_age(dns_rrl_t *rrl, dns_rrl_entry_t *e, isc_stdtime_t now) { dns_rrl_entry_t *e_old; unsigned int ts_gen; int i, ts; ts_gen = rrl->ts_gen; ts = now - rrl->ts_bases[ts_gen]; if (ts < 0) { if (ts < -DNS_RRL_MAX_TIME_TRAVEL) ts = DNS_RRL_FOREVER; else ts = 0; } /* * Make a new timestamp base if the current base is too old. * All entries older than DNS_RRL_MAX_WINDOW seconds are ancient, * useless history. Their timestamps can be treated as if they are * all the same. * We only do arithmetic on more recent timestamps, so bases for * older timestamps can be recycled provided the old timestamps are * marked as ancient history. * This loop is almost always very short because most entries are * recycled after one second and any entries that need to be marked * are older than (DNS_RRL_TS_BASES)*DNS_RRL_MAX_TS seconds. */ if (ts >= DNS_RRL_MAX_TS) { ts_gen = (ts_gen + 1) % DNS_RRL_TS_BASES; for (e_old = ISC_LIST_TAIL(rrl->lru), i = 0; e_old != NULL && (e_old->ts_gen == ts_gen || !ISC_LINK_LINKED(e_old, hlink)); e_old = ISC_LIST_PREV(e_old, lru), ++i) { e_old->ts_valid = ISC_FALSE; } if (i != 0) isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL, DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG1, "rrl new time base scanned %d entries" " at %d for %d %d %d %d", i, now, rrl->ts_bases[ts_gen], rrl->ts_bases[(ts_gen + 1) % DNS_RRL_TS_BASES], rrl->ts_bases[(ts_gen + 2) % DNS_RRL_TS_BASES], rrl->ts_bases[(ts_gen + 3) % DNS_RRL_TS_BASES]); rrl->ts_gen = ts_gen; rrl->ts_bases[ts_gen] = now; ts = 0; } e->ts_gen = ts_gen; e->ts = ts; e->ts_valid = ISC_TRUE; }
void isc__buffer_invalidate(isc_buffer_t *b) { /* * Make 'b' an invalid buffer. */ REQUIRE(ISC_BUFFER_VALID(b)); REQUIRE(!ISC_LINK_LINKED(b, link)); REQUIRE(b->mctx == NULL); ISC__BUFFER_INVALIDATE(b); }
static void destroy_listener(void *arg) { ns_statschannel_t *listener = arg; REQUIRE(listener != NULL); REQUIRE(!ISC_LINK_LINKED(listener, link)); /* We don't have to acquire the lock here since it's already unlinked */ dns_acl_detach(&listener->acl); DESTROYLOCK(&listener->lock); isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); }
static void reset_client(isc_httpd_t *httpd) { /* * Catch errors here. We MUST be in RECV mode, and we MUST NOT have * any outstanding buffers. If we have buffers, we have a leak. */ INSIST(ISC_HTTPD_ISRECV(httpd)); INSIST(!ISC_LINK_LINKED(&httpd->headerbuffer, link)); INSIST(!ISC_LINK_LINKED(&httpd->bodybuffer, link)); httpd->recvbuf[0] = 0; httpd->recvlen = 0; httpd->headers = NULL; httpd->method = ISC_HTTPD_METHODUNKNOWN; httpd->url = NULL; httpd->querystring = NULL; httpd->protocol = NULL; httpd->flags = 0; isc_buffer_clear(&httpd->headerbuffer); isc_buffer_invalidate(&httpd->bodybuffer); }
static void free_client(client_t **c) { client_t *client; INSIST(c != NULL); client = *c; *c = NULL; INSIST(client != NULL); dns_name_free(&client->name, mctx); INSIST(!ISC_LINK_LINKED(client, link)); INSIST(client->find == NULL); isc_mempool_put(cmp, client); }
static void free_tsignode(void *node, void *_unused) { dns_tsigkey_t *key; REQUIRE(node != NULL); UNUSED(_unused); key = node; if (key->generated) { if (ISC_LINK_LINKED(key, link)) ISC_LIST_UNLINK(key->ring->lru, key, link); } dns_tsigkey_detach(&key); }
static void adjust_lru(dns_tsigkey_t *tkey) { if (tkey->generated) { RWLOCK(&tkey->ring->lock, isc_rwlocktype_write); /* * We may have been removed from the LRU list between * removing the read lock and aquiring the write lock. */ if (ISC_LINK_LINKED(tkey, link)) { ISC_LIST_UNLINK(tkey->ring->lru, tkey, link); ISC_LIST_APPEND(tkey->ring->lru, tkey, link); } RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write); } }
isc_result_t isc_ratelimiter_dequeue(isc_ratelimiter_t *rl, isc_event_t *event) { isc_result_t result = ISC_R_SUCCESS; REQUIRE(rl != NULL); REQUIRE(event != NULL); LOCK(&rl->lock); if (ISC_LINK_LINKED(event, ev_link)) { ISC_LIST_UNLINK(rl->pending, event, ev_link); event->ev_sender = NULL; } else result = ISC_R_NOTFOUND; UNLOCK(&rl->lock); return (result); }
/* * Dequeue and return a pointer to the first task on the current ready * list for the manager. * If the task is privileged, dequeue it from the other ready list * as well. * * Caller must hold the task manager lock. */ static inline isc__task_t * pop_readyq(isc__taskmgr_t *manager) { isc__task_t *task; if (manager->mode == isc_taskmgrmode_normal) task = HEAD(manager->ready_tasks); else task = HEAD(manager->ready_priority_tasks); if (task != NULL) { DEQUEUE(manager->ready_tasks, task, ready_link); if (ISC_LINK_LINKED(task, ready_priority_link)) DEQUEUE(manager->ready_priority_tasks, task, ready_priority_link); } return (task); }
static inline isc_result_t generic_tostruct_key(ARGS_TOSTRUCT) { dns_rdata_key_t *key = target; isc_region_t sr; REQUIRE(rdata != NULL); REQUIRE(rdata->length != 0); REQUIRE(key != NULL); REQUIRE(key->common.rdclass == rdata->rdclass); REQUIRE(key->common.rdtype == rdata->type); REQUIRE(!ISC_LINK_LINKED(&key->common, link)); dns_rdata_toregion(rdata, &sr); /* Flags */ if (sr.length < 2) return (ISC_R_UNEXPECTEDEND); key->flags = uint16_fromregion(&sr); isc_region_consume(&sr, 2); /* Protocol */ if (sr.length < 1) return (ISC_R_UNEXPECTEDEND); key->protocol = uint8_fromregion(&sr); isc_region_consume(&sr, 1); /* Algorithm */ if (sr.length < 1) return (ISC_R_UNEXPECTEDEND); key->algorithm = uint8_fromregion(&sr); isc_region_consume(&sr, 1); /* Data */ key->datalen = sr.length; key->data = mem_maybedup(mctx, sr.base, key->datalen); if (key->data == NULL) return (ISC_R_NOMEMORY); key->mctx = mctx; return (ISC_R_SUCCESS); }
static inline isc_result_t generic_tostruct_txt(ARGS_TOSTRUCT) { dns_rdata_txt_t *txt = target; isc_region_t r; REQUIRE(target != NULL); REQUIRE(txt->common.rdclass == rdata->rdclass); REQUIRE(txt->common.rdtype == rdata->type); REQUIRE(!ISC_LINK_LINKED(&txt->common, link)); dns_rdata_toregion(rdata, &r); txt->txt_len = r.length; txt->txt = mem_maybedup(mctx, r.base, r.length); if (txt->txt == NULL) return (ISC_R_NOMEMORY); txt->offset = 0; txt->mctx = mctx; return (ISC_R_SUCCESS); }
static inline void destroy(dns_view_t *view) { dns_dns64_t *dns64; dns_dlzdb_t *dlzdb; REQUIRE(!ISC_LINK_LINKED(view, link)); REQUIRE(isc_refcount_current(&view->references) == 0); REQUIRE(view->weakrefs == 0); REQUIRE(RESSHUTDOWN(view)); REQUIRE(ADBSHUTDOWN(view)); REQUIRE(REQSHUTDOWN(view)); if (view->order != NULL) dns_order_detach(&view->order); if (view->peers != NULL) dns_peerlist_detach(&view->peers); if (view->dynamickeys != NULL) { isc_result_t result; char template[20];
static void isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) { isc_httpd_t *httpd = ev->ev_arg; isc_region_t r; isc_socketevent_t *sev = (isc_socketevent_t *)ev; ENTER("senddone"); INSIST(ISC_HTTPD_ISSEND(httpd)); /* * First, unlink our header buffer from the socket's bufflist. This * is sort of an evil hack, since we know our buffer will be there, * and we know it's address, so we can just remove it directly. */ NOTICE("senddone unlinked header"); ISC_LIST_UNLINK(sev->bufferlist, &httpd->headerbuffer, link); /* * We will always want to clean up our receive buffer, even if we * got an error on send or we are shutting down. * * We will pass in the buffer only if there is data in it. If * there is no data, we will pass in a NULL. */ if (httpd->freecb != NULL) { isc_buffer_t *b = NULL; if (isc_buffer_length(&httpd->bodybuffer) > 0) b = &httpd->bodybuffer; httpd->freecb(b, httpd->freecb_arg); NOTICE("senddone free callback performed"); } if (ISC_LINK_LINKED(&httpd->bodybuffer, link)) { ISC_LIST_UNLINK(sev->bufferlist, &httpd->bodybuffer, link); NOTICE("senddone body buffer unlinked"); } if (sev->result != ISC_R_SUCCESS) { destroy_client(&httpd); goto out; } if ((httpd->flags & HTTPD_CLOSE) != 0) { destroy_client(&httpd); goto out; } ISC_HTTPD_SETRECV(httpd); NOTICE("senddone restarting recv on socket"); reset_client(httpd); r.base = (unsigned char *)httpd->recvbuf; r.length = HTTP_RECVLEN - 1; /* check return code? */ (void)isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone, httpd); out: isc_event_free(&ev); EXIT("senddone"); }