Пример #1
0
static void
free_controlkeylist(controlkeylist_t *keylist, isc_mem_t *mctx) {
	while (!ISC_LIST_EMPTY(*keylist)) {
		controlkey_t *key = ISC_LIST_HEAD(*keylist);
		ISC_LIST_UNLINK(*keylist, key, link);
		free_controlkey(key, mctx);
	}
}
Пример #2
0
isc_result_t
printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
	char servtext[ISC_SOCKADDR_FORMATSIZE];

	/* I've we've gotten this far, we've reached a server. */
	query_error = 0;

	debug("printmessage()");

	isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
	printf("Server:\t\t%s\n", query->userarg);
	printf("Address:\t%s\n", servtext);

	puts("");

	if (!short_form) {
		isc_boolean_t headers = ISC_TRUE;
		puts("------------");
		/*		detailheader(query, msg);*/
		detailsection(query, msg, headers, DNS_SECTION_QUESTION);
		detailsection(query, msg, headers, DNS_SECTION_ANSWER);
		detailsection(query, msg, headers, DNS_SECTION_AUTHORITY);
		detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL);
		puts("------------");
	}

	if (msg->rcode != 0) {
		char nametext[DNS_NAME_FORMATSIZE];
		dns_name_format(query->lookup->name,
				nametext, sizeof(nametext));
		printf("** server can't find %s: %s\n",
		       nametext, rcode_totext(msg->rcode));
		debug("returning with rcode == 0");

		/* the lookup failed */
		print_error |= 1;
		return (ISC_R_SUCCESS);
	}

	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
		puts("Non-authoritative answer:");
	if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
		printsection(query, msg, headers, DNS_SECTION_ANSWER);
	else
		printf("*** Can't find %s: No answer\n",
		       query->lookup->textname);

	if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
	    (query->lookup->rdtype != dns_rdatatype_a)) {
		puts("\nAuthoritative answers can be found from:");
		printsection(query, msg, headers,
			     DNS_SECTION_AUTHORITY);
		printsection(query, msg, headers,
			     DNS_SECTION_ADDITIONAL);
	}
	return (ISC_R_SUCCESS);
}
Пример #3
0
static void
do_find(isc_boolean_t want_event) {
	isc_result_t result;
	isc_boolean_t done = ISC_FALSE;
	unsigned int options;

	options = DNS_ADBFIND_INET | DNS_ADBFIND_INET6;
	if (want_event)
		options |= DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
	dns_fixedname_init(&target);
	result = dns_adb_createfind(view->adb, task, adb_callback, NULL,
				    dns_fixedname_name(&fixed),
				    dns_rootname, 0, options, 0,
				    dns_fixedname_name(&target), 0,
				    &find);
	if (result == ISC_R_SUCCESS) {
		if (!ISC_LIST_EMPTY(find->list)) {
			/*
			 * We have at least some of the addresses for the
			 * name.
			 */
			INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
			print_addresses(find);
			done = ISC_TRUE;
		} else {
			/*
			 * We don't know any of the addresses for this
			 * name.
			 */
			if ((find->options & DNS_ADBFIND_WANTEVENT) == 0) {
				/*
				 * And ADB isn't going to send us any events
				 * either.  This query loses.
				 */
				done = ISC_TRUE;
			}
			/*
			 * If the DNS_ADBFIND_WANTEVENT flag was set, we'll
			 * get an event when something happens.
			 */
		}
	} else if (result == DNS_R_ALIAS) {
		print_name(dns_fixedname_name(&target));
		done = ISC_TRUE;
	} else {
		printf("dns_adb_createfind() returned %s\n",
		       isc_result_totext(result));
		done = ISC_TRUE;
	}

	if (done) {
		if (find != NULL)
			dns_adb_destroyfind(&find);
		isc_app_shutdown();
	}
}
Пример #4
0
void
ns_controls_destroy(ns_controls_t **ctrlsp) {
	ns_controls_t *controls = *ctrlsp;

	REQUIRE(ISC_LIST_EMPTY(controls->listeners));

	isccc_symtab_destroy(&controls->symtab);
	isc_mem_put(controls->server->mctx, controls, sizeof(*controls));
	*ctrlsp = NULL;
}
Пример #5
0
Файл: tkey.c Проект: 274914765/C
static void free_namelist (dns_message_t * msg, dns_namelist_t * namelist)
{
    dns_name_t *name;

    dns_rdataset_t *set;

    while (!ISC_LIST_EMPTY (*namelist))
    {
        name = ISC_LIST_HEAD (*namelist);
        ISC_LIST_UNLINK (*namelist, name, link);
        while (!ISC_LIST_EMPTY (name->list))
        {
            set = ISC_LIST_HEAD (name->list);
            ISC_LIST_UNLINK (name->list, set, link);
            dns_message_puttemprdataset (msg, &set);
        }
        dns_message_puttempname (msg, &name);
    }
}
Пример #6
0
void
dns_diff_clear(dns_diff_t *diff) {
	dns_difftuple_t *t;
	REQUIRE(DNS_DIFF_VALID(diff));
	while ((t = ISC_LIST_HEAD(diff->tuples)) != NULL) {
		ISC_LIST_UNLINK(diff->tuples, t, link);
		dns_difftuple_free(&t);
	}
	ENSURE(ISC_LIST_EMPTY(diff->tuples));
}
Пример #7
0
static void
httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
{
	isc_mem_t *mctx;
	isc_httpdurl_t *url;

	ENTER("httpdmgr_destroy");

	LOCK(&httpdmgr->lock);

	if (!MSHUTTINGDOWN(httpdmgr)) {
		NOTICE("httpdmgr_destroy not shutting down yet");
		UNLOCK(&httpdmgr->lock);
		return;
	}

	/*
	 * If all clients are not shut down, don't do anything yet.
	 */
	if (!ISC_LIST_EMPTY(httpdmgr->running)) {
		NOTICE("httpdmgr_destroy clients still active");
		UNLOCK(&httpdmgr->lock);
		return;
	}

	NOTICE("httpdmgr_destroy detaching socket, task, and timermgr");

	isc_socket_detach(&httpdmgr->sock);
	isc_task_detach(&httpdmgr->task);
	httpdmgr->timermgr = NULL;

	/*
	 * Clear out the list of all actions we know about.  Just free the
	 * memory.
	 */
	url = ISC_LIST_HEAD(httpdmgr->urls);
	while (url != NULL) {
		isc_mem_free(httpdmgr->mctx, url->url);
		ISC_LIST_UNLINK(httpdmgr->urls, url, link);
		isc_mem_put(httpdmgr->mctx, url, sizeof(isc_httpdurl_t));
		url = ISC_LIST_HEAD(httpdmgr->urls);
	}

	UNLOCK(&httpdmgr->lock);
	isc_mutex_destroy(&httpdmgr->lock);

	if (httpdmgr->ondestroy != NULL)
		(httpdmgr->ondestroy)(httpdmgr->cb_arg);

	mctx = httpdmgr->mctx;
	isc_mem_putanddetach(&mctx, httpdmgr, sizeof(isc_httpdmgr_t));

	EXIT("httpdmgr_destroy");
}
Пример #8
0
void
cleanup_entropy(isc_entropy_t **ectx) {
	entropysource_t *source;
	while (!ISC_LIST_EMPTY(sources)) {
		source = ISC_LIST_HEAD(sources);
		ISC_LIST_UNLINK(sources, source, link);
		isc_entropy_destroysource(&source->source);
		isc_mem_put(source->mctx, source, sizeof(*source));
	}
	isc_entropy_detach(ectx);
}
Пример #9
0
static isc_result_t
rdatasetiter_first(dns_rdatasetiter_t *iterator) {
	ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
	dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node;

	REQUIRE(DNS_RDATASETITER_VALID(iterator));

	if (ISC_LIST_EMPTY(ecdbnode->rdatasets))
		return (ISC_R_NOMORE);
	ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets);
	return (ISC_R_SUCCESS);
}
Пример #10
0
isc_boolean_t
isc__taskmgr_ready(isc_taskmgr_t *manager0) {
	isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;

#ifdef USE_SHARED_MANAGER
	if (manager == NULL)
		manager = taskmgr;
#endif
	if (manager == NULL)
		return (ISC_FALSE);
	return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks)));
}
Пример #11
0
void
ns_lwresd_shutdown(void) {
	ns_lwreslistener_t *listener;

	RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);

	while (!ISC_LIST_EMPTY(listeners)) {
		listener = ISC_LIST_HEAD(listeners);
		ISC_LIST_UNLINK(listeners, listener, link);
		ns_lwreslistener_detach(&listener);
	}
}
Пример #12
0
isc_result_t
dns_fwdtable_add(dns_fwdtable_t *fwdtable, const dns_name_t *name,
		 isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy)
{
	isc_result_t result;
	dns_forwarders_t *forwarders;
	dns_forwarder_t *fwd;
	isc_sockaddr_t *sa;

	REQUIRE(VALID_FWDTABLE(fwdtable));

	forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
	if (forwarders == NULL)
		return (ISC_R_NOMEMORY);

	ISC_LIST_INIT(forwarders->fwdrs);
	for (sa = ISC_LIST_HEAD(*addrs);
	     sa != NULL;
	     sa = ISC_LIST_NEXT(sa, link))
	{
		fwd = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarder_t));
		if (fwd == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
		fwd->addr = *sa;
		fwd->dscp = -1;
		ISC_LINK_INIT(fwd, link);
		ISC_LIST_APPEND(forwarders->fwdrs, fwd, link);
	}
	forwarders->fwdpolicy = fwdpolicy;

	RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
	result = dns_rbt_addname(fwdtable->table, name, forwarders);
	RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);

	if (result != ISC_R_SUCCESS)
		goto cleanup;

	return (ISC_R_SUCCESS);

 cleanup:
	while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
		fwd = ISC_LIST_HEAD(forwarders->fwdrs);
		ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
		isc_mem_put(fwdtable->mctx, fwd, sizeof(dns_forwarder_t));
	}
	isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
	return (result);
}
Пример #13
0
static void
auto_detach(void *data, void *arg) {
	dns_forwarders_t *forwarders = data;
	dns_fwdtable_t *fwdtable = arg;
	isc_sockaddr_t *sa;

	UNUSED(arg);

	while (!ISC_LIST_EMPTY(forwarders->addrs)) {
		sa = ISC_LIST_HEAD(forwarders->addrs);
		ISC_LIST_UNLINK(forwarders->addrs, sa, link);
		isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
	}
	isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
}
Пример #14
0
static isc_result_t
listener_startclients(ns_lwreslistener_t *listener) {
	ns_lwdclientmgr_t *cm;
	unsigned int i;
	isc_result_t result = ISC_R_SUCCESS;

	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
		      NS_LOGMODULE_LWRESD, ISC_LOG_DEBUG(6),
		      "listener_startclients: creating %d "
		      "managers with %d clients each",
		      listener->manager->ntasks, listener->manager->nclients);

	/*
	 * Create the client managers.
	 */
	for (i = 0; i < listener->manager->ntasks; i++) {
		result = ns_lwdclientmgr_create(listener,
						listener->manager->nclients,
						ns_g_taskmgr);
		if (result != ISC_R_SUCCESS)
			break;
	}

	/*
	 * Ensure that we have created at least one.
	 */
	if (ISC_LIST_EMPTY(listener->cmgrs))
		return (result);

	/*
	 * Walk the list of clients and start each one up.
	 */
	LOCK(&listener->lock);
	cm = ISC_LIST_HEAD(listener->cmgrs);
	while (cm != NULL) {
		result = ns_lwdclient_startrecv(cm);
		if (result != ISC_R_SUCCESS)
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
				      "could not start lwres "
				      "client handler: %s",
				      isc_result_totext(result));
		cm = ISC_LIST_NEXT(cm, link);
	}
	UNLOCK(&listener->lock);

	return (ISC_R_SUCCESS);
}
Пример #15
0
static void
free_listener(controllistener_t *listener) {
	INSIST(listener->exiting);
	INSIST(!listener->listening);
	INSIST(ISC_LIST_EMPTY(listener->connections));

	if (listener->sock != NULL)
		isc_socket_detach(&listener->sock);

	free_controlkeylist(&listener->keys, listener->mctx);

	if (listener->acl != NULL)
		dns_acl_detach(&listener->acl);

	isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
}
Пример #16
0
static isc_result_t
dispatch_query(struct query_trans *trans) {
	isc_result_t result;
	size_t namelen;
	isc_buffer_t b;
	char buf[4096];	/* XXX ad hoc constant, but should be enough */
	char *cp;

	REQUIRE(trans != NULL);
	REQUIRE(trans->inuse == ISC_FALSE);
	REQUIRE(ISC_LIST_EMPTY(trans->answerlist));
	REQUIRE(outstanding_queries < MAX_QUERIES);

	/* Construct qname */
	cp = fgets(buf, sizeof(buf), fp);
	if (cp == NULL)
		return (ISC_R_NOMORE);
	/* zap NL if any */
	if ((cp = strchr(buf, '\n')) != NULL)
		*cp = '\0';
	namelen = strlen(buf);
	isc_buffer_init(&b, buf, namelen);
	isc_buffer_add(&b, namelen);
	dns_fixedname_init(&trans->fixedname);
	trans->qname = dns_fixedname_name(&trans->fixedname);
	result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	/* Start resolution */
	result = dns_client_startresolve(client, trans->qname,
					 dns_rdataclass_in, trans->type, 0,
					 query_task, process_answer, trans,
					 &trans->xid);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	trans->inuse = ISC_TRUE;
	outstanding_queries++;

	return (ISC_R_SUCCESS);

 cleanup:
	dns_fixedname_invalidate(&trans->fixedname);

	return (result);
}
Пример #17
0
static void
lwdclientmgr_destroy(ns_lwdclientmgr_t *cm) {
	ns_lwdclient_t *client;
	ns_lwreslistener_t *listener;

	LOCK(&cm->lock);
	if (!SHUTTINGDOWN(cm)) {
		UNLOCK(&cm->lock);
		return;
	}

	/*
	 * Run through the idle list and free the clients there.  Idle
	 * clients do not have a recv running nor do they have any finds
	 * or similar running.
	 */
	client = ISC_LIST_HEAD(cm->idle);
	while (client != NULL) {
		ns_lwdclient_log(50, "destroying client %p, manager %p",
				 client, cm);
		ISC_LIST_UNLINK(cm->idle, client, link);
		isc_mem_put(cm->mctx, client, sizeof(*client));
		client = ISC_LIST_HEAD(cm->idle);
	}

	if (!ISC_LIST_EMPTY(cm->running)) {
		UNLOCK(&cm->lock);
		return;
	}

	UNLOCK(&cm->lock);

	lwres_context_destroy(&cm->lwctx);
	cm->view = NULL;
	isc_socket_detach(&cm->sock);
	isc_task_detach(&cm->task);

	DESTROYLOCK(&cm->lock);

	listener = cm->listener;
	ns_lwreslistener_unlinkcm(listener, cm);
	ns_lwdclient_log(50, "destroying manager %p", cm);
	isc_mem_put(cm->mctx, cm, sizeof(*cm));
	ns_lwreslistener_detach(&listener);
}
Пример #18
0
/*
 * Forget a view's list of policy zones.
 */
void
dns_rpz_view_destroy(dns_view_t *view) {
	dns_rpz_zone_t *zone;

	REQUIRE(view != NULL);

	while (!ISC_LIST_EMPTY(view->rpz_zones)) {
		zone = ISC_LIST_HEAD(view->rpz_zones);
		ISC_LIST_UNLINK(view->rpz_zones, zone, link);
		if (dns_name_dynamic(&zone->origin))
			dns_name_free(&zone->origin, view->mctx);
		if (dns_name_dynamic(&zone->nsdname))
			dns_name_free(&zone->nsdname, view->mctx);
		if (dns_name_dynamic(&zone->cname))
			dns_name_free(&zone->cname, view->mctx);
		isc_mem_put(view->mctx, zone, sizeof(*zone));
	}
}
Пример #19
0
static void
detach(dns_db_t **dbp) {
	dns_ecdb_t *ecdb;
	isc_boolean_t need_destroy = ISC_FALSE;

	REQUIRE(dbp != NULL);
	ecdb = (dns_ecdb_t *)*dbp;
	REQUIRE(VALID_ECDB(ecdb));

	LOCK(&ecdb->lock);
	ecdb->references--;
	if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
		need_destroy = ISC_TRUE;
	UNLOCK(&ecdb->lock);

	if (need_destroy)
		destroy_ecdb(&ecdb);

	*dbp = NULL;
}
Пример #20
0
static isc_result_t
free_all_sessions(void) {
	pk11_token_t *token;
	isc_result_t ret = ISC_R_SUCCESS;
	isc_result_t oret;

	for (token = ISC_LIST_HEAD(tokens);
	     token != NULL;
	     token = ISC_LIST_NEXT(token, link)) {
		oret = free_session_list(&token->sessions);
		if (oret != ISC_R_SUCCESS)
			ret = oret;
	}
	if (!ISC_LIST_EMPTY(actives)) {
		ret = ISC_R_ADDRINUSE;
		oret = free_session_list(&actives);
		if (oret != ISC_R_SUCCESS)
			ret = oret;
	}
	return (ret);
}
Пример #21
0
static isc_result_t
ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
		      isc_boolean_t verbose)
{
	isc_result_t result;
	isc_boolean_t purge = ISC_TRUE;

	REQUIRE(NS_INTERFACEMGR_VALID(mgr));

	mgr->generation++;	/* Increment the generation count. */

	result = do_scan(mgr, ext_listen, verbose);
	if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE))
		purge = ISC_FALSE;

	/*
	 * Now go through the interface list and delete anything that
	 * does not have the current generation number.  This is
	 * how we catch interfaces that go away or change their
	 * addresses.
	 */
	if (purge)
		purge_old_interfaces(mgr);

	/*
	 * Warn if we are not listening on any interface, unless
	 * we're in lwresd-only mode, in which case that is to
	 * be expected.
	 */
	if (ext_listen == NULL &&
	    ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
			      "not listening on any interfaces");
	}

	return (result);
}
Пример #22
0
static isc_result_t
free_session_list(pk11_sessionlist_t *slist) {
	pk11_session_t *sp;
	CK_RV rv;
	isc_result_t ret;

	ret = ISC_R_SUCCESS;
	LOCK(&sessionlock);
	while (!ISC_LIST_EMPTY(*slist)) {
		sp = ISC_LIST_HEAD(*slist);
		UNLOCK(&sessionlock);
		if (sp->session != CK_INVALID_HANDLE) {
			rv = pkcs_C_CloseSession(sp->session);
			if (rv != CKR_OK)
				ret = DST_R_CRYPTOFAILURE;
		}
		LOCK(&sessionlock);
		ISC_LIST_UNLINK(*slist, sp, link);
		pk11_mem_put(sp, sizeof(*sp));
	}
	UNLOCK(&sessionlock);

	return (ret);
}
Пример #23
0
void
isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
	isc_taskmgr_t *manager;
	isc_task_t *task;
	unsigned int i;

	/*
	 * Destroy '*managerp'.
	 */

	REQUIRE(managerp != NULL);
	manager = *managerp;
	REQUIRE(VALID_MANAGER(manager));

#ifndef ISC_PLATFORM_USETHREADS
	UNUSED(i);

	if (manager->refs > 1) {
		manager->refs--;
		*managerp = NULL;
		return;
	}
#endif /* ISC_PLATFORM_USETHREADS */

	XTHREADTRACE("isc_taskmgr_destroy");
	/*
	 * Only one non-worker thread may ever call this routine.
	 * If a worker thread wants to initiate shutdown of the
	 * task manager, it should ask some non-worker thread to call
	 * isc_taskmgr_destroy(), e.g. by signalling a condition variable
	 * that the startup thread is sleeping on.
	 */

	/*
	 * Unlike elsewhere, we're going to hold this lock a long time.
	 * We need to do so, because otherwise the list of tasks could
	 * change while we were traversing it.
	 *
	 * This is also the only function where we will hold both the
	 * task manager lock and a task lock at the same time.
	 */

	LOCK(&manager->lock);

	/*
	 * Make sure we only get called once.
	 */
	INSIST(!manager->exiting);
	manager->exiting = ISC_TRUE;

	/*
	 * Post shutdown event(s) to every task (if they haven't already been
	 * posted).
	 */
	for (task = HEAD(manager->tasks);
	     task != NULL;
	     task = NEXT(task, link)) {
		LOCK(&task->lock);
		if (task_shutdown(task))
			ENQUEUE(manager->ready_tasks, task, ready_link);
		UNLOCK(&task->lock);
	}
#ifdef ISC_PLATFORM_USETHREADS
	/*
	 * Wake up any sleeping workers.  This ensures we get work done if
	 * there's work left to do, and if there are already no tasks left
	 * it will cause the workers to see manager->exiting.
	 */
	BROADCAST(&manager->work_available);
	UNLOCK(&manager->lock);

	/*
	 * Wait for all the worker threads to exit.
	 */
	for (i = 0; i < manager->workers; i++)
		(void)isc_thread_join(manager->threads[i], NULL);
#else /* ISC_PLATFORM_USETHREADS */
	/*
	 * Dispatch the shutdown events.
	 */
	UNLOCK(&manager->lock);
	while (isc__taskmgr_ready())
		(void)isc__taskmgr_dispatch();
	if (!ISC_LIST_EMPTY(manager->tasks))
		isc_mem_printallactive(stderr);
	INSIST(ISC_LIST_EMPTY(manager->tasks));
#endif /* ISC_PLATFORM_USETHREADS */

	manager_free(manager);

	*managerp = NULL;
}
Пример #24
0
isc_result_t
ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) {
	const cfg_obj_t *lwreslist = NULL;
	const cfg_obj_t *lwres = NULL;
	const cfg_obj_t *listenerslist = NULL;
	const cfg_listelt_t *element = NULL;
	ns_lwreslistener_t *listener;
	ns_lwreslistenerlist_t newlisteners;
	isc_result_t result;
	char socktext[ISC_SOCKADDR_FORMATSIZE];
	isc_sockaddr_t *addrs = NULL;
	ns_lwresd_t *lwresd = NULL;
	isc_uint32_t count = 0;

	REQUIRE(mctx != NULL);
	REQUIRE(config != NULL);

	RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);

	ISC_LIST_INIT(newlisteners);

	result = cfg_map_get(config, "lwres", &lwreslist);
	if (result != ISC_R_SUCCESS)
		return (ISC_R_SUCCESS);

	LOCK(&listeners_lock);
	/*
	 * Run through the new lwres address list, noting sockets that
	 * are already being listened on and moving them to the new list.
	 *
	 * Identifying duplicates addr/port combinations is left to either
	 * the underlying config code, or to the bind attempt getting an
	 * address-in-use error.
	 */
	for (element = cfg_list_first(lwreslist);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		in_port_t port;

		lwres = cfg_listelt_value(element);
		CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd));

		port = lwresd_g_listenport;
		if (port == 0)
			port = LWRES_UDP_PORT;

		listenerslist = NULL;
		(void)cfg_map_get(lwres, "listen-on", &listenerslist);
		if (listenerslist == NULL) {
			struct in_addr localhost;
			isc_sockaddr_t address;

			localhost.s_addr = htonl(INADDR_LOOPBACK);
			isc_sockaddr_fromin(&address, &localhost, port);
			CHECK(configure_listener(&address, lwresd, mctx,
						 &newlisteners));
		} else {
			isc_uint32_t i;

			CHECK(ns_config_getiplist(config, listenerslist,
						  port, mctx, &addrs, &count));
			for (i = 0; i < count; i++)
				CHECK(configure_listener(&addrs[i], lwresd,
							 mctx, &newlisteners));
			ns_config_putiplist(mctx, &addrs, count);
		}
		ns_lwdmanager_detach(&lwresd);
	}

	/*
	 * Shutdown everything on the listeners list, and remove them from
	 * the list.  Then put all of the new listeners on it.
	 */

	while (!ISC_LIST_EMPTY(listeners)) {
		listener = ISC_LIST_HEAD(listeners);
		ISC_LIST_UNLINK(listeners, listener, link);

		isc_sockaddr_format(&listener->address,
				    socktext, sizeof(socktext));

		listener_shutdown(listener);
		ns_lwreslistener_detach(&listener);

		isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
			      "lwres no longer listening on %s", socktext);
	}

 cleanup:
	ISC_LIST_APPENDLIST(listeners, newlisteners, link);

	if (addrs != NULL)
		ns_config_putiplist(mctx, &addrs, count);

	if (lwresd != NULL)
		ns_lwdmanager_detach(&lwresd);

	UNLOCK(&listeners_lock);

	return (result);
}
Пример #25
0
void
ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
	isc_result_t result;
	dns_name_t *question_name;
	dns_rdataset_t *question_rdataset;
	dns_zone_t *zone = NULL, *raw = NULL, *mayberaw;
	dns_db_t *db = NULL;
	dns_dbversion_t *ver = NULL;
	dns_rdataclass_t question_class;
	rrstream_t *soa_stream = NULL;
	rrstream_t *data_stream = NULL;
	rrstream_t *stream = NULL;
	dns_difftuple_t *current_soa_tuple = NULL;
	dns_name_t *soa_name;
	dns_rdataset_t *soa_rdataset;
	dns_rdata_t soa_rdata = DNS_RDATA_INIT;
	isc_boolean_t have_soa = ISC_FALSE;
	const char *mnemonic = NULL;
	isc_mem_t *mctx = client->mctx;
	dns_message_t *request = client->message;
	xfrout_ctx_t *xfr = NULL;
	isc_quota_t *quota = NULL;
	dns_transfer_format_t format = client->view->transfer_format;
	isc_netaddr_t na;
	dns_peer_t *peer = NULL;
	isc_buffer_t *tsigbuf = NULL;
	char *journalfile;
	char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
	char keyname[DNS_NAME_FORMATSIZE];
	isc_boolean_t is_poll = ISC_FALSE;
	isc_boolean_t is_dlz = ISC_FALSE;
	isc_boolean_t is_ixfr = ISC_FALSE;
	isc_uint32_t begin_serial = 0, current_serial;

	switch (reqtype) {
	case dns_rdatatype_axfr:
		mnemonic = "AXFR";
		break;
	case dns_rdatatype_ixfr:
		mnemonic = "IXFR";
		break;
	default:
		INSIST(0);
		break;
	}

	ns_client_log(client,
		      DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
		      ISC_LOG_DEBUG(6), "%s request", mnemonic);
	/*
	 * Apply quota.
	 */
	result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
			      "%s request denied: %s", mnemonic,
			      isc_result_totext(result));
		goto failure;
	}

	/*
	 * Interpret the question section.
	 */
	result = dns_message_firstname(request, DNS_SECTION_QUESTION);
	INSIST(result == ISC_R_SUCCESS);

	/*
	 * The question section must contain exactly one question, and
	 * it must be for AXFR/IXFR as appropriate.
	 */
	question_name = NULL;
	dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
	question_rdataset = ISC_LIST_HEAD(question_name->list);
	question_class = question_rdataset->rdclass;
	INSIST(question_rdataset->type == reqtype);
	if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
		FAILC(DNS_R_FORMERR, "multiple questions");
	result = dns_message_nextname(request, DNS_SECTION_QUESTION);
	if (result != ISC_R_NOMORE)
		FAILC(DNS_R_FORMERR, "multiple questions");

	result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
			     &zone);

	if (result != ISC_R_SUCCESS) {
		/*
		 * Normal zone table does not have a match.
		 * Try the DLZ database
		 */
		// Temporary: only searching the first DLZ database
		if (! ISC_LIST_EMPTY(client->view->dlz_searched)) {
			result = dns_dlzallowzonexfr(client->view,
						     question_name,
						     &client->peeraddr,
						     &db);

			pfilter_notify(result, client, "zonexfr");
			if (result == ISC_R_NOPERM) {
				char _buf1[DNS_NAME_FORMATSIZE];
				char _buf2[DNS_RDATACLASS_FORMATSIZE];

				result = DNS_R_REFUSED;
				dns_name_format(question_name, _buf1,
						sizeof(_buf1));
				dns_rdataclass_format(question_class,
						      _buf2, sizeof(_buf2));
				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
					      NS_LOGMODULE_XFER_OUT,
					      ISC_LOG_ERROR,
					      "zone transfer '%s/%s' denied",
					      _buf1, _buf2);
				goto failure;
			}
			if (result != ISC_R_SUCCESS)
				FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
				      question_name, question_class);
			is_dlz = ISC_TRUE;
		} else {
			/*
			 * not DLZ and not in normal zone table, we are
			 * not authoritative
			 */
			FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
			      question_name, question_class);
		}
	} else {
		/* zone table has a match */
		switch(dns_zone_gettype(zone)) {
			/* Master and slave zones are OK for transfer. */
			case dns_zone_master:
			case dns_zone_slave:
			case dns_zone_dlz:
				break;
			default:
				FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
				      question_name, question_class);
			}
		CHECK(dns_zone_getdb(zone, &db));
		dns_db_currentversion(db, &ver);
	}

	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
		    "%s question section OK", mnemonic);

	/*
	 * Check the authority section.  Look for a SOA record with
	 * the same name and class as the question.
	 */
	for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
	     result == ISC_R_SUCCESS;
	     result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
	{
		soa_name = NULL;
		dns_message_currentname(request, DNS_SECTION_AUTHORITY,
					&soa_name);

		/*
		 * Ignore data whose owner name is not the zone apex.
		 */
		if (! dns_name_equal(soa_name, question_name))
			continue;

		for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
		     soa_rdataset != NULL;
		     soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
		{
			/*
			 * Ignore non-SOA data.
			 */
			if (soa_rdataset->type != dns_rdatatype_soa)
				continue;
			if (soa_rdataset->rdclass != question_class)
				continue;

			CHECK(dns_rdataset_first(soa_rdataset));
			dns_rdataset_current(soa_rdataset, &soa_rdata);
			result = dns_rdataset_next(soa_rdataset);
			if (result == ISC_R_SUCCESS)
				FAILC(DNS_R_FORMERR,
				      "IXFR authority section "
				      "has multiple SOAs");
			have_soa = ISC_TRUE;
			goto got_soa;
		}
	}
 got_soa:
	if (result != ISC_R_NOMORE)
		CHECK(result);

	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
		    "%s authority section OK", mnemonic);

	/*
	 * If not a DLZ zone, decide whether to allow this transfer.
	 */
	if (!is_dlz) {
		ns_client_aclmsg("zone transfer", question_name, reqtype,
				 client->view->rdclass, msg, sizeof(msg));
		CHECK(ns_client_checkacl(client, NULL, msg,
					 dns_zone_getxfracl(zone),
					 ISC_TRUE, ISC_LOG_ERROR));
	}

	/*
	 * AXFR over UDP is not possible.
	 */
	if (reqtype == dns_rdatatype_axfr &&
	    (client->attributes & NS_CLIENTATTR_TCP) == 0)
		FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");

	/*
	 * Look up the requesting server in the peer table.
	 */
	isc_netaddr_fromsockaddr(&na, &client->peeraddr);
	(void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);

	/*
	 * Decide on the transfer format (one-answer or many-answers).
	 */
	if (peer != NULL)
		(void)dns_peer_gettransferformat(peer, &format);

	/*
	 * Get a dynamically allocated copy of the current SOA.
	 */
	if (is_dlz)
		dns_db_currentversion(db, &ver);

	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
				    &current_soa_tuple));

	current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
	if (reqtype == dns_rdatatype_ixfr) {
		isc_boolean_t provide_ixfr;

		/*
		 * Outgoing IXFR may have been disabled for this peer
		 * or globally.
		 */
		provide_ixfr = client->view->provideixfr;
		if (peer != NULL)
			(void) dns_peer_getprovideixfr(peer, &provide_ixfr);
		if (provide_ixfr == ISC_FALSE)
			goto axfr_fallback;

		if (! have_soa)
			FAILC(DNS_R_FORMERR,
			      "IXFR request missing SOA");

		begin_serial = dns_soa_getserial(&soa_rdata);

		/*
		 * RFC1995 says "If an IXFR query with the same or
		 * newer version number than that of the server
		 * is received, it is replied to with a single SOA
		 * record of the server's current version, just as
		 * in AXFR".  The claim about AXFR is incorrect,
		 * but other than that, we do as the RFC says.
		 *
		 * Sending a single SOA record is also how we refuse
		 * IXFR over UDP (currently, we always do).
		 */
		if (DNS_SERIAL_GE(begin_serial, current_serial) ||
		    (client->attributes & NS_CLIENTATTR_TCP) == 0)
		{
			CHECK(soa_rrstream_create(mctx, db, ver, &stream));
			is_poll = ISC_TRUE;
			goto have_stream;
		}
		journalfile = is_dlz ? NULL : dns_zone_getjournal(zone);
		if (journalfile != NULL)
			result = ixfr_rrstream_create(mctx,
						      journalfile,
						      begin_serial,
						      current_serial,
						      &data_stream);
		else
			result = ISC_R_NOTFOUND;
		if (result == ISC_R_NOTFOUND ||
		    result == ISC_R_RANGE) {
			xfrout_log1(client, question_name, question_class,
				    ISC_LOG_DEBUG(4),
				    "IXFR version not in journal, "
				    "falling back to AXFR");
			mnemonic = "AXFR-style IXFR";
			goto axfr_fallback;
		}
		CHECK(result);
		is_ixfr = ISC_TRUE;
	} else {
	axfr_fallback:
		CHECK(axfr_rrstream_create(mctx, db, ver, &data_stream));
	}

	/*
	 * Bracket the data stream with SOAs.
	 */
	CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
	CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
				       &stream));
	soa_stream = NULL;
	data_stream = NULL;

 have_stream:
	CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
	/*
	 * Create the xfrout context object.  This transfers the ownership
	 * of "stream", "db", "ver", and "quota" to the xfrout context object.
	 */



	if (is_dlz)
		CHECK(xfrout_ctx_create(mctx, client, request->id,
					question_name, reqtype, question_class,
					zone, db, ver, quota, stream,
					dns_message_gettsigkey(request),
					tsigbuf,
					3600,
					3600,
					(format == dns_many_answers) ?
					ISC_TRUE : ISC_FALSE,
					&xfr));
	else
		CHECK(xfrout_ctx_create(mctx, client, request->id,
					question_name, reqtype, question_class,
					zone, db, ver, quota, stream,
					dns_message_gettsigkey(request),
					tsigbuf,
					dns_zone_getmaxxfrout(zone),
					dns_zone_getidleout(zone),
					(format == dns_many_answers) ?
					ISC_TRUE : ISC_FALSE,
					&xfr));

	xfr->mnemonic = mnemonic;
	stream = NULL;
	quota = NULL;

	CHECK(xfr->stream->methods->first(xfr->stream));

	if (xfr->tsigkey != NULL)
		dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
	else
		keyname[0] = '\0';
	if (is_poll)
		xfrout_log1(client, question_name, question_class,
			    ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
	else if (is_ixfr)
		xfrout_log1(client, question_name, question_class,
			    ISC_LOG_INFO, "%s started%s%s (serial %u -> %u)",
			    mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "",
			    keyname, begin_serial, current_serial);
	else
		xfrout_log1(client, question_name, question_class,
			    ISC_LOG_INFO, "%s started%s%s (serial %u)",
			    mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "",
			    keyname, current_serial);


	if (zone != NULL) {
		dns_zone_getraw(zone, &raw);
		mayberaw = (raw != NULL) ? raw : zone;
		if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 &&
		    dns_zone_gettype(mayberaw) == dns_zone_slave) {
			isc_time_t expiretime;
			isc_uint32_t secs;
			dns_zone_getexpiretime(zone, &expiretime);
			secs = isc_time_seconds(&expiretime);
			if (secs >= client->now && result == ISC_R_SUCCESS) {
				client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
				client->expire = secs - client->now;
			}
		}
		if (raw != NULL)
			dns_zone_detach(&raw);
	}

	/*
	 * Hand the context over to sendstream().  Set xfr to NULL;
	 * sendstream() is responsible for either passing the
	 * context on to a later event handler or destroying it.
	 */
	sendstream(xfr);
	xfr = NULL;

	result = ISC_R_SUCCESS;

 failure:
	if (result == DNS_R_REFUSED)
		inc_stats(zone, dns_nsstatscounter_xfrrej);
	if (quota != NULL)
		isc_quota_detach(&quota);
	if (current_soa_tuple != NULL)
		dns_difftuple_free(&current_soa_tuple);
	if (stream != NULL)
		stream->methods->destroy(&stream);
	if (soa_stream != NULL)
		soa_stream->methods->destroy(&soa_stream);
	if (data_stream != NULL)
		data_stream->methods->destroy(&data_stream);
	if (ver != NULL)
		dns_db_closeversion(db, &ver, ISC_FALSE);
	if (db != NULL)
		dns_db_detach(&db);
	if (zone != NULL)
		dns_zone_detach(&zone);
	/* XXX kludge */
	if (xfr != NULL) {
		xfrout_fail(xfr, result, "setting up zone transfer");
	} else if (result != ISC_R_SUCCESS) {
		ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
			      NS_LOGMODULE_XFER_OUT,
			      ISC_LOG_DEBUG(3), "zone transfer setup failed");
		ns_client_error(client, result);
	}
}
Пример #26
0
static isc_result_t ddns_update_ptr (struct data_string *ddns_fwd_name,
				     struct data_string *ddns_rev_name,
				     unsigned long ttl)
{
	ns_updque updqueue;
	ns_updrec *updrec;
	isc_result_t result = ISC_R_UNEXPECTED;

	/*
	 * The DHCP server submits a DNS query which deletes all of the PTR RRs
	 * associated with the lease IP address, and adds a PTR RR whose data
	 * is the client's (possibly disambiguated) host name. The server also
	 * adds a DHCID RR specified in Section 4.3.
	 *   -- "Interaction between DHCP and DNS"
	 */

	ISC_LIST_INIT (updqueue);

	/*
	 * Delete all PTR RRs.
	 */
	updrec = minires_mkupdrec (S_UPDATE,
				   (const char *)ddns_rev_name -> data,
				   C_IN, T_PTR, 0);
	if (!updrec) {
		result = ISC_R_NOMEMORY;
		goto error;
	}

	updrec -> r_data = (unsigned char *)0;
	updrec -> r_size = 0;
	updrec -> r_opcode = DELETE;

	ISC_LIST_APPEND (updqueue, updrec, r_link);

	/*
	 * Add PTR RR.
	 */
	updrec = minires_mkupdrec (S_UPDATE,
				   (const char *)ddns_rev_name -> data,
				   C_IN, T_PTR, ttl);
	if (!updrec) {
		result = ISC_R_NOMEMORY;
		goto error;
	}

	updrec -> r_data = ddns_fwd_name -> data;
	updrec -> r_size = ddns_fwd_name -> len;
	updrec -> r_opcode = ADD;

	ISC_LIST_APPEND (updqueue, updrec, r_link);

	/*
	 * Attempt to perform the update.
	 */
	result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue));
#if defined (DEBUG)
	print_dns_status ((int)result, &updqueue);
#endif
	if (result == ISC_R_SUCCESS) {
		log_info ("added reverse map from %.*s to %.*s",
			  (int)ddns_rev_name -> len,
			  (const char *)ddns_rev_name -> data,
			  (int)ddns_fwd_name -> len,
			  (const char *)ddns_fwd_name -> data);
	} else {
		log_error ("unable to add reverse map from %.*s to %.*s: %s",
			   (int)ddns_rev_name -> len,
			   (const char *)ddns_rev_name -> data,
			   (int)ddns_fwd_name -> len,
			   (const char *)ddns_fwd_name -> data,
			   isc_result_totext (result));
	}

	/* Fall through. */
      error:

	while (!ISC_LIST_EMPTY (updqueue)) {
		if((updqueue).head){
			updrec = ISC_LIST_HEAD (updqueue);
			ISC_LIST_UNLINK (updqueue, updrec, r_link);
			minires_freeupdrec (updrec);
		}
	}

	return result;
}
Пример #27
0
static isc_result_t ddns_remove_ptr (struct data_string *ddns_rev_name)
{
	ns_updque updqueue;
	ns_updrec *updrec;
	isc_result_t result;

	/*
	 * When a lease expires or a DHCP client issues a DHCPRELEASE request,
	 * the DHCP server SHOULD delete the PTR RR that matches the DHCP
	 * binding, if one was successfully added. The server's update query
	 * SHOULD assert that the name in the PTR record matches the name of
	 * the client whose lease has expired or been released.
	 *   -- "Interaction between DHCP and DNS"
	 */

	ISC_LIST_INIT (updqueue);

	/*
	 * Delete the PTR RRset for the leased address.
	 */
	updrec = minires_mkupdrec (S_UPDATE,
				   (const char *)ddns_rev_name -> data,
				   C_IN, T_PTR, 0);
	if (!updrec) {
		result = ISC_R_NOMEMORY;
		goto error;
	}

	updrec -> r_data = (unsigned char *)0;
	updrec -> r_size = 0;
	updrec -> r_opcode = DELETE;

	ISC_LIST_APPEND (updqueue, updrec, r_link);

	/*
	 * Attempt to perform the update.
	 */
	result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue));
