📄 controlconf.c
字号:
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 + -