Esempio n. 1
0
static void
isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
	isc_result_t result;
	isc_httpdmgr_t *httpdmgr = ev->ev_arg;
	isc_httpd_t *httpd;
	isc_region_t r;
	isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev;
	isc_sockaddr_t peeraddr;

	ENTER("accept");

	LOCK(&httpdmgr->lock);
	if (MSHUTTINGDOWN(httpdmgr)) {
		NOTICE("accept shutting down, goto out");
		goto out;
	}

	if (nev->result == ISC_R_CANCELED) {
		NOTICE("accept canceled, goto out");
		goto out;
	}

	if (nev->result != ISC_R_SUCCESS) {
		/* XXXMLG log failure */
		NOTICE("accept returned failure, goto requeue");
		goto requeue;
	}

	(void)isc_socket_getpeername(nev->newsocket, &peeraddr);
	if (httpdmgr->client_ok != NULL &&
	    !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) {
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}

	httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
	if (httpd == NULL) {
		/* XXXMLG log failure */
		NOTICE("accept failed to allocate memory, goto requeue");
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}

	httpd->mgr = httpdmgr;
	ISC_LINK_INIT(httpd, link);
	ISC_LIST_APPEND(httpdmgr->running, httpd, link);
	ISC_HTTPD_SETRECV(httpd);
	httpd->sock = nev->newsocket;
	isc_socket_setname(httpd->sock, "httpd", NULL);
	httpd->flags = 0;

	/*
	 * Initialize the buffer for our headers.
	 */
	httpd->headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
	if (httpd->headerdata == NULL) {
		isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}
	httpd->headerlen = HTTP_SENDGROW;
	isc_buffer_init(&httpd->headerbuffer, httpd->headerdata,
			httpd->headerlen);

	ISC_LIST_INIT(httpd->bufflist);

	isc_buffer_initnull(&httpd->bodybuffer);
	reset_client(httpd);

	r.base = (unsigned char *)httpd->recvbuf;
	r.length = HTTP_RECVLEN - 1;
	result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
				 httpd);
	/* FIXME!!! */
	POST(result);
	NOTICE("accept queued recv on socket");

 requeue:
	result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
				   httpdmgr);
	if (result != ISC_R_SUCCESS) {
		/* XXXMLG what to do?  Log failure... */
		NOTICE("accept could not reaccept due to failure");
	}

 out:
	UNLOCK(&httpdmgr->lock);

	httpdmgr_destroy(httpdmgr);

	isc_event_free(&ev);

	EXIT("accept");
}
Esempio n. 2
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;
			isc_boolean_t offline;

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

			offline = ISC_FALSE;
			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);
				if (t->rdata.flags & DNS_RDATA_OFFLINE)
					offline = ISC_TRUE;
				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);
				}
			} 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)
					isc_log_write(DIFF_COMMON_LOGARGS,
						      ISC_LOG_WARNING,
						      "update with no effect");
			} 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);
}
Esempio n. 3
0
static void
add_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)
{
	isc_mem_t *mctx = cp->server->mctx;
	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;
	isc_result_t result = ISC_R_SUCCESS;

	listener = isc_mem_get(mctx, sizeof(*listener));
	if (listener == NULL)
		result = ISC_R_NOMEMORY;

	if (result == ISC_R_SUCCESS) {
		listener->mctx = NULL;
		isc_mem_attach(mctx, &listener->mctx);
		listener->controls = cp;
		listener->task = cp->server->task;
		listener->address = *addr;
		listener->sock = NULL;
		listener->listening = ISC_FALSE;
		listener->exiting = ISC_FALSE;
		listener->acl = NULL;
		listener->type = type;
		listener->perm = 0;
		listener->owner = 0;
		listener->group = 0;
		ISC_LINK_INIT(listener, link);
		ISC_LIST_INIT(listener->keys);
		ISC_LIST_INIT(listener->connections);

		/*
		 * Make the acl.
		 */
		if (control != NULL && type == isc_sockettype_tcp) {
			allow = cfg_tuple_get(control, "allow");
			result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
						    aclconfctx, mctx, 0,
						    &new_acl);
		} else {
			result = dns_acl_any(mctx, &new_acl);
		}
	}

	if (result == ISC_R_SUCCESS) {
		dns_acl_attach(new_acl, &listener->acl);
		dns_acl_detach(&new_acl);

		if (config != NULL)
			get_key_info(config, control, &global_keylist,
				     &control_keylist);

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

		if (result != ISC_R_SUCCESS && control != NULL)
			cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
				    "couldn't install keys for "
				    "command channel %s: %s",
				    socktext, isc_result_totext(result));
	}

	if (result == ISC_R_SUCCESS) {
		int pf = isc_sockaddr_pf(&listener->address);
		if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
#ifdef ISC_PLATFORM_HAVESYSUNH
		    (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) ||
#endif
		    (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
			result = ISC_R_FAMILYNOSUPPORT;
	}

	if (result == ISC_R_SUCCESS && type == isc_sockettype_unix)
		isc_socket_cleanunix(&listener->address, ISC_FALSE);

	if (result == ISC_R_SUCCESS)
		result = isc_socket_create(ns_g_socketmgr,
					   isc_sockaddr_pf(&listener->address),
					   type, &listener->sock);
	if (result == ISC_R_SUCCESS)
		isc_socket_setname(listener->sock, "control", NULL);

#ifndef ISC_ALLOW_MAPPED
	if (result == ISC_R_SUCCESS)
		isc_socket_ipv6only(listener->sock, ISC_TRUE);
#endif

	if (result == ISC_R_SUCCESS)
		result = isc_socket_bind(listener->sock, &listener->address,
					 ISC_SOCKET_REUSEADDRESS);

	if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
		listener->perm = cfg_obj_asuint32(cfg_tuple_get(control,
								"perm"));
		listener->owner = cfg_obj_asuint32(cfg_tuple_get(control,
								 "owner"));
		listener->group = cfg_obj_asuint32(cfg_tuple_get(control,
								 "group"));
		result = isc_socket_permunix(&listener->address, listener->perm,
					     listener->owner, listener->group);
	}
	if (result == ISC_R_SUCCESS)
		result = control_listen(listener);

	if (result == ISC_R_SUCCESS)
		result = control_accept(listener);

	if (result == ISC_R_SUCCESS) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
			      "command channel listening on %s", socktext);
		*listenerp = listener;

	} else {
		if (listener != NULL) {
			listener->exiting = ISC_TRUE;
			free_listener(listener);
		}

		if (control != NULL)
			cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
				    "couldn't add command channel %s: %s",
				    socktext, isc_result_totext(result));
		else
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
				      "couldn't add command channel %s: %s",
				      socktext, isc_result_totext(result));

		*listenerp = NULL;
	}

	/* XXXDCL return error results? fail hard? */
}
Esempio n. 4
0
static isc_result_t
dlz_ldap_create(const char *dlzname, unsigned int argc, char *argv[],
		void *driverarg, void **dbdata)
{
	isc_result_t result;
	ldap_instance_t *ldap_inst = NULL;
	dbinstance_t *dbi = NULL;
	int protocol;
	int method;

#ifdef ISC_PLATFORM_USETHREADS
	/* if multi-threaded, we need a few extra variables. */
	int dbcount;
	char *endp;
/* db_list_t *dblist = NULL; */
	int i;

#endif /* ISC_PLATFORM_USETHREADS */

	UNUSED(dlzname);
	UNUSED(driverarg);

#ifdef ISC_PLATFORM_USETHREADS
	/* if debugging, let user know we are multithreaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "LDAP driver running multithreaded");
#else /* ISC_PLATFORM_USETHREADS */
	/* if debugging, let user know we are single threaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "LDAP driver running single threaded");
#endif /* ISC_PLATFORM_USETHREADS */

	if (argc < 9) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver requires at least "
			      "8 command line args.");
		return (ISC_R_FAILURE);
	}

	/* no more than 13 arg's should be passed to the driver */
	if (argc > 12) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver cannot accept more than "
			      "11 command line args.");
		return (ISC_R_FAILURE);
	}

	/* determine protocol version. */
	if (strncasecmp(argv[2], V2, strlen(V2)) == 0) {
		protocol = 2;
	} else if (strncasecmp(argv[2], V3, strlen(V3)) == 0) {
		protocol = 3;
	} else {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver protocol must be either %s or %s",
			      V2, V3);
		return (ISC_R_FAILURE);
	}

	/* determine connection method. */
	if (strncasecmp(argv[3], SIMPLE, strlen(SIMPLE)) == 0) {
		method = LDAP_AUTH_SIMPLE;
	} else if (strncasecmp(argv[3], KRB41, strlen(KRB41)) == 0) {
		method = LDAP_AUTH_KRBV41;
	} else if (strncasecmp(argv[3], KRB42, strlen(KRB42)) == 0) {
		method = LDAP_AUTH_KRBV42;
	} else {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver authentication method must be "
			      "one of %s, %s or %s",
			      SIMPLE, KRB41, KRB42);
		return (ISC_R_FAILURE);
	}

	/* multithreaded build can have multiple DB connections */
#ifdef ISC_PLATFORM_USETHREADS

	/* check how many db connections we should create */
	dbcount = strtol(argv[1], &endp, 10);
	if (*endp != '\0' || dbcount < 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "LDAP driver database connection count "
			      "must be positive.");
		return (ISC_R_FAILURE);
	}
#endif

	/* check that LDAP URL parameters make sense */
	switch(argc) {
	case 12:
		result = dlz_ldap_checkURL(argv[11], 0, "allow zone transfer");
		if (result != ISC_R_SUCCESS)
			return (result);
	case 11:
		result = dlz_ldap_checkURL(argv[10], 3, "all nodes");
		if (result != ISC_R_SUCCESS)
			return (result);
	case 10:
		if (strlen(argv[9]) > 0) {
			result = dlz_ldap_checkURL(argv[9], 3, "authority");
			if (result != ISC_R_SUCCESS)
				return (result);
		}
	case 9:
		result = dlz_ldap_checkURL(argv[8], 3, "lookup");
		if (result != ISC_R_SUCCESS)
			return (result);
		result = dlz_ldap_checkURL(argv[7], 0, "find zone");
		if (result != ISC_R_SUCCESS)
			return (result);
		break;
	default:
		/* not really needed, should shut up compiler. */
		result = ISC_R_FAILURE;
	}

	/* allocate memory for LDAP instance */
	ldap_inst = isc_mem_get(ns_g_mctx, sizeof(ldap_instance_t));
	if (ldap_inst == NULL)
		return (ISC_R_NOMEMORY);
	memset(ldap_inst, 0, sizeof(ldap_instance_t));

	/* store info needed to automatically re-connect. */
	ldap_inst->protocol = protocol;
	ldap_inst->method = method;
	ldap_inst->hosts = isc_mem_strdup(ns_g_mctx, argv[6]);
	if (ldap_inst->hosts == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}
	ldap_inst->user = isc_mem_strdup(ns_g_mctx, argv[4]);
	if (ldap_inst->user == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}
	ldap_inst->cred = isc_mem_strdup(ns_g_mctx, argv[5]);
	if (ldap_inst->cred == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

#ifdef ISC_PLATFORM_USETHREADS
	/* allocate memory for database connection list */
	ldap_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
	if (ldap_inst->db == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/* initialize DB connection list */
	ISC_LIST_INIT(*(ldap_inst->db));

	/*
	 * create the appropriate number of database instances (DBI)
	 * append each new DBI to the end of the list
	 */
	for (i = 0; i < dbcount; i++) {

#endif /* ISC_PLATFORM_USETHREADS */

		/* how many queries were passed in from config file? */
		switch(argc) {
		case 9:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     NULL, argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 10:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     argv[9], argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 11:
			result = build_sqldbinstance(ns_g_mctx, argv[10], NULL,
						     argv[9], argv[7], argv[8],
						     NULL, &dbi);
			break;
		case 12:
			result = build_sqldbinstance(ns_g_mctx, argv[10],
						     argv[11], argv[9],
						     argv[7], argv[8],
						     NULL, &dbi);
			break;
		default:
			/* not really needed, should shut up compiler. */
			result = ISC_R_FAILURE;
		}

		if (result == ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "LDAP driver created "
				      "database instance object.");
		} else { /* unsuccessful?, log err msg and cleanup. */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not create "
				      "database instance object.");
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS
		/* when multithreaded, build a list of DBI's */
		ISC_LINK_INIT(dbi, link);
		ISC_LIST_APPEND(*(ldap_inst->db), dbi, link);
#else
		/*
		 * when single threaded, hold onto the one connection
		 * instance.
		 */
		ldap_inst->db = dbi;

#endif
		/* attempt to connect */
		result = dlz_ldap_connect(ldap_inst, dbi);

		/*
		 * if db connection cannot be created, log err msg and
		 * cleanup.
		 */
		switch(result) {
			/* success, do nothing */
		case ISC_R_SUCCESS:
			break;
			/*
			 * no memory means ldap_init could not
			 * allocate memory
			 */
		case ISC_R_NOMEMORY:
#ifdef ISC_PLATFORM_USETHREADS
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not allocate memory "
				      "for connection number %u",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not allocate memory "
				      "for connection");
#endif
			goto cleanup;
			break;
			/*
			 * no perm means ldap_set_option could not set
			 * protocol version
			 */
		case ISC_R_NOPERM:
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "set protocol version.");
			result = ISC_R_FAILURE;
			goto cleanup;
			break;
			/* failure means couldn't connect to ldap server */
		case ISC_R_FAILURE:
#ifdef ISC_PLATFORM_USETHREADS
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "bind connection number %u to server.",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "LDAP driver could not "
				      "bind connection to server.");
#endif
			goto cleanup;
			break;
			/*
			 * default should never happen.  If it does,
			 * major errors.
			 */
		default:
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "dlz_ldap_create() failed: %s",
					 isc_result_totext(result));
			result = ISC_R_UNEXPECTED;
			goto cleanup;
			break;
		} /* end switch(result) */


#ifdef ISC_PLATFORM_USETHREADS

		/* set DBI = null for next loop through. */
		dbi = NULL;
	}	/* end for loop */

#endif /* ISC_PLATFORM_USETHREADS */


	/* set dbdata to the ldap_instance we created. */
	*dbdata = ldap_inst;

	/* hey, we got through all of that ok, return success. */
	return(ISC_R_SUCCESS);

 cleanup:
	dlz_ldap_destroy(NULL, ldap_inst);

	return(ISC_R_FAILURE);
}
Esempio n. 5
0
isc_result_t
res_nupdate(res_state statp, ns_updrec *rrecp_in) {
	ns_updrec *rrecp;
	union {
	    double answer[PACKETSZ / sizeof (double)];
	    HEADER h;
	} __tmp;
	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,
					__tmp.answer, sizeof __tmp.answer, &rval);
		tkey_free (&key);
	} else if (rcode == ISC_R_NOTFOUND || rcode == ISC_R_KEY_UNKNOWN) {
		rcode = res_nsend(statp, packet, n,
				  __tmp.answer, sizeof __tmp.answer, &rval);
	}
	if (rcode != ISC_R_SUCCESS)
		goto undone;

	rcode = ns_rcode_to_isc (__tmp.h.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;
}
Esempio n. 6
0
File: tkey.c Progetto: jhbsz/netbsd
static isc_result_t
add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
		isc_uint32_t ttl, dns_namelist_t *namelist)
{
	isc_result_t result;
	isc_region_t r, newr;
	dns_rdata_t *newrdata = NULL;
	dns_name_t *newname = NULL;
	dns_rdatalist_t *newlist = NULL;
	dns_rdataset_t *newset = NULL;
	isc_buffer_t *tmprdatabuf = NULL;

	RETERR(dns_message_gettemprdata(msg, &newrdata));

	dns_rdata_toregion(rdata, &r);
	RETERR(isc_buffer_allocate(msg->mctx, &tmprdatabuf, r.length));
	isc_buffer_availableregion(tmprdatabuf, &newr);
	memcpy(newr.base, r.base, r.length);
	dns_rdata_fromregion(newrdata, rdata->rdclass, rdata->type, &newr);
	dns_message_takebuffer(msg, &tmprdatabuf);

	RETERR(dns_message_gettempname(msg, &newname));
	dns_name_init(newname, NULL);
	RETERR(dns_name_dup(name, msg->mctx, newname));

	RETERR(dns_message_gettemprdatalist(msg, &newlist));
	newlist->rdclass = newrdata->rdclass;
	newlist->type = newrdata->type;
	newlist->covers = 0;
	newlist->ttl = ttl;
	ISC_LIST_INIT(newlist->rdata);
	ISC_LIST_APPEND(newlist->rdata, newrdata, link);

	RETERR(dns_message_gettemprdataset(msg, &newset));
	dns_rdataset_init(newset);
	RETERR(dns_rdatalist_tordataset(newlist, newset));

	ISC_LIST_INIT(newname->list);
	ISC_LIST_APPEND(newname->list, newset, link);

	ISC_LIST_APPEND(*namelist, newname, link);

	return (ISC_R_SUCCESS);

 failure:
	if (newrdata != NULL) {
		if (ISC_LINK_LINKED(newrdata, link)) {
			INSIST(newlist != NULL);
			ISC_LIST_UNLINK(newlist->rdata, newrdata, link);
		}
		dns_message_puttemprdata(msg, &newrdata);
	}
	if (newname != NULL)
		dns_message_puttempname(msg, &newname);
	if (newset != NULL) {
		dns_rdataset_disassociate(newset);
		dns_message_puttemprdataset(msg, &newset);
	}
	if (newlist != NULL)
		dns_message_puttemprdatalist(msg, &newlist);
	return (result);
}
/*%
 * create an instance of the driver.  Remember, only 1 copy of the driver's
 * code is ever loaded, the driver has to remember which context it's
 * operating in.  This is done via use of the dbdata argument which is
 * passed into all query functions.
 */
static isc_result_t
odbc_create(const char *dlzname, unsigned int argc, char *argv[],
	    void *driverarg, void **dbdata)
{
	isc_result_t result;
	odbc_instance_t *odbc_inst = NULL;
	dbinstance_t *db = NULL;
	SQLRETURN sqlRes;

#ifdef ISC_PLATFORM_USETHREADS
	/* if multi-threaded, we need a few extra variables. */
	int dbcount;
	int i;
	char *endp;

#endif /* ISC_PLATFORM_USETHREADS */

	UNUSED(dlzname);
	UNUSED(driverarg);

#ifdef ISC_PLATFORM_USETHREADS
	/* if debugging, let user know we are multithreaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "Odbc driver running multithreaded");
#else /* ISC_PLATFORM_USETHREADS */
	/* if debugging, let user know we are single threaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "Odbc driver running single threaded");
#endif /* ISC_PLATFORM_USETHREADS */

	/* verify we have at least 5 arg's passed to the driver */
	if (argc < 5) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver requires at least "
			      "4 command line args.");
		return (ISC_R_FAILURE);
	}

	/* no more than 8 arg's should be passed to the driver */
	if (argc > 8) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver cannot accept more than "
			      "7 command line args.");
		return (ISC_R_FAILURE);
	}

	/* multithreaded build can have multiple DB connections */
#ifdef ISC_PLATFORM_USETHREADS

	/* check how many db connections we should create */
	dbcount = strtol(argv[1], &endp, 10);
	if (*endp != '\0' || dbcount < 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver database connection count "
			      "must be positive.");
		return (ISC_R_FAILURE);
	}

#endif /* ISC_PLATFORM_USETHREADS */

	/* allocate memory for odbc instance */
	odbc_inst = isc_mem_get(ns_g_mctx, sizeof(odbc_instance_t));
	if (odbc_inst == NULL)
		return (ISC_R_NOMEMORY);
	memset(odbc_inst, 0, sizeof(odbc_instance_t));

	/* parse connection string and get paramters. */

	/* get odbc database dsn - required */
	odbc_inst->dsn = (SQLCHAR *) getParameterValue(argv[2],
						       "dsn=");
	if (odbc_inst->dsn == NULL) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "odbc driver requires a dns parameter.");
		result = ISC_R_FAILURE;
		goto cleanup;
	}
	/* get odbc database username */
	/* if no username was passed, set odbc_inst.user = NULL; */
	odbc_inst->user = (SQLCHAR *) getParameterValue(argv[2],
							"user="******"pass="******"Odbc driver unable to allocate memory");
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
		/*set ODBC version = 3 */
		sqlRes = SQLSetEnvAttr(odbc_inst->sql_env,
				       SQL_ATTR_ODBC_VERSION,
				       (void *) SQL_OV_ODBC3, 0);
		if (!sqlOK(sqlRes)) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
				      "Unable to configure ODBC environment");
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	}

#ifdef ISC_PLATFORM_USETHREADS

	/* allocate memory for database connection list */
	odbc_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
	if (odbc_inst->db == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}


	/* initialize DB connection list */
	ISC_LIST_INIT(*odbc_inst->db);

	/* create the appropriate number of database instances (DBI) */
	/* append each new DBI to the end of the list */
	for (i=0; i < dbcount; i++) {

#endif /* ISC_PLATFORM_USETHREADS */

		/* how many queries were passed in from config file? */
		switch(argc) {
		case 5:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     NULL, argv[3], argv[4],
						     NULL, &db);
			break;
		case 6:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     argv[5], argv[3], argv[4],
						     NULL, &db);
			break;
		case 7:
			result = build_sqldbinstance(ns_g_mctx, argv[6], NULL,
						     argv[5], argv[3], argv[4],
						     NULL, &db);
			break;
		case 8:
			result = build_sqldbinstance(ns_g_mctx, argv[6],
						     argv[7], argv[5], argv[3],
						     argv[4], NULL, &db);
			break;
		default:
			/* not really needed, should shut up compiler. */
			result = ISC_R_FAILURE;
		}

		/* unsuccessful?, log err msg and cleanup. */
		if (result != ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver could not create "
				      "database instance object.");
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS

		/* when multithreaded, build a list of DBI's */
		ISC_LINK_INIT(db, link);
		ISC_LIST_APPEND(*odbc_inst->db, db, link);

#endif

		result = odbc_connect(odbc_inst, (odbc_db_t **) &(db->dbconn));

		if (result != ISC_R_SUCCESS) {

#ifdef ISC_PLATFORM_USETHREADS

			/*
			 * if multi threaded, let user know which
			 * connection failed.  user could be
			 * attempting to create 10 db connections and
			 * for some reason the db backend only allows
			 * 9.
			 */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver failed to create database "
				      "connection number %u after 3 attempts",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver failed to create database "
				      "connection after 3 attempts");
#endif
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS

		/* set DB = null for next loop through. */
		db = NULL;

	}	/* end for loop */

#else
	/* tell odbc_inst about the db connection we just created. */
	odbc_inst->db = db;

#endif

	/* set dbdata to the odbc_instance we created. */
	*dbdata = odbc_inst;

	/* hey, we got through all of that ok, return success. */
	return(ISC_R_SUCCESS);

 cleanup:

	destroy_odbc_instance(odbc_inst);

	return result;
}
Esempio n. 8
0
/*
 * Arrange to send as much as we can of "stream" without blocking.
 *
 * Requires:
 *	The stream iterator is initialized and points at an RR,
 *      or possibly at the end of the stream (that is, the
 *      _first method of the iterator has been called).
 */
static void
sendstream(xfrout_ctx_t *xfr) {
	dns_message_t *tcpmsg = NULL;
	dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
	isc_result_t result;
	isc_region_t used;
	isc_region_t region;
	dns_rdataset_t *qrdataset;
	dns_name_t *msgname = NULL;
	dns_rdata_t *msgrdata = NULL;
	dns_rdatalist_t *msgrdl = NULL;
	dns_rdataset_t *msgrds = NULL;
	dns_compress_t cctx;
	isc_boolean_t cleanup_cctx = ISC_FALSE;
	isc_boolean_t is_tcp;

	int n_rrs;

	isc_buffer_clear(&xfr->buf);
	isc_buffer_clear(&xfr->txlenbuf);
	isc_buffer_clear(&xfr->txbuf);

	is_tcp = ISC_TF((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0);
	if (!is_tcp) {
		/*
		 * In the UDP case, we put the response data directly into
		 * the client message.
		 */
		msg = xfr->client->message;
		CHECK(dns_message_reply(msg, ISC_TRUE));
	} else {
		/*
		 * TCP. Build a response dns_message_t, temporarily storing
		 * the raw, uncompressed owner names and RR data contiguously
		 * in xfr->buf.  We know that if the uncompressed data fits
		 * in xfr->buf, the compressed data will surely fit in a TCP
		 * message.
		 */

		CHECK(dns_message_create(xfr->mctx,
					 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
		msg = tcpmsg;

		msg->id = xfr->id;
		msg->rcode = dns_rcode_noerror;
		msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
		if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
			msg->flags |= DNS_MESSAGEFLAG_RA;
		CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
		CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
		if (xfr->lasttsig != NULL)
			isc_buffer_free(&xfr->lasttsig);

		/*
		 * Add a EDNS option to the message?
		 */
		if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
			dns_rdataset_t *opt = NULL;

			CHECK(ns_client_addopt(xfr->client, msg, &opt));
			CHECK(dns_message_setopt(msg, opt));
			/*
			 * Add to first message only.
			 */
			xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID;
			xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE;
		}

		/*
		 * Account for reserved space.
		 */
		if (xfr->tsigkey != NULL)
			INSIST(msg->reserved != 0U);
		isc_buffer_add(&xfr->buf, msg->reserved);

		/*
		 * Include a question section in the first message only.
		 * BIND 8.2.1 will not recognize an IXFR if it does not
		 * have a question section.
		 */
		if (xfr->nmsg == 0) {
			dns_name_t *qname = NULL;
			isc_region_t r;

			/*
			 * Reserve space for the 12-byte message header
			 * and 4 bytes of question.
			 */
			isc_buffer_add(&xfr->buf, 12 + 4);

			qrdataset = NULL;
			result = dns_message_gettemprdataset(msg, &qrdataset);
			if (result != ISC_R_SUCCESS)
				goto failure;
			dns_rdataset_makequestion(qrdataset,
					xfr->client->message->rdclass,
					xfr->qtype);

			result = dns_message_gettempname(msg, &qname);
			if (result != ISC_R_SUCCESS)
				goto failure;
			dns_name_init(qname, NULL);
			isc_buffer_availableregion(&xfr->buf, &r);
			INSIST(r.length >= xfr->qname->length);
			r.length = xfr->qname->length;
			isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
					  xfr->qname->length);
			dns_name_fromregion(qname, &r);
			ISC_LIST_INIT(qname->list);
			ISC_LIST_APPEND(qname->list, qrdataset, link);

			dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
		} else {
			/*
			 * Reserve space for the 12-byte message header
			 */
			isc_buffer_add(&xfr->buf, 12);
			msg->tcp_continuation = 1;
		}
	}

	/*
	 * Try to fit in as many RRs as possible, unless "one-answer"
	 * format has been requested.
	 */
	for (n_rrs = 0; ; n_rrs++) {
		dns_name_t *name = NULL;
		isc_uint32_t ttl;
		dns_rdata_t *rdata = NULL;

		unsigned int size;
		isc_region_t r;

		msgname = NULL;
		msgrdata = NULL;
		msgrdl = NULL;
		msgrds = NULL;

		xfr->stream->methods->current(xfr->stream,
					      &name, &ttl, &rdata);
		size = name->length + 10 + rdata->length;
		isc_buffer_availableregion(&xfr->buf, &r);
		if (size >= r.length) {
			/*
			 * RR would not fit.  If there are other RRs in the
			 * buffer, send them now and leave this RR to the
			 * next message.  If this RR overflows the buffer
			 * all by itself, fail.
			 *
			 * In theory some RRs might fit in a TCP message
			 * when compressed even if they do not fit when
			 * uncompressed, but surely we don't want
			 * to send such monstrosities to an unsuspecting
			 * slave.
			 */
			if (n_rrs == 0) {
				xfrout_log(xfr, ISC_LOG_WARNING,
					   "RR too large for zone transfer "
					   "(%d bytes)", size);
				/* XXX DNS_R_RRTOOLARGE? */
				result = ISC_R_NOSPACE;
				goto failure;
			}
			break;
		}

		if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
			log_rr(name, rdata, ttl); /* XXX */

		result = dns_message_gettempname(msg, &msgname);
		if (result != ISC_R_SUCCESS)
			goto failure;
		dns_name_init(msgname, NULL);
		isc_buffer_availableregion(&xfr->buf, &r);
		INSIST(r.length >= name->length);
		r.length = name->length;
		isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
		dns_name_fromregion(msgname, &r);

		/* Reserve space for RR header. */
		isc_buffer_add(&xfr->buf, 10);

		result = dns_message_gettemprdata(msg, &msgrdata);
		if (result != ISC_R_SUCCESS)
			goto failure;
		isc_buffer_availableregion(&xfr->buf, &r);
		r.length = rdata->length;
		isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
		dns_rdata_init(msgrdata);
		dns_rdata_fromregion(msgrdata,
				     rdata->rdclass, rdata->type, &r);

		result = dns_message_gettemprdatalist(msg, &msgrdl);
		if (result != ISC_R_SUCCESS)
			goto failure;
		msgrdl->type = rdata->type;
		msgrdl->rdclass = rdata->rdclass;
		msgrdl->ttl = ttl;
		if (rdata->type == dns_rdatatype_sig ||
		    rdata->type == dns_rdatatype_rrsig)
			msgrdl->covers = dns_rdata_covers(rdata);
		else
			msgrdl->covers = dns_rdatatype_none;
		ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);

		result = dns_message_gettemprdataset(msg, &msgrds);
		if (result != ISC_R_SUCCESS)
			goto failure;
		result = dns_rdatalist_tordataset(msgrdl, msgrds);
		INSIST(result == ISC_R_SUCCESS);

		ISC_LIST_APPEND(msgname->list, msgrds, link);

		dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
		msgname = NULL;

		result = xfr->stream->methods->next(xfr->stream);
		if (result == ISC_R_NOMORE) {
			xfr->end_of_stream = ISC_TRUE;
			break;
		}
		CHECK(result);

		if (! xfr->many_answers)
			break;
		/*
		 * At this stage, at least 1 RR has been rendered into
		 * the message. Check if we want to clamp this message
		 * here (TCP only).
		 */
		if ((isc_buffer_usedlength(&xfr->buf) >=
		     ns_g_server->transfer_tcp_message_size) && is_tcp)
			break;
	}

	if (is_tcp) {
		CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
		dns_compress_setsensitive(&cctx, ISC_TRUE);
		cleanup_cctx = ISC_TRUE;
		CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
		CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
		CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
		CHECK(dns_message_renderend(msg));
		dns_compress_invalidate(&cctx);
		cleanup_cctx = ISC_FALSE;

		isc_buffer_usedregion(&xfr->txbuf, &used);
		isc_buffer_putuint16(&xfr->txlenbuf,
				     (isc_uint16_t)used.length);
		region.base = xfr->txlenbuf.base;
		region.length = 2 + used.length;
		xfrout_log(xfr, ISC_LOG_DEBUG(8),
			   "sending TCP message of %d bytes",
			   used.length);
		CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
				      &region, xfr->client->task,
				      xfrout_senddone,
				      xfr));
		xfr->sends++;
	} else {
		xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
		ns_client_send(xfr->client);
		xfr->stream->methods->pause(xfr->stream);
		xfrout_ctx_destroy(&xfr);
		return;
	}

	/* Advance lasttsig to be the last TSIG generated */
	CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));

	xfr->nmsg++;

 failure:
	if (msgname != NULL) {
		if (msgrds != NULL) {
			if (dns_rdataset_isassociated(msgrds))
				dns_rdataset_disassociate(msgrds);
			dns_message_puttemprdataset(msg, &msgrds);
		}
		if (msgrdl != NULL) {
			ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
			dns_message_puttemprdatalist(msg, &msgrdl);
		}
		if (msgrdata != NULL)
			dns_message_puttemprdata(msg, &msgrdata);
		dns_message_puttempname(msg, &msgname);
	}

	if (tcpmsg != NULL)
		dns_message_destroy(&tcpmsg);

	if (cleanup_cctx)
		dns_compress_invalidate(&cctx);
	/*
	 * Make sure to release any locks held by database
	 * iterators before returning from the event handler.
	 */
	xfr->stream->methods->pause(xfr->stream);

	if (result == ISC_R_SUCCESS)
		return;

	xfrout_fail(xfr, result, "sending zone data");
}
Esempio n. 9
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));
}
Esempio n. 10
0
static void
dlz_initialize(void) {
	RUNTIME_CHECK(isc_rwlock_init(&dlz_implock, 0, 0) == ISC_R_SUCCESS);
	ISC_LIST_INIT(dlz_implementations);
}
Esempio n. 11
0
void
ns_aclconfctx_init(ns_aclconfctx_t *ctx) {
	ISC_LIST_INIT(ctx->named_acl_cache);
}
Esempio n. 12
0
isc_result_t
ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
		    isc_taskmgr_t *taskmgr)
{
	ns_lwresd_t *lwresd = listener->manager;
	ns_lwdclientmgr_t *cm;
	ns_lwdclient_t *client;
	unsigned int i;
	isc_result_t result;

	cm = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclientmgr_t));
	if (cm == NULL)
		return (ISC_R_NOMEMORY);

	result = isc_mutex_init(&cm->lock);
	if (result != ISC_R_SUCCESS)
		goto freecm;

	cm->listener = NULL;
	ns_lwreslistener_attach(listener, &cm->listener);
	cm->mctx = lwresd->mctx;
	cm->sock = NULL;
	isc_socket_attach(listener->sock, &cm->sock);
	cm->view = lwresd->view;
	cm->lwctx = NULL;
	cm->task = NULL;
	cm->flags = 0;
	ISC_LINK_INIT(cm, link);
	ISC_LIST_INIT(cm->idle);
	ISC_LIST_INIT(cm->running);

	result = lwres_context_create(&cm->lwctx, cm->mctx,
				      ns__lwresd_memalloc, ns__lwresd_memfree,
				      LWRES_CONTEXT_SERVERMODE);
	 if (result != ISC_R_SUCCESS)
		goto errout;

	for (i = 0; i < nclients; i++) {
		client = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclient_t));
		if (client != NULL) {
			ns_lwdclient_log(50, "created client %p, manager %p",
					 client, cm);
			ns_lwdclient_initialize(client, cm);
		}
	}

	/*
	 * If we could create no clients, clean up and return.
	 */
	if (ISC_LIST_EMPTY(cm->idle)) {
		result = ISC_R_NOMEMORY;
		goto errout;
	}

	result = isc_task_create(taskmgr, 0, &cm->task);
	if (result != ISC_R_SUCCESS)
		goto errout;
	isc_task_setname(cm->task, "lwdclient", NULL);

	/*
	 * This MUST be last, since there is no way to cancel an onshutdown...
	 */
	result = isc_task_onshutdown(cm->task, lwdclientmgr_shutdown_callback,
				     cm);
	if (result != ISC_R_SUCCESS)
		goto errout;

	ns_lwreslistener_linkcm(listener, cm);

	return (ISC_R_SUCCESS);

 errout:
	client = ISC_LIST_HEAD(cm->idle);
	while (client != NULL) {
		ISC_LIST_UNLINK(cm->idle, client, link);
		isc_mem_put(lwresd->mctx, client, sizeof(*client));
		client = ISC_LIST_HEAD(cm->idle);
	}

	if (cm->task != NULL)
		isc_task_detach(&cm->task);

	if (cm->lwctx != NULL)
		lwres_context_destroy(&cm->lwctx);

	DESTROYLOCK(&cm->lock);

 freecm:
	isc_mem_put(lwresd->mctx, cm, sizeof(*cm));
	return (result);
}
Esempio n. 13
0
static void
addlookup(char *opt) {
	dig_lookup_t *lookup;
	isc_result_t result;
	isc_textregion_t tr;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	char store[MXNAME];

	debug("addlookup()");
	tr.base = deftype;
	tr.length = strlen(deftype);
	result = dns_rdatatype_fromtext(&rdtype, &tr);
	if (result != ISC_R_SUCCESS) {
		printf("unknown query type: %s\n", deftype);
		rdclass = dns_rdatatype_a;
	}
	tr.base = defclass;
	tr.length = strlen(defclass);
	result = dns_rdataclass_fromtext(&rdclass, &tr);
	if (result != ISC_R_SUCCESS) {
		printf("unknown query class: %s\n", defclass);
		rdclass = dns_rdataclass_in;
	}
	lookup = make_empty_lookup();
	if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
	    == ISC_R_SUCCESS) {
		safecpy(lookup->textname, store, sizeof(lookup->textname));
		lookup->rdtype = dns_rdatatype_ptr;
		lookup->rdtypeset = ISC_TRUE;
	} else {
		safecpy(lookup->textname, opt, sizeof(lookup->textname));
		lookup->rdtype = rdtype;
		lookup->rdtypeset = ISC_TRUE;
	}
	lookup->rdclass = rdclass;
	lookup->rdclassset = ISC_TRUE;
	lookup->trace = ISC_FALSE;
	lookup->trace_root = lookup->trace;
	lookup->ns_search_only = ISC_FALSE;
	lookup->identify = identify;
	lookup->recurse = recurse;
	lookup->aaonly = aaonly;
	lookup->retries = tries;
	lookup->udpsize = 0;
	lookup->comments = comments;
	lookup->tcp_mode = tcpmode;
	lookup->stats = stats;
	lookup->section_question = section_question;
	lookup->section_answer = section_answer;
	lookup->section_authority = section_authority;
	lookup->section_additional = section_additional;
	lookup->new_search = ISC_TRUE;
	if (nofail)
		lookup->servfail_stops = ISC_FALSE;
	ISC_LIST_INIT(lookup->q);
	ISC_LINK_INIT(lookup, link);
	ISC_LIST_APPEND(lookup_list, lookup, link);
	lookup->origin = NULL;
	ISC_LIST_INIT(lookup->my_server_list);
	debug("looking up %s", lookup->textname);
}
Esempio n. 14
0
isc_result_t
isc_app_start(void) {
	isc_result_t result;
	int presult;
	sigset_t sset;
	char strbuf[ISC_STRERRORSIZE];

	/*
	 * Start an ISC library application.
	 */

#ifdef NEED_PTHREAD_INIT
	/*
	 * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this.
	 */
	presult = pthread_init();
	if (presult != 0) {
		isc__strerror(presult, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_app_start() pthread_init: %s", strbuf);
		return (ISC_R_UNEXPECTED);
	}
#endif

#ifdef HAVE_LINUXTHREADS
	main_thread = pthread_self();
#endif

	result = isc_mutex_init(&lock);
	if (result != ISC_R_SUCCESS)
		return (result);

#ifndef HAVE_SIGWAIT
	/*
	 * Install do-nothing handlers for SIGINT and SIGTERM.
	 *
	 * We install them now because BSDI 3.1 won't block
	 * the default actions, regardless of what we do with
	 * pthread_sigmask().
	 */
	result = handle_signal(SIGINT, exit_action);
	if (result != ISC_R_SUCCESS)
		return (result);
	result = handle_signal(SIGTERM, exit_action);
	if (result != ISC_R_SUCCESS)
		return (result);
#endif

	/*
	 * Always ignore SIGPIPE.
	 */
	result = handle_signal(SIGPIPE, SIG_IGN);
	if (result != ISC_R_SUCCESS)
		return (result);

	/*
	 * On Solaris 2, delivery of a signal whose action is SIG_IGN
	 * will not cause sigwait() to return. We may have inherited
	 * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent
	 * process (e.g, Solaris cron).  Set an action of SIG_DFL to make
	 * sure sigwait() works as expected.  Only do this for SIGTERM and
	 * SIGINT if we don't have sigwait(), since a different handler is
	 * installed above.
	 */
	result = handle_signal(SIGHUP, SIG_DFL);
	if (result != ISC_R_SUCCESS)
		return (result);

#ifdef HAVE_SIGWAIT
	result = handle_signal(SIGTERM, SIG_DFL);
	if (result != ISC_R_SUCCESS)
		return (result);
	result = handle_signal(SIGINT, SIG_DFL);
	if (result != ISC_R_SUCCESS)
		return (result);
#endif

#ifdef ISC_PLATFORM_USETHREADS
	/*
	 * Block SIGHUP, SIGINT, SIGTERM.
	 *
	 * If isc_app_start() is called from the main thread before any other
	 * threads have been created, then the pthread_sigmask() call below
	 * will result in all threads having SIGHUP, SIGINT and SIGTERM
	 * blocked by default, ensuring that only the thread that calls
	 * sigwait() for them will get those signals.
	 */
	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_start() sigsetops: %s", strbuf);
		return (ISC_R_UNEXPECTED);
	}
	presult = pthread_sigmask(SIG_BLOCK, &sset, NULL);
	if (presult != 0) {
		isc__strerror(presult, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_app_start() pthread_sigmask: %s",
				 strbuf);
		return (ISC_R_UNEXPECTED);
	}
#else /* ISC_PLATFORM_USETHREADS */
	/*
	 * Unblock SIGHUP, SIGINT, SIGTERM.
	 *
	 * If we're not using threads, we need to make sure that SIGHUP,
	 * SIGINT and SIGTERM are not inherited as blocked from the parent
	 * process.
	 */
	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_start() sigsetops: %s", strbuf);
		return (ISC_R_UNEXPECTED);
	}
	presult = sigprocmask(SIG_UNBLOCK, &sset, NULL);
	if (presult != 0) {
		isc__strerror(presult, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_app_start() sigprocmask: %s", strbuf);
		return (ISC_R_UNEXPECTED);
	}
#endif /* ISC_PLATFORM_USETHREADS */

	ISC_LIST_INIT(on_run);

	return (ISC_R_SUCCESS);
}
Esempio n. 15
0
void
isc_ondestroy_init(isc_ondestroy_t *ondest) {
	ondest->magic = ONDESTROY_MAGIC;
	ISC_LIST_INIT(ondest->events);
}
Esempio n. 16
0
int
main(int argc, char **argv) {
	char *qname;
	ns_msg msg;
	int len, rc = 0;
	unsigned char answer[NS_MAXMSG];
	unsigned rcode;
	struct srv *se;

	if (argc < 3)
		usage();

	ISC_LIST_INIT(prio_list);

	srandom(time(NULL));

	res_init();

	qname = argv[1];

	len = res_query(qname, ns_c_in, ns_t_srv, answer, sizeof answer);
	if (len < 0) {
		herror("res_query");
		return (EXIT_FAILURE);
	}

	if (ns_initparse(answer, len, &msg) < 0) {
		perror("ns_initparse");
		return (EXIT_FAILURE);
	}

	rcode = ns_msg_getflag(msg, ns_f_rcode);
	if (rcode != ns_r_noerror) {
		fprintf(stderr, "wrapsrv: query for %s returned rcode %u\n",
			qname, rcode);
		return (EXIT_FAILURE);
	}

	if (ns_msg_count(msg, ns_s_an) == 0) {
		fprintf(stderr, "wrapsrv: query for %s returned no answers\n",
			qname);
		return (EXIT_FAILURE);
	}

	parse_answer_section(&msg);
#ifdef DEBUG
	print_tuples();
	fprintf(stderr, "\n");
#endif

	while ((se = next_tuple()) != NULL) {
		if ((rc = do_cmd(se, argc, argv)) == 0)
			break;
#ifdef DEBUG
		fprintf(stderr, "\n");
#endif
	}

	free_tuples();

	return (rc);
}
Esempio n. 17
0
isc_boolean_t
key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
	      isc_mem_t *mctx, isc_boolean_t *exact)
{
	isc_result_t result;
	isc_boolean_t conflict = ISC_FALSE;
	dns_dnsseckeylist_t matchkeys;
	dns_dnsseckey_t *key = NULL;
	isc_uint16_t id, oldid;
	isc_uint32_t rid, roldid;
	dns_secalg_t alg;

	if (exact != NULL)
		*exact = ISC_FALSE;

	id = dst_key_id(dstkey);
	rid = dst_key_rid(dstkey);
	alg = dst_key_alg(dstkey);

	ISC_LIST_INIT(matchkeys);
	result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys);
	if (result == ISC_R_NOTFOUND)
		return (ISC_FALSE);

	while (!ISC_LIST_EMPTY(matchkeys) && !conflict) {
		key = ISC_LIST_HEAD(matchkeys);
		if (dst_key_alg(key->key) != alg)
			goto next;

		oldid = dst_key_id(key->key);
		roldid = dst_key_rid(key->key);

		if (oldid == rid || roldid == id || id == oldid) {
			conflict = ISC_TRUE;
			if (id != oldid) {
				if (verbose > 1)
					fprintf(stderr, "Key ID %d could "
						"collide with %d\n",
						id, oldid);
			} else {
				if (exact != NULL)
					*exact = ISC_TRUE;
				if (verbose > 1)
					fprintf(stderr, "Key ID %d exists\n",
						id);
			}
		}

 next:
		ISC_LIST_UNLINK(matchkeys, key, link);
		dns_dnsseckey_destroy(mctx, &key);
	}

	/* Finish freeing the list */
	while (!ISC_LIST_EMPTY(matchkeys)) {
		key = ISC_LIST_HEAD(matchkeys);
		ISC_LIST_UNLINK(matchkeys, key, link);
		dns_dnsseckey_destroy(mctx, &key);
	}

	return (conflict);
}
Esempio n. 18
0
static void
update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete,
		   dns_name_t *name)
{
	isc_result_t result;
	isc_uint32_t ttl;
	char *word;
	dns_rdataclass_t rdataclass;
	dns_rdatatype_t rdatatype;
	dns_rdata_t *rdata = NULL;
	dns_rdatalist_t *rdatalist = NULL;
	dns_rdataset_t *rdataset = NULL;
	isc_textregion_t region;

	/*
	 * Read the owner name.
	 */
	parse_name(&cmdline, name);

	rdata = isc_mem_get(mctx, sizeof(*rdata));
	if (rdata == NULL) {
		fprintf(stderr, "memory allocation for rdata failed\n");
		exit(1);
	}
	dns_rdata_init(rdata);

	/*
	 * If this is an add, read the TTL and verify that it's in range.
	 * If it's a delete, ignore a TTL if present (for compatibility).
	 */
	word = nsu_strsep(&cmdline, " \t\r\n");
	if (word == NULL || *word == 0) {
		if (!isdelete) {
			fprintf(stderr, "could not read owner ttl\n");
			exit(1);
		}
		else {
			ttl = 0;
			rdataclass = dns_rdataclass_any;
			rdatatype = dns_rdatatype_any;
			rdata->flags = DNS_RDATA_UPDATE;
			goto doneparsing;
		}
	}
	result = isc_parse_uint32(&ttl, word, 10);
	if (result != ISC_R_SUCCESS) {
		if (isdelete) {
			ttl = 0;
			goto parseclass;
		} else {
			fprintf(stderr, "ttl '%s': %s\n", word,
				isc_result_totext(result));
			exit(1);
		}
	}

	if (isdelete)
		ttl = 0;
	else if (ttl > TTL_MAX) {
		fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
			word, TTL_MAX);
		exit(1);
	}

	/*
	 * Read the class or type.
	 */
	word = nsu_strsep(&cmdline, " \t\r\n");
 parseclass:
	if (word == NULL || *word == 0) {
		if (isdelete) {
			rdataclass = dns_rdataclass_any;
			rdatatype = dns_rdatatype_any;
			rdata->flags = DNS_RDATA_UPDATE;
		goto doneparsing;
		} else {
			fprintf(stderr, "could not read class or type\n");
			exit(1);
		}
	}
	region.base = word;
	region.length = strlen(word);
	result = dns_rdataclass_fromtext(&rdataclass, &region);
	if (result == ISC_R_SUCCESS) {
		/*
		 * Now read the type.
		 */
		word = nsu_strsep(&cmdline, " \t\r\n");
		if (word == NULL || *word == 0) {
			if (isdelete) {
				rdataclass = dns_rdataclass_any;
				rdatatype = dns_rdatatype_any;
				rdata->flags = DNS_RDATA_UPDATE;
				goto doneparsing;
			} else {
				fprintf(stderr, "could not read type\n");
				exit(1);
			}
		}
		region.base = word;
		region.length = strlen(word);
		result = dns_rdatatype_fromtext(&rdatatype, &region);
		if (result != ISC_R_SUCCESS) {
			fprintf(stderr, "'%s' is not a valid type: %s\n",
				word, isc_result_totext(result));
			exit(1);
		}
	} else {
		rdataclass = default_rdataclass;
		result = dns_rdatatype_fromtext(&rdatatype, &region);
		if (result != ISC_R_SUCCESS) {
			fprintf(stderr, "'%s' is not a valid class or type: "
				"%s\n", word, isc_result_totext(result));
			exit(1);
		}
	}

	parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);

	if (isdelete) {
		if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
			rdataclass = dns_rdataclass_any;
		else
			rdataclass = dns_rdataclass_none;
	} else {
		if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
			fprintf(stderr, "could not read rdata\n");
			exit(1);
		}
	}

 doneparsing:

	rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
	if (rdatalist == NULL) {
		fprintf(stderr, "memory allocation for rdatalist failed\n");
		exit(1);
	}
	dns_rdatalist_init(rdatalist);
	rdatalist->type = rdatatype;
	rdatalist->rdclass = rdataclass;
	rdatalist->covers = rdatatype;
	rdatalist->ttl = (dns_ttl_t)ttl;
	ISC_LIST_INIT(rdatalist->rdata);
	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
	ISC_LIST_APPEND(usedrdatalists, rdatalist, link);

	rdataset = isc_mem_get(mctx, sizeof(*rdataset));
	if (rdataset == NULL) {
		fprintf(stderr, "memory allocation for rdataset failed\n");
		exit(1);
	}
	dns_rdataset_init(rdataset);
	dns_rdatalist_tordataset(rdatalist, rdataset);
	ISC_LIST_INIT(name->list);
	ISC_LIST_APPEND(name->list, rdataset, link);
}
Esempio n. 19
0
File: tkey.c Progetto: jhbsz/netbsd
isc_result_t
dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
		      dns_tsig_keyring_t *ring)
{
	isc_result_t result = ISC_R_SUCCESS;
	dns_rdata_tkey_t tkeyin, tkeyout;
	isc_boolean_t freetkeyin = ISC_FALSE;
	dns_name_t *qname, *name, *keyname, *signer, tsigner;
	dns_fixedname_t fkeyname;
	dns_rdataset_t *tkeyset;
	dns_rdata_t rdata;
	dns_namelist_t namelist;
	char tkeyoutdata[512];
	isc_buffer_t tkeyoutbuf;

	REQUIRE(msg != NULL);
	REQUIRE(tctx != NULL);
	REQUIRE(ring != NULL);

	ISC_LIST_INIT(namelist);

	/*
	 * Interpret the question section.
	 */
	result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
	if (result != ISC_R_SUCCESS)
		return (DNS_R_FORMERR);

	qname = NULL;
	dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname);

	/*
	 * Look for a TKEY record that matches the question.
	 */
	tkeyset = NULL;
	name = NULL;
	result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname,
				      dns_rdatatype_tkey, 0, &name, &tkeyset);
	if (result != ISC_R_SUCCESS) {
		/*
		 * Try the answer section, since that's where Win2000
		 * puts it.
		 */
		if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
					 dns_rdatatype_tkey, 0, &name,
					 &tkeyset) != ISC_R_SUCCESS) {
			result = DNS_R_FORMERR;
			tkey_log("dns_tkey_processquery: couldn't find a TKEY "
				 "matching the question");
			goto failure;
		}
	}
	result = dns_rdataset_first(tkeyset);
	if (result != ISC_R_SUCCESS) {
		result = DNS_R_FORMERR;
		goto failure;
	}
	dns_rdata_init(&rdata);
	dns_rdataset_current(tkeyset, &rdata);

	RETERR(dns_rdata_tostruct(&rdata, &tkeyin, NULL));
	freetkeyin = ISC_TRUE;

	if (tkeyin.error != dns_rcode_noerror) {
		result = DNS_R_FORMERR;
		goto failure;
	}

	/*
	 * Before we go any farther, verify that the message was signed.
	 * GSSAPI TKEY doesn't require a signature, the rest do.
	 */
	dns_name_init(&tsigner, NULL);
	result = dns_message_signer(msg, &tsigner);
	if (result != ISC_R_SUCCESS) {
		if (tkeyin.mode == DNS_TKEYMODE_GSSAPI &&
		    result == ISC_R_NOTFOUND)
		       signer = NULL;
		else {
			tkey_log("dns_tkey_processquery: query was not "
				 "properly signed - rejecting");
			result = DNS_R_FORMERR;
			goto failure;
		}
	} else
		signer = &tsigner;

	tkeyout.common.rdclass = tkeyin.common.rdclass;
	tkeyout.common.rdtype = tkeyin.common.rdtype;
	ISC_LINK_INIT(&tkeyout.common, link);
	tkeyout.mctx = msg->mctx;

	dns_name_init(&tkeyout.algorithm, NULL);
	dns_name_clone(&tkeyin.algorithm, &tkeyout.algorithm);

	tkeyout.inception = tkeyout.expire = 0;
	tkeyout.mode = tkeyin.mode;
	tkeyout.error = 0;
	tkeyout.keylen = tkeyout.otherlen = 0;
	tkeyout.key = tkeyout.other = NULL;

	/*
	 * A delete operation must have a fully specified key name.  If this
	 * is not a delete, we do the following:
	 * if (qname != ".")
	 *	keyname = qname + defaultdomain
	 * else
	 *	keyname = <random hex> + defaultdomain
	 */
	if (tkeyin.mode != DNS_TKEYMODE_DELETE) {
		dns_tsigkey_t *tsigkey = NULL;

		if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) {
			tkey_log("dns_tkey_processquery: tkey-domain not set");
			result = DNS_R_REFUSED;
			goto failure;
		}

		dns_fixedname_init(&fkeyname);
		keyname = dns_fixedname_name(&fkeyname);

		if (!dns_name_equal(qname, dns_rootname)) {
			unsigned int n = dns_name_countlabels(qname);
			RUNTIME_CHECK(dns_name_copy(qname, keyname, NULL)
				      == ISC_R_SUCCESS);
			dns_name_getlabelsequence(keyname, 0, n - 1, keyname);
		} else {
			static char hexdigits[16] = {
				'0', '1', '2', '3', '4', '5', '6', '7',
				'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
			unsigned char randomdata[16];
			char randomtext[32];
			isc_buffer_t b;
			unsigned int i, j;

			result = isc_entropy_getdata(tctx->ectx,
						     randomdata,
						     sizeof(randomdata),
						     NULL, 0);
			if (result != ISC_R_SUCCESS)
				goto failure;

			for (i = 0, j = 0; i < sizeof(randomdata); i++) {
				unsigned char val = randomdata[i];
				randomtext[j++] = hexdigits[val >> 4];
				randomtext[j++] = hexdigits[val & 0xF];
			}
			isc_buffer_init(&b, randomtext, sizeof(randomtext));
			isc_buffer_add(&b, sizeof(randomtext));
			result = dns_name_fromtext(keyname, &b, NULL, 0, NULL);
			if (result != ISC_R_SUCCESS)
				goto failure;
		}

		if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) {
			/* Yup.  This is a hack */
			result = dns_name_concatenate(keyname, dns_rootname,
						      keyname, NULL);
			if (result != ISC_R_SUCCESS)
				goto failure;
		} else {
			result = dns_name_concatenate(keyname, tctx->domain,
						      keyname, NULL);
			if (result != ISC_R_SUCCESS)
				goto failure;
		}

		result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);

		if (result == ISC_R_SUCCESS) {
			tkeyout.error = dns_tsigerror_badname;
			dns_tsigkey_detach(&tsigkey);
			goto failure_with_tkey;
		} else if (result != ISC_R_NOTFOUND)
			goto failure;
	} else
Esempio n. 20
0
static void
make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive,
	    isc_boolean_t isrrset, dns_name_t *name)
{
	isc_result_t result;
	char *word;
	isc_textregion_t region;
	dns_rdataset_t *rdataset = NULL;
	dns_rdatalist_t *rdatalist = NULL;
	dns_rdataclass_t rdataclass;
	dns_rdatatype_t rdatatype;
	dns_rdata_t *rdata = NULL;

	/*
	 * Read the owner name
	 */
	parse_name(&cmdline, name);

	/*
	 * If this is an rrset prereq, read the class or type.
	 */
	if (isrrset) {
		word = nsu_strsep(&cmdline, " \t\r\n");
		if (word == NULL || *word == 0) {
			fprintf(stderr, "could not read class or type\n");
			exit(1);
		}
		region.base = word;
		region.length = strlen(word);
		result = dns_rdataclass_fromtext(&rdataclass, &region);
		if (result == ISC_R_SUCCESS) {
			/*
			 * Now read the type.
			 */
			word = nsu_strsep(&cmdline, " \t\r\n");
			if (word == NULL || *word == 0) {
				fprintf(stderr, "could not read type\n");
				exit(1);
			}
			region.base = word;
			region.length = strlen(word);
			result = dns_rdatatype_fromtext(&rdatatype, &region);
			if (result != ISC_R_SUCCESS) {
				fprintf(stderr, "invalid type: %s\n", word);
				exit(1);
			}
		} else {
			rdataclass = default_rdataclass;
			result = dns_rdatatype_fromtext(&rdatatype, &region);
			if (result != ISC_R_SUCCESS) {
				fprintf(stderr, "invalid type: %s\n", word);
				exit(1);
			}
		}
	} else
		rdatatype = dns_rdatatype_any;

	rdata = isc_mem_get(mctx, sizeof(*rdata));
	if (rdata == NULL) {
		fprintf(stderr, "memory allocation for rdata failed\n");
		exit(1);
	}
	dns_rdata_init(rdata);

	if (isrrset && ispositive)
		parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);
	else
		rdata->flags = DNS_RDATA_UPDATE;

	rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
	if (rdatalist == NULL) {
		fprintf(stderr, "memory allocation for rdatalist failed\n");
		exit(1);
	}
	dns_rdatalist_init(rdatalist);
	rdatalist->type = rdatatype;
	if (ispositive) {
		if (isrrset && rdata->data != NULL)
			rdatalist->rdclass = rdataclass;
		else
			rdatalist->rdclass = dns_rdataclass_any;
	} else
		rdatalist->rdclass = dns_rdataclass_none;
	rdatalist->covers = 0;
	rdatalist->ttl = 0;
	rdata->rdclass = rdatalist->rdclass;
	rdata->type = rdatatype;
	ISC_LIST_INIT(rdatalist->rdata);
	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
	ISC_LIST_APPEND(usedrdatalists, rdatalist, link);

	rdataset = isc_mem_get(mctx, sizeof(*rdataset));
	if (rdataset == NULL) {
		fprintf(stderr, "memory allocation for rdataset failed\n");
		exit(1);
	}
	dns_rdataset_init(rdataset);
	dns_rdatalist_tordataset(rdatalist, rdataset);
	ISC_LIST_INIT(name->list);
	ISC_LIST_APPEND(name->list, rdataset, link);
}
Esempio n. 21
0
isc_result_t
dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
	dns_rdata_sig_t sig;	/* SIG(0) */
	unsigned char data[512];
	unsigned char header[DNS_MESSAGE_HEADERLEN];
	isc_buffer_t headerbuf, databuf, sigbuf;
	unsigned int sigsize;
	isc_buffer_t *dynbuf = NULL;
	dns_rdata_t *rdata;
	dns_rdatalist_t *datalist;
	dns_rdataset_t *dataset;
	isc_region_t r;
	isc_stdtime_t now;
	dst_context_t *ctx = NULL;
	isc_mem_t *mctx;
	isc_result_t result;
	isc_boolean_t signeedsfree = ISC_TRUE;

	REQUIRE(msg != NULL);
	REQUIRE(key != NULL);

	if (is_response(msg))
		REQUIRE(msg->query.base != NULL);

	mctx = msg->mctx;

	memset(&sig, 0, sizeof(sig));

	sig.mctx = mctx;
	sig.common.rdclass = dns_rdataclass_any;
	sig.common.rdtype = dns_rdatatype_sig;	/* SIG(0) */
	ISC_LINK_INIT(&sig.common, link);

	sig.covered = 0;
	sig.algorithm = dst_key_alg(key);
	sig.labels = 0; /* the root name */
	sig.originalttl = 0;

	isc_stdtime_get(&now);
	sig.timesigned = now - DNS_TSIG_FUDGE;
	sig.timeexpire = now + DNS_TSIG_FUDGE;

	sig.keyid = dst_key_id(key);

	dns_name_init(&sig.signer, NULL);
	dns_name_clone(dst_key_name(key), &sig.signer);

	sig.siglen = 0;
	sig.signature = NULL;

	isc_buffer_init(&databuf, data, sizeof(data));

	RETERR(dst_context_create(key, mctx, &ctx));

	/*
	 * Digest the fields of the SIG - we can cheat and use
	 * dns_rdata_fromstruct.  Since siglen is 0, the digested data
	 * is identical to dns format.
	 */
	RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any,
				    dns_rdatatype_sig /* SIG(0) */,
				    &sig, &databuf));
	isc_buffer_usedregion(&databuf, &r);
	RETERR(dst_context_adddata(ctx, &r));

	/*
	 * If this is a response, digest the query.
	 */
	if (is_response(msg))
		RETERR(dst_context_adddata(ctx, &msg->query));

	/*
	 * Digest the header.
	 */
	isc_buffer_init(&headerbuf, header, sizeof(header));
	dns_message_renderheader(msg, &headerbuf);
	isc_buffer_usedregion(&headerbuf, &r);
	RETERR(dst_context_adddata(ctx, &r));

	/*
	 * Digest the remainder of the message.
	 */
	isc_buffer_usedregion(msg->buffer, &r);
	isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
	RETERR(dst_context_adddata(ctx, &r));

	RETERR(dst_key_sigsize(key, &sigsize));
	sig.siglen = sigsize;
	sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen);
	if (sig.signature == NULL) {
		result = ISC_R_NOMEMORY;
		goto failure;
	}

	isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
	RETERR(dst_context_sign(ctx, &sigbuf));
	dst_context_destroy(&ctx);

	rdata = NULL;
	RETERR(dns_message_gettemprdata(msg, &rdata));
	RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
	RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
				    dns_rdatatype_sig /* SIG(0) */,
				    &sig, dynbuf));

	isc_mem_put(mctx, sig.signature, sig.siglen);
	signeedsfree = ISC_FALSE;

	dns_message_takebuffer(msg, &dynbuf);

	datalist = NULL;
	RETERR(dns_message_gettemprdatalist(msg, &datalist));
	datalist->rdclass = dns_rdataclass_any;
	datalist->type = dns_rdatatype_sig;	/* SIG(0) */
	datalist->covers = 0;
	datalist->ttl = 0;
	ISC_LIST_INIT(datalist->rdata);
	ISC_LIST_APPEND(datalist->rdata, rdata, link);
	dataset = NULL;
	RETERR(dns_message_gettemprdataset(msg, &dataset));
	dns_rdataset_init(dataset);
	RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS);
	msg->sig0 = dataset;

	return (ISC_R_SUCCESS);

failure:
	if (dynbuf != NULL)
		isc_buffer_free(&dynbuf);
	if (signeedsfree)
		isc_mem_put(mctx, sig.signature, sig.siglen);
	if (ctx != NULL)
		dst_context_destroy(&ctx);

	return (result);
}
Esempio n. 22
0
int
main(int argc, char *argv[]) {
	int ch;
	struct addrinfo hints, *res;
	int gai_error;
	dns_client_t *client = NULL;
	char *zonenamestr = NULL;
	char *keyfilename = NULL;
	char *prereqstr = NULL;
	isc_sockaddrlist_t auth_servers;
	char *auth_server = NULL;
	char *recursive_server = NULL;
	isc_sockaddr_t sa_auth, sa_recursive;
	isc_sockaddrlist_t rec_servers;
	isc_result_t result;
	isc_boolean_t isdelete;
	isc_buffer_t b, *buf;
	dns_fixedname_t zname0, pname0, uname0;
	size_t namelen;
	dns_name_t *zname = NULL, *uname, *pname;
	dns_rdataset_t *rdataset;
	dns_rdatalist_t *rdatalist;
	dns_rdata_t *rdata;
	dns_namelist_t updatelist, prereqlist, *prereqlistp = NULL;
	isc_mem_t *umctx = NULL;

	while ((ch = getopt(argc, argv, "a:k:p:r:z:")) != -1) {
		switch (ch) {
		case 'k':
			keyfilename = optarg;
			break;
		case 'a':
			auth_server = optarg;
			break;
		case 'p':
			prereqstr = optarg;
			break;
		case 'r':
			recursive_server = optarg;
			break;
		case 'z':
			zonenamestr = optarg;
			break;
		default:
			usage();
		}
	}

	argc -= optind;
	argv += optind;
	if (argc < 2)
		usage();

	/* command line argument validation */
	if (strcmp(argv[0], "delete") == 0)
		isdelete = ISC_TRUE;
	else if (strcmp(argv[0], "add") == 0)
		isdelete = ISC_FALSE;
	else {
		fprintf(stderr, "invalid update command: %s\n", argv[0]);
		exit(1);
	}

	if (auth_server == NULL && recursive_server == NULL) {
		fprintf(stderr, "authoritative or recursive server "
			"must be specified\n");
		usage();
	}

	/* Initialization */
	ISC_LIST_INIT(usedbuffers);
	ISC_LIST_INIT(usedrdatalists);
	ISC_LIST_INIT(prereqlist);
	ISC_LIST_INIT(auth_servers);
	isc_lib_register();
	result = dns_lib_init();
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr, "dns_lib_init failed: %d\n", result);
		exit(1);
	}
	result = isc_mem_create(0, 0, &umctx);
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr, "failed to crate mctx\n");
		exit(1);
	}

	result = dns_client_create(&client, 0);
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr, "dns_client_create failed: %d\n", result);
		exit(1);
	}

	/* Set the authoritative server */
	if (auth_server != NULL) {
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_protocol = IPPROTO_UDP;
		hints.ai_flags = AI_NUMERICHOST;
		gai_error = getaddrinfo(auth_server, "53", &hints, &res);
		if (gai_error != 0) {
			fprintf(stderr, "getaddrinfo failed: %s\n",
				gai_strerror(gai_error));
			exit(1);
		}
		INSIST(res->ai_addrlen <= sizeof(sa_auth.type));
		memcpy(&sa_auth.type, res->ai_addr, res->ai_addrlen);
		freeaddrinfo(res);
		sa_auth.length = res->ai_addrlen;
		ISC_LINK_INIT(&sa_auth, link);

		ISC_LIST_APPEND(auth_servers, &sa_auth, link);
	}

	/* Set the recursive server */
	if (recursive_server != NULL) {
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_protocol = IPPROTO_UDP;
		hints.ai_flags = AI_NUMERICHOST;
		gai_error = getaddrinfo(recursive_server, "53", &hints, &res);
		if (gai_error != 0) {
			fprintf(stderr, "getaddrinfo failed: %s\n",
				gai_strerror(gai_error));
			exit(1);
		}
		INSIST(res->ai_addrlen <= sizeof(sa_recursive.type));
		memcpy(&sa_recursive.type, res->ai_addr, res->ai_addrlen);
		freeaddrinfo(res);
		sa_recursive.length = res->ai_addrlen;
		ISC_LINK_INIT(&sa_recursive, link);
		ISC_LIST_INIT(rec_servers);
		ISC_LIST_APPEND(rec_servers, &sa_recursive, link);
		result = dns_client_setservers(client, dns_rdataclass_in,
					       NULL, &rec_servers);
		if (result != ISC_R_SUCCESS) {
			fprintf(stderr, "set server failed: %d\n", result);
			exit(1);
		}
	}

	/* Construct zone name */
	zname = NULL;
	if (zonenamestr != NULL) {
		namelen = strlen(zonenamestr);
		isc_buffer_init(&b, zonenamestr, namelen);
		isc_buffer_add(&b, namelen);
		dns_fixedname_init(&zname0);
		zname = dns_fixedname_name(&zname0);
		result = dns_name_fromtext(zname, &b, dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS)
			fprintf(stderr, "failed to convert zone name: %d\n",
				result);
	}

	/* Construct prerequisite name (if given) */
	if (prereqstr != NULL) {
		dns_fixedname_init(&pname0);
		pname = dns_fixedname_name(&pname0);
		evaluate_prereq(umctx, prereqstr, pname);
		ISC_LIST_APPEND(prereqlist, pname, link);
		prereqlistp = &prereqlist;
	}

	/* Construct update name */
	ISC_LIST_INIT(updatelist);
	dns_fixedname_init(&uname0);
	uname = dns_fixedname_name(&uname0);
	update_addordelete(umctx, argv[1], isdelete, uname);
	ISC_LIST_APPEND(updatelist, uname, link);

	/* Set up TSIG/SIG(0) key (if given) */
	if (keyfilename != NULL)
		setup_tsec(keyfilename, umctx);

	/* Perform update */
	result = dns_client_update(client,
				   default_rdataclass, /* XXX: fixed */
				   zname, prereqlistp, &updatelist,
				   (auth_server == NULL) ? NULL :
				   &auth_servers, tsec, 0);
	if (result != ISC_R_SUCCESS) {
		fprintf(stderr,
			"update failed: %s\n", dns_result_totext(result));
	} else
		fprintf(stderr, "update succeeded\n");

	/* Cleanup */
	while ((pname = ISC_LIST_HEAD(prereqlist)) != NULL) {
		while ((rdataset = ISC_LIST_HEAD(pname->list)) != NULL) {
			ISC_LIST_UNLINK(pname->list, rdataset, link);
			dns_rdataset_disassociate(rdataset);
			isc_mem_put(umctx, rdataset, sizeof(*rdataset));
		}
		ISC_LIST_UNLINK(prereqlist, pname, link);
	}
	while ((uname = ISC_LIST_HEAD(updatelist)) != NULL) {
		while ((rdataset = ISC_LIST_HEAD(uname->list)) != NULL) {
			ISC_LIST_UNLINK(uname->list, rdataset, link);
			dns_rdataset_disassociate(rdataset);
			isc_mem_put(umctx, rdataset, sizeof(*rdataset));
		}
		ISC_LIST_UNLINK(updatelist, uname, link);
	}
	while ((rdatalist = ISC_LIST_HEAD(usedrdatalists)) != NULL) {
		while ((rdata = ISC_LIST_HEAD(rdatalist->rdata)) != NULL) {
			ISC_LIST_UNLINK(rdatalist->rdata, rdata, link);
			isc_mem_put(umctx, rdata, sizeof(*rdata));
		}
		ISC_LIST_UNLINK(usedrdatalists, rdatalist, link);
		isc_mem_put(umctx, rdatalist, sizeof(*rdatalist));
	}
	while ((buf = ISC_LIST_HEAD(usedbuffers)) != NULL) {
		ISC_LIST_UNLINK(usedbuffers, buf, link);
		isc_buffer_free(&buf);
	}
	if (tsec != NULL)
		dns_tsec_destroy(&tsec);
	isc_mem_destroy(&umctx);
	dns_client_destroy(&client);
	dns_lib_shutdown();

	exit(0);
}
Esempio n. 23
0
/***
 *** Task Manager.
 ***/
static void
dispatch(isc_taskmgr_t *manager) {
	isc_task_t *task;
#ifndef ISC_PLATFORM_USETHREADS
	unsigned int total_dispatch_count = 0;
	isc_tasklist_t ready_tasks;
#endif /* ISC_PLATFORM_USETHREADS */

	REQUIRE(VALID_MANAGER(manager));

	/*
	 * Again we're trying to hold the lock for as short a time as possible
	 * and to do as little locking and unlocking as possible.
	 *
	 * In both while loops, the appropriate lock must be held before the
	 * while body starts.  Code which acquired the lock at the top of
	 * the loop would be more readable, but would result in a lot of
	 * extra locking.  Compare:
	 *
	 * Straightforward:
	 *
	 *	LOCK();
	 *	...
	 *	UNLOCK();
	 *	while (expression) {
	 *		LOCK();
	 *		...
	 *		UNLOCK();
	 *
	 *	       	Unlocked part here...
	 *
	 *		LOCK();
	 *		...
	 *		UNLOCK();
	 *	}
	 *
	 * Note how if the loop continues we unlock and then immediately lock.
	 * For N iterations of the loop, this code does 2N+1 locks and 2N+1
	 * unlocks.  Also note that the lock is not held when the while
	 * condition is tested, which may or may not be important, depending
	 * on the expression.
	 *
	 * As written:
	 *
	 *	LOCK();
	 *	while (expression) {
	 *		...
	 *		UNLOCK();
	 *
	 *	       	Unlocked part here...
	 *
	 *		LOCK();
	 *		...
	 *	}
	 *	UNLOCK();
	 *
	 * For N iterations of the loop, this code does N+1 locks and N+1
	 * unlocks.  The while expression is always protected by the lock.
	 */

#ifndef ISC_PLATFORM_USETHREADS
	ISC_LIST_INIT(ready_tasks);
#endif
	LOCK(&manager->lock);
	while (!FINISHED(manager)) {
#ifdef ISC_PLATFORM_USETHREADS
		/*
		 * For reasons similar to those given in the comment in
		 * isc_task_send() above, it is safe for us to dequeue
		 * the task while only holding the manager lock, and then
		 * change the task to running state while only holding the
		 * task lock.
		 */
		while ((EMPTY(manager->ready_tasks) ||
		        manager->exclusive_requested) &&
		  	!FINISHED(manager)) 
	  	{
			XTHREADTRACE(isc_msgcat_get(isc_msgcat,
						    ISC_MSGSET_GENERAL,
						    ISC_MSG_WAIT, "wait"));
			WAIT(&manager->work_available, &manager->lock);
			XTHREADTRACE(isc_msgcat_get(isc_msgcat,
						    ISC_MSGSET_TASK,
						    ISC_MSG_AWAKE, "awake"));
		}
#else /* ISC_PLATFORM_USETHREADS */
		if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM ||
		    EMPTY(manager->ready_tasks))
			break;
#endif /* ISC_PLATFORM_USETHREADS */
		XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
					    ISC_MSG_WORKING, "working"));

		task = HEAD(manager->ready_tasks);
		if (task != NULL) {
			unsigned int dispatch_count = 0;
			isc_boolean_t done = ISC_FALSE;
			isc_boolean_t requeue = ISC_FALSE;
			isc_boolean_t finished = ISC_FALSE;
			isc_event_t *event;

			INSIST(VALID_TASK(task));

			/*
			 * Note we only unlock the manager lock if we actually
			 * have a task to do.  We must reacquire the manager
			 * lock before exiting the 'if (task != NULL)' block.
			 */
			DEQUEUE(manager->ready_tasks, task, ready_link);
			manager->tasks_running++;
			UNLOCK(&manager->lock);

			LOCK(&task->lock);
			INSIST(task->state == task_state_ready);
			task->state = task_state_running;
			XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
					      ISC_MSG_RUNNING, "running"));
			isc_stdtime_get(&task->now);
			do {
				if (!EMPTY(task->events)) {
					event = HEAD(task->events);
					DEQUEUE(task->events, event, ev_link);

					/*
					 * Execute the event action.
					 */
					XTRACE(isc_msgcat_get(isc_msgcat,
							    ISC_MSGSET_TASK,
							    ISC_MSG_EXECUTE,
							    "execute action"));
					if (event->ev_action != NULL) {
						UNLOCK(&task->lock);
						(event->ev_action)(task,event);
						LOCK(&task->lock);
					}
					dispatch_count++;
#ifndef ISC_PLATFORM_USETHREADS
					total_dispatch_count++;
#endif /* ISC_PLATFORM_USETHREADS */
				}

				if (task->references == 0 &&
				    EMPTY(task->events) &&
				    !TASK_SHUTTINGDOWN(task)) {
					isc_boolean_t was_idle;

					/*
					 * There are no references and no
					 * pending events for this task,
					 * which means it will not become
					 * runnable again via an external
					 * action (such as sending an event
					 * or detaching).
					 *
					 * We initiate shutdown to prevent
					 * it from becoming a zombie.
					 *
					 * We do this here instead of in
					 * the "if EMPTY(task->events)" block
					 * below because:
					 *
					 *	If we post no shutdown events,
					 *	we want the task to finish.
					 *
					 *	If we did post shutdown events,
					 *	will still want the task's
					 *	quantum to be applied.
					 */
					was_idle = task_shutdown(task);
					INSIST(!was_idle);
				}

				if (EMPTY(task->events)) {
					/*
					 * Nothing else to do for this task
					 * right now.
					 */
					XTRACE(isc_msgcat_get(isc_msgcat,
							      ISC_MSGSET_TASK,
							      ISC_MSG_EMPTY,
							      "empty"));
					if (task->references == 0 &&
					    TASK_SHUTTINGDOWN(task)) {
						/*
						 * The task is done.
						 */
						XTRACE(isc_msgcat_get(
							       isc_msgcat,
							       ISC_MSGSET_TASK,
							       ISC_MSG_DONE,
							       "done"));
						finished = ISC_TRUE;
						task->state = task_state_done;
					} else
						task->state = task_state_idle;
					done = ISC_TRUE;
				} else if (dispatch_count >= task->quantum) {
					/*
					 * Our quantum has expired, but
					 * there is more work to be done.
					 * We'll requeue it to the ready
					 * queue later.
					 *
					 * We don't check quantum until
					 * dispatching at least one event,
					 * so the minimum quantum is one.
					 */
					XTRACE(isc_msgcat_get(isc_msgcat,
							      ISC_MSGSET_TASK,
							      ISC_MSG_QUANTUM,
							      "quantum"));
					task->state = task_state_ready;
					requeue = ISC_TRUE;
					done = ISC_TRUE;
				}
			} while (!done);
			UNLOCK(&task->lock);

			if (finished)
				task_finished(task);

			LOCK(&manager->lock);
			manager->tasks_running--;
#ifdef ISC_PLATFORM_USETHREADS
			if (manager->exclusive_requested &&
			    manager->tasks_running == 1) {
				SIGNAL(&manager->exclusive_granted);
			}
#endif /* ISC_PLATFORM_USETHREADS */
			if (requeue) {
				/*
				 * We know we're awake, so we don't have
				 * to wakeup any sleeping threads if the
				 * ready queue is empty before we requeue.
				 *
				 * A possible optimization if the queue is
				 * empty is to 'goto' the 'if (task != NULL)'
				 * block, avoiding the ENQUEUE of the task
				 * and the subsequent immediate DEQUEUE
				 * (since it is the only executable task).
				 * We don't do this because then we'd be
				 * skipping the exit_requested check.  The
				 * cost of ENQUEUE is low anyway, especially
				 * when you consider that we'd have to do
				 * an extra EMPTY check to see if we could
				 * do the optimization.  If the ready queue
				 * were usually nonempty, the 'optimization'
				 * might even hurt rather than help.
				 */
#ifdef ISC_PLATFORM_USETHREADS
				ENQUEUE(manager->ready_tasks, task,
					ready_link);
#else
				ENQUEUE(ready_tasks, task, ready_link);
#endif
			}
		}
	}
#ifndef ISC_PLATFORM_USETHREADS
	ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link);
#endif
	UNLOCK(&manager->lock);
}
Esempio n. 24
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;
}
Esempio n. 25
0
int
main(int argc, char **argv) {
	isc_result_t result;
	isc_logdestination_t destination;

	UNUSED(argc);
	UNUSED(argv);

	dns_result_register();
	result = isc_app_start();
	check_result(result, "isc_app_start()");

	isc_stdtime_get(&now);

	result = isc_mutex_init(&client_lock);
	check_result(result, "isc_mutex_init(&client_lock)");
	ISC_LIST_INIT(clients);

	/*
	 * EVERYTHING needs a memory context.
	 */
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);

	cmp = NULL;
	RUNTIME_CHECK(isc_mempool_create(mctx, sizeof(client_t), &cmp)
		      == ISC_R_SUCCESS);
	isc_mempool_setname(cmp, "adb test clients");

	result = isc_entropy_create(mctx, &ectx);
	check_result(result, "isc_entropy_create()");
	result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
	check_result(result, "isc_hash_create()");

	result = isc_log_create(mctx, &lctx, &lcfg);
	check_result(result, "isc_log_create()");
	isc_log_setcontext(lctx);
	dns_log_init(lctx);
	dns_log_setcontext(lctx);

	/*
	 * Create and install the default channel.
	 */
	destination.file.stream = stderr;
	destination.file.name = NULL;
	destination.file.versions = ISC_LOG_ROLLNEVER;
	destination.file.maximum_size = 0;
	result = isc_log_createchannel(lcfg, "_default",
				       ISC_LOG_TOFILEDESC,
				       ISC_LOG_DYNAMIC,
				       &destination, ISC_LOG_PRINTTIME);
	check_result(result, "isc_log_createchannel()");
	result = isc_log_usechannel(lcfg, "_default", NULL, NULL);
	check_result(result, "isc_log_usechannel()");

	/*
	 * Set the initial debug level.
	 */
	isc_log_setdebuglevel(lctx, 2);

	create_managers();

	t1 = NULL;
	result = isc_task_create(taskmgr, 0, &t1);
	check_result(result, "isc_task_create t1");
	t2 = NULL;
	result = isc_task_create(taskmgr, 0, &t2);
	check_result(result, "isc_task_create t2");

	printf("task 1 = %p\n", t1);
	printf("task 2 = %p\n", t2);

	create_view();

	adb = view->adb;

	/*
	 * Lock the entire client list here.  This will cause all events
	 * for found names to block as well.
	 */
	CLOCK();
	lookup("f.root-servers.net.");		/* Should be in hints */
	lookup("www.iengines.com");		/* should fetch */
	lookup("www.isc.org");			/* should fetch */
	lookup("www.flame.org");		/* should fetch */
	lookup("kechara.flame.org.");		/* should fetch */
	lookup("moghedien.flame.org.");		/* should fetch */
	lookup("mailrelay.flame.org.");		/* should fetch */
	lookup("ipv4v6.flame.org.");		/* should fetch */
	lookup("nonexistant.flame.org.");	/* should fail to be found */
	lookup("foobar.badns.flame.org.");	/* should fail utterly (NS) */
	lookup("i.root-servers.net.");		/* Should be in hints */
	lookup("www.firstcard.com.");
	lookup("dns04.flame.org.");
	CUNLOCK();

	sleep(10);

	dns_adb_dump(adb, stderr);

	sleep(10);

	CLOCK();
	lookup("f.root-servers.net.");		/* Should be in hints */
	lookup("www.iengines.com");		/* should fetch */
	lookup("www.isc.org");			/* should fetch */
	lookup("www.flame.org");		/* should fetch */
	lookup("kechara.flame.org.");		/* should fetch */
	lookup("moghedien.flame.org.");		/* should fetch */
	lookup("mailrelay.flame.org.");		/* should fetch */
	lookup("ipv4v6.flame.org.");		/* should fetch */
	lookup("nonexistant.flame.org.");	/* should fail to be found */
	lookup("foobar.badns.flame.org.");	/* should fail utterly (NS) */
	lookup("i.root-servers.net.");		/* Should be in hints */
	CUNLOCK();

	sleep(20);

	dns_adb_dump(adb, stderr);

	isc_task_detach(&t1);
	isc_task_detach(&t2);

	isc_mem_stats(mctx, stdout);
	dns_adb_dump(adb, stderr);

	isc_app_run();

	dns_adb_dump(adb, stderr);

	dns_view_detach(&view);
	adb = NULL;

	fprintf(stderr, "Destroying socket manager\n");
	isc_socketmgr_destroy(&socketmgr);
	fprintf(stderr, "Destroying timer manager\n");
	isc_timermgr_destroy(&timermgr);

	fprintf(stderr, "Destroying task manager\n");
	isc_taskmgr_destroy(&taskmgr);

	isc_log_destroy(&lctx);

	isc_hash_destroy();
	isc_entropy_detach(&ectx);

	isc_mempool_destroy(&cmp);
	isc_mem_stats(mctx, stdout);
	isc_mem_destroy(&mctx);

	isc_app_finish();

	return (0);
}
int
main(int argc, char *argv[]) {
	int i, ch;
	char *startstr = NULL, *endstr = NULL;
	dns_fixedname_t fdomain;
	dns_name_t *domain = NULL;
	char *output = NULL;
	char *endp;
	unsigned char data[65536];
	dns_db_t *db;
	dns_dbversion_t *version;
	dns_diff_t diff;
	dns_difftuple_t *tuple;
	dns_fixedname_t tname;
	dst_key_t *key = NULL;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	dns_rdataset_t rdataset;
	dns_rdataclass_t rdclass;
	isc_result_t result;
	isc_buffer_t b;
	isc_region_t r;
	isc_log_t *log = NULL;
	keynode_t *keynode;
	unsigned int eflags;
	isc_boolean_t pseudorandom = ISC_FALSE;
	isc_boolean_t tryverify = ISC_FALSE;

	result = isc_mem_create(0, 0, &mctx);
	if (result != ISC_R_SUCCESS)
		fatal("failed to create memory context: %s",
		      isc_result_totext(result));

	dns_result_register();

	while ((ch = isc_commandline_parse(argc, argv, "as:e:t:r:v:ph")) != -1)
	{
		switch (ch) {
		case 'a':
			tryverify = ISC_TRUE;
			break;
		case 's':
			startstr = isc_commandline_argument;
			break;

		case 'e':
			endstr = isc_commandline_argument;
			break;

		case 't':
			endp = NULL;
			ttl = strtol(isc_commandline_argument, &endp, 0);
			if (*endp != '\0')
				fatal("TTL must be numeric");
			break;

		case 'r':
			setup_entropy(mctx, isc_commandline_argument, &ectx);
			break;

		case 'v':
			endp = NULL;
			verbose = strtol(isc_commandline_argument, &endp, 0);
			if (*endp != '\0')
				fatal("verbose level must be numeric");
			break;

		case 'p':
			pseudorandom = ISC_TRUE;
			break;

		case 'h':
		default:
			usage();

		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;

	if (argc < 1)
		usage();

	if (ectx == NULL)
		setup_entropy(mctx, NULL, &ectx);
	eflags = ISC_ENTROPY_BLOCKING;
	if (!pseudorandom)
		eflags |= ISC_ENTROPY_GOODONLY;
	result = dst_lib_init(mctx, ectx, eflags);
	if (result != ISC_R_SUCCESS)
		fatal("could not initialize dst: %s", 
		      isc_result_totext(result));

	isc_stdtime_get(&now);

	if (startstr != NULL)
		starttime = strtotime(startstr, now, now);
	else
		starttime = now;

	if (endstr != NULL)
		endtime = strtotime(endstr, now, starttime);
	else
		endtime = starttime + (30 * 24 * 60 * 60);

	if (ttl == -1) {
		ttl = 3600;
		fprintf(stderr, "%s: TTL not specified, assuming 3600\n",
			program);
	}

	setup_logging(verbose, mctx, &log);

	dns_diff_init(mctx, &diff);
	rdclass = 0;

	ISC_LIST_INIT(keylist);

	for (i = 0; i < argc; i++) {
		char namestr[DNS_NAME_FORMATSIZE];
		isc_buffer_t namebuf;

		key = NULL;
		result = dst_key_fromnamedfile(argv[i], DST_TYPE_PUBLIC,
					       mctx, &key);
		if (result != ISC_R_SUCCESS)
			fatal("error loading key from %s: %s", argv[i],
			      isc_result_totext(result));
		if (rdclass == 0)
			rdclass = dst_key_class(key);

		isc_buffer_init(&namebuf, namestr, sizeof(namestr));
		result = dns_name_tofilenametext(dst_key_name(key),
						 ISC_FALSE,
						 &namebuf);
		check_result(result, "dns_name_tofilenametext");
		isc_buffer_putuint8(&namebuf, 0);

		if (domain == NULL) {
			dns_fixedname_init(&fdomain);
			domain = dns_fixedname_name(&fdomain);
			dns_name_copy(dst_key_name(key), domain, NULL);
		} else if (!dns_name_equal(domain, dst_key_name(key))) {
			char str[DNS_NAME_FORMATSIZE];
			dns_name_format(domain, str, sizeof(str));
			fatal("all keys must have the same owner - %s "
			      "and %s do not match", str, namestr);
		}

		if (output == NULL) {
			output = isc_mem_allocate(mctx,
						  strlen("keyset-") +
						  strlen(namestr) + 1);
			if (output == NULL)
				fatal("out of memory");
			sprintf(output, "keyset-%s", namestr);
		}

		if (dst_key_iszonekey(key)) {
			dst_key_t *zonekey = NULL;
			result = dst_key_fromnamedfile(argv[i],
						       DST_TYPE_PUBLIC |
						       DST_TYPE_PRIVATE,
						       mctx, &zonekey);
			if (result != ISC_R_SUCCESS)
				fatal("failed to read private key %s: %s",
				      argv[i], isc_result_totext(result));
			if (!zonekey_on_list(zonekey)) {
				keynode = isc_mem_get(mctx, sizeof(keynode_t));
				if (keynode == NULL)
					fatal("out of memory");
				keynode->key = zonekey;
				ISC_LIST_INITANDAPPEND(keylist, keynode, link);
			} else
				dst_key_free(&zonekey);
		}
		dns_rdata_reset(&rdata);
		isc_buffer_init(&b, data, sizeof(data));
		result = dst_key_todns(key, &b);
		dst_key_free(&key);
		if (result != ISC_R_SUCCESS)
			fatal("failed to convert key %s to a DNS KEY: %s",
			      argv[i], isc_result_totext(result));
		isc_buffer_usedregion(&b, &r);
		dns_rdata_fromregion(&rdata, rdclass, dns_rdatatype_dnskey, &r);
		tuple = NULL;
		result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
					      domain, ttl, &rdata, &tuple);
		check_result(result, "dns_difftuple_create");
		dns_diff_append(&diff, &tuple);
	}

	db = NULL;
	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
			       rdclass, 0, NULL, &db);
	if (result != ISC_R_SUCCESS)
		fatal("failed to create a database");

	version = NULL;
	dns_db_newversion(db, &version);

	result = dns_diff_apply(&diff, db, version);
	check_result(result, "dns_diff_apply");
	dns_diff_clear(&diff);

	dns_fixedname_init(&tname);
	dns_rdataset_init(&rdataset);
	result = dns_db_find(db, domain, version, dns_rdatatype_dnskey, 0, 0,
			     NULL, dns_fixedname_name(&tname), &rdataset,
			     NULL);
	check_result(result, "dns_db_find");

	if (ISC_LIST_EMPTY(keylist))
		fprintf(stderr,
			"%s: no private zone key found; not self-signing\n",
			program);
	for (keynode = ISC_LIST_HEAD(keylist);
	     keynode != NULL;
	     keynode = ISC_LIST_NEXT(keynode, link))
	{
		dns_rdata_reset(&rdata);
		isc_buffer_init(&b, data, sizeof(data));
		result = dns_dnssec_sign(domain, &rdataset, keynode->key,
					 &starttime, &endtime, mctx, &b,
					 &rdata);
		isc_entropy_stopcallbacksources(ectx);
		if (result != ISC_R_SUCCESS) {
			char keystr[KEY_FORMATSIZE];
			key_format(keynode->key, keystr, sizeof(keystr));
			fatal("failed to sign keyset with key %s: %s",
			      keystr, isc_result_totext(result));
		}
		if (tryverify) {
			result = dns_dnssec_verify(domain, &rdataset,
						   keynode->key, ISC_TRUE,
						   mctx, &rdata);
			if (result != ISC_R_SUCCESS) {
				char keystr[KEY_FORMATSIZE];
				key_format(keynode->key, keystr, sizeof(keystr));
				fatal("signature from key '%s' failed to "
				      "verify: %s",
				      keystr, isc_result_totext(result));
			}
		}
		tuple = NULL;
		result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
					      domain, ttl, &rdata, &tuple);
		check_result(result, "dns_difftuple_create");
		dns_diff_append(&diff, &tuple);
	}

	result = dns_diff_apply(&diff, db, version);
	check_result(result, "dns_diff_apply");
	dns_diff_clear(&diff);

	dns_rdataset_disassociate(&rdataset);

	dns_db_closeversion(db, &version, ISC_TRUE);
	result = dns_db_dump(db, version, output);
	if (result != ISC_R_SUCCESS) {
		char domainstr[DNS_NAME_FORMATSIZE];
		dns_name_format(domain, domainstr, sizeof(domainstr));
		fatal("failed to write database for %s to %s",
		      domainstr, output);
	}

	printf("%s\n", output);

	dns_db_detach(&db);

	while (!ISC_LIST_EMPTY(keylist)) {
		keynode = ISC_LIST_HEAD(keylist);
		ISC_LIST_UNLINK(keylist, keynode, link);
		dst_key_free(&keynode->key);
		isc_mem_put(mctx, keynode, sizeof(keynode_t));
	}

	cleanup_logging(&log);
	cleanup_entropy(&ectx);

	isc_mem_free(mctx, output);
	dst_lib_destroy();
	if (verbose > 10)
		isc_mem_stats(mctx, stdout);
	isc_mem_destroy(&mctx);
	return (0);
}
Esempio n. 27
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,
					      "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);
}
Esempio n. 28
0
void
initialize() {
	ISC_LIST_INIT(errormsg_list);
	InitializeCriticalSection(&ErrorMsgLock);
	initialized = TRUE;
}
Esempio n. 29
0
isc_result_t
ns_controls_configure(ns_controls_t *cp, const cfg_obj_t *config,
		      cfg_aclconfctx_t *aclconfctx)
{
	controllistener_t *listener;
	controllistenerlist_t new_listeners;
	const cfg_obj_t *controlslist = NULL;
	const cfg_listelt_t *element, *element2;
	char socktext[ISC_SOCKADDR_FORMATSIZE];

	ISC_LIST_INIT(new_listeners);

	/*
	 * Get the list of named.conf 'controls' statements.
	 */
	(void)cfg_map_get(config, "controls", &controlslist);

	/*
	 * Run through the new control channel 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 (controlslist != NULL) {
		for (element = cfg_list_first(controlslist);
		     element != NULL;
		     element = cfg_list_next(element)) {
			const cfg_obj_t *controls;
			const cfg_obj_t *inetcontrols = NULL;

			controls = cfg_listelt_value(element);
			(void)cfg_map_get(controls, "inet", &inetcontrols);
			if (inetcontrols == NULL)
				continue;

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

				/*
				 * The parser handles BIND 8 configuration file
				 * syntax, so it allows unix phrases as well
				 * inet phrases with no keys{} clause.
				 */
				control = cfg_listelt_value(element2);

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

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

				isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_CONTROL,
					      ISC_LOG_DEBUG(9),
					      "processing control channel %s",
					      socktext);

				update_listener(cp, &listener, control, config,
						&addr, aclconfctx, socktext,
						isc_sockettype_tcp);

				if (listener != NULL)
					/*
					 * Remove the listener from the old
					 * list, so it won't be shut down.
					 */
					ISC_LIST_UNLINK(cp->listeners,
							listener, link);
				else
					/*
					 * This is a new listener.
					 */
					add_listener(cp, &listener, control,
						     config, &addr, aclconfctx,
						     socktext,
						     isc_sockettype_tcp);

				if (listener != NULL)
					ISC_LIST_APPEND(new_listeners,
							listener, link);
			}
		}
		for (element = cfg_list_first(controlslist);
		     element != NULL;
		     element = cfg_list_next(element)) {
			const cfg_obj_t *controls;
			const cfg_obj_t *unixcontrols = NULL;

			controls = cfg_listelt_value(element);
			(void)cfg_map_get(controls, "unix", &unixcontrols);
			if (unixcontrols == NULL)
				continue;

			for (element2 = cfg_list_first(unixcontrols);
			     element2 != NULL;
			     element2 = cfg_list_next(element2)) {
				const cfg_obj_t *control;
				const cfg_obj_t *path;
				isc_sockaddr_t addr;
				isc_result_t result;

				/*
				 * The parser handles BIND 8 configuration file
				 * syntax, so it allows unix phrases as well
				 * inet phrases with no keys{} clause.
				 */
				control = cfg_listelt_value(element2);

				path = cfg_tuple_get(control, "path");
				result = isc_sockaddr_frompath(&addr,
						      cfg_obj_asstring(path));
				if (result != ISC_R_SUCCESS) {
					isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_CONTROL,
					      ISC_LOG_DEBUG(9),
					      "control channel '%s': %s",
					      cfg_obj_asstring(path),
					      isc_result_totext(result));
					continue;
				}

				isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_CONTROL,
					      ISC_LOG_DEBUG(9),
					      "processing control channel '%s'",
					      cfg_obj_asstring(path));

				update_listener(cp, &listener, control, config,
						&addr, aclconfctx,
						cfg_obj_asstring(path),
						isc_sockettype_unix);

				if (listener != NULL)
					/*
					 * Remove the listener from the old
					 * list, so it won't be shut down.
					 */
					ISC_LIST_UNLINK(cp->listeners,
							listener, link);
				else
					/*
					 * This is a new listener.
					 */
					add_listener(cp, &listener, control,
						     config, &addr, aclconfctx,
						     cfg_obj_asstring(path),
						     isc_sockettype_unix);

				if (listener != NULL)
					ISC_LIST_APPEND(new_listeners,
							listener, link);
			}
		}
	} else {
		int i;

		for (i = 0; i < 2; i++) {
			isc_sockaddr_t addr;

			if (i == 0) {
				struct in_addr localhost;

				if (isc_net_probeipv4() != ISC_R_SUCCESS)
					continue;
				localhost.s_addr = htonl(INADDR_LOOPBACK);
				isc_sockaddr_fromin(&addr, &localhost, 0);
			} else {
				if (isc_net_probeipv6() != ISC_R_SUCCESS)
					continue;
				isc_sockaddr_fromin6(&addr,
						     &in6addr_loopback, 0);
			}
			isc_sockaddr_setport(&addr, NS_CONTROL_PORT);

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

			update_listener(cp, &listener, NULL, NULL,
					&addr, NULL, socktext,
					isc_sockettype_tcp);

			if (listener != NULL)
				/*
				 * Remove the listener from the old
				 * list, so it won't be shut down.
				 */
				ISC_LIST_UNLINK(cp->listeners,
						listener, link);
			else
				/*
				 * This is a new listener.
				 */
				add_listener(cp, &listener, NULL, NULL,
					     &addr, NULL, socktext,
					     isc_sockettype_tcp);

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

	/*
	 * ns_control_shutdown() will stop whatever is on the global
	 * listeners list, which currently only has whatever sockaddrs
	 * were in the previous configuration (if any) that do not
	 * remain in the current configuration.
	 */
	controls_shutdown(cp);

	/*
	 * Put all of the valid listeners on the listeners list.
	 * Anything already on listeners in the process of shutting
	 * down will be taken care of by listen_done().
	 */
	ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link);
	return (ISC_R_SUCCESS);
}
Esempio n. 30
0
isc_result_t
isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
		    isc_httpdclientok_t *client_ok,
		    isc_httpdondestroy_t *ondestroy, void *cb_arg,
		    isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdmgrp)
{
	isc_result_t result;
	isc_httpdmgr_t *httpdmgr;

	REQUIRE(mctx != NULL);
	REQUIRE(sock != NULL);
	REQUIRE(task != NULL);
	REQUIRE(tmgr != NULL);
	REQUIRE(httpdmgrp != NULL && *httpdmgrp == NULL);

	httpdmgr = isc_mem_get(mctx, sizeof(isc_httpdmgr_t));
	if (httpdmgr == NULL)
		return (ISC_R_NOMEMORY);

	result = isc_mutex_init(&httpdmgr->lock);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(mctx, httpdmgr, sizeof(isc_httpdmgr_t));
		return (result);
	}
	httpdmgr->mctx = NULL;
	isc_mem_attach(mctx, &httpdmgr->mctx);
	httpdmgr->sock = NULL;
	isc_socket_attach(sock, &httpdmgr->sock);
	httpdmgr->task = NULL;
	isc_task_attach(task, &httpdmgr->task);
	httpdmgr->timermgr = tmgr; /* XXXMLG no attach function? */
	httpdmgr->client_ok = client_ok;
	httpdmgr->ondestroy = ondestroy;
	httpdmgr->cb_arg = cb_arg;
	httpdmgr->flags = 0;

	ISC_LIST_INIT(httpdmgr->running);
	ISC_LIST_INIT(httpdmgr->urls);

	/* XXXMLG ignore errors on isc_socket_listen() */
	result = isc_socket_listen(sock, SOMAXCONN);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_socket_listen() failed: %s",
				 isc_result_totext(result));
		goto cleanup;
	}

	(void)isc_socket_filter(sock, "httpready");

	result = isc_socket_accept(sock, task, isc_httpd_accept, httpdmgr);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	httpdmgr->render_404 = render_404;
	httpdmgr->render_500 = render_500;

	*httpdmgrp = httpdmgr;
	return (ISC_R_SUCCESS);

  cleanup:
	isc_task_detach(&httpdmgr->task);
	isc_socket_detach(&httpdmgr->sock);
	isc_mem_detach(&httpdmgr->mctx);
	(void)isc_mutex_destroy(&httpdmgr->lock);
	isc_mem_put(mctx, httpdmgr, sizeof(isc_httpdmgr_t));
	return (result);
}