⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 controlconf.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 3 页
字号:
	return (result);}			/* * Ensures that both '*global_keylistp' and '*control_keylistp' are * valid or both are NULL. */static voidget_key_info(cfg_obj_t *config, cfg_obj_t *control,	     cfg_obj_t **global_keylistp, cfg_obj_t **control_keylistp){	isc_result_t result;	cfg_obj_t *control_keylist = NULL;	cfg_obj_t *global_keylist = NULL;	REQUIRE(global_keylistp != NULL && *global_keylistp == NULL);	REQUIRE(control_keylistp != NULL && *control_keylistp == NULL);	control_keylist = cfg_tuple_get(control, "keys");	if (!cfg_obj_isvoid(control_keylist) &&	    cfg_list_first(control_keylist) != NULL) {		result = cfg_map_get(config, "key", &global_keylist);		if (result == ISC_R_SUCCESS) {			*global_keylistp = global_keylist;			*control_keylistp = control_keylist;		}	}}static voidupdate_listener(ns_controls_t *cp,		controllistener_t **listenerp, cfg_obj_t *control,		cfg_obj_t *config, isc_sockaddr_t *addr,		ns_aclconfctx_t *aclconfctx, const char *socktext){	controllistener_t *listener;	cfg_obj_t *allow;	cfg_obj_t *global_keylist = NULL;	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.		 */		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));	/*	 * Now, keep the old access list unless a new one can be made.	 */	if (control != NULL) {		allow = cfg_tuple_get(control, "allow");		result = ns_acl_fromconfig(allow, config, aclconfctx,					   listener->mctx, &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);	} else		/* XXXDCL say the old acl is still used? */		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));	*listenerp = listener;}static voidadd_listener(ns_controls_t *cp, controllistener_t **listenerp,	     cfg_obj_t *control, cfg_obj_t *config, isc_sockaddr_t *addr,	     ns_aclconfctx_t *aclconfctx, const char *socktext){	isc_mem_t *mctx = cp->server->mctx;	controllistener_t *listener;	cfg_obj_t *allow;	cfg_obj_t *global_keylist = NULL;	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->controls = cp;		listener->mctx = mctx;		listener->task = cp->server->task;		listener->address = *addr;		listener->sock = NULL;		listener->listening = ISC_FALSE;		listener->exiting = ISC_FALSE;		listener->acl = NULL;		ISC_LINK_INIT(listener, link);		ISC_LIST_INIT(listener->keys);		ISC_LIST_INIT(listener->connections);		/*		 * Make the acl.		 */		if (control != NULL) {			allow = cfg_tuple_get(control, "allow");			result = ns_acl_fromconfig(allow, config, aclconfctx,						   mctx, &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) ||		    (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))			result = ISC_R_FAMILYNOSUPPORT;	}	if (result == ISC_R_SUCCESS)		result = isc_socket_create(ns_g_socketmgr,					   isc_sockaddr_pf(&listener->address),					   isc_sockettype_tcp,					   &listener->sock);	if (result == ISC_R_SUCCESS)		result = isc_socket_bind(listener->sock,					 &listener->address);	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? */}isc_result_tns_controls_configure(ns_controls_t *cp, cfg_obj_t *config,		      ns_aclconfctx_t *aclconfctx){	controllistener_t *listener;	controllistenerlist_t new_listeners;	cfg_obj_t *controlslist = NULL;	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)) {			cfg_obj_t *controls;			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)) {				cfg_obj_t *control;				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.				 *				 * "unix" phrases have been reported as				 * unsupported by the parser.				 */				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);				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);				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);			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);			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);}isc_result_tns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp) {	isc_mem_t *mctx = server->mctx;	isc_result_t result;	ns_controls_t *controls = isc_mem_get(mctx, sizeof(*controls));	if (controls == NULL)		return (ISC_R_NOMEMORY);	controls->server = server;	ISC_LIST_INIT(controls->listeners);	controls->shuttingdown = ISC_FALSE;	controls->symtab = NULL;	result = isccc_cc_createsymtab(&controls->symtab);	if (result != ISC_R_SUCCESS) {		isc_mem_put(server->mctx, controls, sizeof(*controls));		return (result);	}	*ctrlsp = controls;	return (ISC_R_SUCCESS);}voidns_controls_destroy(ns_controls_t **ctrlsp) {	ns_controls_t *controls = *ctrlsp;	REQUIRE(ISC_LIST_EMPTY(controls->listeners));	isccc_symtab_destroy(&controls->symtab);	isc_mem_put(controls->server->mctx, controls, sizeof(*controls));	*ctrlsp = NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -