📄 server.c
字号:
/* * 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 INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM 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.18 2003/09/19 13:40:42 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/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/cfg.h>#include <isccfg/check.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/peer.h>#include <dns/rdataclass.h>#include <dns/rdatastruct.h>#include <dns/resolver.h>#include <dns/rootns.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/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 CHECKFATAL(op, msg) \ do { result = (op); \ if (result != ISC_R_SUCCESS) \ fatal(msg, result); \ } while (0) \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_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);/* * 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; 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);}#ifdef ISC_RFC2535static 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_key_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_key; /* * 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);}#endif/* * 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;#ifdef ISC_RFC2535 cfg_obj_t *keys = NULL; cfg_obj_t *voptions = NULL; cfg_listelt_t *element, *element2; cfg_obj_t *keylist; cfg_obj_t *key;#endif dns_keytable_t *keytable = NULL; CHECK(dns_keytable_create(mctx, &keytable));#ifndef ISC_RFC2535 UNUSED(vconfig); UNUSED(config);#else 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)); } }#endif dns_keytable_detach(target); *target = keytable; /* Transfer ownership. */ keytable = NULL; 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, attrs, attrmask, &disp); if (result != ISC_R_SUCCESS) { isc_sockaddr_t any; char buf[ISC_SOCKADDR_FORMATSIZE]; switch (af) { case AF_INET: isc_sockaddr_any(&any); break; case AF_INET6: isc_sockaddr_any6(&any); break; } if (isc_sockaddr_equal(&sa, &any)) return (ISC_R_SUCCESS); isc_sockaddr_format(&sa, buf, sizeof(buf)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "could not get query source dispatcher (%s)", buf); return (result); } *dispatchp = disp; return (ISC_R_SUCCESS);}static isc_result_tconfigure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { isc_sockaddr_t *sa; isc_netaddr_t na; dns_peer_t *peer; cfg_obj_t *obj; char *str; isc_result_t result; sa = cfg_obj_assockaddr(cfg_map_getname(cpeer)); isc_netaddr_fromsockaddr(&na, sa); peer = NULL; result = dns_peer_new(mctx, &na, &peer); if (result != ISC_R_SUCCESS) return (result); obj = NULL; (void)cfg_map_get(cpeer, "bogus", &obj); if (obj != NULL) dns_peer_setbogus(peer, cfg_obj_asboolean(obj)); obj = NULL; (void)cfg_map_get(cpeer, "provide-ixfr", &obj); if (obj != NULL) dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)); obj = NULL; (void)cfg_map_get(cpeer, "request-ixfr", &obj); if (obj != NULL) dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)); obj = NULL; (void)cfg_map_get(cpeer, "edns", &obj); if (obj != NULL) dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)); obj = NULL; (void)cfg_map_get(cpeer, "transfers", &obj); if (obj != NULL) dns_peer_settransfers(peer, cfg_obj_asuint32(obj)); obj = NULL; (void)cfg_map_get(cpeer, "transfer-format", &obj); if (obj != NULL) { str = cfg_obj_asstring(obj); if (strcasecmp(str, "many-answers") == 0) dns_peer_settransferformat(peer, dns_many_answers); else if (strcasecmp(str, "one-answer") == 0) dns_peer_settransferformat(peer, dns_one_answer); else INSIST(0); } obj = NULL; (void)cfg_map_get(cpeer, "keys", &obj); if (obj != NULL) { result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); if (result != ISC_R_SUCCESS) goto cleanup; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -