Ejemplo n.º 1
0
static void
register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist,
	      controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext)
{
	controlkey_t *keyid, *next;
	const cfg_obj_t *keydef;
	char secret[1024];
	isc_buffer_t b;
	isc_result_t result;

	/*
	 * Find the keys corresponding to the keyids used by this listener.
	 */
	for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) {
		next = ISC_LIST_NEXT(keyid, link);

		result = cfgkeylist_find(keylist, keyid->keyname, &keydef);
		if (result != ISC_R_SUCCESS) {
			cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
				    "couldn't find key '%s' for use with "
				    "command channel %s",
				    keyid->keyname, socktext);
			ISC_LIST_UNLINK(*keyids, keyid, link);
			free_controlkey(keyid, mctx);
		} else {
			const cfg_obj_t *algobj = NULL;
			const cfg_obj_t *secretobj = NULL;
			const char *algstr = NULL;
			const char *secretstr = NULL;
			unsigned int algtype;

			(void)cfg_map_get(keydef, "algorithm", &algobj);
			(void)cfg_map_get(keydef, "secret", &secretobj);
			INSIST(algobj != NULL && secretobj != NULL);

			algstr = cfg_obj_asstring(algobj);
			secretstr = cfg_obj_asstring(secretobj);

			if (ns_config_getkeyalgorithm2(algstr, NULL,
					&algtype, NULL) != ISC_R_SUCCESS)
			{
				cfg_obj_log(control, ns_g_lctx,
					    ISC_LOG_WARNING,
					    "unsupported algorithm '%s' in "
					    "key '%s' for use with command "
					    "channel %s",
					    algstr, keyid->keyname, socktext);
				ISC_LIST_UNLINK(*keyids, keyid, link);
				free_controlkey(keyid, mctx);
				continue;
			}

			keyid->algorithm = algtype;
			isc_buffer_init(&b, secret, sizeof(secret));
			result = isc_base64_decodestring(secretstr, &b);

			if (result != ISC_R_SUCCESS) {
				cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
					    "secret for key '%s' on "
					    "command channel %s: %s",
					    keyid->keyname, socktext,
					    isc_result_totext(result));
				ISC_LIST_UNLINK(*keyids, keyid, link);
				free_controlkey(keyid, mctx);
				continue;
			}

			keyid->secret.length = isc_buffer_usedlength(&b);
			keyid->secret.base = isc_mem_get(mctx,
							 keyid->secret.length);
			if (keyid->secret.base == NULL) {
				cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
					   "couldn't register key '%s': "
					   "out of memory", keyid->keyname);
				ISC_LIST_UNLINK(*keyids, keyid, link);
				free_controlkey(keyid, mctx);
				break;
			}
			memmove(keyid->secret.base, isc_buffer_base(&b),
				keyid->secret.length);
		}
	}
}
Ejemplo n.º 2
0
/*
 * Poll each source, trying to get data from it to stuff into the entropy
 * pool.
 */
