Пример #1
0
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);
}
Пример #2
0
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);
    }
}
Пример #3
0
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));
}
Пример #4
0
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, &region);

	ds->key_tag = uint16_fromregion(&region);
	isc_region_consume(&region, 2);
	ds->algorithm = uint8_fromregion(&region);
	isc_region_consume(&region, 1);
	ds->digest_type = uint8_fromregion(&region);
	isc_region_consume(&region, 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);
}
Пример #5
0
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);
}
Пример #6
0
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;
}
Пример #7
0
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);
}
Пример #8
0
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));
}
Пример #9
0
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);
}
Пример #11
0
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);
}
Пример #12
0
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);
	}
}
Пример #13
0
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);
}
Пример #14
0
/*
 * 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);
}
Пример #15
0
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);
}
Пример #16
0
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);
}
Пример #17
0
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];
Пример #18
0
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");
}