#if defined (DEBUG)
	print_dns_status ((int)result, &updqueue);
#endif
	if (result == ISC_R_SUCCESS) {
		log_info ("removed reverse map on %.*s",
			  (int)ddns_rev_name -> len,
			  (const char *)ddns_rev_name -> data);
	} else {
		if (result != ISC_R_NXRRSET && result != ISC_R_NXDOMAIN)
			log_error ("can't remove reverse map on %.*s: %s",
				   (int)ddns_rev_name -> len,
				   (const char *)ddns_rev_name -> data,
				   isc_result_totext (result));
	}

	/* Not there is success. */
	if (result == ISC_R_NXRRSET || result == ISC_R_NXDOMAIN)
		result = ISC_R_SUCCESS;

	/* Fall through. */
      error:

	while (!ISC_LIST_EMPTY (updqueue)) {
		if((updqueue).head){
			updrec = ISC_LIST_HEAD (updqueue);
			ISC_LIST_UNLINK (updqueue, updrec, r_link);
			minires_freeupdrec (updrec);
		}
	}

	return result;
}
Пример #28
0
isc_boolean_t
isc__taskmgr_ready(void) {
	if (taskmgr == NULL)
		return (ISC_FALSE);
	return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks)));
}
Пример #29
0
static void
resolve_ns(isc_task_t *task, isc_event_t *event) {
	struct probe_trans *trans = event->ev_arg;
	dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
	dns_name_t *name;
	dns_rdataset_t *rdataset;
	isc_result_t result = ISC_R_SUCCESS;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	struct probe_ns *pns;

	REQUIRE(task == probe_task);
	REQUIRE(trans->inuse == ISC_TRUE);
	INSIST(outstanding_probes > 0);

	for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
	     name = ISC_LIST_NEXT(name, link)) {
		for (rdataset = ISC_LIST_HEAD(name->list);
		     rdataset != NULL;
		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
			(void)print_rdataset(rdataset, name);

			if (rdataset->type != dns_rdatatype_ns)
				continue;

			for (result = dns_rdataset_first(rdataset);
			     result == ISC_R_SUCCESS;
			     result = dns_rdataset_next(rdataset)) {
				dns_rdata_ns_t ns;

				dns_rdataset_current(rdataset, &rdata);
				/*
				 * Extract the name from the NS record.
				 */
				result = dns_rdata_tostruct(&rdata, &ns, NULL);
				if (result != ISC_R_SUCCESS)
					continue;

				pns = isc_mem_get(mctx, sizeof(*pns));
				if (pns == NULL) {
					fprintf(stderr,
						"resolve_ns: mem_get failed");
					result = ISC_R_NOMEMORY;
					POST(result);
					/*
					 * XXX: should we continue with the
					 * available servers anyway?
					 */
					goto cleanup;
				}

				dns_fixedname_init(&pns->fixedname);
				pns->name =
					dns_fixedname_name(&pns->fixedname);
				ISC_LINK_INIT(pns, link);
				ISC_LIST_APPEND(trans->nslist, pns, link);
				ISC_LIST_INIT(pns->servers);

				dns_name_copy(&ns.name, pns->name, NULL);
				dns_rdata_reset(&rdata);
				dns_rdata_freestruct(&ns);
			}
		}
	}

 cleanup:
	dns_client_freeresanswer(client, &rev->answerlist);
	dns_client_destroyrestrans(&trans->resid);
	isc_event_free(&event);

	if (!ISC_LIST_EMPTY(trans->nslist)) {
		/* Go get addresses of NSes */
		trans->current_ns = ISC_LIST_HEAD(trans->nslist);
		result = fetch_nsaddress(trans);
	} else
		result = ISC_R_FAILURE;

	if (result == ISC_R_SUCCESS)
		return;

	reset_probe(trans);
}
Пример #30
0
static isc_result_t
process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
	       dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx,
	       dns_rdata_tkey_t *tkeyout,
	       dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
{
	isc_result_t result = ISC_R_SUCCESS;
	dns_name_t *keyname, ourname;
	dns_rdataset_t *keyset = NULL;
	dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT;
	isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE;
	dst_key_t *pubkey = NULL;
	isc_buffer_t ourkeybuf, *shared = NULL;
	isc_region_t r, r2, ourkeyr;
	unsigned char keydata[DST_KEY_MAXSIZE];
	unsigned int sharedsize;
	isc_buffer_t secret;
	unsigned char *randomdata = NULL, secretdata[256];
	dns_ttl_t ttl = 0;

	if (tctx->dhkey == NULL) {
		tkey_log("process_dhtkey: tkey-dhkey not defined");
		tkeyout->error = dns_tsigerror_badalg;
		return (DNS_R_REFUSED);
	}

	if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) {
		tkey_log("process_dhtkey: algorithms other than "
			 "hmac-md5 are not supported");
		tkeyout->error = dns_tsigerror_badalg;
		return (ISC_R_SUCCESS);
	}

	/*
	 * Look for a DH KEY record that will work with ours.
	 */
	for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
	     result == ISC_R_SUCCESS && !found_key;
	     result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) {
		keyname = NULL;
		dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
		keyset = NULL;
		result = dns_message_findtype(keyname, dns_rdatatype_key, 0,
					      &keyset);
		if (result != ISC_R_SUCCESS)
			continue;

		for (result = dns_rdataset_first(keyset);
		     result == ISC_R_SUCCESS && !found_key;
		     result = dns_rdataset_next(keyset)) {
			dns_rdataset_current(keyset, &keyrdata);
			pubkey = NULL;
			result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
							 msg->mctx, &pubkey);
			if (result != ISC_R_SUCCESS) {
				dns_rdata_reset(&keyrdata);
				continue;
			}
			if (dst_key_alg(pubkey) == DNS_KEYALG_DH) {
				if (dst_key_paramcompare(pubkey, tctx->dhkey))
				{
					found_key = ISC_TRUE;
					ttl = keyset->ttl;
					break;
				} else
					found_incompatible = ISC_TRUE;
			}
			dst_key_free(&pubkey);
			dns_rdata_reset(&keyrdata);
		}
	}

	if (!found_key) {
		if (found_incompatible) {
			tkey_log("process_dhtkey: found an incompatible key");
			tkeyout->error = dns_tsigerror_badkey;
			return (ISC_R_SUCCESS);
		} else {
			tkey_log("process_dhtkey: failed to find a key");
			return (DNS_R_FORMERR);
		}
	}

	RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist));

	isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata));
	RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf));
	isc_buffer_usedregion(&ourkeybuf, &ourkeyr);
	dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any,
			     dns_rdatatype_key, &ourkeyr);

	dns_name_init(&ourname, NULL);
	dns_name_clone(dst_key_name(tctx->dhkey), &ourname);

	/*
	 * XXXBEW The TTL should be obtained from the database, if it exists.
	 */
	RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist));

	RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize));
	RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize));

	result = dst_key_computesecret(pubkey, tctx->dhkey, shared);
	if (result != ISC_R_SUCCESS) {
		tkey_log("process_dhtkey: failed to compute shared secret: %s",
			 isc_result_totext(result));
		goto failure;
	}
	dst_key_free(&pubkey);

	isc_buffer_init(&secret, secretdata, sizeof(secretdata));

	randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT);
	if (randomdata == NULL)
		goto failure;

	result = dst__entropy_getdata(randomdata, TKEY_RANDOM_AMOUNT,
				      ISC_FALSE);
	if (result != ISC_R_SUCCESS) {
		tkey_log("process_dhtkey: failed to obtain entropy: %s",
			 isc_result_totext(result));
		goto failure;
	}

	r.base = randomdata;
	r.length = TKEY_RANDOM_AMOUNT;
	r2.base = tkeyin->key;
	r2.length = tkeyin->keylen;
	RETERR(compute_secret(shared, &r2, &r, &secret));
	isc_buffer_free(&shared);

	RETERR(dns_tsigkey_create(name, &tkeyin->algorithm,
				  isc_buffer_base(&secret),
				  isc_buffer_usedlength(&secret),
				  ISC_TRUE, signer, tkeyin->inception,
				  tkeyin->expire, ring->mctx, ring, NULL));

	/* This key is good for a long time */
	tkeyout->inception = tkeyin->inception;
	tkeyout->expire = tkeyin->expire;

	tkeyout->key = randomdata;
	tkeyout->keylen = TKEY_RANDOM_AMOUNT;

	return (ISC_R_SUCCESS);

 failure:
	if (!ISC_LIST_EMPTY(*namelist))
		free_namelist(msg, namelist);
	if (shared != NULL)
		isc_buffer_free(&shared);
	if (pubkey != NULL)
		dst_key_free(&pubkey);
	if (randomdata != NULL)
		isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT);
	return (result);
}