static void fillpool (isc_entropy_t * ent, unsigned int desired, isc_boolean_t blocking)
{
    unsigned int added;

    unsigned int remaining;

    unsigned int needed;

    unsigned int nsource;

    isc_entropysource_t *source;

    REQUIRE (VALID_ENTROPY (ent));

    needed = desired;

    /*
     * This logic is a little strange, so an explanation is in order.
     *
     * If needed is 0, it means we are being asked to "fill to whatever
     * we think is best."  This means that if we have at least a
     * partially full pool (say, > 1/4th of the pool) we probably don't
     * need to add anything.
     *
     * Also, we will check to see if the "pseudo" count is too high.
     * If it is, try to mix in better data.  Too high is currently
     * defined as 1/4th of the pool.
     *
     * Next, if we are asked to add a specific bit of entropy, make
     * certain that we will do so.  Clamp how much we try to add to
     * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
     *
     * Note that if we are in a blocking mode, we will only try to
     * get as much data as we need, not as much as we might want
     * to build up.
     */
    if (needed == 0)
    {
        REQUIRE (!blocking);

        if ((ent->pool.entropy >= RND_POOLBITS / 4) && (ent->pool.pseudo <= RND_POOLBITS / 4))
            return;

        needed = THRESHOLD_BITS * 4;
    }
    else
    {
        needed = ISC_MAX (needed, THRESHOLD_BITS);
        needed = ISC_MIN (needed, RND_POOLBITS);
    }

    /*
     * In any case, clamp how much we need to how much we can add.
     */
    needed = ISC_MIN (needed, RND_POOLBITS - ent->pool.entropy);

    /*
     * But wait!  If we're not yet initialized, we need at least
     *  THRESHOLD_BITS
     * of randomness.
     */
    if (ent->initialized < THRESHOLD_BITS)
        needed = ISC_MAX (needed, THRESHOLD_BITS - ent->initialized);

    /*
     * Poll each file source to see if we can read anything useful from
     * it.  XXXMLG When where are multiple sources, we should keep a
     * record of which one we last used so we can start from it (or the
     * next one) to avoid letting some sources build up entropy while
     * others are always drained.
     */

    added = 0;
    remaining = needed;
    if (ent->nextsource == NULL)
    {
        ent->nextsource = ISC_LIST_HEAD (ent->sources);
        if (ent->nextsource == NULL)
            return;
    }
    source = ent->nextsource;
  again_file:
    for (nsource = 0; nsource < ent->nsources; nsource++)
    {
        unsigned int got;

        if (remaining == 0)
            break;

        got = 0;

        switch (source->type)
        {
            case ENTROPY_SOURCETYPE_FILE:
                got = get_from_filesource (source, remaining);
                break;

            case ENTROPY_SOURCETYPE_USOCKET:
                got = get_from_usocketsource (source, remaining);
                break;
        }

        added += got;

        remaining -= ISC_MIN (remaining, got);

        source = ISC_LIST_NEXT (source, link);
        if (source == NULL)
            source = ISC_LIST_HEAD (ent->sources);
    }
    ent->nextsource = source;

    if (blocking && remaining != 0)
    {
        int fds;

        fds = wait_for_sources (ent);
        if (fds > 0)
            goto again_file;
    }

    /*
     * Here, if there are bits remaining to be had and we can block,
     * check to see if we have a callback source.  If so, call them.
     */
    source = ISC_LIST_HEAD (ent->sources);
    while ((remaining != 0) && (source != NULL))
    {
        unsigned int got;

        got = 0;

        if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
            got = get_from_callback (source, remaining, blocking);

        added += got;
        remaining -= ISC_MIN (remaining, got);

        if (added >= needed)
            break;

        source = ISC_LIST_NEXT (source, link);
    }

    /*
     * Mark as initialized if we've added enough data.
     */
    if (ent->initialized < THRESHOLD_BITS)
        ent->initialized += added;
}
Ejemplo n.º 3
0
void
isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, xmlTextWriterPtr writer) {
	isc__taskmgr_t *mgr = (isc__taskmgr_t *)mgr0;
	isc__task_t *task;

	LOCK(&mgr->lock);

	/*
	 * Write out the thread-model, and some details about each depending
	 * on which type is enabled.
	 */
	xmlTextWriterStartElement(writer, ISC_XMLCHAR "thread-model");
#ifdef ISC_PLATFORM_USETHREADS
	xmlTextWriterStartElement(writer, ISC_XMLCHAR "type");
	xmlTextWriterWriteString(writer, ISC_XMLCHAR "threaded");
	xmlTextWriterEndElement(writer); /* type */

	xmlTextWriterStartElement(writer, ISC_XMLCHAR "worker-threads");
	xmlTextWriterWriteFormatString(writer, "%d", mgr->workers);
	xmlTextWriterEndElement(writer); /* worker-threads */
#else /* ISC_PLATFORM_USETHREADS */
	xmlTextWriterStartElement(writer, ISC_XMLCHAR "type");
	xmlTextWriterWriteString(writer, ISC_XMLCHAR "non-threaded");
	xmlTextWriterEndElement(writer); /* type */

	xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
	xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
	xmlTextWriterEndElement(writer); /* references */
#endif /* ISC_PLATFORM_USETHREADS */

	xmlTextWriterStartElement(writer, ISC_XMLCHAR "default-quantum");
	xmlTextWriterWriteFormatString(writer, "%d", mgr->default_quantum);
	xmlTextWriterEndElement(writer); /* default-quantum */

	xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-running");
	xmlTextWriterWriteFormatString(writer, "%d", mgr->tasks_running);
	xmlTextWriterEndElement(writer); /* tasks-running */

	xmlTextWriterEndElement(writer); /* thread-model */

	xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks");
	task = ISC_LIST_HEAD(mgr->tasks);
	while (task != NULL) {
		LOCK(&task->lock);
		xmlTextWriterStartElement(writer, ISC_XMLCHAR "task");

		if (task->name[0] != 0) {
			xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
			xmlTextWriterWriteFormatString(writer, "%s",
						       task->name);
			xmlTextWriterEndElement(writer); /* name */
		}

		xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
		xmlTextWriterWriteFormatString(writer, "%d", task->references);
		xmlTextWriterEndElement(writer); /* references */

		xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
		xmlTextWriterWriteFormatString(writer, "%p", task);
		xmlTextWriterEndElement(writer); /* id */

		xmlTextWriterStartElement(writer, ISC_XMLCHAR "state");
		xmlTextWriterWriteFormatString(writer, "%s",
					       statenames[task->state]);
		xmlTextWriterEndElement(writer); /* state */

		xmlTextWriterStartElement(writer, ISC_XMLCHAR "quantum");
		xmlTextWriterWriteFormatString(writer, "%d", task->quantum);
		xmlTextWriterEndElement(writer); /* quantum */

		xmlTextWriterEndElement(writer);

		UNLOCK(&task->lock);
		task = ISC_LIST_NEXT(task, link);
	}
	xmlTextWriterEndElement(writer); /* tasks */

	UNLOCK(&mgr->lock);
}
Ejemplo n.º 4
0
isc_result_t
dns_diff_print(dns_diff_t *diff, FILE *file) {
	isc_result_t result;
	dns_difftuple_t *t;
	char *mem = NULL;
	unsigned int size = 2048;
	const char *op = NULL;

	REQUIRE(DNS_DIFF_VALID(diff));

	mem = isc_mem_get(diff->mctx, size);
	if (mem == NULL)
		return (ISC_R_NOMEMORY);

	for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
	     t = ISC_LIST_NEXT(t, link))
	{
		isc_buffer_t buf;
		isc_region_t r;

		dns_rdatalist_t rdl;
		dns_rdataset_t rds;
		dns_rdata_t rd = DNS_RDATA_INIT;

		result = diff_tuple_tordataset(t, &rd, &rdl, &rds);
		if (result != ISC_R_SUCCESS) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "diff_tuple_tordataset failed: %s",
					 dns_result_totext(result));
			result =  ISC_R_UNEXPECTED;
			goto cleanup;
		}
 again:
		isc_buffer_init(&buf, mem, size);
		result = dns_rdataset_totext(&rds, &t->name,
					     ISC_FALSE, ISC_FALSE, &buf);

		if (result == ISC_R_NOSPACE) {
			isc_mem_put(diff->mctx, mem, size);
			size += 1024;
			mem = isc_mem_get(diff->mctx, size);
			if (mem == NULL) {
				result = ISC_R_NOMEMORY;
				goto cleanup;
			}
			goto again;
		}

		if (result != ISC_R_SUCCESS)
			goto cleanup;
		/*
		 * Get rid of final newline.
		 */
		INSIST(buf.used >= 1 &&
		       ((char *) buf.base)[buf.used-1] == '\n');
		buf.used--;

		isc_buffer_usedregion(&buf, &r);
		switch (t->op) {
		case DNS_DIFFOP_EXISTS: op = "exists"; break;
		case DNS_DIFFOP_ADD: op = "add"; break;
		case DNS_DIFFOP_DEL: op = "del"; break;
		case DNS_DIFFOP_ADDRESIGN: op = "add re-sign"; break;
		case DNS_DIFFOP_DELRESIGN: op = "del re-sign"; break;
		}
		if (file != NULL)
			fprintf(file, "%s %.*s\n", op, (int) r.length,
				(char *) r.base);
		else
			isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_DEBUG(7),
				      "%s %.*s", op, (int) r.length,
				      (char *) r.base);
	}
	result = ISC_R_SUCCESS;
 cleanup:
	if (mem != NULL)
		isc_mem_put(diff->mctx, mem, size);
	return (result);
}
Ejemplo n.º 5
0
Archivo: app.c Proyecto: jhbsz/netbsd
ISC_APPFUNC_SCOPE isc_result_t
isc__app_ctxrun(isc_appctx_t *ctx0) {
	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
	int result;
	isc_event_t *event, *next_event;
	isc_task_t *task;
	sigset_t sset;
	char strbuf[ISC_STRERRORSIZE];
#ifdef HAVE_SIGWAIT
	int sig;
#endif

	REQUIRE(VALID_APPCTX(ctx));

#ifdef HAVE_LINUXTHREADS
	REQUIRE(main_thread == pthread_self());
#endif

	LOCK(&ctx->lock);

	if (!ctx->running) {
		ctx->running = ISC_TRUE;

		/*
		 * Post any on-run events (in FIFO order).
		 */
		for (event = ISC_LIST_HEAD(ctx->on_run);
		     event != NULL;
		     event = next_event) {
			next_event = ISC_LIST_NEXT(event, ev_link);
			ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
			task = event->ev_sender;
			event->ev_sender = NULL;
			isc_task_sendanddetach(&task, &event);
		}

	}

	UNLOCK(&ctx->lock);

#ifndef HAVE_SIGWAIT
	/*
	 * Catch SIGHUP.
	 *
	 * We do this here to ensure that the signal handler is installed
	 * (i.e. that it wasn't a "one-shot" handler).
	 */
	if (ctx == &isc_g_appctx) {
		result = handle_signal(SIGHUP, reload_action);
		if (result != ISC_R_SUCCESS)
			return (ISC_R_SUCCESS);
	}
#endif

	/*
	 * When we are using multiple contexts, we don't rely on signals.
	 */
	if (ctx == &isc_g_appctx) {

	/*
	 * There is no danger if isc_app_shutdown() is called before we wait
	 * for signals.  Signals are blocked, so any such signal will simply
	 * be made pending and we will get it when we call sigwait().
	 */

	while (!ctx->want_shutdown) {
#ifdef HAVE_SIGWAIT
		/*
		 * Wait for SIGHUP, SIGINT, or SIGTERM.
		 */
		if (sigemptyset(&sset) != 0 ||
		    sigaddset(&sset, SIGHUP) != 0 ||
		    sigaddset(&sset, SIGINT) != 0 ||
		    sigaddset(&sset, SIGTERM) != 0) {
			isc__strerror(errno, strbuf, sizeof(strbuf));
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "isc_app_run() sigsetops: %s", strbuf);
			return (ISC_R_UNEXPECTED);
		}

#ifndef HAVE_UNIXWARE_SIGWAIT
		result = sigwait(&sset, &sig);
		if (result == 0) {
			if (sig == SIGINT || sig == SIGTERM)
				ctx->want_shutdown = ISC_TRUE;
			else if (sig == SIGHUP)
				ctx->want_reload = ISC_TRUE;
		}

#else /* Using UnixWare sigwait semantics. */
		sig = sigwait(&sset);
		if (sig >= 0) {
			if (sig == SIGINT || sig == SIGTERM)
				ctx->want_shutdown = ISC_TRUE;
			else if (sig == SIGHUP)
				ctx->want_reload = ISC_TRUE;
		}

#endif /* HAVE_UNIXWARE_SIGWAIT */
#else  /* Don't have sigwait(). */
		/*
		 * Listen for all signals.
		 */
		if (sigemptyset(&sset) != 0) {
			isc__strerror(errno, strbuf, sizeof(strbuf));
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "isc_app_run() sigsetops: %s",
					 strbuf);
			return (ISC_R_UNEXPECTED);
		}
		result = sigsuspend(&sset);
#endif /* HAVE_SIGWAIT */

		if (ctx->want_reload) {
			ctx->want_reload = ISC_FALSE;
			return (ISC_R_RELOAD);
		}

		if (ctx->want_shutdown && ctx->blocked)
			exit(1);
	}
	} else {

	(void)isc__taskmgr_dispatch(ctx->taskmgr);
#ifndef ISC_PLATFORM_USETHREADS
	result = evloop(ctx);
	if (result != ISC_R_SUCCESS)
		return (result);
#endif
	}

	return (ISC_R_SUCCESS);
}
Ejemplo n.º 6
0
isc_result_t
ns_stats_dump(ns_server_t *server, FILE *fp) {
	isc_stdtime_t now;
	isc_result_t result;
	dns_view_t *view;
	dns_zone_t *zone, *next;
	stats_dumparg_t dumparg;
	isc_uint64_t nsstat_values[dns_nsstatscounter_max];
	isc_uint64_t resstat_values[dns_resstatscounter_max];
	isc_uint64_t zonestat_values[dns_zonestatscounter_max];
	isc_uint64_t sockstat_values[isc_sockstatscounter_max];

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

	/* Set common fields */
	dumparg.type = statsformat_file;
	dumparg.arg = fp;

	isc_stdtime_get(&now);
	fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);

	fprintf(fp, "++ Incoming Requests ++\n");
	dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg, 0);

	fprintf(fp, "++ Incoming Queries ++\n");
	dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
				&dumparg, 0);

	fprintf(fp, "++ Outgoing Queries ++\n");
	for (view = ISC_LIST_HEAD(server->viewlist);
	     view != NULL;
	     view = ISC_LIST_NEXT(view, link)) {
		if (view->resquerystats == NULL)
			continue;
		if (strcmp(view->name, "_default") == 0)
			fprintf(fp, "[View: default]\n");
		else
			fprintf(fp, "[View: %s]\n", view->name);
		dns_rdatatypestats_dump(view->resquerystats, rdtypestat_dump,
					&dumparg, 0);
	}

	fprintf(fp, "++ Name Server Statistics ++\n");
	(void) dump_counters(server->nsstats, statsformat_file, fp, NULL,
			     nsstats_desc, dns_nsstatscounter_max,
			     nsstats_index, nsstat_values, 0);

	fprintf(fp, "++ Zone Maintenance Statistics ++\n");
	(void) dump_counters(server->zonestats, statsformat_file, fp, NULL,
			     zonestats_desc, dns_zonestatscounter_max,
			     zonestats_index, zonestat_values, 0);

	fprintf(fp, "++ Resolver Statistics ++\n");
	fprintf(fp, "[Common]\n");
	(void) dump_counters(server->resolverstats, statsformat_file, fp, NULL,
			     resstats_desc, dns_resstatscounter_max,
			     resstats_index, resstat_values, 0);
	for (view = ISC_LIST_HEAD(server->viewlist);
	     view != NULL;
	     view = ISC_LIST_NEXT(view, link)) {
		if (view->resstats == NULL)
			continue;
		if (strcmp(view->name, "_default") == 0)
			fprintf(fp, "[View: default]\n");
		else
			fprintf(fp, "[View: %s]\n", view->name);
		(void) dump_counters(view->resstats, statsformat_file, fp, NULL,
				     resstats_desc, dns_resstatscounter_max,
				     resstats_index, resstat_values, 0);
	}

	fprintf(fp, "++ Cache DB RRsets ++\n");
	for (view = ISC_LIST_HEAD(server->viewlist);
	     view != NULL;
	     view = ISC_LIST_NEXT(view, link)) {
		dns_stats_t *cachestats;

		cachestats = dns_db_getrrsetstats(view->cachedb);
		if (cachestats == NULL)
			continue;
		if (strcmp(view->name, "_default") == 0)
			fprintf(fp, "[View: default]\n");
		else
			fprintf(fp, "[View: %s (Cache: %s)]\n", view->name,
				dns_cache_getname(view->cache));
		if (dns_view_iscacheshared(view)) {
			/*
			 * Avoid dumping redundant statistics when the cache is
			 * shared.
			 */
			continue;
		}
		dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg,
				       0);
	}

	fprintf(fp, "++ Socket I/O Statistics ++\n");
	(void) dump_counters(server->sockstats, statsformat_file, fp, NULL,
			     sockstats_desc, isc_sockstatscounter_max,
			     sockstats_index, sockstat_values, 0);

	fprintf(fp, "++ Per Zone Query Statistics ++\n");
	zone = NULL;
	for (result = dns_zone_first(server->zonemgr, &zone);
	     result == ISC_R_SUCCESS;
	     next = NULL, result = dns_zone_next(zone, &next), zone = next)
	{
		isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
		if (zonestats != NULL) {
			char zonename[DNS_NAME_FORMATSIZE];

			dns_name_format(dns_zone_getorigin(zone),
					zonename, sizeof(zonename));
			view = dns_zone_getview(zone);

			fprintf(fp, "[%s", zonename);
			if (strcmp(view->name, "_default") != 0)
				fprintf(fp, " (view: %s)", view->name);
			fprintf(fp, "]\n");

			(void) dump_counters(zonestats, statsformat_file, fp,
					     NULL, nsstats_desc,
					     dns_nsstatscounter_max,
					     nsstats_index, nsstat_values, 0);
		}
	}

	fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);

	return (ISC_R_SUCCESS);	/* this function currently always succeeds */
}
Ejemplo n.º 7
0
static isc_result_t
diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
	   isc_boolean_t warn)
{
	dns_difftuple_t *t;
	dns_dbnode_t *node = NULL;
	isc_result_t result;
	char namebuf[DNS_NAME_FORMATSIZE];
	char typebuf[DNS_RDATATYPE_FORMATSIZE];
	char classbuf[DNS_RDATACLASS_FORMATSIZE];

	REQUIRE(DNS_DIFF_VALID(diff));
	REQUIRE(DNS_DB_VALID(db));

	t = ISC_LIST_HEAD(diff->tuples);
	while (t != NULL) {
		dns_name_t *name;

		INSIST(node == NULL);
		name = &t->name;
		/*
		 * Find the node.
		 * We create the node if it does not exist.
		 * This will cause an empty node to be created if the diff
		 * contains a deletion of an RR at a nonexistent name,
		 * but such diffs should never be created in the first
		 * place.
		 */

		while (t != NULL && dns_name_equal(&t->name, name)) {
			dns_rdatatype_t type, covers;
			dns_diffop_t op;
			dns_rdatalist_t rdl;
			dns_rdataset_t rds;
			dns_rdataset_t ardataset;
			dns_rdataset_t *modified = NULL;

			op = t->op;
			type = t->rdata.type;
			covers = rdata_covers(&t->rdata);

			/*
			 * Collect a contiguous set of updates with
			 * the same operation (add/delete) and RR type
			 * into a single rdatalist so that the
			 * database rrset merging/subtraction code
			 * can work more efficiently than if each
			 * RR were merged into / subtracted from
			 * the database separately.
			 *
			 * This is done by linking rdata structures from the
			 * diff into "rdatalist".  This uses the rdata link
			 * field, not the diff link field, so the structure
			 * of the diff itself is not affected.
			 */

			rdl.type = type;
			rdl.covers = covers;
			rdl.rdclass = t->rdata.rdclass;
			rdl.ttl = t->ttl;
			ISC_LIST_INIT(rdl.rdata);
			ISC_LINK_INIT(&rdl, link);

			node = NULL;
			if (type != dns_rdatatype_nsec3 &&
			    covers != dns_rdatatype_nsec3)
				CHECK(dns_db_findnode(db, name, ISC_TRUE,
						      &node));
			else
				CHECK(dns_db_findnsec3node(db, name, ISC_TRUE,
							   &node));

			while (t != NULL &&
			       dns_name_equal(&t->name, name) &&
			       t->op == op &&
			       t->rdata.type == type &&
			       rdata_covers(&t->rdata) == covers)
			{
				dns_name_format(name, namebuf, sizeof(namebuf));
				dns_rdatatype_format(t->rdata.type, typebuf,
						     sizeof(typebuf));
				dns_rdataclass_format(t->rdata.rdclass,
						      classbuf,
						      sizeof(classbuf));
				if (t->ttl != rdl.ttl && warn)
					isc_log_write(DIFF_COMMON_LOGARGS,
						ISC_LOG_WARNING,
						"'%s/%s/%s': TTL differs in "
						"rdataset, adjusting "
						"%lu -> %lu",
						namebuf, typebuf, classbuf,
						(unsigned long) t->ttl,
						(unsigned long) rdl.ttl);
				ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
				t = ISC_LIST_NEXT(t, link);
			}

			/*
			 * Convert the rdatalist into a rdataset.
			 */
			dns_rdataset_init(&rds);
			CHECK(dns_rdatalist_tordataset(&rdl, &rds));
			if (rds.type == dns_rdatatype_rrsig)
				switch (op) {
				case DNS_DIFFOP_ADDRESIGN:
				case DNS_DIFFOP_DELRESIGN:
					modified = &ardataset;
					dns_rdataset_init(modified);
					break;
				default:
					break;
				}
			rds.trust = dns_trust_ultimate;

			/*
			 * Merge the rdataset into the database.
			 */
			switch (op) {
			case DNS_DIFFOP_ADD:
			case DNS_DIFFOP_ADDRESIGN:
				result = dns_db_addrdataset(db, node, ver,
							    0, &rds,
							    DNS_DBADD_MERGE|
							    DNS_DBADD_EXACT|
							    DNS_DBADD_EXACTTTL,
							    modified);
				break;
			case DNS_DIFFOP_DEL:
			case DNS_DIFFOP_DELRESIGN:
				result = dns_db_subtractrdataset(db, node, ver,
							       &rds,
							       DNS_DBSUB_EXACT,
							       modified);
				break;
			default:
				INSIST(0);
			}

			if (result == ISC_R_SUCCESS) {
				if (modified != NULL) {
					isc_stdtime_t resign;
					resign = setresign(modified,
							   diff->resign);
					dns_db_setsigningtime(db, modified,
							      resign);
					if (diff->resign == 0 &&
					    (op == DNS_DIFFOP_ADDRESIGN ||
					     op == DNS_DIFFOP_DELRESIGN))
						isc_log_write(
							DIFF_COMMON_LOGARGS,
							ISC_LOG_WARNING,
							"resign requested "
							"with 0 resign "
							"interval");
				}
			} else if (result == DNS_R_UNCHANGED) {
				/*
				 * This will not happen when executing a
				 * dynamic update, because that code will
				 * generate strictly minimal diffs.
				 * It may happen when receiving an IXFR
				 * from a server that is not as careful.
				 * Issue a warning and continue.
				 */
				if (warn) {
					char classbuf[DNS_RDATATYPE_FORMATSIZE];
					char namebuf[DNS_NAME_FORMATSIZE];

					dns_name_format(dns_db_origin(db),
							namebuf,
							sizeof(namebuf));
					dns_rdataclass_format(dns_db_class(db),
							      classbuf,
							      sizeof(classbuf));
					isc_log_write(DIFF_COMMON_LOGARGS,
						      ISC_LOG_WARNING,
						      "%s/%s: dns_diff_apply: "
						      "update with no effect",
						      namebuf, classbuf);
				}
			} else if (result == DNS_R_NXRRSET) {
				/*
				 * OK.
				 */
			} else {
				if (modified != NULL &&
				    dns_rdataset_isassociated(modified))
					dns_rdataset_disassociate(modified);
				CHECK(result);
			}
			dns_db_detachnode(db, &node);
			if (modified != NULL &&
			    dns_rdataset_isassociated(modified))
				dns_rdataset_disassociate(modified);
		}
	}
	return (ISC_R_SUCCESS);

 failure:
	if (node != NULL)
		dns_db_detachnode(db, &node);
	return (result);
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
static isc_result_t
do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
	isc_boolean_t verbose)
{
	isc_interfaceiter_t *iter = NULL;
	isc_boolean_t scan_ipv4 = ISC_FALSE;
	isc_boolean_t scan_ipv6 = ISC_FALSE;
	isc_boolean_t adjusting = ISC_FALSE;
	isc_boolean_t ipv6only = ISC_TRUE;
	isc_boolean_t ipv6pktinfo = ISC_TRUE;
	isc_result_t result;
	isc_netaddr_t zero_address, zero_address6;
	ns_listenelt_t *le;
	isc_sockaddr_t listen_addr;
	ns_interface_t *ifp;
	isc_boolean_t log_explicit = ISC_FALSE;
	isc_boolean_t dolistenon;

	if (ext_listen != NULL)
		adjusting = ISC_TRUE;

	if (isc_net_probeipv6() == ISC_R_SUCCESS)
		scan_ipv6 = ISC_TRUE;
#ifdef WANT_IPV6
	else
		isc_log_write(IFMGR_COMMON_LOGARGS,
			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
			      "no IPv6 interfaces found");
#endif

	if (isc_net_probeipv4() == ISC_R_SUCCESS)
		scan_ipv4 = ISC_TRUE;
	else
		isc_log_write(IFMGR_COMMON_LOGARGS,
			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
			      "no IPv4 interfaces found");

	/*
	 * A special, but typical case; listen-on-v6 { any; }.
	 * When we can make the socket IPv6-only, open a single wildcard
	 * socket for IPv6 communication.  Otherwise, make separate socket
	 * for each IPv6 address in order to avoid accepting IPv4 packets
	 * as the form of mapped addresses unintentionally unless explicitly
	 * allowed.
	 */
#ifndef ISC_ALLOW_MAPPED
	if (scan_ipv6 == ISC_TRUE &&
	    isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
		ipv6only = ISC_FALSE;
		log_explicit = ISC_TRUE;
	}
#endif
	if (scan_ipv6 == ISC_TRUE &&
	    isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
		ipv6pktinfo = ISC_FALSE;
		log_explicit = ISC_TRUE;
	}
	if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
		for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
		     le != NULL;
		     le = ISC_LIST_NEXT(le, link)) {
			struct in6_addr in6a;

			if (!listenon_is_ip6_any(le))
				continue;

			in6a = in6addr_any;
			isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);

			ifp = find_matching_interface(mgr, &listen_addr);
			if (ifp != NULL) {
				ifp->generation = mgr->generation;
			} else {
				isc_log_write(IFMGR_COMMON_LOGARGS,
					      ISC_LOG_INFO,
					      "listening on IPv6 "
					      "interfaces, port %u",
					      le->port);
				result = ns_interface_setup(mgr, &listen_addr,
							    "<any>", &ifp,
							    ISC_TRUE);
				if (result == ISC_R_SUCCESS)
					ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
				else
					isc_log_write(IFMGR_COMMON_LOGARGS,
						      ISC_LOG_ERROR,
						      "listening on all IPv6 "
						      "interfaces failed");
				/* Continue. */
			}
		}
	}

	isc_netaddr_any(&zero_address);
	isc_netaddr_any6(&zero_address6);

	result = isc_interfaceiter_create(mgr->mctx, &iter);
	if (result != ISC_R_SUCCESS)
		return (result);

	if (adjusting == ISC_FALSE) {
		result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
		if (result != ISC_R_SUCCESS)
			goto cleanup_iter;
		result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
		if (result != ISC_R_SUCCESS)
			goto cleanup_iter;
		clearlistenon(mgr);
	}

	for (result = isc_interfaceiter_first(iter);
	     result == ISC_R_SUCCESS;
	     result = isc_interfaceiter_next(iter))
	{
		isc_interface_t interface;
		ns_listenlist_t *ll;
		unsigned int family;

		result = isc_interfaceiter_current(iter, &interface);
		if (result != ISC_R_SUCCESS)
			break;

		family = interface.address.family;
		if (family != AF_INET && family != AF_INET6)
			continue;
		if (scan_ipv4 == ISC_FALSE && family == AF_INET)
			continue;
		if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
			continue;

		/*
		 * Test for the address being nonzero rather than testing
		 * INTERFACE_F_UP, because on some systems the latter
		 * follows the media state and we could end up ignoring
		 * the interface for an entire rescan interval due to
		 * a temporary media glitch at rescan time.
		 */
		if (family == AF_INET &&
		    isc_netaddr_equal(&interface.address, &zero_address)) {
			continue;
		}
		if (family == AF_INET6 &&
		    isc_netaddr_equal(&interface.address, &zero_address6)) {
			continue;
		}

		if (adjusting == ISC_FALSE) {
			result = setup_locals(mgr, &interface);
			if (result != ISC_R_SUCCESS)
				goto ignore_interface;
		}

		ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
		dolistenon = ISC_TRUE;
		for (le = ISC_LIST_HEAD(ll->elts);
		     le != NULL;
		     le = ISC_LIST_NEXT(le, link))
		{
			int match;
			isc_boolean_t ipv6_wildcard = ISC_FALSE;
			isc_netaddr_t listen_netaddr;
			isc_sockaddr_t listen_sockaddr;

			/*
			 * Construct a socket address for this IP/port
			 * combination.
			 */
			if (family == AF_INET) {
				isc_netaddr_fromin(&listen_netaddr,
						   &interface.address.type.in);
			} else {
				isc_netaddr_fromin6(&listen_netaddr,
						    &interface.address.type.in6);
				isc_netaddr_setzone(&listen_netaddr,
						    interface.address.zone);
			}
			isc_sockaddr_fromnetaddr(&listen_sockaddr,
						 &listen_netaddr,
						 le->port);

			/*
			 * See if the address matches the listen-on statement;
			 * if not, ignore the interface.
			 */
			(void)dns_acl_match(&listen_netaddr, NULL, le->acl,
					    &mgr->aclenv, &match, NULL);
			if (match <= 0)
				continue;

			if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
				setup_listenon(mgr, &interface, le->port);
				dolistenon = ISC_FALSE;
			}

			/*
			 * The case of "any" IPv6 address will require
			 * special considerations later, so remember it.
			 */
			if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
			    listenon_is_ip6_any(le))
				ipv6_wildcard = ISC_TRUE;

			/*
			 * When adjusting interfaces with extra a listening
			 * list, see if the address matches the extra list.
			 * If it does, and is also covered by a wildcard
			 * interface, we need to listen on the address
			 * explicitly.
			 */
			if (adjusting == ISC_TRUE) {
				ns_listenelt_t *ele;

				match = 0;
				for (ele = ISC_LIST_HEAD(ext_listen->elts);
				     ele != NULL;
				     ele = ISC_LIST_NEXT(ele, link)) {
					(void)dns_acl_match(&listen_netaddr,
							    NULL, ele->acl,
							    NULL, &match, NULL);
					if (match > 0 &&
					    (ele->port == le->port ||
					    ele->port == 0))
						break;
					else
						match = 0;
				}
				if (ipv6_wildcard == ISC_TRUE && match == 0)
					continue;
			}

			ifp = find_matching_interface(mgr, &listen_sockaddr);
			if (ifp != NULL) {
				ifp->generation = mgr->generation;
			} else {
				char sabuf[ISC_SOCKADDR_FORMATSIZE];

				if (adjusting == ISC_FALSE &&
				    ipv6_wildcard == ISC_TRUE)
					continue;

				if (log_explicit && family == AF_INET6 &&
				    !adjusting && listenon_is_ip6_any(le)) {
					isc_log_write(IFMGR_COMMON_LOGARGS,
						      verbose ? ISC_LOG_INFO :
							      ISC_LOG_DEBUG(1),
						      "IPv6 socket API is "
						      "incomplete; explicitly "
						      "binding to each IPv6 "
						      "address separately");
					log_explicit = ISC_FALSE;
				}
				isc_sockaddr_format(&listen_sockaddr,
						    sabuf, sizeof(sabuf));
				isc_log_write(IFMGR_COMMON_LOGARGS,
					      ISC_LOG_INFO,
					      "%s"
					      "listening on %s interface "
					      "%s, %s",
					      (adjusting == ISC_TRUE) ?
					      "additionally " : "",
					      (family == AF_INET) ?
					      "IPv4" : "IPv6",
					      interface.name, sabuf);

				result = ns_interface_setup(mgr,
							    &listen_sockaddr,
							    interface.name,
							    &ifp,
							    (adjusting == ISC_TRUE) ?
							    ISC_FALSE :
							    ISC_TRUE);

				if (result != ISC_R_SUCCESS) {
					isc_log_write(IFMGR_COMMON_LOGARGS,
						      ISC_LOG_ERROR,
						      "creating %s interface "
						      "%s failed; interface "
						      "ignored",
						      (family == AF_INET) ?
						      "IPv4" : "IPv6",
						      interface.name);
				}
				/* Continue. */
			}

		}
		continue;

	ignore_interface:
		isc_log_write(IFMGR_COMMON_LOGARGS,
			      ISC_LOG_ERROR,
			      "ignoring %s interface %s: %s",
			      (family == AF_INET) ? "IPv4" : "IPv6",
			      interface.name, isc_result_totext(result));
		continue;
	}
	if (result != ISC_R_NOMORE)
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "interface iteration failed: %s",
				 isc_result_totext(result));
	else
		result = ISC_R_SUCCESS;
 cleanup_iter:
	isc_interfaceiter_destroy(&iter);
	return (result);
}
Ejemplo n.º 10
0
static void
request_done(isc_task_t *task, isc_event_t *event) {
	struct probe_trans *trans = event->ev_arg;
	dns_clientreqevent_t *rev = (dns_clientreqevent_t *)event;
	dns_message_t *rmessage;
	struct probe_ns *pns;
	struct server *server;
	isc_result_t result;
	query_result_t *resultp;
	dns_name_t *name;
	dns_rdataset_t *rdataset;
	dns_rdatatype_t type;

	REQUIRE(task == probe_task);
	REQUIRE(trans != NULL && trans->inuse == ISC_TRUE);
	rmessage = rev->rmessage;
	REQUIRE(rmessage == trans->rmessage);
	INSIST(outstanding_probes > 0);

	server = trans->current_ns->current_server;
	INSIST(server != NULL);

	if (server->result_a == none) {
		type = dns_rdatatype_a;
		resultp = &server->result_a;
	} else {
		resultp = &server->result_aaaa;
		type = dns_rdatatype_aaaa;
	}

	if (rev->result == ISC_R_SUCCESS) {
		if ((rmessage->flags & DNS_MESSAGEFLAG_AA) == 0)
			*resultp = lame;
		else if (rmessage->rcode == dns_rcode_nxdomain)
			*resultp = nxdomain;
		else if (rmessage->rcode != dns_rcode_noerror)
			*resultp = othererr;
		else if (rmessage->counts[DNS_SECTION_ANSWER] == 0) {
			/* no error but empty answer */
			*resultp = notype;
		} else {
			result = dns_message_firstname(rmessage,
						       DNS_SECTION_ANSWER);
			while (result == ISC_R_SUCCESS) {
				name = NULL;
				dns_message_currentname(rmessage,
							DNS_SECTION_ANSWER,
							&name);
				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_cname ||
					    rdataset->type ==
					    dns_rdatatype_dname) {
						/* Should chase the chain? */
						*resultp = exist;
						goto found;
					} else if (rdataset->type == type) {
						*resultp = exist;
						goto found;
					}
				}
				result = dns_message_nextname(rmessage,
							      DNS_SECTION_ANSWER);
			}

			/*
			 * Something unexpected happened: the response
			 * contained a non-empty authoritative answer, but we
			 * could not find an expected result.
			 */
			*resultp = unexpected;
		}
	} else if (rev->result == DNS_R_RECOVERABLE ||
		   rev->result == DNS_R_BADLABELTYPE) {
		/* Broken response.  Try identifying known cases. */
		*resultp = brokenanswer;

		if (rmessage->counts[DNS_SECTION_ANSWER] > 0) {
			result = dns_message_firstname(rmessage,
						       DNS_SECTION_ANSWER);
			while (result == ISC_R_SUCCESS) {
				/*
				 * Check to see if the response has multiple
				 * CNAME RRs.  Update the result code if so.
				 */
				name = NULL;
				dns_message_currentname(rmessage,
							DNS_SECTION_ANSWER,
							&name);
				for (rdataset = ISC_LIST_HEAD(name->list);
				     rdataset != NULL;
				     rdataset = ISC_LIST_NEXT(rdataset,
							      link)) {
					if (rdataset->type ==
					    dns_rdatatype_cname &&
					    dns_rdataset_count(rdataset) > 1) {
						*resultp = multiplecname;
						goto found;
					}
				}
				result = dns_message_nextname(rmessage,
							      DNS_SECTION_ANSWER);
			}
		}

		if (rmessage->counts[DNS_SECTION_AUTHORITY] > 0) {
			result = dns_message_firstname(rmessage,
						       DNS_SECTION_AUTHORITY);
			while (result == ISC_R_SUCCESS) {
				/*
				 * Check to see if the response has multiple
				 * SOA RRs.  Update the result code if so.
				 */
				name = NULL;
				dns_message_currentname(rmessage,
							DNS_SECTION_AUTHORITY,
							&name);
				for (rdataset = ISC_LIST_HEAD(name->list);
				     rdataset != NULL;
				     rdataset = ISC_LIST_NEXT(rdataset,
							      link)) {
					if (rdataset->type ==
					    dns_rdatatype_soa &&
					    dns_rdataset_count(rdataset) > 1) {
						*resultp = multiplesoa;
						goto found;
					}
				}
				result = dns_message_nextname(rmessage,
							      DNS_SECTION_AUTHORITY);
			}
		}
	} else if (rev->result == ISC_R_TIMEDOUT)
		*resultp = timedout;
	else {
		fprintf(stderr, "unexpected result: %d (domain=%s, server=",
			rev->result, trans->domain);
		print_address(stderr, &server->address);
		fputc('\n', stderr);
		*resultp = unexpected;
	}

 found:
	INSIST(*resultp != none);
	if (type == dns_rdatatype_a && *resultp == exist)
		trans->qname_found = ISC_TRUE;

	dns_client_destroyreqtrans(&trans->reqid);
	isc_event_free(&event);
	dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE);

	result = probe_name(trans, type);
	if (result == ISC_R_NOMORE) {
		/* We've tried all addresses of all servers. */
		if (type == dns_rdatatype_a && trans->qname_found) {
			/*
			 * If we've explored A RRs and found an existent
			 * record, we can move to AAAA.
			 */
			trans->current_ns = ISC_LIST_HEAD(trans->nslist);
			probe_name(trans, dns_rdatatype_aaaa);
			result = ISC_R_SUCCESS;
		} else if (type == dns_rdatatype_a) {
			/*
			 * No server provided an existent A RR of this name.
			 * Try next label.
			 */
			dns_fixedname_invalidate(&trans->fixedname);
			trans->qname = NULL;
			result = set_nextqname(trans);
			if (result == ISC_R_SUCCESS) {
				trans->current_ns =
					ISC_LIST_HEAD(trans->nslist);
				for (pns = trans->current_ns; pns != NULL;
				     pns = ISC_LIST_NEXT(pns, link)) {
					for (server = ISC_LIST_HEAD(pns->servers);
					     server != NULL;
					     server = ISC_LIST_NEXT(server,
								    link)) {
						INSIST(server->result_aaaa ==
						       none);
						server->result_a = none;
					}
				}
				result = probe_name(trans, dns_rdatatype_a);
			}
		}
		if (result != ISC_R_SUCCESS) {
			/*
			 * We've explored AAAA RRs or failed to find a valid
			 * query label.  Wrap up the result and move to the
			 * next domain.
			 */
			reset_probe(trans);
		}
	} else if (result != ISC_R_SUCCESS)
		reset_probe(trans); /* XXX */
}
Ejemplo n.º 11
0
static void
resolve_nsaddress(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;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	struct probe_ns *pns = trans->current_ns;
	isc_result_t result;

	REQUIRE(task == probe_task);
	REQUIRE(trans->inuse == ISC_TRUE);
	REQUIRE(pns != NULL);
	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_a)
				continue;

			for (result = dns_rdataset_first(rdataset);
			     result == ISC_R_SUCCESS;
			     result = dns_rdataset_next(rdataset)) {
				dns_rdata_in_a_t rdata_a;
				struct server *server;

				dns_rdataset_current(rdataset, &rdata);
				result = dns_rdata_tostruct(&rdata, &rdata_a,
							    NULL);
				if (result != ISC_R_SUCCESS)
					continue;

				server = isc_mem_get(mctx, sizeof(*server));
				if (server == NULL) {
					fprintf(stderr, "resolve_nsaddress: "
						"mem_get failed");
					result = ISC_R_NOMEMORY;
					POST(result);
					goto cleanup;
				}
				isc_sockaddr_fromin(&server->address,
						    &rdata_a.in_addr, 53);
				ISC_LINK_INIT(server, link);
				server->result_a = none;
				server->result_aaaa = none;
				ISC_LIST_APPEND(pns->servers, server, link);
			}
		}
	}

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

 next_ns:
	trans->current_ns = ISC_LIST_NEXT(pns, link);
	if (trans->current_ns == NULL) {
		trans->current_ns = ISC_LIST_HEAD(trans->nslist);
		dns_fixedname_invalidate(&trans->fixedname);
		trans->qname = NULL;
		result = set_nextqname(trans);
		if (result == ISC_R_SUCCESS)
			 result = probe_name(trans, dns_rdatatype_a);
	} else {
		result = fetch_nsaddress(trans);
		if (result != ISC_R_SUCCESS)
			goto next_ns; /* XXX: this is unlikely to succeed */
	}

	if (result != ISC_R_SUCCESS)
		reset_probe(trans);
}
Ejemplo n.º 12
0
isc_result_t
res_nupdate(res_state statp, ns_updrec *rrecp_in) {
	ns_updrec *rrecp;
	double answer[PACKETSZ / sizeof (double)];
	double packet[2*PACKETSZ / sizeof (double)];
	struct zonegrp *zptr, tgrp;
	int nzones = 0, nscount = 0;
	unsigned n;
	unsigned rval;
	struct sockaddr_in nsaddrs[MAXNS];
	ns_tsig_key *key;
	void *zcookie = 0;
	void *zcookp = &zcookie;
	isc_result_t rcode;

      again:
	/* Make sure all the updates are in the same zone, and find out
	   what zone they are in. */
	zptr = NULL;
	for (rrecp = rrecp_in; rrecp; rrecp = ISC_LIST_NEXT(rrecp, r_link)) {
		/* Find the origin for it if there is one. */
		tgrp.z_class = rrecp->r_class;
		rcode = res_findzonecut(statp, rrecp->r_dname, tgrp.z_class,
					RES_EXHAUSTIVE,
					tgrp.z_origin,
					sizeof tgrp.z_origin,
					tgrp.z_nsaddrs, MAXNS, &tgrp.z_nscount,
					zcookp);
		if (rcode != ISC_R_SUCCESS)
			goto done;
		if (tgrp.z_nscount <= 0) {
			rcode = ISC_R_NOTZONE;
			goto done;
		}
		/* Make a group for it if there isn't one. */
		if (zptr == NULL) {
			zptr = malloc(sizeof *zptr);
			if (zptr == NULL) {
				rcode = ISC_R_NOMEMORY;
				goto done;
			}
			*zptr = tgrp;
			zptr->z_flags = 0;
			ISC_LIST_INIT(zptr->z_rrlist);
		} else if (ns_samename(tgrp.z_origin, zptr->z_origin) == 0 ||
			   tgrp.z_class != zptr->z_class) {
			/* Some of the records are in different zones. */
			rcode = ISC_R_CROSSZONE;
			goto done;
		}
		/* Thread this rrecp onto the zone group. */
		ISC_LIST_APPEND(zptr->z_rrlist, rrecp, r_glink);
	}

	/* Construct zone section and prepend it. */
	rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
			     zptr->z_class, ns_t_soa, 0);
	if (rrecp == NULL) {
		rcode = ISC_R_UNEXPECTED;
		goto done;
	}
	ISC_LIST_PREPEND(zptr->z_rrlist, rrecp, r_glink);
	zptr->z_flags |= ZG_F_ZONESECTADDED;

	/* Marshall the update message. */
	n = sizeof packet;
	rcode = res_nmkupdate(statp,
			      ISC_LIST_HEAD(zptr->z_rrlist), packet, &n);
	if (rcode != ISC_R_SUCCESS)
		goto done;

	/* Temporarily replace the resolver's nameserver set. */
	nscount = nscopy(nsaddrs, statp->nsaddr_list, statp->nscount);
	statp->nscount = nsprom(statp->nsaddr_list,
				zptr->z_nsaddrs, zptr->z_nscount);

	/* Send the update and remember the result. */
	key = (ns_tsig_key *)0;
	rcode = find_tsig_key (&key, zptr->z_origin, zcookie);
	if (rcode == ISC_R_SUCCESS) {
		rcode = res_nsendsigned(statp, packet, n, key,
					answer, sizeof answer, &rval);
		tkey_free (&key);
	} else if (rcode == ISC_R_NOTFOUND || rcode == ISC_R_KEY_UNKNOWN) {
		rcode = res_nsend(statp, packet, n,
				  answer, sizeof answer, &rval);
	}
	if (rcode != ISC_R_SUCCESS)
		goto undone;

	rcode = ns_rcode_to_isc (((HEADER *)answer)->rcode);
	if (zcookie && rcode == ISC_R_BADSIG) {
		repudiate_zone (&zcookie);
	}

 undone:
	/* Restore resolver's nameserver set. */
	statp->nscount = nscopy(statp->nsaddr_list, nsaddrs, nscount);
	nscount = 0;
 done:
	if (zptr) {
		if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0)
			res_freeupdrec(ISC_LIST_HEAD(zptr->z_rrlist));
		free(zptr);
	}

	/* If the update failed because we used a cached zone and it
	   didn't work, try it again without the cached zone. */
	if (zcookp && (rcode == ISC_R_NOTZONE || rcode == ISC_R_BADSIG)) {
		zcookp = 0;
		goto again;
	}

	if (zcookie)
		forget_zone (&zcookie);
	return rcode;
}
Ejemplo n.º 13
0
isc_result_t
dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
		     dns_dbnode_t *node, dns_rdatatype_t covers,
		     isc_stdtime_t now, dns_ttl_t maxttl,
		     isc_boolean_t optout, dns_rdataset_t *addedrdataset)
{
	isc_result_t result;
	isc_buffer_t buffer;
	isc_region_t r;
	dns_rdataset_t *rdataset;
	dns_rdatatype_t type;
	dns_name_t *name;
	dns_ttl_t ttl;
	dns_trust_t trust;
	dns_rdata_t rdata[DNS_NCACHE_RDATA];
	dns_rdataset_t ncrdataset;
	dns_rdatalist_t ncrdatalist;
	unsigned char data[4096];
	unsigned int next = 0;

	/*
	 * Convert the authority data from 'message' into a negative cache
	 * rdataset, and store it in 'cache' at 'node'.
	 */

	REQUIRE(message != NULL);

	/*
	 * We assume that all data in the authority section has been
	 * validated by the caller.
	 */

	/*
	 * Initialize the list.
	 */
	ncrdatalist.rdclass = dns_db_class(cache);
	ncrdatalist.type = 0;
	ncrdatalist.covers = covers;
	ncrdatalist.ttl = maxttl;
	ISC_LIST_INIT(ncrdatalist.rdata);
	ISC_LINK_INIT(&ncrdatalist, link);

	/*
	 * Build an ncache rdatas into buffer.
	 */
	ttl = maxttl;
	trust = 0xffff;
	isc_buffer_init(&buffer, data, sizeof(data));
	if (message->counts[DNS_SECTION_AUTHORITY])
		result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
	else
		result = ISC_R_NOMORE;
	while (result == ISC_R_SUCCESS) {
		name = NULL;
		dns_message_currentname(message, DNS_SECTION_AUTHORITY,
					&name);
		if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) {
			for (rdataset = ISC_LIST_HEAD(name->list);
			     rdataset != NULL;
			     rdataset = ISC_LIST_NEXT(rdataset, link)) {
				if ((rdataset->attributes &
				     DNS_RDATASETATTR_NCACHE) == 0)
					continue;
				type = rdataset->type;
				if (type == dns_rdatatype_rrsig)
					type = rdataset->covers;
				if (type == dns_rdatatype_soa ||
				    type == dns_rdatatype_nsec ||
				    type == dns_rdatatype_nsec3) {
					if (ttl > rdataset->ttl)
						ttl = rdataset->ttl;
					if (trust > rdataset->trust)
						trust = rdataset->trust;
					/*
					 * Copy the owner name to the buffer.
					 */
					dns_name_toregion(name, &r);
					result = isc_buffer_copyregion(&buffer,
								       &r);
					if (result != ISC_R_SUCCESS)
						return (result);
					/*
					 * Copy the type to the buffer.
					 */
					isc_buffer_availableregion(&buffer,
								   &r);
					if (r.length < 3)
						return (ISC_R_NOSPACE);
					isc_buffer_putuint16(&buffer,
							     rdataset->type);
					isc_buffer_putuint8(&buffer,
					       (unsigned char)rdataset->trust);
					/*
					 * Copy the rdataset into the buffer.
					 */
					result = copy_rdataset(rdataset,
							       &buffer);
					if (result != ISC_R_SUCCESS)
						return (result);

					if (next >= DNS_NCACHE_RDATA)
						return (ISC_R_NOSPACE);
					dns_rdata_init(&rdata[next]);
					isc_buffer_remainingregion(&buffer, &r);
					rdata[next].data = r.base;
					rdata[next].length = r.length;
					rdata[next].rdclass =
						ncrdatalist.rdclass;
					rdata[next].type = 0;
					rdata[next].flags = 0;
					ISC_LIST_APPEND(ncrdatalist.rdata,
							&rdata[next], link);
					isc_buffer_forward(&buffer, r.length);
					next++;
				}
			}
		}
		result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
	}
	if (result != ISC_R_NOMORE)
		return (result);

	if (trust == 0xffff) {
		if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 &&
		    message->counts[DNS_SECTION_ANSWER] == 0) {
			/*
			 * The response has aa set and we haven't followed
			 * any CNAME or DNAME chains.
			 */
			trust = dns_trust_authauthority;
		} else
			trust = dns_trust_additional;
		ttl = 0;
	}

	INSIST(trust != 0xffff);

	ncrdatalist.ttl = ttl;

	dns_rdataset_init(&ncrdataset);
	RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
		      == ISC_R_SUCCESS);
	ncrdataset.trust = trust;
	ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE;
	if (message->rcode == dns_rcode_nxdomain)
		ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
	if (optout)
		ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT;

	return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset,
				   0, addedrdataset));
}
Ejemplo n.º 14
0
static void
update_listener(ns_controls_t *cp, controllistener_t **listenerp,
		const cfg_obj_t *control, const cfg_obj_t *config,
		isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
		const char *socktext, isc_sockettype_t type)
{
	controllistener_t *listener;
	const cfg_obj_t *allow;
	const cfg_obj_t *global_keylist = NULL;
	const cfg_obj_t *control_keylist = NULL;
	dns_acl_t *new_acl = NULL;
	controlkeylist_t keys;
	isc_result_t result = ISC_R_SUCCESS;

	for (listener = ISC_LIST_HEAD(cp->listeners);
	     listener != NULL;
	     listener = ISC_LIST_NEXT(listener, link))
		if (isc_sockaddr_equal(addr, &listener->address))
			break;

	if (listener == NULL) {
		*listenerp = NULL;
		return;
	}

	/*
	 * There is already a listener for this sockaddr.
	 * Update the access list and key information.
	 *
	 * First try to deal with the key situation.  There are a few
	 * possibilities:
	 *  (a)	It had an explicit keylist and still has an explicit keylist.
	 *  (b)	It had an automagic key and now has an explicit keylist.
	 *  (c)	It had an explicit keylist and now needs an automagic key.
	 *  (d) It has an automagic key and still needs the automagic key.
	 *
	 * (c) and (d) are the annoying ones.  The caller needs to know
	 * that it should use the automagic configuration for key information
	 * in place of the named.conf configuration.
	 *
	 * XXXDCL There is one other hazard that has not been dealt with,
	 * the problem that if a key change is being caused by a control
	 * channel reload, then the response will be with the new key
	 * and not able to be decrypted by the client.
	 */
	if (control != NULL)
		get_key_info(config, control, &global_keylist,
			     &control_keylist);

	if (control_keylist != NULL) {
		INSIST(global_keylist != NULL);

		ISC_LIST_INIT(keys);
		result = controlkeylist_fromcfg(control_keylist,
						listener->mctx, &keys);
		if (result == ISC_R_SUCCESS) {
			free_controlkeylist(&listener->keys, listener->mctx);
			listener->keys = keys;
			register_keys(control, global_keylist, &listener->keys,
				      listener->mctx, socktext);
		}
	} else {
		free_controlkeylist(&listener->keys, listener->mctx);
		result = get_rndckey(listener->mctx, &listener->keys);
	}

	if (result != ISC_R_SUCCESS && global_keylist != NULL) {
		/*
		 * This message might be a little misleading since the
		 * "new keys" might in fact be identical to the old ones,
		 * but tracking whether they are identical just for the
		 * sake of avoiding this message would be too much trouble.
		 */
		if (control != NULL)
			cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
				    "couldn't install new keys for "
				    "command channel %s: %s",
				    socktext, isc_result_totext(result));
		else
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
				      "couldn't install new keys for "
				      "command channel %s: %s",
				      socktext, isc_result_totext(result));
	}

	/*
	 * Now, keep the old access list unless a new one can be made.
	 */
	if (control != NULL && type == isc_sockettype_tcp) {
		allow = cfg_tuple_get(control, "allow");
		result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
					    aclconfctx, listener->mctx, 0,
					    &new_acl);
	} else {
		result = dns_acl_any(listener->mctx, &new_acl);
	}

	if (result == ISC_R_SUCCESS) {
		dns_acl_detach(&listener->acl);
		dns_acl_attach(new_acl, &listener->acl);
		dns_acl_detach(&new_acl);
		/* XXXDCL say the old acl is still used? */
	} else if (control != NULL)
		cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
			    "couldn't install new acl for "
			    "command channel %s: %s",
			    socktext, isc_result_totext(result));
	else
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
			      "couldn't install new acl for "
			      "command channel %s: %s",
			      socktext, isc_result_totext(result));

	if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
		isc_uint32_t perm, owner, group;
		perm  = cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
		owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner"));
		group = cfg_obj_asuint32(cfg_tuple_get(control, "group"));
		result = ISC_R_SUCCESS;
		if (listener->perm != perm || listener->owner != owner ||
		    listener->group != group)
			result = isc_socket_permunix(&listener->address, perm,
						     owner, group);
		if (result == ISC_R_SUCCESS) {
			listener->perm = perm;
			listener->owner = owner;
			listener->group = group;
		} else if (control != NULL)
			cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
				    "couldn't update ownership/permission for "
				    "command channel %s", socktext);
	}

	*listenerp = listener;
}
Ejemplo n.º 15
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;
	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;
#ifdef DLZ
	isc_boolean_t is_dlz = ISC_FALSE;
#endif

	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)
#ifdef DLZ
	{
		/*
		 * Normal zone table does not have a match.  Try the DLZ database
		 */
		if (client->view->dlzdatabase != NULL) {
			result = dns_dlzallowzonexfr(client->view,
						     question_name, &client->peeraddr,
						     &db);

			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)
#endif
			FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
				  question_name, question_class);
#ifdef DLZ
			is_dlz = ISC_TRUE;
			/*
			 * DLZ only support full zone transfer, not incremental
			 */
			if (reqtype != dns_rdatatype_axfr) {
				mnemonic = "AXFR-style IXFR";
				reqtype = dns_rdatatype_axfr;
			}

		} 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 */
#endif
		switch(dns_zone_gettype(zone)) {
			case dns_zone_master:
			case dns_zone_slave:
				break;	/* Master and slave zones are OK for transfer. */
			default:
				FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
			}
		CHECK(dns_zone_getdb(zone, &db));
		dns_db_currentversion(db, &ver);
#ifdef DLZ
	}
#endif

	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);

	/*
	 * Decide whether to allow this transfer.
	 */
#ifdef DLZ
	/*
	 * if not a DLZ zone decide whether to allow this transfer.
	 */
	if (!is_dlz) {
#endif
		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));
#ifdef DLZ
	}
#endif

	/*
	 * 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.
	 */
#ifdef DLZ
	if (is_dlz)
		dns_db_currentversion(db, &ver);
#endif
	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
				    &current_soa_tuple));

	if (reqtype == dns_rdatatype_ixfr) {
		isc_uint32_t begin_serial, current_serial;
		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);
		current_serial = dns_soa_getserial(&current_soa_tuple->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 = 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);
	} else {
	axfr_fallback:
		CHECK(axfr_rrstream_create(mctx, db, ver,
					   &data_stream));
	}

	/*
	 * Bracket the 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.
	 */



#ifdef DLZ
	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
#endif
		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
		xfrout_log1(client, question_name, question_class,
			    ISC_LOG_INFO, "%s started%s%s", mnemonic,
			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);

	/*
	 * 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);
	}
}
Ejemplo n.º 16
0
isc_result_t
irs_context_create(irs_context_t **contextp) {
	isc_result_t result;
	irs_context_t *context;
	isc_appctx_t *actx = NULL;
	isc_mem_t *mctx = NULL;
	isc_taskmgr_t *taskmgr = NULL;
	isc_socketmgr_t *socketmgr = NULL;
	isc_timermgr_t *timermgr = NULL;
	dns_client_t *client = NULL;
	isc_sockaddrlist_t *nameservers;
	irs_dnsconf_dnskeylist_t *trustedkeys;
	irs_dnsconf_dnskey_t *trustedkey;

	isc_lib_register();
	result = dns_lib_init();
	if (result != ISC_R_SUCCESS)
		return (result);

	result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
	if (result != ISC_R_SUCCESS)
		return (result);

	result = isc_app_ctxstart(actx);
	if (result != ISC_R_SUCCESS) {
		ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
		return (result);
	}

	context = isc_mem_get(mctx, sizeof(*context));
	if (context == NULL) {
		ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
		return (ISC_R_NOMEMORY);
	}

	context->mctx = mctx;
	context->actx = actx;
	context->taskmgr = taskmgr;
	context->socketmgr = socketmgr;
	context->timermgr = timermgr;
	context->resconf = NULL;
	context->dnsconf = NULL;
	context->task = NULL;
	result = isc_task_create(taskmgr, 0, &context->task);
	if (result != ISC_R_SUCCESS)
		goto fail;

	/* Create a DNS client object */
	result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr,
				    0, &client);
	if (result != ISC_R_SUCCESS)
		goto fail;
	context->dnsclient = client;

	/* Read resolver configuration file */
	result = irs_resconf_load(mctx, RESOLV_CONF, &context->resconf);
	if (result != ISC_R_SUCCESS)
		goto fail;
	/* Set nameservers */
	nameservers = irs_resconf_getnameservers(context->resconf);
	result = dns_client_setservers(client, dns_rdataclass_in, NULL,
				       nameservers);
	if (result != ISC_R_SUCCESS)
		goto fail;

	/* Read advanced DNS configuration (if any) */
	result = irs_dnsconf_load(mctx, DNS_CONF, &context->dnsconf);
	if (result != ISC_R_SUCCESS)
		goto fail;
	trustedkeys = irs_dnsconf_gettrustedkeys(context->dnsconf);
	for (trustedkey = ISC_LIST_HEAD(*trustedkeys);
	     trustedkey != NULL;
	     trustedkey = ISC_LIST_NEXT(trustedkey, link)) {
		result = dns_client_addtrustedkey(client, dns_rdataclass_in,
						  trustedkey->keyname,
						  trustedkey->keydatabuf);
		if (result != ISC_R_SUCCESS)
			goto fail;
	}

	context->magic = IRS_CONTEXT_MAGIC;
	*contextp = context;

	return (ISC_R_SUCCESS);

  fail:
	if (context->task != NULL)
		isc_task_detach(&context->task);
	if (context->resconf != NULL)
		irs_resconf_destroy(&context->resconf);
	if (context->dnsconf != NULL)
		irs_dnsconf_destroy(&context->dnsconf);
	if (client != NULL)
		dns_client_destroy(&client);
	ctxs_destroy(NULL, &actx, &taskmgr, &socketmgr, &timermgr);
	isc_mem_putanddetach(&mctx, context, sizeof(*context));

	return (result);
}
Ejemplo n.º 17
0
isc_result_t
ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config,
			 cfg_aclconfctx_t *aclconfctx)
{
	ns_statschannel_t *listener, *listener_next;
	ns_statschannellist_t new_listeners;
	const cfg_obj_t *statschannellist = NULL;
	const cfg_listelt_t *element, *element2;
	char socktext[ISC_SOCKADDR_FORMATSIZE];

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

	ISC_LIST_INIT(new_listeners);

	/*
	 * Get the list of named.conf 'statistics-channels' statements.
	 */
	(void)cfg_map_get(config, "statistics-channels", &statschannellist);

	/*
	 * Run through the new address/port list, noting sockets that are
	 * already being listened on and moving them to the new list.
	 *
	 * Identifying duplicate addr/port combinations is left to either
	 * the underlying config code, or to the bind attempt getting an
	 * address-in-use error.
	 */
	if (statschannellist != NULL) {
#ifndef HAVE_LIBXML2
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
			      "statistics-channels specified but not effective "
			      "due to missing XML library");
#endif

		for (element = cfg_list_first(statschannellist);
		     element != NULL;
		     element = cfg_list_next(element)) {
			const cfg_obj_t *statschannel;
			const cfg_obj_t *listenercfg = NULL;

			statschannel = cfg_listelt_value(element);
			(void)cfg_map_get(statschannel, "inet",
					  &listenercfg);
			if (listenercfg == NULL)
				continue;

			for (element2 = cfg_list_first(listenercfg);
			     element2 != NULL;
			     element2 = cfg_list_next(element2)) {
				const cfg_obj_t *listen_params;
				const cfg_obj_t *obj;
				isc_sockaddr_t addr;

				listen_params = cfg_listelt_value(element2);

				obj = cfg_tuple_get(listen_params, "address");
				addr = *cfg_obj_assockaddr(obj);
				if (isc_sockaddr_getport(&addr) == 0)
					isc_sockaddr_setport(&addr, NS_STATSCHANNEL_HTTPPORT);

				isc_sockaddr_format(&addr, socktext,
						    sizeof(socktext));

				isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_SERVER,
					      ISC_LOG_DEBUG(9),
					      "processing statistics "
					      "channel %s",
					      socktext);

				update_listener(server, &listener,
						listen_params, config, &addr,
						aclconfctx, socktext);

				if (listener != NULL) {
					/*
					 * Remove the listener from the old
					 * list, so it won't be shut down.
					 */
					ISC_LIST_UNLINK(server->statschannels,
							listener, link);
				} else {
					/*
					 * This is a new listener.
					 */
					isc_result_t r;

					r = add_listener(server, &listener,
							 listen_params, config,
							 &addr, aclconfctx,
							 socktext);
					if (r != ISC_R_SUCCESS) {
						cfg_obj_log(listen_params,
							    ns_g_lctx,
							    ISC_LOG_WARNING,
							    "couldn't allocate "
							    "statistics channel"
							    " %s: %s",
							    socktext,
							    isc_result_totext(r));
					}
				}

				if (listener != NULL)
					ISC_LIST_APPEND(new_listeners, listener,
							link);
			}
		}
	}

	for (listener = ISC_LIST_HEAD(server->statschannels);
	     listener != NULL;
	     listener = listener_next) {
		listener_next = ISC_LIST_NEXT(listener, link);
		ISC_LIST_UNLINK(server->statschannels, listener, link);
		shutdown_listener(listener);
	}

	ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link);
	return (ISC_R_SUCCESS);
}
Ejemplo n.º 18
0
static void
isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
{
	isc_region_t r;
	isc_result_t result;
	isc_httpd_t *httpd = ev->ev_arg;
	isc_socketevent_t *sev = (isc_socketevent_t *)ev;
	isc_httpdurl_t *url;
	isc_time_t now;
	char datebuf[32];  /* Only need 30, but safety first */

	ENTER("recv");

	INSIST(ISC_HTTPD_ISRECV(httpd));

	if (sev->result != ISC_R_SUCCESS) {
		NOTICE("recv destroying client");
		destroy_client(&httpd);
		goto out;
	}

	result = process_request(httpd, sev->n);
	if (result == ISC_R_NOTFOUND) {
		if (httpd->recvlen >= HTTP_RECVLEN - 1) {
			destroy_client(&httpd);
			goto out;
		}
		r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen;
		r.length = HTTP_RECVLEN - httpd->recvlen - 1;
		/* check return code? */
		(void)isc_socket_recv(httpd->sock, &r, 1, task,
				      isc_httpd_recvdone, httpd);
		goto out;
	} else if (result != ISC_R_SUCCESS) {
		destroy_client(&httpd);
		goto out;
	}

	ISC_HTTPD_SETSEND(httpd);

	/*
	 * XXXMLG Call function here.  Provide an add-header function
	 * which will append the common headers to a response we generate.
	 */
	isc_buffer_initnull(&httpd->bodybuffer);
	isc_time_now(&now);
	isc_time_formathttptimestamp(&now, datebuf, sizeof(datebuf));
	url = ISC_LIST_HEAD(httpd->mgr->urls);
	while (url != NULL) {
		if (strcmp(httpd->url, url->url) == 0)
			break;
		url = ISC_LIST_NEXT(url, link);
	}
	if (url == NULL)
		result = httpd->mgr->render_404(httpd->url, httpd->querystring,
						NULL,
						&httpd->retcode,
						&httpd->retmsg,
						&httpd->mimetype,
						&httpd->bodybuffer,
						&httpd->freecb,
						&httpd->freecb_arg);
	else
		result = url->action(httpd->url, httpd->querystring,
				     url->action_arg,
				     &httpd->retcode, &httpd->retmsg,
				     &httpd->mimetype, &httpd->bodybuffer,
				     &httpd->freecb, &httpd->freecb_arg);
	if (result != ISC_R_SUCCESS) {
		result = httpd->mgr->render_500(httpd->url, httpd->querystring,
						NULL, &httpd->retcode,
						&httpd->retmsg,
						&httpd->mimetype,
						&httpd->bodybuffer,
						&httpd->freecb,
						&httpd->freecb_arg);
		RUNTIME_CHECK(result == ISC_R_SUCCESS);
	}

	isc_httpd_response(httpd);
	isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
	isc_httpd_addheader(httpd, "Date", datebuf);
	isc_httpd_addheader(httpd, "Expires", datebuf);
	isc_httpd_addheader(httpd, "Last-Modified", datebuf);
	isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
	isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
	isc_httpd_addheader(httpd, "Server: libisc", NULL);
	isc_httpd_addheaderuint(httpd, "Content-Length",
				isc_buffer_usedlength(&httpd->bodybuffer));
	isc_httpd_endheaders(httpd);  /* done */

	ISC_LIST_APPEND(httpd->bufflist, &httpd->headerbuffer, link);
	/*
	 * Link the data buffer into our send queue, should we have any data
	 * rendered into it.  If no data is present, we won't do anything
	 * with the buffer.
	 */
	if (isc_buffer_length(&httpd->bodybuffer) > 0)
		ISC_LIST_APPEND(httpd->bufflist, &httpd->bodybuffer, link);

	/* check return code? */
	(void)isc_socket_sendv(httpd->sock, &httpd->bufflist, task,
			       isc_httpd_senddone, httpd);

 out:
	isc_event_free(&ev);
	EXIT("recv");
}
Ejemplo n.º 19
0
static isc_result_t
generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
	char boottime[sizeof "yyyy-mm-ddThh:mm:ssZ"];
	char nowstr[sizeof "yyyy-mm-ddThh:mm:ssZ"];
	isc_time_t now;
	xmlTextWriterPtr writer = NULL;
	xmlDocPtr doc = NULL;
	int xmlrc;
	dns_view_t *view;
	stats_dumparg_t dumparg;
	dns_stats_t *cachestats;
	isc_uint64_t nsstat_values[dns_nsstatscounter_max];
	isc_uint64_t resstat_values[dns_resstatscounter_max];
	isc_uint64_t zonestat_values[dns_zonestatscounter_max];
	isc_uint64_t sockstat_values[isc_sockstatscounter_max];
	isc_result_t result;

	isc_time_now(&now);
	isc_time_formatISO8601(&ns_g_boottime, boottime, sizeof boottime);
	isc_time_formatISO8601(&now, nowstr, sizeof nowstr);

	writer = xmlNewTextWriterDoc(&doc, 0);
	if (writer == NULL)
		goto error;
	TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL));
	TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet",
			ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.xsl\""));
	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "isc"));
	TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
					 ISC_XMLCHAR "1.0"));

	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "bind"));
	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
	TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
					 ISC_XMLCHAR "2.2"));

	/* Set common fields for statistics dump */
	dumparg.type = statsformat_xml;
	dumparg.arg = writer;

	/*
	 * Start by rendering the views we know of here.  For each view we
	 * know of, call its rendering function.
	 */
	view = ISC_LIST_HEAD(server->viewlist);
	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views"));
	while (view != NULL) {
		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "view"));

		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "name"));
		TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR view->name));
		TRY0(xmlTextWriterEndElement(writer));

		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zones"));
		result = dns_zt_apply(view->zonetable, ISC_TRUE, zone_xmlrender,
				      writer);
		if (result != ISC_R_SUCCESS)
			goto error;
		TRY0(xmlTextWriterEndElement(writer));

		if (view->resquerystats != NULL) {
			dumparg.result = ISC_R_SUCCESS;
			dns_rdatatypestats_dump(view->resquerystats,
						rdtypestat_dump, &dumparg, 0);
			if (dumparg.result != ISC_R_SUCCESS)
				goto error;
		}

		if (view->resstats != NULL) {
			result = dump_counters(view->resstats, statsformat_xml,
					       writer, "resstat",
					       resstats_xmldesc,
					       dns_resstatscounter_max,
					       resstats_index, resstat_values,
					       ISC_STATSDUMP_VERBOSE);
			if (result != ISC_R_SUCCESS)
				goto error;
		}

		cachestats = dns_db_getrrsetstats(view->cachedb);
		if (cachestats != NULL) {
			TRY0(xmlTextWriterStartElement(writer,
						       ISC_XMLCHAR "cache"));
			TRY0(xmlTextWriterWriteAttribute(writer,
					 ISC_XMLCHAR "name",
					 ISC_XMLCHAR
					 dns_cache_getname(view->cache)));
			dumparg.result = ISC_R_SUCCESS;
			dns_rdatasetstats_dump(cachestats, rdatasetstats_dump,
					       &dumparg, 0);
			if (dumparg.result != ISC_R_SUCCESS)
				goto error;
			TRY0(xmlTextWriterEndElement(writer)); /* cache */
		}

		TRY0(xmlTextWriterEndElement(writer)); /* view */

		view = ISC_LIST_NEXT(view, link);
	}
	TRY0(xmlTextWriterEndElement(writer)); /* views */

	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socketmgr"));
	isc_socketmgr_renderxml(ns_g_socketmgr, writer);
	TRY0(xmlTextWriterEndElement(writer)); /* socketmgr */

	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr"));
	isc_taskmgr_renderxml(ns_g_taskmgr, writer);
	TRY0(xmlTextWriterEndElement(writer)); /* taskmgr */

	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server"));
	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time"));
	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime));
	TRY0(xmlTextWriterEndElement(writer));
	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time"));
	TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr));
	TRY0(xmlTextWriterEndElement(writer));

	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "requests"));
	dumparg.result = ISC_R_SUCCESS;
	dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg,
			     0);
	if (dumparg.result != ISC_R_SUCCESS)
		goto error;
	TRY0(xmlTextWriterEndElement(writer)); /* requests */

	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "queries-in"));
	dumparg.result = ISC_R_SUCCESS;
	dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
				&dumparg, 0);
	if (dumparg.result != ISC_R_SUCCESS)
		goto error;
	TRY0(xmlTextWriterEndElement(writer)); /* queries-in */

	result = dump_counters(server->nsstats, statsformat_xml, writer,
			       "nsstat", nsstats_xmldesc,
				dns_nsstatscounter_max,
				nsstats_index, nsstat_values,
				ISC_STATSDUMP_VERBOSE);
	if (result != ISC_R_SUCCESS)
		goto error;

	result = dump_counters(server->zonestats, statsformat_xml, writer,
			       "zonestat", zonestats_xmldesc,
			       dns_zonestatscounter_max, zonestats_index,
			       zonestat_values, ISC_STATSDUMP_VERBOSE);
	if (result != ISC_R_SUCCESS)
		goto error;

	/*
	 * Most of the common resolver statistics entries are 0, so we don't
	 * use the verbose dump here.
	 */
	result = dump_counters(server->resolverstats, statsformat_xml, writer,
			       "resstat", resstats_xmldesc,
			       dns_resstatscounter_max, resstats_index,
			       resstat_values, 0);
	if (result != ISC_R_SUCCESS)
		goto error;

	result = dump_counters(server->sockstats, statsformat_xml, writer,
			       "sockstat", sockstats_xmldesc,
			       isc_sockstatscounter_max, sockstats_index,
			       sockstat_values, ISC_STATSDUMP_VERBOSE);
	if (result != ISC_R_SUCCESS)
		goto error;

	TRY0(xmlTextWriterEndElement(writer)); /* server */

	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory"));
	isc_mem_renderxml(writer);
	TRY0(xmlTextWriterEndElement(writer)); /* memory */

	TRY0(xmlTextWriterEndElement(writer)); /* statistics */
	TRY0(xmlTextWriterEndElement(writer)); /* bind */
	TRY0(xmlTextWriterEndElement(writer)); /* isc */

	TRY0(xmlTextWriterEndDocument(writer));

	xmlFreeTextWriter(writer);

	xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 1);
	xmlFreeDoc(doc);
	return (ISC_R_SUCCESS);

 error:
	if (writer != NULL)
		xmlFreeTextWriter(writer);
	if (doc != NULL)
		xmlFreeDoc(doc);
	return (ISC_R_FAILURE);
}
Ejemplo n.º 20
0
isc_result_t
pk11_parse_uri(pk11_object_t *obj, const char *label,
	       isc_mem_t *mctx, pk11_optype_t optype)
{
	CK_ATTRIBUTE *attr;
	pk11_token_t *token = NULL;
	char *uri, *p, *a, *na, *v;
	size_t len, l;
	FILE *stream = NULL;
	char pin[PINLEN];
	isc_boolean_t gotpin = ISC_FALSE;
	isc_result_t ret;

	/* get values to work on */
	len = strlen(label) + 1;
	uri = isc_mem_get(mctx, len);
	if (uri == NULL)
		return (ISC_R_NOMEMORY);
	memmove(uri, label, len);

	/* get the URI scheme */
	p = strchr(uri, ':');
	if (p == NULL)
		DST_RET(DST_R_NOENGINE);
	*p++ = '\0';
	if (strcmp(uri, "pkcs11") != 0)
		DST_RET(DST_R_NOENGINE);

	/* get attributes */
	for (na = p; na != NULL;) {
		a = na;
		p = strchr(a, ';');
		if (p == NULL) {
			/* last attribute */
			na = NULL;
		} else {
			*p++ = '\0';
			na = p;
		}
		p = strchr(a, '=');
		if (p != NULL) {
			*p++ = '\0';
			v = p;
		} else
			v = a;
		l = 0;
		v = percent_decode(v, &l);
		if (v == NULL)
			DST_RET(DST_R_NOENGINE);
		if ((a == v) || (strcmp(a, "object") == 0)) {
			/* object: CKA_LABEL */
			attr = pk11_attribute_bytype(obj, CKA_LABEL);
			if (attr != NULL)
				DST_RET(DST_R_NOENGINE);
			attr = push_attribute(obj, mctx, l);
			if (attr == NULL)
				DST_RET(ISC_R_NOMEMORY);
			attr->type = CKA_LABEL;
			memmove(attr->pValue, v, l);
		} else if (strcmp(a, "token") == 0) {
			/* token: CK_TOKEN_INFO label */
			if (token == NULL)
				for (token = ISC_LIST_HEAD(tokens);
				     token != NULL;
				     token = ISC_LIST_NEXT(token, link))
					if (pk11strcmp(v, l, token->name, 32))
						break;
		} else if (strcmp(a, "manufacturer") == 0) {
			/* manufacturer: CK_TOKEN_INFO manufacturerID */
			if (token == NULL)
				for (token = ISC_LIST_HEAD(tokens);
				     token != NULL;
				     token = ISC_LIST_NEXT(token, link))
					if (pk11strcmp(v, l, token->manuf, 32))
						break;
		} else if (strcmp(a, "serial") == 0) {
			/* serial: CK_TOKEN_INFO serialNumber */
			if (token == NULL)
				for (token = ISC_LIST_HEAD(tokens);
				     token != NULL;
				     token = ISC_LIST_NEXT(token, link))
					if (pk11strcmp(v, l, token->serial, 16))
						break;
		} else if (strcmp(a, "model") == 0) {
			/* model: CK_TOKEN_INFO model */
			if (token == NULL)
				for (token = ISC_LIST_HEAD(tokens);
				     token != NULL;
				     token = ISC_LIST_NEXT(token, link))
					if (pk11strcmp(v, l, token->model, 16))
						break;
		} else if (strcmp(a, "library-manufacturer") == 0) {
			/* ignored */
		} else if (strcmp(a, "library-description") == 0) {
			/* ignored */
		} else if (strcmp(a, "library-version") == 0) {
			/* ignored */
		} else if (strcmp(a, "object-type") == 0) {
			/* object-type: CKA_CLASS */
			/* only private makes sense */
			if (strcmp(v, "private") != 0)
				DST_RET(DST_R_NOENGINE);
		} else if (strcmp(a, "id") == 0) {
			/* id: CKA_ID */
			attr = pk11_attribute_bytype(obj, CKA_ID);
			if (attr != NULL)
				DST_RET(DST_R_NOENGINE);
			attr = push_attribute(obj, mctx, l);
			if (attr == NULL)
				DST_RET(ISC_R_NOMEMORY);
			attr->type = CKA_ID;
			memmove(attr->pValue, v, l);
		} else if (strcmp(a, "pin-source") == 0) {
			/* pin-source: PIN */
			ret = isc_stdio_open(v, "r", &stream);
			if (ret != ISC_R_SUCCESS)
				goto err;
			memset(pin, 0, PINLEN);
			ret = isc_stdio_read(pin, 1, PINLEN - 1, stream, NULL);
			if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF))
				goto err;
			ret = isc_stdio_close(stream);
			stream = NULL;
			if (ret != ISC_R_SUCCESS)
				goto err;
			gotpin = ISC_TRUE;
		} else
			DST_RET(DST_R_NOENGINE);
	}

	if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) &&
	    (pk11_attribute_bytype(obj, CKA_ID) == NULL))
		DST_RET(ISC_R_NOTFOUND);

	if (token == NULL) {
		if (optype == OP_RSA)
			token = best_rsa_token;
		else if (optype == OP_DSA)
			token = best_dsa_token;
		else if (optype == OP_DH)
			token = best_dh_token;
		else if (optype == OP_EC)
			token = best_ec_token;
	}
	if (token == NULL)
		DST_RET(ISC_R_NOTFOUND);
	obj->slot = token->slotid;
	if (gotpin) {
		memmove(token->pin, pin, PINLEN);
		obj->reqlogon = ISC_TRUE;
	}

	ret = ISC_R_SUCCESS;

  err:
	if (stream != NULL)
		(void) isc_stdio_close(stream);
	isc_mem_put(mctx, uri, len);
	return (ret);
}
Ejemplo n.º 21
0
isc_result_t
dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
	      void *add_private)
{
	dns_difftuple_t *t;
	isc_result_t result;

	REQUIRE(DNS_DIFF_VALID(diff));

	t = ISC_LIST_HEAD(diff->tuples);
	while (t != NULL) {
		dns_name_t *name;

		name = &t->name;
		while (t != NULL && dns_name_equal(&t->name, name)) {
			dns_rdatatype_t type, covers;
			dns_diffop_t op;
			dns_rdatalist_t rdl;
			dns_rdataset_t rds;

			op = t->op;
			type = t->rdata.type;
			covers = rdata_covers(&t->rdata);

			rdl.type = type;
			rdl.covers = covers;
			rdl.rdclass = t->rdata.rdclass;
			rdl.ttl = t->ttl;
			ISC_LIST_INIT(rdl.rdata);
			ISC_LINK_INIT(&rdl, link);

			while (t != NULL && dns_name_equal(&t->name, name) &&
			       t->op == op && t->rdata.type == type &&
			       rdata_covers(&t->rdata) == covers)
			{
				ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
				t = ISC_LIST_NEXT(t, link);
			}

			/*
			 * Convert the rdatalist into a rdataset.
			 */
			dns_rdataset_init(&rds);
			CHECK(dns_rdatalist_tordataset(&rdl, &rds));
			rds.trust = dns_trust_ultimate;

			INSIST(op == DNS_DIFFOP_ADD);
			result = (*addfunc)(add_private, name, &rds);
			if (result == DNS_R_UNCHANGED) {
				isc_log_write(DIFF_COMMON_LOGARGS,
					      ISC_LOG_WARNING,
					      "dns_diff_load: "
					      "update with no effect");
			} else if (result == ISC_R_SUCCESS ||
				   result == DNS_R_NXRRSET) {
				/*
				 * OK.
				 */
			} else {
				CHECK(result);
			}
		}
	}
	result = ISC_R_SUCCESS;
 failure:
	return (result);
}
Ejemplo n.º 22
0
void
pk11_dump_tokens(void)
{
	pk11_token_t *token;
	isc_boolean_t first;

	printf("DEFAULTS\n");
	printf("\trand_token=%p\n", rand_token);
	printf("\tbest_rsa_token=%p\n", best_rsa_token);
	printf("\tbest_dsa_token=%p\n", best_dsa_token);
	printf("\tbest_dh_token=%p\n", best_dh_token);
	printf("\tdigest_token=%p\n", digest_token);
	printf("\tbest_ec_token=%p\n", best_ec_token);

	for (token = ISC_LIST_HEAD(tokens);
	     token != NULL;
	     token = ISC_LIST_NEXT(token, link)) {
		printf("\nTOKEN\n");
		printf("\taddress=%p\n", token);
		printf("\tslotID=%lu\n", token->slotid);
		printf("\tlabel=%.32s\n", token->name);
		printf("\tmanufacturerID=%.32s\n", token->manuf);
		printf("\tmodel=%.16s\n", token->model);
		printf("\tserialNumber=%.16s\n", token->serial);
		printf("\tsupported operations=0x%x (", token->operations);
		first = ISC_TRUE;
		if (token->operations & (1 << OP_RAND)) {
			if (!first)
				printf(",");
			first = ISC_FALSE;
			printf("RAND");
		}
		if (token->operations & (1 << OP_RSA)) {
			if (!first)
				printf(",");
			first = ISC_FALSE;
			printf("RSA");
		}
		if (token->operations & (1 << OP_DSA)) {
			if (!first)
				printf(",");
			first = ISC_FALSE;
			printf("DSA");
		}
		if (token->operations & (1 << OP_DH)) {
			if (!first)
				printf(",");
			first = ISC_FALSE;
			printf("DH");
		}
		if (token->operations & (1 << OP_DIGEST)) {
			if (!first)
				printf(",");
			first = ISC_FALSE;
			printf("DIGEST");
		}
		if (token->operations & (1 << OP_EC)) {
			if (!first)
				printf(",");
			first = ISC_FALSE;
			printf("EC");
		}
		printf(")\n");
	}
}
Ejemplo n.º 23
0
Archivo: app.c Proyecto: execunix/vinos
isc_result_t
isc__app_run(void) {
	isc_event_t *event, *next_event;
	isc_task_t *task;
	HANDLE *pHandles = NULL;

	REQUIRE(main_thread == GetCurrentThread());
	LOCK(&lock);
	if (!running) {
		running = ISC_TRUE;

		/*
		 * Post any on-run events (in FIFO order).
		 */
		for (event = ISC_LIST_HEAD(on_run);
		     event != NULL;
		     event = next_event) {
			next_event = ISC_LIST_NEXT(event, ev_link);
			ISC_LIST_UNLINK(on_run, event, ev_link);
			task = event->ev_sender;
			event->ev_sender = NULL;
			isc_task_sendanddetach(&task, &event);
		}

	}

	UNLOCK(&lock);

	/*
	 * There is no danger if isc_app_shutdown() is called before we wait
	 * for events.
	 */

	while (!want_shutdown) {
		dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, hEvents,
						      FALSE, INFINITE);

		/* See why we returned */

		if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
			/*
			 * The return was due to one of the events
			 * being signaled
			 */
			switch (WaitSucceededIndex(dwWaitResult)) {
			case RELOAD_EVENT:
				want_reload = ISC_TRUE;
				break;

			case SHUTDOWN_EVENT:
				want_shutdown = ISC_TRUE;
				break;
			}
		}
		if (want_reload) {
			want_reload = ISC_FALSE;
			return (ISC_R_RELOAD);
		}

		if (want_shutdown && blocked)
			exit(-1);
	}

	return (ISC_R_SUCCESS);
}
Ejemplo n.º 24
0
isc_result_t
pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype,
		 isc_boolean_t rw, isc_boolean_t logon,
		 const char *pin, CK_SLOT_ID slot)
{
	pk11_token_t *token = NULL;
	pk11_sessionlist_t *freelist;
	pk11_session_t *sp;
	isc_result_t ret = ISC_R_SUCCESS;

	dst__pkcs11_init(NULL, NULL);
	LOCK(&sessionlock);
	/* wait for initialization to finish */
	UNLOCK(&sessionlock);

	memset(ctx, 0, sizeof(pk11_context_t));
	ctx->handle = NULL;
	ctx->session = CK_INVALID_HANDLE;
	switch(optype) {
#ifdef PKCS11CRYPTO
	case OP_RAND:
		token = rand_token;
		break;
	case OP_DIGEST:
		token = digest_token;
		break;
	case OP_ANY:
		for (token = ISC_LIST_HEAD(tokens);
		     token != NULL;
		     token = ISC_LIST_NEXT(token, link))
			if (token->slotid == slot)
				break;
		break;
#endif
	default:
		for (token = ISC_LIST_HEAD(tokens);
		     token != NULL;
		     token = ISC_LIST_NEXT(token, link))
			if (token->slotid == slot)
				break;
#ifdef PKCS11CRYPTO
		if ((token == NULL) ||
		    ((token->operations & (1 << optype)) == 0))
			return (ISC_R_NOTFOUND);
#endif
		break;
	}
	if (token == NULL)
		return (ISC_R_NOTFOUND);

	/* Override the token's PIN */
	if (logon && pin != NULL && *pin != '\0') {
		memset(token->pin, 0, PINLEN);
		strncpy(token->pin, pin, PINLEN);
	}

	freelist = &token->sessions;

	LOCK(&sessionlock);
	sp = ISC_LIST_HEAD(*freelist);
	if (sp != NULL) {
		ISC_LIST_UNLINK(*freelist, sp, link);
		ISC_LIST_APPEND(actives, sp, link);
		UNLOCK(&sessionlock);
		if (logon)
			ret = token_login(sp);
		ctx->handle = sp;
		ctx->session = sp->session;
		return (ret);
	}
	UNLOCK(&sessionlock);

	sp = pk11_mem_get(sizeof(*sp));
	if (sp == NULL)
		return (ISC_R_NOMEMORY);
	sp->magic = SES_MAGIC;
	sp->token = token;
	sp->session = CK_INVALID_HANDLE;
	ISC_LINK_INIT(sp, link);
	ret = setup_session(sp, token, rw);
	if ((ret == ISC_R_SUCCESS) && logon)
		ret = token_login(sp);
	LOCK(&sessionlock);
	ISC_LIST_APPEND(actives, sp, link);
	UNLOCK(&sessionlock);
	ctx->handle = sp;
	ctx->session = sp->session;
	return (ret);
}
Ejemplo n.º 25
0
static void
destroy_odbc_instance(odbc_instance_t *odbc_inst) {

#ifdef ISC_PLATFORM_USETHREADS

	dbinstance_t *ndbi = NULL;
	dbinstance_t *dbi = NULL;

	/* get the first DBI in the list */
	ndbi = ISC_LIST_HEAD(*odbc_inst->db);

	/* loop through the list */
	while (ndbi != NULL) {
		dbi = ndbi;
		/* get the next DBI in the list */
		ndbi = ISC_LIST_NEXT(dbi, link);

		/* if we have a connection / statement object in memory */
		if (dbi->dbconn != NULL) {
			/* free statement handle */
			if (((odbc_db_t *) (dbi->dbconn))->stmnt != NULL) {
				SQLFreeHandle(SQL_HANDLE_STMT,
					      ((odbc_db_t *)
					       (dbi->dbconn))->stmnt);
				((odbc_db_t *) (dbi->dbconn))->stmnt = NULL;
			}

			/* disconnect from database & free connection handle */
			if (((odbc_db_t *) (dbi->dbconn))->dbc != NULL) {
				SQLDisconnect(((odbc_db_t *)
					       dbi->dbconn)->dbc);
				SQLFreeHandle(SQL_HANDLE_DBC,
					      ((odbc_db_t *)
					       (dbi->dbconn))->dbc);
				((odbc_db_t *) (dbi->dbconn))->dbc = NULL;
			}

			/* free memory that held connection & statement. */
			isc_mem_free(ns_g_mctx, dbi->dbconn);
		}
		/* release all memory that comprised a DBI */
		destroy_sqldbinstance(dbi);
	}
	/* release memory for the list structure */
	isc_mem_put(ns_g_mctx, odbc_inst->db, sizeof(db_list_t));

#else /* ISC_PLATFORM_USETHREADS */

	/* free statement handle */
	if (((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt != NULL) {
		SQLFreeHandle(SQL_HANDLE_STMT,
			      ((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt);
		((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt = NULL;
	}

	/* disconnect from database, free connection handle */
	if (((odbc_db_t *) (odbc_inst->db->dbconn))->dbc != NULL) {
		SQLDisconnect(((odbc_db_t *) (odbc_inst->db->dbconn))->dbc);
		SQLFreeHandle(SQL_HANDLE_DBC,
			      ((odbc_db_t *) (odbc_inst->db->dbconn))->dbc);
		((odbc_db_t *) (odbc_inst->db->dbconn))->dbc = NULL;
	}
	/*	free mem for the odbc_db_t structure held in db */
	if (((odbc_db_t *) odbc_inst->db->dbconn) != NULL) {
		isc_mem_free(ns_g_mctx, odbc_inst->db->dbconn);
		odbc_inst->db->dbconn = NULL;
	}

	if (odbc_inst->db != NULL)
		destroy_sqldbinstance(odbc_inst->db);

#endif /* ISC_PLATFORM_USETHREADS */


	/* free sql environment */
	if (odbc_inst->sql_env != NULL)
		SQLFreeHandle(SQL_HANDLE_ENV, odbc_inst->sql_env);

	/* free ODBC instance strings */
	if (odbc_inst->dsn != NULL)
		isc_mem_free(ns_g_mctx, odbc_inst->dsn);
	if (odbc_inst->pass != NULL)
		isc_mem_free(ns_g_mctx, odbc_inst->pass);
	if (odbc_inst->user != NULL)
		isc_mem_free(ns_g_mctx, odbc_inst->user);

	/* free memory for odbc_inst */
	if (odbc_inst != NULL)
		isc_mem_put(ns_g_mctx, odbc_inst, sizeof(odbc_instance_t));

}
Ejemplo n.º 26
0
static isc_result_t
printsection (dig_query_t * query, dns_message_t * msg, isc_boolean_t headers, dns_section_t section)
{
    isc_result_t result, loopresult;

    dns_name_t *name;

    dns_rdataset_t *rdataset = NULL;

    dns_rdata_t rdata = DNS_RDATA_INIT;

    char namebuf[DNS_NAME_FORMATSIZE];

    UNUSED (query);
    UNUSED (headers);

    debug ("printsection()");

    result = dns_message_firstname (msg, section);
    if (result == ISC_R_NOMORE)
        return (ISC_R_SUCCESS);
    else if (result != ISC_R_SUCCESS)
        return (result);
    for (;;)
    {
        name = NULL;
        dns_message_currentname (msg, section, &name);
        for (rdataset = ISC_LIST_HEAD (name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT (rdataset, link))
        {
            loopresult = dns_rdataset_first (rdataset);
            while (loopresult == ISC_R_SUCCESS)
            {
                dns_rdataset_current (rdataset, &rdata);
                switch (rdata.type)
                {
                    case dns_rdatatype_a:
                        if (section != DNS_SECTION_ANSWER)
                            goto def_short_section;
                        dns_name_format (name, namebuf, sizeof (namebuf));
                        printf ("Name:\t%s\n", namebuf);
                        printa (&rdata);
                        break;
                    case dns_rdatatype_soa:
                        dns_name_format (name, namebuf, sizeof (namebuf));
                        printf ("%s\n", namebuf);
                        printsoa (&rdata);
                        break;
                    default:
                      def_short_section:
                        dns_name_format (name, namebuf, sizeof (namebuf));
                        printf ("%s\t", namebuf);
                        printrdata (&rdata);
                        break;
                }
                dns_rdata_reset (&rdata);
                loopresult = dns_rdataset_next (rdataset);
            }
        }
        result = dns_message_nextname (msg, section);
        if (result == ISC_R_NOMORE)
            break;
        else if (result != ISC_R_SUCCESS)
        {
            return (result);
        }
    }
    return (ISC_R_SUCCESS);
}
Ejemplo n.º 27
0
static int wait_for_sources (isc_entropy_t * ent)
{
    isc_entropysource_t *source;

    int maxfd, fd;

    int cc;

    fd_set reads;

    fd_set writes;

    maxfd = -1;
    FD_ZERO (&reads);
    FD_ZERO (&writes);

    source = ISC_LIST_HEAD (ent->sources);
    while (source != NULL)
    {
        if (source->type == ENTROPY_SOURCETYPE_FILE)
        {
            fd = source->sources.file.handle;
            if (fd >= 0)
            {
                maxfd = ISC_MAX (maxfd, fd);
                FD_SET (fd, &reads);
            }
        }
        if (source->type == ENTROPY_SOURCETYPE_USOCKET)
        {
            fd = source->sources.usocket.handle;
            if (fd >= 0)
            {
                switch (source->sources.usocket.status)
                {
                    case isc_usocketsource_disconnected:
                        break;
                    case isc_usocketsource_connecting:
                    case isc_usocketsource_connected:
                    case isc_usocketsource_ndesired:
                        maxfd = ISC_MAX (maxfd, fd);
                        FD_SET (fd, &writes);
                        break;
                    case isc_usocketsource_wrote:
                    case isc_usocketsource_reading:
                        maxfd = ISC_MAX (maxfd, fd);
                        FD_SET (fd, &reads);
                        break;
                }
            }
        }
        source = ISC_LIST_NEXT (source, link);
    }

    if (maxfd < 0)
        return (-1);

    cc = select (maxfd + 1, &reads, &writes, NULL, NULL);
    if (cc < 0)
        return (-1);

    return (cc);
}
Ejemplo n.º 28
0
static isc_result_t
detailsection (dig_query_t * query, dns_message_t * msg, isc_boolean_t headers, dns_section_t section)
{
    isc_result_t result, loopresult;

    dns_name_t *name;

    dns_rdataset_t *rdataset = NULL;

    dns_rdata_t rdata = DNS_RDATA_INIT;

    char namebuf[DNS_NAME_FORMATSIZE];

    UNUSED (query);

    debug ("detailsection()");

    if (headers)
    {
        switch (section)
        {
            case DNS_SECTION_QUESTION:
                puts ("    QUESTIONS:");
                break;
            case DNS_SECTION_ANSWER:
                puts ("    ANSWERS:");
                break;
            case DNS_SECTION_AUTHORITY:
                puts ("    AUTHORITY RECORDS:");
                break;
            case DNS_SECTION_ADDITIONAL:
                puts ("    ADDITIONAL RECORDS:");
                break;
        }
    }

    result = dns_message_firstname (msg, section);
    if (result == ISC_R_NOMORE)
        return (ISC_R_SUCCESS);
    else if (result != ISC_R_SUCCESS)
        return (result);
    for (;;)
    {
        name = NULL;
        dns_message_currentname (msg, section, &name);
        for (rdataset = ISC_LIST_HEAD (name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT (rdataset, link))
        {
            if (section == DNS_SECTION_QUESTION)
            {
                dns_name_format (name, namebuf, sizeof (namebuf));
                printf ("\t%s, ", namebuf);
                dns_rdatatype_format (rdataset->type, namebuf, sizeof (namebuf));
                printf ("type = %s, ", namebuf);
                dns_rdataclass_format (rdataset->rdclass, namebuf, sizeof (namebuf));
                printf ("class = %s\n", namebuf);
            }
            loopresult = dns_rdataset_first (rdataset);
            while (loopresult == ISC_R_SUCCESS)
            {
                dns_rdataset_current (rdataset, &rdata);

                dns_name_format (name, namebuf, sizeof (namebuf));
                printf ("    ->  %s\n", namebuf);

                switch (rdata.type)
                {
                    case dns_rdatatype_soa:
                        printsoa (&rdata);
                        break;
                    default:
                        printf ("\t");
                        printrdata (&rdata);
                }
                dns_rdata_reset (&rdata);
                printf ("\tttl = %u\n", rdataset->ttl);
                loopresult = dns_rdataset_next (rdataset);
            }
        }
        result = dns_message_nextname (msg, section);
        if (result == ISC_R_NOMORE)
            break;
        else if (result != ISC_R_SUCCESS)
        {
            return (result);
        }
    }
    return (ISC_R_SUCCESS);
}
Ejemplo n.º 29
0
static void
update_stat(struct probe_trans *trans) {
	struct probe_ns *pns;
	struct server *server;
	struct lcl_stat local_stat;
	unsigned int err_count = 0;
	const char *stattype;

	increment_entry(&number_of_domains);
	memset(&local_stat, 0, sizeof(local_stat));

	/* Update per sever statistics */
	for (pns = ISC_LIST_HEAD(trans->nslist); pns != NULL;
	     pns = ISC_LIST_NEXT(pns, link)) {
		for (server = ISC_LIST_HEAD(pns->servers); server != NULL;
		     server = ISC_LIST_NEXT(server, link)) {
			increment_entry(&number_of_servers);

			if (server->result_aaaa == exist ||
			    server->result_aaaa == notype) {
				/*
				 * Don't care about the result of A query if
				 * the answer to AAAA query was expected.
				 */
				stattype = "valid";
				increment_entry(&server_stat.valid);
				increment_entry(&local_stat.valid);
			} else if (server->result_a == exist) {
				switch (server->result_aaaa) {
				case exist:
				case notype:
					stattype = "valid";
					increment_entry(&server_stat.valid);
					increment_entry(&local_stat.valid);
					break;
				case timedout:
					stattype = "ignore";
					increment_entry(&server_stat.ignore);
					increment_entry(&local_stat.ignore);
					break;
				case nxdomain:
					stattype = "nxdomain";
					increment_entry(&server_stat.nxdomain);
					increment_entry(&local_stat.nxdomain);
					break;
				case othererr:
					stattype = "othererr";
					increment_entry(&server_stat.othererr);
					increment_entry(&local_stat.othererr);
					break;
				case multiplesoa:
					stattype = "multiplesoa";
					increment_entry(&server_stat.multiplesoa);
					increment_entry(&local_stat.multiplesoa);
					break;
				case multiplecname:
					stattype = "multiplecname";
					increment_entry(&server_stat.multiplecname);
					increment_entry(&local_stat.multiplecname);
					break;
				case brokenanswer:
					stattype = "brokenanswer";
					increment_entry(&server_stat.brokenanswer);
					increment_entry(&local_stat.brokenanswer);
					break;
				case lame:
					stattype = "lame";
					increment_entry(&server_stat.lame);
					increment_entry(&local_stat.lame);
					break;
				default:
					stattype = "unknown";
					increment_entry(&server_stat.unknown);
					increment_entry(&local_stat.unknown);
					break;
				}
			} else {
				stattype = "unknown";
				increment_entry(&server_stat.unknown);
				increment_entry(&local_stat.unknown);
			}

			if (verbose_level > 1 ||
			    (verbose_level == 1 &&
			     strcmp(stattype, "valid") != 0 &&
			     strcmp(stattype, "unknown") != 0)) {
				print_name(pns->name);
				putchar('(');
				print_address(stdout, &server->address);
				printf(") for %s:%s\n", trans->domain,
				       stattype);
			}
		}
	}

	/* Update per domain statistics */
	if (local_stat.ignore > 0U) {
		if (verbose_level > 0)
			printf("%s:ignore\n", trans->domain);
		increment_entry(&domain_stat.ignore);
		err_count++;
	}
	if (local_stat.nxdomain > 0U) {
		if (verbose_level > 0)
			printf("%s:nxdomain\n", trans->domain);
		increment_entry(&domain_stat.nxdomain);
		err_count++;
	}
	if (local_stat.othererr > 0U) {
		if (verbose_level > 0)
			printf("%s:othererr\n", trans->domain);
		increment_entry(&domain_stat.othererr);
		err_count++;
	}
	if (local_stat.multiplesoa > 0U) {
		if (verbose_level > 0)
			printf("%s:multiplesoa\n", trans->domain);
		increment_entry(&domain_stat.multiplesoa);
		err_count++;
	}
	if (local_stat.multiplecname > 0U) {
		if (verbose_level > 0)
			printf("%s:multiplecname\n", trans->domain);
		increment_entry(&domain_stat.multiplecname);
		err_count++;
	}
	if (local_stat.brokenanswer > 0U) {
		if (verbose_level > 0)
			printf("%s:brokenanswer\n", trans->domain);
		increment_entry(&domain_stat.brokenanswer);
		err_count++;
	}
	if (local_stat.lame > 0U) {
		if (verbose_level > 0)
			printf("%s:lame\n", trans->domain);
		increment_entry(&domain_stat.lame);
		err_count++;
	}

	if (err_count > 1U)
		increment_entry(&multiple_error_domains);

	/*
	 * We regard the domain as valid if and only if no authoritative server
	 * has a problem and at least one server is known to be valid.
	 */
	if (local_stat.valid > 0U && err_count == 0U) {
		if (verbose_level > 1)
			printf("%s:valid\n", trans->domain);
		increment_entry(&domain_stat.valid);
	}

	/*
	 * If the domain has no available server or all servers have the
	 * 'unknown' result, the domain's result is also regarded as unknown.
	 */
	if (local_stat.valid == 0U && err_count == 0U) {
		if (verbose_level > 1)
			printf("%s:unknown\n", trans->domain);
		increment_entry(&domain_stat.unknown);
	}
}
Ejemplo n.º 30
0
static void
control_recvmessage(isc_task_t *task, isc_event_t *event) {
	controlconnection_t *conn;
	controllistener_t *listener;
	controlkey_t *key;
	isccc_sexpr_t *request = NULL;
	isccc_sexpr_t *response = NULL;
	isccc_region_t ccregion;
	isc_uint32_t algorithm;
	isccc_region_t secret;
	isc_stdtime_t now;
	isc_buffer_t b;
	isc_region_t r;
	isc_uint32_t len;
	isc_buffer_t text;
	char textarray[2*1024];
	isc_result_t result;
	isc_result_t eresult;
	isccc_sexpr_t *_ctrl;
	isccc_time_t sent;
	isccc_time_t exp;
	isc_uint32_t nonce;

	REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);

	conn = event->ev_arg;
	listener = conn->listener;
	algorithm = DST_ALG_UNKNOWN;
	secret.rstart = NULL;

	/* Is the server shutting down? */
	if (listener->controls->shuttingdown)
		goto cleanup;

	if (conn->ccmsg.result != ISC_R_SUCCESS) {
		if (conn->ccmsg.result != ISC_R_CANCELED &&
		    conn->ccmsg.result != ISC_R_EOF)
			log_invalid(&conn->ccmsg, conn->ccmsg.result);
		goto cleanup;
	}

	request = NULL;

	for (key = ISC_LIST_HEAD(listener->keys);
	     key != NULL;
	     key = ISC_LIST_NEXT(key, link))
	{
		ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer);
		ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer);
		secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
		if (secret.rstart == NULL)
			goto cleanup;
		memmove(secret.rstart, key->secret.base, key->secret.length);
		secret.rend = secret.rstart + key->secret.length;
		algorithm = key->algorithm;
		result = isccc_cc_fromwire(&ccregion, &request,
					   algorithm, &secret);
		if (result == ISC_R_SUCCESS)
			break;
		isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
		if (result != ISCCC_R_BADAUTH) {
			log_invalid(&conn->ccmsg, result);
			goto cleanup;
		}
	}

	if (key == NULL) {
		log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
		goto cleanup;
	}

	/* We shouldn't be getting a reply. */
	if (isccc_cc_isreply(request)) {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	isc_stdtime_get(&now);

	/*
	 * Limit exposure to replay attacks.
	 */
	_ctrl = isccc_alist_lookup(request, "_ctrl");
	if (_ctrl == NULL) {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
		if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) {
			log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW);
			goto cleanup_request;
		}
	} else {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	/*
	 * Expire messages that are too old.
	 */
	if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
	    now > exp) {
		log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED);
		goto cleanup_request;
	}

	/*
	 * Duplicate suppression (required for UDP).
	 */
	isccc_cc_cleansymtab(listener->controls->symtab, now);
	result = isccc_cc_checkdup(listener->controls->symtab, request, now);
	if (result != ISC_R_SUCCESS) {
		if (result == ISC_R_EXISTS)
			result = ISCCC_R_DUPLICATE;
		log_invalid(&conn->ccmsg, result);
		goto cleanup_request;
	}

	if (conn->nonce != 0 &&
	    (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS ||
	     conn->nonce != nonce)) {
		log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
		goto cleanup_request;
	}

	isc_buffer_init(&text, textarray, sizeof(textarray));

	/*
	 * Establish nonce.
	 */
	if (conn->nonce == 0) {
		while (conn->nonce == 0)
			isc_random_get(&conn->nonce);
		eresult = ISC_R_SUCCESS;
	} else
		eresult = ns_control_docommand(request, &text);

	result = isccc_cc_createresponse(request, now, now + 60, &response);
	if (result != ISC_R_SUCCESS)
		goto cleanup_request;
	if (eresult != ISC_R_SUCCESS) {
		isccc_sexpr_t *data;

		data = isccc_alist_lookup(response, "_data");
		if (data != NULL) {
			const char *estr = isc_result_totext(eresult);
			if (isccc_cc_definestring(data, "err", estr) == NULL)
				goto cleanup_response;
		}
	}

	if (isc_buffer_usedlength(&text) > 0) {
		isccc_sexpr_t *data;

		data = isccc_alist_lookup(response, "_data");
		if (data != NULL) {
			char *str = (char *)isc_buffer_base(&text);
			if (isccc_cc_definestring(data, "text", str) == NULL)
				goto cleanup_response;
		}
	}

	_ctrl = isccc_alist_lookup(response, "_ctrl");
	if (_ctrl == NULL ||
	    isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL)
		goto cleanup_response;

	ccregion.rstart = conn->buffer + 4;
	ccregion.rend = conn->buffer + sizeof(conn->buffer);
	result = isccc_cc_towire(response, &ccregion, algorithm, &secret);
	if (result != ISC_R_SUCCESS)
		goto cleanup_response;
	isc_buffer_init(&b, conn->buffer, 4);
	len = sizeof(conn->buffer) - REGION_SIZE(ccregion);
	isc_buffer_putuint32(&b, len - 4);
	r.base = conn->buffer;
	r.length = len;

	result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
	if (result != ISC_R_SUCCESS)
		goto cleanup_response;
	conn->sending = ISC_TRUE;

	isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
	isccc_sexpr_free(&request);
	isccc_sexpr_free(&response);
	return;

 cleanup_response:
	isccc_sexpr_free(&response);

 cleanup_request:
	isccc_sexpr_free(&request);
	isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));

 cleanup:
	isc_socket_detach(&conn->sock);
	isccc_ccmsg_invalidate(&conn->ccmsg);
	conn->ccmsg_valid = ISC_FALSE;
	maybe_free_connection(conn);
	maybe_free_listener(listener);
}