📄 server.c
字号:
/* * Copyright (C) 2004-2006 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.419.18.49 2006/12/07 05:24:19 marka Exp $ *//*! \file */#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/acache.h>#include <dns/adb.h>#include <dns/cache.h>#include <dns/db.h>#include <dns/dispatch.h>#ifdef DLZ#include <dns/dlz.h>#endif#include <dns/forward.h>#include <dns/journal.h>#include <dns/keytable.h>#include <dns/lib.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>#ifdef HAVE_LIBSCF#include <named/ns_smf_globals.h>#include <stdlib.h>#endif/*% * 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;};/* * These zones should not leak onto the Internet. */static const struct { const char *zone; isc_boolean_t rfc1918;} empty_zones[] = {#ifdef notyet /* RFC 1918 */ { "10.IN-ADDR.ARPA", ISC_TRUE }, { "16.172.IN-ADDR.ARPA", ISC_TRUE }, { "17.172.IN-ADDR.ARPA", ISC_TRUE }, { "18.172.IN-ADDR.ARPA", ISC_TRUE }, { "19.172.IN-ADDR.ARPA", ISC_TRUE }, { "20.172.IN-ADDR.ARPA", ISC_TRUE }, { "21.172.IN-ADDR.ARPA", ISC_TRUE }, { "22.172.IN-ADDR.ARPA", ISC_TRUE }, { "23.172.IN-ADDR.ARPA", ISC_TRUE }, { "24.172.IN-ADDR.ARPA", ISC_TRUE }, { "25.172.IN-ADDR.ARPA", ISC_TRUE }, { "26.172.IN-ADDR.ARPA", ISC_TRUE }, { "27.172.IN-ADDR.ARPA", ISC_TRUE }, { "28.172.IN-ADDR.ARPA", ISC_TRUE }, { "29.172.IN-ADDR.ARPA", ISC_TRUE }, { "30.172.IN-ADDR.ARPA", ISC_TRUE }, { "31.172.IN-ADDR.ARPA", ISC_TRUE }, { "168.192.IN-ADDR.ARPA", ISC_TRUE },#endif /* RFC 3330 */ { "127.IN-ADDR.ARPA", ISC_FALSE }, /* LOOPBACK */ { "254.169.IN-ADDR.ARPA", ISC_FALSE }, /* LINK LOCAL */ { "2.0.192.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET */ { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE }, /* BROADCAST */ /* Local IPv6 Unicast Addresses */ { "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE }, { "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE }, /* LOCALLY ASSIGNED LOCAL ADDRES S SCOPE */ { "D.F.IP6.ARPA", ISC_FALSE }, { "8.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ { "9.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ { "A.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ { "B.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ { NULL, ISC_FALSE }};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(const cfg_obj_t *listener, const cfg_obj_t *config, cfg_aclconfctx_t *actx, isc_mem_t *mctx, ns_listenelt_t **target);static isc_result_tns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, cfg_aclconfctx_t *actx, isc_mem_t *mctx, ns_listenlist_t **target);static isc_result_tconfigure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype);static isc_result_tconfigure_alternates(const cfg_obj_t *config, dns_view_t *view, const cfg_obj_t *alternates);static isc_result_tconfigure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, cfg_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(const cfg_obj_t *vconfig, const cfg_obj_t *config, const char *aclname, cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp){ isc_result_t result; const cfg_obj_t *maps[3]; const 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) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); if (options != NULL) maps[i++] = options; } maps[i] = NULL; (void)ns_config_get(maps, aclname, &aclobj); if (aclobj == NULL) /* * No value available. *aclp == NULL. */ return (ISC_R_SUCCESS); result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx, mctx, aclp); return (result);}static isc_result_tconfigure_view_dnsseckey(const cfg_obj_t *vconfig, const 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; const 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 { const 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; if ((keystruct.algorithm == DST_ALG_RSASHA1 || keystruct.algorithm == DST_ALG_RSAMD5) && r.length > 1 && r.base[0] == 1 && r.base[1] == 3) cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "trusted key '%s' has a weak exponent", keynamestr); 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(const cfg_obj_t *vconfig, const cfg_obj_t *config, isc_mem_t *mctx, dns_keytable_t **target){ isc_result_t result; const cfg_obj_t *keys = NULL; const cfg_obj_t *voptions = NULL; const cfg_listelt_t *element, *element2; const cfg_obj_t *keylist; const 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(const cfg_obj_t *mbs, dns_resolver_t *resolver){ const cfg_listelt_t *element; const 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_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -