Example #1
0
/*
 * initialization routine.  Might be needed if the code is ROMized.
 */
void
init_lib(void)
{
	lib_nextbuf = 0;
	ipv4_works = (ISC_R_SUCCESS == isc_net_probeipv4());
	ipv6_works = (ISC_R_SUCCESS == isc_net_probeipv6());
	lib_inited = 1;
}
Example #2
0
/*
 * initialization routine.  Might be needed if the code is ROMized.
 */
void
init_lib(void)
{
	if (lib_inited)
		return;
	ipv4_works = (ISC_R_SUCCESS == isc_net_probeipv4());
	ipv6_works = (ISC_R_SUCCESS == isc_net_probeipv6());
	init_systime();
	lib_inited = TRUE;
}
Example #3
0
static isc_result_t
listener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) {
	isc_socket_t *sock = NULL;
	isc_result_t result = ISC_R_SUCCESS;
	int pf;

	pf = isc_sockaddr_pf(address);
	if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
	    (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
		return (ISC_R_FAMILYNOSUPPORT);

	listener->address = *address;

	if (isc_sockaddr_getport(&listener->address) == 0) {
		in_port_t port;
		port = lwresd_g_listenport;
		if (port == 0)
			port = LWRES_UDP_PORT;
		isc_sockaddr_setport(&listener->address, port);
	}

	sock = NULL;
	result = isc_socket_create(ns_g_socketmgr, pf,
				   isc_sockettype_udp, &sock);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
			      "failed to create lwres socket: %s",
			      isc_result_totext(result));
		return (result);
	}

	result = isc_socket_bind(sock, &listener->address,
				 ISC_SOCKET_REUSEADDRESS);
	if (result != ISC_R_SUCCESS) {
		char socktext[ISC_SOCKADDR_FORMATSIZE];
		isc_sockaddr_format(&listener->address, socktext,
				    sizeof(socktext));
		isc_socket_detach(&sock);
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
			      "failed to add lwres socket: %s: %s",
			      socktext, isc_result_totext(result));
		return (result);
	}
	listener->sock = sock;
	return (ISC_R_SUCCESS);
}
Example #4
0
int
main(int argc, char *argv[]) {
	isc_mem_t *mctx;
	isc_boolean_t verbose = ISC_FALSE;
	unsigned int workers = 2;
	isc_taskmgr_t *taskmgr;
	isc_task_t *task;
	isc_timermgr_t *timermgr;
	dns_view_t *view;
	int ch;
	isc_socketmgr_t *socketmgr;
	dns_dispatchmgr_t *dispatchmgr;
	isc_netaddr_t na;
	dns_byaddr_t *byaddr;
	isc_result_t result;
	unsigned int options = 0;
	dns_cache_t *cache;

	RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);

	dns_result_register();

	mctx = NULL;
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);

	while ((ch = isc_commandline_parse(argc, argv, "nvw:")) != -1) {
		switch (ch) {
		case 'n':
			/*
			 * We only try nibbles, so do nothing for this option.
			 */
			break;
		case 'v':
			verbose = ISC_TRUE;
			break;
		case 'w':
			workers = (unsigned int)atoi(isc_commandline_argument);
			break;
		}
	}

	if (verbose) {
		printf("%u workers\n", workers);
		printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4()));
		printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6()));
	}

	taskmgr = NULL;
	RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr)
		      == ISC_R_SUCCESS);
	task = NULL;
	RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task)
		      == ISC_R_SUCCESS);
	isc_task_setname(task, "byaddr", NULL);

	dispatchmgr = NULL;
	RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr)
		      == ISC_R_SUCCESS);

	timermgr = NULL;
	RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
	socketmgr = NULL;
	RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);

	cache = NULL;
	RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr,
				       dns_rdataclass_in, "rbt", 0, NULL,
				       &cache) == ISC_R_SUCCESS);

	view = NULL;
	RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default",
				      &view) == ISC_R_SUCCESS);

	{
		unsigned int attrs;
		dns_dispatch_t *disp4 = NULL;
		dns_dispatch_t *disp6 = NULL;

		if (isc_net_probeipv4() == ISC_R_SUCCESS) {
			isc_sockaddr_t any4;

			isc_sockaddr_any(&any4);

			attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
			RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
							  socketmgr,
							  taskmgr, &any4,
							  512, 6, 1024,
							  17, 19, attrs,
							  attrs, &disp4)
				      == ISC_R_SUCCESS);
			INSIST(disp4 != NULL);
		}

		if (isc_net_probeipv6() == ISC_R_SUCCESS) {
			isc_sockaddr_t any6;

			isc_sockaddr_any6(&any6);

			attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
			RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
							  socketmgr,
							  taskmgr, &any6,
							  512, 6, 1024,
							  17, 19, attrs,
							  attrs, &disp6)
				      == ISC_R_SUCCESS);
			INSIST(disp6 != NULL);
		}

		RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1,
						      socketmgr,
						      timermgr, 0,
						      dispatchmgr,
						      disp4, disp6) ==
		      ISC_R_SUCCESS);

		if (disp4 != NULL)
		    dns_dispatch_detach(&disp4);
		if (disp6 != NULL)
		    dns_dispatch_detach(&disp6);
	}

	{
		struct in_addr ina;
		isc_sockaddr_t sa;
		isc_sockaddrlist_t sal;

		ISC_LIST_INIT(sal);
		ina.s_addr = inet_addr("127.0.0.1");
		isc_sockaddr_fromin(&sa, &ina, 53);
		ISC_LIST_APPEND(sal, &sa, link);

		RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname,
					       &sal, dns_fwdpolicy_only)
			      == ISC_R_SUCCESS);
	}

	dns_view_setcache(view, cache);
	dns_view_freeze(view);

	dns_cache_detach(&cache);

	printf("address = %s\n", argv[isc_commandline_index]);
	na.family = AF_INET;
	if (inet_pton(AF_INET, argv[isc_commandline_index],
		      (char *)&na.type.in) != 1) {
		na.family = AF_INET6;
		if (inet_pton(AF_INET6, argv[isc_commandline_index],
			      (char *)&na.type.in6) != 1) {
			printf("unknown address format\n");
			exit(1);
		}
	}

	result = dns_byaddr_create(mctx, &na, view, options, task,
				   done, NULL, &byaddr);
	if (result != ISC_R_SUCCESS) {
		printf("dns_byaddr_create() returned %s\n",
		       isc_result_totext(result));
		RUNTIME_CHECK(0);
	}

	(void)isc_app_run();

	/*
	 * XXXRTH if we get a control-C before we get to isc_app_run(),
	 * we're in trouble (because we might try to destroy things before
	 * they've been created.
	 */

	dns_view_detach(&view);

	isc_task_shutdown(task);
	isc_task_detach(&task);

	dns_dispatchmgr_destroy(&dispatchmgr);

	isc_taskmgr_destroy(&taskmgr);

	isc_socketmgr_destroy(&socketmgr);
	isc_timermgr_destroy(&timermgr);

	if (verbose)
		isc_mem_stats(mctx, stdout);
	isc_mem_destroy(&mctx);

	isc_app_finish();

	return (0);
}
Example #5
0
static isc_result_t
do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
	isc_boolean_t verbose)
{
	isc_interfaceiter_t *iter = NULL;
	isc_boolean_t scan_ipv4 = ISC_FALSE;
	isc_boolean_t scan_ipv6 = ISC_FALSE;
	isc_boolean_t adjusting = ISC_FALSE;
	isc_boolean_t ipv6only = ISC_TRUE;
	isc_boolean_t ipv6pktinfo = ISC_TRUE;
	isc_result_t result;
	isc_netaddr_t zero_address, zero_address6;
	ns_listenelt_t *le;
	isc_sockaddr_t listen_addr;
	ns_interface_t *ifp;
	isc_boolean_t log_explicit = ISC_FALSE;
	isc_boolean_t dolistenon;

	if (ext_listen != NULL)
		adjusting = ISC_TRUE;

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

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

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

			if (!listenon_is_ip6_any(le))
				continue;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		}
		continue;

	ignore_interface:
		isc_log_write(IFMGR_COMMON_LOGARGS,
			      ISC_LOG_ERROR,
			      "ignoring %s interface %s: %s",
			      (family == AF_INET) ? "IPv4" : "IPv6",
			      interface.name, isc_result_totext(result));
		continue;
	}
	if (result != ISC_R_NOMORE)
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "interface iteration failed: %s",
				 isc_result_totext(result));
	else
		result = ISC_R_SUCCESS;
 cleanup_iter:
	isc_interfaceiter_destroy(&iter);
	return (result);
}
Example #6
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);
}
Example #7
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? */
}
Example #8
0
static void
parse_command_line(int argc, char *argv[]) {
	int ch;
	int port;
	const char *p;

	save_command_line(argc, argv);

	/*
	 * NS_MAIN_ARGS is defined in main.h, so that it can be used
	 * both by named and by ntservice hooks.
	 */
	isc_commandline_errprint = ISC_FALSE;
	while ((ch = isc_commandline_parse(argc, argv, NS_MAIN_ARGS)) != -1) {
		switch (ch) {
		case '4':
			if (ns_g_disable4)
				ns_main_earlyfatal("cannot specify -4 and -6");
			if (isc_net_probeipv4() != ISC_R_SUCCESS)
				ns_main_earlyfatal("IPv4 not supported by OS");
			isc_net_disableipv6();
			ns_g_disable6 = ISC_TRUE;
			break;
		case '6':
			if (ns_g_disable6)
				ns_main_earlyfatal("cannot specify -4 and -6");
			if (isc_net_probeipv6() != ISC_R_SUCCESS)
				ns_main_earlyfatal("IPv6 not supported by OS");
			isc_net_disableipv4();
			ns_g_disable4 = ISC_TRUE;
			break;
		case 'c':
			ns_g_conffile = isc_commandline_argument;
			lwresd_g_conffile = isc_commandline_argument;
			if (lwresd_g_useresolvconf)
				ns_main_earlyfatal("cannot specify -c and -C");
			ns_g_conffileset = ISC_TRUE;
			break;
		case 'C':
			lwresd_g_resolvconffile = isc_commandline_argument;
			if (ns_g_conffileset)
				ns_main_earlyfatal("cannot specify -c and -C");
			lwresd_g_useresolvconf = ISC_TRUE;
			break;
		case 'd':
			ns_g_debuglevel = parse_int(isc_commandline_argument,
						    "debug level");
			break;
		case 'D':
			/* Descriptive comment for 'ps'. */
			break;
		case 'E':
			ns_g_engine = isc_commandline_argument;
			break;
		case 'f':
			ns_g_foreground = ISC_TRUE;
			break;
		case 'g':
			ns_g_foreground = ISC_TRUE;
			ns_g_logstderr = ISC_TRUE;
			break;
		/* XXXBEW -i should be removed */
		case 'i':
			lwresd_g_defaultpidfile = isc_commandline_argument;
			break;
		case 'l':
			ns_g_lwresdonly = ISC_TRUE;
			break;
		case 'M':
			if (strcmp(isc_commandline_argument, "external") == 0)
				isc_mem_defaultflags = 0;
			break;
		case 'm':
			set_flags(isc_commandline_argument, mem_debug_flags,
				  &isc_mem_debugging);
			break;
		case 'N': /* Deprecated. */
		case 'n':
			ns_g_cpus = parse_int(isc_commandline_argument,
					      "number of cpus");
			if (ns_g_cpus == 0)
				ns_g_cpus = 1;
			break;
		case 'p':
			port = parse_int(isc_commandline_argument, "port");
			if (port < 1 || port > 65535)
				ns_main_earlyfatal("port '%s' out of range",
						   isc_commandline_argument);
			ns_g_port = port;
			break;
		/* XXXBEW Should -P be removed? */
		case 'P':
			port = parse_int(isc_commandline_argument, "port");
			if (port < 1 || port > 65535)
				ns_main_earlyfatal("port '%s' out of range",
						   isc_commandline_argument);
			lwresd_g_listenport = port;
			break;
		case 's':
			/* XXXRTH temporary syntax */
			want_stats = ISC_TRUE;
			break;
		case 'S':
			maxsocks = parse_int(isc_commandline_argument,
					     "max number of sockets");
			break;
		case 't':
			/* XXXJAB should we make a copy? */
			ns_g_chrootdir = isc_commandline_argument;
			break;
		case 'T':	/* NOT DOCUMENTED */
			/*
			 * force the server to behave (or misbehave) in
			 * specified ways for testing purposes.
			 *
			 * clienttest: make clients single shot with their
			 * 	       own memory context.
			 * delay=xxxx: delay client responses by xxxx ms to
			 *	       simulate remote servers.
			 * dscp=x:     check that dscp values are as
			 * 	       expected and assert otherwise.
			 */
			if (!strcmp(isc_commandline_argument, "clienttest"))
				ns_g_clienttest = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "nosoa"))
				ns_g_nosoa = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "noaa"))
				ns_g_noaa = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "maxudp512"))
				maxudp = 512;
			else if (!strcmp(isc_commandline_argument, "maxudp1460"))
				maxudp = 1460;
			else if (!strcmp(isc_commandline_argument, "dropedns"))
				ns_g_dropedns = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "noedns"))
				ns_g_noedns = ISC_TRUE;
			else if (!strncmp(isc_commandline_argument,
					  "maxudp=", 7))
				maxudp = atoi(isc_commandline_argument + 7);
			else if (!strncmp(isc_commandline_argument,
					  "delay=", 6))
				ns_g_delay = atoi(isc_commandline_argument + 6);
			else if (!strcmp(isc_commandline_argument, "nosyslog"))
				ns_g_nosyslog = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "nonearest"))
				ns_g_nonearest = ISC_TRUE;
			else if (!strncmp(isc_commandline_argument, "dscp=", 5))
				isc_dscp_check_value =
					   atoi(isc_commandline_argument + 5);
			else if (!strncmp(isc_commandline_argument,
					  "mkeytimers=", 11))
			{
				p = strtok(isc_commandline_argument + 11, "/");
				if (p == NULL)
					ns_main_earlyfatal("bad mkeytimer");
				dns_zone_mkey_hour = atoi(p);
				if (dns_zone_mkey_hour == 0)
					ns_main_earlyfatal("bad mkeytimer");

				p = strtok(NULL, "/");
				if (p == NULL) {
					dns_zone_mkey_day =
						(24 * dns_zone_mkey_hour);
					dns_zone_mkey_month =
						(30 * dns_zone_mkey_day);
					break;
				}
				dns_zone_mkey_day = atoi(p);
				if (dns_zone_mkey_day < dns_zone_mkey_hour)
					ns_main_earlyfatal("bad mkeytimer");

				p = strtok(NULL, "/");
				if (p == NULL) {
					dns_zone_mkey_month =
						(30 * dns_zone_mkey_day);
					break;
				}
				dns_zone_mkey_month = atoi(p);
				if (dns_zone_mkey_month < dns_zone_mkey_day)
					ns_main_earlyfatal("bad mkeytimer");
			} else if (!strcmp(isc_commandline_argument, "notcp"))
				ns_g_notcp = ISC_TRUE;
			else
				fprintf(stderr, "unknown -T flag '%s\n",
					isc_commandline_argument);
			break;
		case 'U':
			ns_g_udpdisp = parse_int(isc_commandline_argument,
						 "number of UDP listeners "
						 "per interface");
			break;
		case 'u':
			ns_g_username = isc_commandline_argument;
			break;
		case 'v':
			printf("%s %s%s%s <id:%s>\n",
			       ns_g_product, ns_g_version,
			       (*ns_g_description != '\0') ? " " : "",
			       ns_g_description, ns_g_srcid);
			exit(0);
		case 'V':
			printf("%s %s%s%s <id:%s>\n", ns_g_product, ns_g_version,
			       (*ns_g_description != '\0') ? " " : "",
			       ns_g_description, ns_g_srcid);
			printf("running on %s\n", ns_os_uname());
			printf("built by %s with %s\n",
			       ns_g_builder, ns_g_configargs);
#ifdef __clang__
			printf("compiled by CLANG %s\n", __VERSION__);
#else
#if defined(__ICC) || defined(__INTEL_COMPILER)
			printf("compiled by ICC %s\n", __VERSION__);
#else
#ifdef __GNUC__
			printf("compiled by GCC %s\n", __VERSION__);
#endif
#endif
#endif
#ifdef _MSC_VER
			printf("compiled by MSVC %d\n", _MSC_VER);
#endif
#ifdef __SUNPRO_C
			printf("compiled by Solaris Studio %x\n", __SUNPRO_C);
#endif
#ifdef OPENSSL
			printf("compiled with OpenSSL version: %s\n",
			       OPENSSL_VERSION_TEXT);
			printf("linked to OpenSSL version: %s\n",
			       SSLeay_version(SSLEAY_VERSION));
#endif
#ifdef HAVE_LIBXML2
			printf("compiled with libxml2 version: %s\n",
			       LIBXML_DOTTED_VERSION);
			printf("linked to libxml2 version: %s\n",
			       xmlParserVersion);
#endif
#if defined(HAVE_JSON) && defined(JSON_C_VERSION)
			printf("compiled with libjson-c version: %s\n",
			       JSON_C_VERSION);
			printf("linked to libjson-c version: %s\n",
			       json_c_version());
#endif
			exit(0);
		case 'F':
			/* Reserved for FIPS mode */
			/* FALLTHROUGH */
		case '?':
			usage();
			if (isc_commandline_option == '?')
				exit(0);
			p = strchr(NS_MAIN_ARGS, isc_commandline_option);
			if (p == NULL || *++p != ':')
				ns_main_earlyfatal("unknown option '-%c'",
						   isc_commandline_option);
			else
				ns_main_earlyfatal("option '-%c' requires "
						   "an argument",
						   isc_commandline_option);
			/* FALLTHROUGH */
		default:
			ns_main_earlyfatal("parsing options returned %d", ch);
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;
	POST(argv);

	if (argc > 0) {
		usage();
		ns_main_earlyfatal("extra command line arguments");
	}
}
Example #9
0
static void
parse_command_line(int argc, char *argv[]) {
	int ch;
	int port;
	isc_boolean_t disable6 = ISC_FALSE;
	isc_boolean_t disable4 = ISC_FALSE;

	save_command_line(argc, argv);

	isc_commandline_errprint = ISC_FALSE;
	while ((ch = isc_commandline_parse(argc, argv,
					   "46c:C:d:E:fFgi:lm:n:N:p:P:"
					   "sS:t:T:u:vVx:")) != -1) {
		switch (ch) {
		case '4':
			if (disable4)
				ns_main_earlyfatal("cannot specify -4 and -6");
			if (isc_net_probeipv4() != ISC_R_SUCCESS)
				ns_main_earlyfatal("IPv4 not supported by OS");
			isc_net_disableipv6();
			disable6 = ISC_TRUE;
			break;
		case '6':
			if (disable6)
				ns_main_earlyfatal("cannot specify -4 and -6");
			if (isc_net_probeipv6() != ISC_R_SUCCESS)
				ns_main_earlyfatal("IPv6 not supported by OS");
			isc_net_disableipv4();
			disable4 = ISC_TRUE;
			break;
		case 'c':
			ns_g_conffile = isc_commandline_argument;
			lwresd_g_conffile = isc_commandline_argument;
			if (lwresd_g_useresolvconf)
				ns_main_earlyfatal("cannot specify -c and -C");
			ns_g_conffileset = ISC_TRUE;
			break;
		case 'C':
			lwresd_g_resolvconffile = isc_commandline_argument;
			if (ns_g_conffileset)
				ns_main_earlyfatal("cannot specify -c and -C");
			lwresd_g_useresolvconf = ISC_TRUE;
			break;
		case 'd':
			ns_g_debuglevel = parse_int(isc_commandline_argument,
						    "debug level");
			break;
		case 'E':
			ns_g_engine = isc_commandline_argument;
			break;
		case 'f':
			ns_g_foreground = ISC_TRUE;
			break;
		case 'g':
			ns_g_foreground = ISC_TRUE;
			ns_g_logstderr = ISC_TRUE;
			break;
		/* XXXBEW -i should be removed */
		case 'i':
			lwresd_g_defaultpidfile = isc_commandline_argument;
			break;
		case 'l':
			ns_g_lwresdonly = ISC_TRUE;
			break;
		case 'm':
			set_flags(isc_commandline_argument, mem_debug_flags,
				  &isc_mem_debugging);
			break;
		case 'N': /* Deprecated. */
		case 'n':
			ns_g_cpus = parse_int(isc_commandline_argument,
					      "number of cpus");
			if (ns_g_cpus == 0)
				ns_g_cpus = 1;
			break;
		case 'p':
			port = parse_int(isc_commandline_argument, "port");
			if (port < 1 || port > 65535)
				ns_main_earlyfatal("port '%s' out of range",
						   isc_commandline_argument);
			ns_g_port = port;
			break;
		/* XXXBEW Should -P be removed? */
		case 'P':
			port = parse_int(isc_commandline_argument, "port");
			if (port < 1 || port > 65535)
				ns_main_earlyfatal("port '%s' out of range",
						   isc_commandline_argument);
			lwresd_g_listenport = port;
			break;
		case 's':
			/* XXXRTH temporary syntax */
			want_stats = ISC_TRUE;
			break;
		case 'S':
			maxsocks = parse_int(isc_commandline_argument,
					     "max number of sockets");
			break;
		case 't':
			/* XXXJAB should we make a copy? */
			ns_g_chrootdir = isc_commandline_argument;
			break;
		case 'T':
			/*
			 * clienttest: make clients single shot with their
			 * 	       own memory context.
			 */
			if (!strcmp(isc_commandline_argument, "clienttest"))
				ns_g_clienttest = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "maxudp512"))
				maxudp = 512;
			else if (!strcmp(isc_commandline_argument, "maxudp1460"))
				maxudp = 1460;
			else
				fprintf(stderr, "unknown -T flag '%s\n",
					isc_commandline_argument);
			break;
		case 'u':
			ns_g_username = isc_commandline_argument;
			break;
		case 'v':
			printf("BIND %s\n", ns_g_version);
			exit(0);
		case 'V':
			printf("BIND %s built with %s\n", ns_g_version,
				ns_g_configargs);
			exit(0);
		case 'F':
			/* Reserved for FIPS mode */
			/* FALLTHROUGH */
		case '?':
			usage();
			if (isc_commandline_option == '?')
				exit(0);
			ns_main_earlyfatal("unknown option '-%c'",
					   isc_commandline_option);
			/* FALLTHROUGH */
		default:
			ns_main_earlyfatal("parsing options returned %d", ch);
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;

	if (argc > 0) {
		usage();
		ns_main_earlyfatal("extra command line arguments");
	}
}
Example #10
0
int
main(int argc, char *argv[]) {
	isc_boolean_t verbose = ISC_FALSE;
	unsigned int workers = 2;
	isc_timermgr_t *timermgr;
	int ch;
	isc_socketmgr_t *socketmgr;
	dns_dispatchmgr_t *dispatchmgr;
	dns_cache_t *cache;
	isc_buffer_t b;

	RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);

	dns_result_register();

	mctx = NULL;
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);

	RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
		      == ISC_R_SUCCESS);

	while ((ch = isc_commandline_parse(argc, argv, "d:vw:")) != -1) {
		switch (ch) {
		case 'd':
			level = (unsigned int)atoi(isc_commandline_argument);
			break;
		case 'v':
			verbose = ISC_TRUE;
			break;
		case 'w':
			workers = (unsigned int)atoi(isc_commandline_argument);
			break;
		}
	}

	log_init();

	if (verbose) {
		printf("%u workers\n", workers);
		printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4()));
		printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6()));
	}

	taskmgr = NULL;
	RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr) ==
		      ISC_R_SUCCESS);
	task = NULL;
	RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task) ==
		      ISC_R_SUCCESS);
	isc_task_setname(task, "byname", NULL);

	dispatchmgr = NULL;
	RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr)
		      == ISC_R_SUCCESS);

	timermgr = NULL;
	RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
	socketmgr = NULL;
	RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);

	cache = NULL;
	RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr,
				       dns_rdataclass_in, "rbt", 0, NULL,
				       &cache) == ISC_R_SUCCESS);

	view = NULL;
	RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default",
				      &view) == ISC_R_SUCCESS);

	{
		unsigned int attrs;
		dns_dispatch_t *disp4 = NULL;
		dns_dispatch_t *disp6 = NULL;

		if (isc_net_probeipv4() == ISC_R_SUCCESS) {
			isc_sockaddr_t any4;
			isc_sockaddr_any(&any4);

			attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
			RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
							  socketmgr,
							  taskmgr, &any4,
							  512, 6, 1024,
							  17, 19, attrs,
							  attrs, &disp4)
				      == ISC_R_SUCCESS);
			INSIST(disp4 != NULL);
		}

		if (isc_net_probeipv6() == ISC_R_SUCCESS) {
			isc_sockaddr_t any6;

			isc_sockaddr_any6(&any6);

			attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
			RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
							  socketmgr,
							  taskmgr, &any6,
							  512, 6, 1024,
							  17, 19, attrs,
							  attrs, &disp6)
				      == ISC_R_SUCCESS);
			INSIST(disp6 != NULL);
		}

		RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1,
						      socketmgr,
						      timermgr, 0,
						      dispatchmgr,
						      disp4, disp6) ==
		      ISC_R_SUCCESS);

		if (disp4 != NULL)
			dns_dispatch_detach(&disp4);
		if (disp6 != NULL)
			dns_dispatch_detach(&disp6);
	}

	{
		struct in_addr ina;
		isc_sockaddr_t sa;
		isc_sockaddrlist_t sal;

		ISC_LIST_INIT(sal);
		ina.s_addr = inet_addr("127.0.0.1");
		isc_sockaddr_fromin(&sa, &ina, 53);
		ISC_LIST_APPEND(sal, &sa, link);

		RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname,
					       &sal, dns_fwdpolicy_only)
			      == ISC_R_SUCCESS);
	}

	dns_view_setcache(view, cache);
	dns_view_freeze(view);

	dns_cache_detach(&cache);

	printf("name = %s\n", argv[isc_commandline_index]);
	isc_buffer_init(&b, argv[isc_commandline_index],
			strlen(argv[isc_commandline_index]));
	isc_buffer_add(&b, strlen(argv[isc_commandline_index]));
	dns_fixedname_init(&fixed);
	dns_fixedname_init(&target);
	RUNTIME_CHECK(dns_name_fromtext(dns_fixedname_name(&fixed), &b,
					dns_rootname, 0, NULL) ==
		      ISC_R_SUCCESS);

	RUNTIME_CHECK(isc_app_onrun(mctx, task, run, NULL) == ISC_R_SUCCESS);

	(void)isc_app_run();

	dns_view_detach(&view);
	isc_task_shutdown(task);
	isc_task_detach(&task);

	dns_dispatchmgr_destroy(&dispatchmgr);

	isc_taskmgr_destroy(&taskmgr);

	isc_socketmgr_destroy(&socketmgr);
	isc_timermgr_destroy(&timermgr);

	isc_log_destroy(&lctx);

	isc_hash_destroy();
	isc_entropy_detach(&ectx);

	if (verbose)
		isc_mem_stats(mctx, stdout);
	isc_mem_destroy(&mctx);

	isc_app_finish();

	return (0);
}
Example #11
0
isc_result_t
bind9_getaddresses(const char *hostname, in_port_t port,
		   isc_sockaddr_t *addrs, int addrsize, int *addrcount)
{
	struct in_addr in4;
	struct in6_addr in6;
	isc_boolean_t have_ipv4, have_ipv6;
	int i;

#ifdef USE_GETADDRINFO
	struct addrinfo *ai = NULL, *tmpai, hints;
	int result;
#else
	struct hostent *he;
#endif

	REQUIRE(hostname != NULL);
	REQUIRE(addrs != NULL);
	REQUIRE(addrcount != NULL);
	REQUIRE(addrsize > 0);

	have_ipv4 = ISC_TF((isc_net_probeipv4() == ISC_R_SUCCESS));
	have_ipv6 = ISC_TF((isc_net_probeipv6() == ISC_R_SUCCESS));

	/*
	 * Try IPv4, then IPv6.  In order to handle the extended format
	 * for IPv6 scoped addresses (address%scope_ID), we'll use a local
	 * working buffer of 128 bytes.  The length is an ad-hoc value, but
	 * should be enough for this purpose; the buffer can contain a string
	 * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
	 * addresses (up to 46 bytes), the delimiter character and the
	 * terminating NULL character.
	 */
	if (inet_pton(AF_INET, hostname, &in4) == 1) {
		if (have_ipv4)
			isc_sockaddr_fromin(&addrs[0], &in4, port);
		else
			isc_sockaddr_v6fromin(&addrs[0], &in4, port);
		*addrcount = 1;
		return (ISC_R_SUCCESS);
	} else if (strlen(hostname) <= 127U) {
		char tmpbuf[128], *d;
		isc_uint32_t zone = 0;

		strcpy(tmpbuf, hostname);
		d = strchr(tmpbuf, '%');
		if (d != NULL)
			*d = '\0';

		if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) {
			isc_netaddr_t na;

			if (!have_ipv6)
				return (ISC_R_FAMILYNOSUPPORT);

			if (d != NULL) {
#ifdef ISC_PLATFORM_HAVESCOPEID
				isc_result_t result;

				result = isc_netscope_pton(AF_INET6, d + 1,
							   &in6, &zone);
				    
				if (result != ISC_R_SUCCESS)
					return (result);
#else
				/*
				 * The extended format is specified while the
				 * system does not provide the ability to use
				 * it.  Throw an explicit error instead of
				 * ignoring the specified value.
				 */
				return (ISC_R_BADADDRESSFORM);
#endif
			}

			isc_netaddr_fromin6(&na, &in6);
			isc_netaddr_setzone(&na, zone);
			isc_sockaddr_fromnetaddr(&addrs[0],
						 (const isc_netaddr_t *)&na,
						 port);

			*addrcount = 1;
			return (ISC_R_SUCCESS);
			
		}
	}
#ifdef USE_GETADDRINFO
	memset(&hints, 0, sizeof(hints));
	if (!have_ipv6)
		hints.ai_family = PF_INET;
	else if (!have_ipv4)
		hints.ai_family = PF_INET6;
	else {
		hints.ai_family = PF_UNSPEC;
#ifdef AI_ADDRCONFIG
		hints.ai_flags = AI_ADDRCONFIG;
#endif
	}
	hints.ai_socktype = SOCK_STREAM;
#ifdef AI_ADDRCONFIG
 again:
#endif
	result = getaddrinfo(hostname, NULL, &hints, &ai);
	switch (result) {
	case 0:
		break;
	case EAI_NONAME:
#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
	case EAI_NODATA:
#endif
		return (ISC_R_NOTFOUND);
#ifdef AI_ADDRCONFIG
	case EAI_BADFLAGS:
		if ((hints.ai_flags & AI_ADDRCONFIG) != 0) {
			hints.ai_flags &= ~AI_ADDRCONFIG;
			goto again;
		}
#endif
	default:
		return (ISC_R_FAILURE);
	}
	for (tmpai = ai, i = 0;
	     tmpai != NULL && i < addrsize;
	     tmpai = tmpai->ai_next)
	{
		if (tmpai->ai_family != AF_INET &&
		    tmpai->ai_family != AF_INET6)
			continue;
		if (tmpai->ai_family == AF_INET) {
			struct sockaddr_in *sin;
			sin = (struct sockaddr_in *)tmpai->ai_addr;
			isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, port);
		} else {
			struct sockaddr_in6 *sin6;
			sin6 = (struct sockaddr_in6 *)tmpai->ai_addr;
			isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr,
					     port);
		}
		i++;

	}
	freeaddrinfo(ai);
	*addrcount = i;
#else
	he = gethostbyname(hostname);
	if (he == NULL) {
		switch (h_errno) {
		case HOST_NOT_FOUND:
#ifdef NO_DATA
		case NO_DATA:
#endif
#if defined(NO_ADDRESS) && (!defined(NO_DATA) || (NO_DATA != NO_ADDRESS))
		case NO_ADDRESS:
#endif
			return (ISC_R_NOTFOUND);
		default:
			return (ISC_R_FAILURE);
		}
	}
	if (he->h_addrtype != AF_INET && he->h_addrtype != AF_INET6)
		return (ISC_R_NOTFOUND);
	for (i = 0; i < addrsize; i++) {
		if (he->h_addrtype == AF_INET) {
			struct in_addr *inp;
			inp = (struct in_addr *)(he->h_addr_list[i]);
			if (inp == NULL)
				break;
			isc_sockaddr_fromin(&addrs[i], inp, port);
		} else {
			struct in6_addr *in6p;
			in6p = (struct in6_addr *)(he->h_addr_list[i]);
			if (in6p == NULL)
				break;
			isc_sockaddr_fromin6(&addrs[i], in6p, port);
		}
	}
	*addrcount = i;
#endif
	if (*addrcount == 0)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
}
Example #12
0
File: main.c Project: bnjf/bind9
static void
parse_command_line(int argc, char *argv[]) {
	int ch;
	int port;
	const char *p;
	isc_boolean_t disable6 = ISC_FALSE;
	isc_boolean_t disable4 = ISC_FALSE;

	save_command_line(argc, argv);

	/* PLEASE keep options synchronized when main is hooked! */
#define CMDLINE_FLAGS "46c:C:d:D:E:fFgi:lm:n:N:p:P:sS:t:T:U:u:vVx:"
	isc_commandline_errprint = ISC_FALSE;
	while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
		switch (ch) {
		case '4':
			if (disable4)
				ns_main_earlyfatal("cannot specify -4 and -6");
			if (isc_net_probeipv4() != ISC_R_SUCCESS)
				ns_main_earlyfatal("IPv4 not supported by OS");
			isc_net_disableipv6();
			disable6 = ISC_TRUE;
			break;
		case '6':
			if (disable6)
				ns_main_earlyfatal("cannot specify -4 and -6");
			if (isc_net_probeipv6() != ISC_R_SUCCESS)
				ns_main_earlyfatal("IPv6 not supported by OS");
			isc_net_disableipv4();
			disable4 = ISC_TRUE;
			break;
		case 'c':
			ns_g_conffile = isc_commandline_argument;
			lwresd_g_conffile = isc_commandline_argument;
			if (lwresd_g_useresolvconf)
				ns_main_earlyfatal("cannot specify -c and -C");
			ns_g_conffileset = ISC_TRUE;
			break;
		case 'C':
			lwresd_g_resolvconffile = isc_commandline_argument;
			if (ns_g_conffileset)
				ns_main_earlyfatal("cannot specify -c and -C");
			lwresd_g_useresolvconf = ISC_TRUE;
			break;
		case 'd':
			ns_g_debuglevel = parse_int(isc_commandline_argument,
						    "debug level");
			break;
		case 'D':
			/* Descriptive comment for 'ps'. */
			break;
		case 'E':
			ns_g_engine = isc_commandline_argument;
			break;
		case 'f':
			ns_g_foreground = ISC_TRUE;
			break;
		case 'g':
			ns_g_foreground = ISC_TRUE;
			ns_g_logstderr = ISC_TRUE;
			break;
		/* XXXBEW -i should be removed */
		case 'i':
			lwresd_g_defaultpidfile = isc_commandline_argument;
			break;
		case 'l':
			ns_g_lwresdonly = ISC_TRUE;
			break;
		case 'm':
			set_flags(isc_commandline_argument, mem_debug_flags,
				  &isc_mem_debugging);
			break;
		case 'N': /* Deprecated. */
		case 'n':
			ns_g_cpus = parse_int(isc_commandline_argument,
					      "number of cpus");
			if (ns_g_cpus == 0)
				ns_g_cpus = 1;
			break;
		case 'p':
			port = parse_int(isc_commandline_argument, "port");
			if (port < 1 || port > 65535)
				ns_main_earlyfatal("port '%s' out of range",
						   isc_commandline_argument);
			ns_g_port = port;
			break;
		/* XXXBEW Should -P be removed? */
		case 'P':
			port = parse_int(isc_commandline_argument, "port");
			if (port < 1 || port > 65535)
				ns_main_earlyfatal("port '%s' out of range",
						   isc_commandline_argument);
			lwresd_g_listenport = port;
			break;
		case 's':
			/* XXXRTH temporary syntax */
			want_stats = ISC_TRUE;
			break;
		case 'S':
			maxsocks = parse_int(isc_commandline_argument,
					     "max number of sockets");
			break;
		case 't':
			/* XXXJAB should we make a copy? */
			ns_g_chrootdir = isc_commandline_argument;
			break;
		case 'T':	/* NOT DOCUMENTED */
			/*
			 * force the server to behave (or misbehave) in
			 * specified ways for testing purposes.
			 *
			 * clienttest: make clients single shot with their
			 * 	       own memory context.
			 * delay=xxxx: delay client responses by xxxx ms to
			 *	       simulate remote servers.
			 * dscp=x:     check that dscp values are as
			 * 	       expected and assert otherwise.
			 */
			if (!strcmp(isc_commandline_argument, "clienttest"))
				ns_g_clienttest = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "nosoa"))
				ns_g_nosoa = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "noaa"))
				ns_g_noaa = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "maxudp512"))
				maxudp = 512;
			else if (!strcmp(isc_commandline_argument, "maxudp1460"))
				maxudp = 1460;
			else if (!strcmp(isc_commandline_argument, "dropedns"))
				ns_g_dropedns = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "noedns"))
				ns_g_noedns = ISC_TRUE;
			else if (!strncmp(isc_commandline_argument,
					  "maxudp=", 7))
				maxudp = atoi(isc_commandline_argument + 7);
			else if (!strncmp(isc_commandline_argument,
					  "delay=", 6))
				ns_g_delay = atoi(isc_commandline_argument + 6);
			else if (!strcmp(isc_commandline_argument, "nosyslog"))
				ns_g_nosyslog = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "nonearest"))
				ns_g_nonearest = ISC_TRUE;
			else if (!strncmp(isc_commandline_argument, "dscp=", 5))
				isc_dscp_check_value =
					   atoi(isc_commandline_argument + 5);
			else
				fprintf(stderr, "unknown -T flag '%s\n",
					isc_commandline_argument);
			break;
		case 'U':
			ns_g_udpdisp = parse_int(isc_commandline_argument,
						 "number of UDP listeners "
						 "per interface");
			break;
		case 'u':
			ns_g_username = isc_commandline_argument;
			break;
		case 'v':
			printf("%s %s", ns_g_product, ns_g_version);
			if (*ns_g_description != 0)
				printf(" %s", ns_g_description);
			printf("\n");
			exit(0);
		case 'V':
			printf("%s %s", ns_g_product, ns_g_version);
			if (*ns_g_description != 0)
				printf(" %s", ns_g_description);
			printf(" <id:%s> built by %s with %s\n", ns_g_srcid,
			       ns_g_builder, ns_g_configargs);
#ifdef __clang__
			printf("compiled by CLANG %s\n", __VERSION__);
#else
#if defined(__ICC) || defined(__INTEL_COMPILER)
			printf("compiled by ICC %s\n", __VERSION__);
#else
#ifdef __GNUC__
			printf("compiled by GCC %s\n", __VERSION__);
#endif
#endif
#endif
#ifdef _MSC_VER
			printf("compiled by MSVC %d\n", _MSC_VER);
#endif
#ifdef __SUNPRO_C
			printf("compiled by Solaris Studio %x\n", __SUNPRO_C);
#endif
#ifdef OPENSSL
			printf("using OpenSSL version: %s\n",
			       OPENSSL_VERSION_TEXT);
#endif
#ifdef HAVE_LIBXML2
			printf("using libxml2 version: %s\n",
			       LIBXML_DOTTED_VERSION);
#endif
			exit(0);
		case 'F':
			/* Reserved for FIPS mode */
			/* FALLTHROUGH */
		case '?':
			usage();
			if (isc_commandline_option == '?')
				exit(0);
			p = strchr(CMDLINE_FLAGS, isc_commandline_option);
			if (p == NULL || *++p != ':')
				ns_main_earlyfatal("unknown option '-%c'",
						   isc_commandline_option);
			else
				ns_main_earlyfatal("option '-%c' requires "
						   "an argument",
						   isc_commandline_option);
			/* FALLTHROUGH */
		default:
			ns_main_earlyfatal("parsing options returned %d", ch);
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;
	POST(argv);

	if (argc > 0) {
		usage();
		ns_main_earlyfatal("extra command line arguments");
	}
}
Example #13
0
static isc_boolean_t
dash_option(char *option, char *next, isc_boolean_t *open_type_class) {
	char opt, *value;
	isc_result_t result;
	isc_boolean_t value_from_next;
	isc_textregion_t tr;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	char textname[MAXNAME];
	struct in_addr in4;
	struct in6_addr in6;
	in_port_t srcport;
	isc_uint32_t num;
	char *hash;

	while (strpbrk(option, single_dash_opts) == &option[0]) {
		/*
		 * Since the -[46himv] options do not take an argument,
		 * account for them (in any number and/or combination)
		 * if they appear as the first character(s) of a q-opt.
		 */
		opt = option[0];
		switch (opt) {
		case '4':
			if (isc_net_probeipv4() != ISC_R_SUCCESS)
				fatal("IPv4 networking not available");
			if (use_ipv6) {
				isc_net_disableipv6();
				use_ipv6 = ISC_FALSE;
			}
			break;
		case '6':
			if (isc_net_probeipv6() != ISC_R_SUCCESS)
				fatal("IPv6 networking not available");
			if (use_ipv4) {
				isc_net_disableipv4();
				use_ipv4 = ISC_FALSE;
			}
			break;
		case 'h':
			usage();
			exit(0);
			/* NOTREACHED */
		case 'i':
			no_sigs = ISC_TRUE;
			dlv_validation = ISC_FALSE;
			root_validation = ISC_FALSE;
			break;
		case 'm':
			/* handled in preparse_args() */
			break;
		case 'v':
			fputs("delv " VERSION "\n", stderr);
			exit(0);
			/* NOTREACHED */
		default:
			INSIST(0);
		}
		if (strlen(option) > 1U)
			option = &option[1];
		else
			return (ISC_FALSE);
	}
	opt = option[0];
	if (strlen(option) > 1U) {
		value_from_next = ISC_FALSE;
		value = &option[1];
	} else {
		value_from_next = ISC_TRUE;
		value = next;
	}
	if (value == NULL)
		goto invalid_option;
	switch (opt) {
	case 'a':
		anchorfile = isc_mem_strdup(mctx, value);
		if (anchorfile == NULL)
			fatal("out of memory");
		return (value_from_next);
	case 'b':
		hash = strchr(value, '#');
		if (hash != NULL) {
			result = parse_uint(&num, hash + 1, 0xffff, "port");
			if (result != ISC_R_SUCCESS)
				fatal("Couldn't parse port number");
			srcport = num;
			*hash = '\0';
		} else
			srcport = 0;

		if (inet_pton(AF_INET, value, &in4) == 1) {
			if (srcaddr4 != NULL)
				fatal("Only one local address per family "
				      "can be specified\n");
			isc_sockaddr_fromin(&a4, &in4, srcport);
			srcaddr4 = &a4;
		} else if (inet_pton(AF_INET6, value, &in6) == 1) {
			if (srcaddr6 != NULL)
				fatal("Only one local address per family "
				      "can be specified\n");
			isc_sockaddr_fromin6(&a6, &in6, srcport);
			srcaddr6 = &a6;
		} else {
			if (hash != NULL)
				*hash = '#';
			fatal("Invalid address %s", value);
		}
		if (hash != NULL)
			*hash = '#';
		return (value_from_next);
	case 'c':
		if (classset)
			warn("extra query class");

		*open_type_class = ISC_FALSE;
		tr.base = value;
		tr.length = strlen(value);
		result = dns_rdataclass_fromtext(&rdclass,
						 (isc_textregion_t *)&tr);
		if (result == ISC_R_SUCCESS)
			classset = ISC_TRUE;
		else if (rdclass != dns_rdataclass_in)
			warn("ignoring non-IN query class");
		else
			warn("ignoring invalid class");
		return (value_from_next);
	case 'd':
		result = parse_uint(&num, value, 99, "debug level");
		if (result != ISC_R_SUCCESS)
			fatal("Couldn't parse debug level");
		loglevel = num;
		return (value_from_next);
	case 'p':
		port = value;
		return (value_from_next);
	case 'q':
		if (curqname != NULL) {
			warn("extra query name");
			isc_mem_free(mctx, curqname);
		}
		curqname = isc_mem_strdup(mctx, value);
		if (curqname == NULL)
			fatal("out of memory");
		return (value_from_next);
	case 't':
		*open_type_class = ISC_FALSE;
		tr.base = value;
		tr.length = strlen(value);
		result = dns_rdatatype_fromtext(&rdtype,
					(isc_textregion_t *)&tr);
		if (result == ISC_R_SUCCESS) {
			if (typeset)
				warn("extra query type");
			if (rdtype == dns_rdatatype_ixfr ||
			    rdtype == dns_rdatatype_axfr)
				fatal("Transfer not supported");
			qtype = rdtype;
			typeset = ISC_TRUE;
		} else
			warn("ignoring invalid type");
		return (value_from_next);
	case 'x':
		result = get_reverse(textname, sizeof(textname), value,
				     ISC_FALSE);
		if (result == ISC_R_SUCCESS) {
			if (curqname != NULL) {
				isc_mem_free(mctx, curqname);
				warn("extra query name");
			}
			curqname = isc_mem_strdup(mctx, textname);
			if (curqname == NULL)
				fatal("out of memory");
			if (typeset)
				warn("extra query type");
			qtype = dns_rdatatype_ptr;
			typeset = ISC_TRUE;
		} else {
			fprintf(stderr, "Invalid IP address %s\n", value);
			exit(1);
		}
		return (value_from_next);
	invalid_option:
	default:
		fprintf(stderr, "Invalid option: -%s\n", option);
		usage();
	}
	/* NOTREACHED */
	return (ISC_FALSE);
}