📄 server.c
字号:
/* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: server.c,v 1.339.2.15.2.56 2004/06/18 04:39:48 marka Exp $ */#include <config.h>#include <stdlib.h>#include <isc/app.h>#include <isc/base64.h>#include <isc/dir.h>#include <isc/entropy.h>#include <isc/file.h>#include <isc/hash.h>#include <isc/lex.h>#include <isc/parseint.h>#include <isc/print.h>#include <isc/resource.h>#include <isc/stdio.h>#include <isc/string.h>#include <isc/task.h>#include <isc/timer.h>#include <isc/util.h>#include <isccfg/namedconf.h>#include <bind9/check.h>#include <dns/adb.h>#include <dns/cache.h>#include <dns/db.h>#include <dns/dispatch.h>#include <dns/forward.h>#include <dns/journal.h>#include <dns/keytable.h>#include <dns/master.h>#include <dns/masterdump.h>#include <dns/order.h>#include <dns/peer.h>#include <dns/portlist.h>#include <dns/rdataclass.h>#include <dns/rdataset.h>#include <dns/rdatastruct.h>#include <dns/resolver.h>#include <dns/rootns.h>#include <dns/secalg.h>#include <dns/stats.h>#include <dns/tkey.h>#include <dns/view.h>#include <dns/zone.h>#include <dns/zt.h>#include <dst/dst.h>#include <dst/result.h>#include <named/client.h>#include <named/config.h>#include <named/control.h>#include <named/interfacemgr.h>#include <named/log.h>#include <named/logconf.h>#include <named/lwresd.h>#include <named/main.h>#include <named/os.h>#include <named/server.h>#include <named/tkeyconf.h>#include <named/tsigconf.h>#include <named/zoneconf.h>/* * Check an operation for failure. Assumes that the function * using it has a 'result' variable and a 'cleanup' label. */#define CHECK(op) \ do { result = (op); \ if (result != ISC_R_SUCCESS) goto cleanup; \ } while (0)#define CHECKM(op, msg) \ do { result = (op); \ if (result != ISC_R_SUCCESS) { \ isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ NS_LOGMODULE_SERVER, \ ISC_LOG_ERROR, \ "%s: %s", msg, \ isc_result_totext(result)); \ goto cleanup; \ } \ } while (0) \#define CHECKMF(op, msg, file) \ do { result = (op); \ if (result != ISC_R_SUCCESS) { \ isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ NS_LOGMODULE_SERVER, \ ISC_LOG_ERROR, \ "%s '%s': %s", msg, file, \ isc_result_totext(result)); \ goto cleanup; \ } \ } while (0) \#define CHECKFATAL(op, msg) \ do { result = (op); \ if (result != ISC_R_SUCCESS) \ fatal(msg, result); \ } while (0) \struct ns_dispatch { isc_sockaddr_t addr; unsigned int dispatchgen; dns_dispatch_t *dispatch; ISC_LINK(struct ns_dispatch) link;};struct dumpcontext { isc_mem_t *mctx; isc_boolean_t dumpcache; isc_boolean_t dumpzones; FILE *fp; ISC_LIST(struct viewlistentry) viewlist; struct viewlistentry *view; struct zonelistentry *zone; dns_dumpctx_t *mdctx; dns_db_t *db; dns_db_t *cache; isc_task_t *task; dns_dbversion_t *version;};struct viewlistentry { dns_view_t *view; ISC_LINK(struct viewlistentry) link; ISC_LIST(struct zonelistentry) zonelist;};struct zonelistentry { dns_zone_t *zone; ISC_LINK(struct zonelistentry) link;};static voidfatal(const char *msg, isc_result_t result);static voidns_server_reload(isc_task_t *task, isc_event_t *event);static isc_result_tns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config, ns_aclconfctx_t *actx, isc_mem_t *mctx, ns_listenelt_t **target);static isc_result_tns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config, ns_aclconfctx_t *actx, isc_mem_t *mctx, ns_listenlist_t **target);static isc_result_tconfigure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, cfg_obj_t *forwarders, cfg_obj_t *forwardtype);static isc_result_tconfigure_alternates(cfg_obj_t *config, dns_view_t *view, cfg_obj_t *alternates);static isc_result_tconfigure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, ns_aclconfctx_t *aclconf);static voidend_reserved_dispatches(ns_server_t *server, isc_boolean_t all);/* * Configure a single view ACL at '*aclp'. Get its configuration by * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl' * (for a global default). */static isc_result_tconfigure_view_acl(cfg_obj_t *vconfig, cfg_obj_t *config, const char *aclname, ns_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp){ isc_result_t result; cfg_obj_t *maps[3]; cfg_obj_t *aclobj = NULL; int i = 0; if (*aclp != NULL) dns_acl_detach(aclp); if (vconfig != NULL) maps[i++] = cfg_tuple_get(vconfig, "options"); if (config != NULL) { cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); if (options != NULL) maps[i++] = options; } maps[i] = NULL; result = ns_config_get(maps, aclname, &aclobj); if (aclobj == NULL) /* * No value available. *aclp == NULL. */ return (ISC_R_SUCCESS); result = ns_acl_fromconfig(aclobj, config, actx, mctx, aclp); return (result);}static isc_result_tconfigure_view_dnsseckey(cfg_obj_t *vconfig, cfg_obj_t *key, dns_keytable_t *keytable, isc_mem_t *mctx){ dns_rdataclass_t viewclass; dns_rdata_dnskey_t keystruct; isc_uint32_t flags, proto, alg; char *keystr, *keynamestr; unsigned char keydata[4096]; isc_buffer_t keydatabuf; unsigned char rrdata[4096]; isc_buffer_t rrdatabuf; isc_region_t r; dns_fixedname_t fkeyname; dns_name_t *keyname; isc_buffer_t namebuf; isc_result_t result; dst_key_t *dstkey = NULL; flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); keyname = dns_fixedname_name(&fkeyname); keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); if (vconfig == NULL) viewclass = dns_rdataclass_in; else { cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class"); CHECK(ns_config_getclass(classobj, dns_rdataclass_in, &viewclass)); } keystruct.common.rdclass = viewclass; keystruct.common.rdtype = dns_rdatatype_dnskey; /* * The key data in keystruct is not dynamically allocated. */ keystruct.mctx = NULL; ISC_LINK_INIT(&keystruct.common, link); if (flags > 0xffff) CHECKM(ISC_R_RANGE, "key flags"); if (proto > 0xff) CHECKM(ISC_R_RANGE, "key protocol"); if (alg > 0xff) CHECKM(ISC_R_RANGE, "key algorithm"); keystruct.flags = (isc_uint16_t)flags; keystruct.protocol = (isc_uint8_t)proto; keystruct.algorithm = (isc_uint8_t)alg; isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); CHECK(isc_base64_decodestring(keystr, &keydatabuf)); isc_buffer_usedregion(&keydatabuf, &r); keystruct.datalen = r.length; keystruct.data = r.base; CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, keystruct.common.rdtype, &keystruct, &rrdatabuf)); dns_fixedname_init(&fkeyname); isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); isc_buffer_add(&namebuf, strlen(keynamestr)); CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, ISC_FALSE, NULL)); CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, mctx, &dstkey)); CHECK(dns_keytable_add(keytable, &dstkey)); INSIST(dstkey == NULL); return (ISC_R_SUCCESS); cleanup: if (result == DST_R_NOCRYPTO) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, "ignoring trusted key for '%s': no crypto support", keynamestr); result = ISC_R_SUCCESS; } else { cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, "configuring trusted key for '%s': %s", keynamestr, isc_result_totext(result)); result = ISC_R_FAILURE; } if (dstkey != NULL) dst_key_free(&dstkey); return (result);}/* * Configure DNSSEC keys for a view. Currently used only for * the security roots. * * The per-view configuration values and the server-global defaults are read * from 'vconfig' and 'config'. The variable to be configured is '*target'. */static isc_result_tconfigure_view_dnsseckeys(cfg_obj_t *vconfig, cfg_obj_t *config, isc_mem_t *mctx, dns_keytable_t **target){ isc_result_t result; cfg_obj_t *keys = NULL; cfg_obj_t *voptions = NULL; cfg_listelt_t *element, *element2; cfg_obj_t *keylist; cfg_obj_t *key; dns_keytable_t *keytable = NULL; CHECK(dns_keytable_create(mctx, &keytable)); if (vconfig != NULL) voptions = cfg_tuple_get(vconfig, "options"); keys = NULL; if (voptions != NULL) (void)cfg_map_get(voptions, "trusted-keys", &keys); if (keys == NULL) (void)cfg_map_get(config, "trusted-keys", &keys); for (element = cfg_list_first(keys); element != NULL; element = cfg_list_next(element)) { keylist = cfg_listelt_value(element); for (element2 = cfg_list_first(keylist); element2 != NULL; element2 = cfg_list_next(element2)) { key = cfg_listelt_value(element2); CHECK(configure_view_dnsseckey(vconfig, key, keytable, mctx)); } } dns_keytable_detach(target); *target = keytable; /* Transfer ownership. */ keytable = NULL; result = ISC_R_SUCCESS; cleanup: return (result);}static isc_result_tmustbesecure(cfg_obj_t *mbs, dns_resolver_t *resolver){ cfg_listelt_t *element; cfg_obj_t *obj; const char *str; dns_fixedname_t fixed; dns_name_t *name; isc_boolean_t value; isc_result_t result; isc_buffer_t b; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); for (element = cfg_list_first(mbs); element != NULL; element = cfg_list_next(element)) { obj = cfg_listelt_value(element); str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL)); value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); CHECK(dns_resolver_setmustbesecure(resolver, name, value)); } result = ISC_R_SUCCESS; cleanup: return (result);}/* * Get a dispatch appropriate for the resolver of a given view. */static isc_result_tget_view_querysource_dispatch(cfg_obj_t **maps, int af, dns_dispatch_t **dispatchp){ isc_result_t result; dns_dispatch_t *disp; isc_sockaddr_t sa; unsigned int attrs, attrmask; cfg_obj_t *obj = NULL; /* * Make compiler happy. */ result = ISC_R_FAILURE; switch (af) { case AF_INET: result = ns_config_get(maps, "query-source", &obj); INSIST(result == ISC_R_SUCCESS); break; case AF_INET6: result = ns_config_get(maps, "query-source-v6", &obj); INSIST(result == ISC_R_SUCCESS); break; default: INSIST(0); } sa = *(cfg_obj_assockaddr(obj)); INSIST(isc_sockaddr_pf(&sa) == af); /* * If we don't support this address family, we're done! */ switch (af) { case AF_INET: result = isc_net_probeipv4(); break; case AF_INET6: result = isc_net_probeipv6(); break; default: INSIST(0); } if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); /* * Try to find a dispatcher that we can share. */ attrs = 0; attrs |= DNS_DISPATCHATTR_UDP; switch (af) { case AF_INET: attrs |= DNS_DISPATCHATTR_IPV4; break; case AF_INET6: attrs |= DNS_DISPATCHATTR_IPV6; break; } attrmask = 0; attrmask |= DNS_DISPATCHATTR_UDP; attrmask |= DNS_DISPATCHATTR_TCP; attrmask |= DNS_DISPATCHATTR_IPV4; attrmask |= DNS_DISPATCHATTR_IPV6; disp = NULL; result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, ns_g_taskmgr, &sa, 4096, 1000, 32768, 16411, 16433,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -