2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: server.c,v 1.339.2.15.2.59 2004/11/10 22:13:56 marka Exp $ */
25 #include <isc/base64.h>
27 #include <isc/entropy.h>
31 #include <isc/parseint.h>
32 #include <isc/print.h>
33 #include <isc/resource.h>
34 #include <isc/stdio.h>
35 #include <isc/string.h>
37 #include <isc/timer.h>
40 #include <isccfg/namedconf.h>
42 #include <bind9/check.h>
45 #include <dns/cache.h>
47 #include <dns/dispatch.h>
48 #include <dns/forward.h>
49 #include <dns/journal.h>
50 #include <dns/keytable.h>
51 #include <dns/master.h>
52 #include <dns/masterdump.h>
53 #include <dns/order.h>
55 #include <dns/portlist.h>
56 #include <dns/rdataclass.h>
57 #include <dns/rdataset.h>
58 #include <dns/rdatastruct.h>
59 #include <dns/resolver.h>
60 #include <dns/rootns.h>
61 #include <dns/secalg.h>
62 #include <dns/stats.h>
69 #include <dst/result.h>
71 #include <named/client.h>
72 #include <named/config.h>
73 #include <named/control.h>
74 #include <named/interfacemgr.h>
75 #include <named/log.h>
76 #include <named/logconf.h>
77 #include <named/lwresd.h>
78 #include <named/main.h>
80 #include <named/server.h>
81 #include <named/tkeyconf.h>
82 #include <named/tsigconf.h>
83 #include <named/zoneconf.h>
86 * Check an operation for failure. Assumes that the function
87 * using it has a 'result' variable and a 'cleanup' label.
91 if (result != ISC_R_SUCCESS) goto cleanup; \
94 #define CHECKM(op, msg) \
96 if (result != ISC_R_SUCCESS) { \
97 isc_log_write(ns_g_lctx, \
98 NS_LOGCATEGORY_GENERAL, \
99 NS_LOGMODULE_SERVER, \
102 isc_result_totext(result)); \
107 #define CHECKMF(op, msg, file) \
108 do { result = (op); \
109 if (result != ISC_R_SUCCESS) { \
110 isc_log_write(ns_g_lctx, \
111 NS_LOGCATEGORY_GENERAL, \
112 NS_LOGMODULE_SERVER, \
114 "%s '%s': %s", msg, file, \
115 isc_result_totext(result)); \
120 #define CHECKFATAL(op, msg) \
121 do { result = (op); \
122 if (result != ISC_R_SUCCESS) \
123 fatal(msg, result); \
128 unsigned int dispatchgen;
129 dns_dispatch_t *dispatch;
130 ISC_LINK(struct ns_dispatch) link;
135 isc_boolean_t dumpcache;
136 isc_boolean_t dumpzones;
138 ISC_LIST(struct viewlistentry) viewlist;
139 struct viewlistentry *view;
140 struct zonelistentry *zone;
141 dns_dumpctx_t *mdctx;
145 dns_dbversion_t *version;
148 struct viewlistentry {
150 ISC_LINK(struct viewlistentry) link;
151 ISC_LIST(struct zonelistentry) zonelist;
154 struct zonelistentry {
156 ISC_LINK(struct zonelistentry) link;
160 fatal(const char *msg, isc_result_t result);
163 ns_server_reload(isc_task_t *task, isc_event_t *event);
166 ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config,
167 ns_aclconfctx_t *actx,
168 isc_mem_t *mctx, ns_listenelt_t **target);
170 ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config,
171 ns_aclconfctx_t *actx,
172 isc_mem_t *mctx, ns_listenlist_t **target);
175 configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
176 cfg_obj_t *forwarders, cfg_obj_t *forwardtype);
179 configure_alternates(cfg_obj_t *config, dns_view_t *view,
180 cfg_obj_t *alternates);
183 configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
184 isc_mem_t *mctx, dns_view_t *view,
185 ns_aclconfctx_t *aclconf);
188 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
191 * Configure a single view ACL at '*aclp'. Get its configuration by
192 * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl'
193 * (for a global default).
196 configure_view_acl(cfg_obj_t *vconfig, cfg_obj_t *config,
197 const char *aclname, ns_aclconfctx_t *actx,
198 isc_mem_t *mctx, dns_acl_t **aclp)
202 cfg_obj_t *aclobj = NULL;
206 dns_acl_detach(aclp);
208 maps[i++] = cfg_tuple_get(vconfig, "options");
209 if (config != NULL) {
210 cfg_obj_t *options = NULL;
211 (void)cfg_map_get(config, "options", &options);
217 result = ns_config_get(maps, aclname, &aclobj);
220 * No value available. *aclp == NULL.
222 return (ISC_R_SUCCESS);
224 result = ns_acl_fromconfig(aclobj, config, actx, mctx, aclp);
230 configure_view_dnsseckey(cfg_obj_t *vconfig, cfg_obj_t *key,
231 dns_keytable_t *keytable, isc_mem_t *mctx)
233 dns_rdataclass_t viewclass;
234 dns_rdata_dnskey_t keystruct;
235 isc_uint32_t flags, proto, alg;
236 char *keystr, *keynamestr;
237 unsigned char keydata[4096];
238 isc_buffer_t keydatabuf;
239 unsigned char rrdata[4096];
240 isc_buffer_t rrdatabuf;
242 dns_fixedname_t fkeyname;
244 isc_buffer_t namebuf;
246 dst_key_t *dstkey = NULL;
248 flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
249 proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
250 alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
251 keyname = dns_fixedname_name(&fkeyname);
252 keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
255 viewclass = dns_rdataclass_in;
257 cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
258 CHECK(ns_config_getclass(classobj, dns_rdataclass_in,
261 keystruct.common.rdclass = viewclass;
262 keystruct.common.rdtype = dns_rdatatype_dnskey;
264 * The key data in keystruct is not dynamically allocated.
266 keystruct.mctx = NULL;
268 ISC_LINK_INIT(&keystruct.common, link);
271 CHECKM(ISC_R_RANGE, "key flags");
273 CHECKM(ISC_R_RANGE, "key protocol");
275 CHECKM(ISC_R_RANGE, "key algorithm");
276 keystruct.flags = (isc_uint16_t)flags;
277 keystruct.protocol = (isc_uint8_t)proto;
278 keystruct.algorithm = (isc_uint8_t)alg;
280 isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
281 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
283 keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
284 CHECK(isc_base64_decodestring(keystr, &keydatabuf));
285 isc_buffer_usedregion(&keydatabuf, &r);
286 keystruct.datalen = r.length;
287 keystruct.data = r.base;
289 CHECK(dns_rdata_fromstruct(NULL,
290 keystruct.common.rdclass,
291 keystruct.common.rdtype,
292 &keystruct, &rrdatabuf));
293 dns_fixedname_init(&fkeyname);
294 isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr));
295 isc_buffer_add(&namebuf, strlen(keynamestr));
296 CHECK(dns_name_fromtext(keyname, &namebuf,
297 dns_rootname, ISC_FALSE,
299 CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
302 CHECK(dns_keytable_add(keytable, &dstkey));
303 INSIST(dstkey == NULL);
304 return (ISC_R_SUCCESS);
307 if (result == DST_R_NOCRYPTO) {
308 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
309 "ignoring trusted key for '%s': no crypto support",
311 result = ISC_R_SUCCESS;
313 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
314 "configuring trusted key for '%s': %s",
315 keynamestr, isc_result_totext(result));
316 result = ISC_R_FAILURE;
320 dst_key_free(&dstkey);
326 * Configure DNSSEC keys for a view. Currently used only for
327 * the security roots.
329 * The per-view configuration values and the server-global defaults are read
330 * from 'vconfig' and 'config'. The variable to be configured is '*target'.
333 configure_view_dnsseckeys(cfg_obj_t *vconfig, cfg_obj_t *config,
334 isc_mem_t *mctx, dns_keytable_t **target)
337 cfg_obj_t *keys = NULL;
338 cfg_obj_t *voptions = NULL;
339 cfg_listelt_t *element, *element2;
342 dns_keytable_t *keytable = NULL;
344 CHECK(dns_keytable_create(mctx, &keytable));
347 voptions = cfg_tuple_get(vconfig, "options");
350 if (voptions != NULL)
351 (void)cfg_map_get(voptions, "trusted-keys", &keys);
353 (void)cfg_map_get(config, "trusted-keys", &keys);
355 for (element = cfg_list_first(keys);
357 element = cfg_list_next(element))
359 keylist = cfg_listelt_value(element);
360 for (element2 = cfg_list_first(keylist);
362 element2 = cfg_list_next(element2))
364 key = cfg_listelt_value(element2);
365 CHECK(configure_view_dnsseckey(vconfig, key,
370 dns_keytable_detach(target);
371 *target = keytable; /* Transfer ownership. */
373 result = ISC_R_SUCCESS;
380 mustbesecure(cfg_obj_t *mbs, dns_resolver_t *resolver)
382 cfg_listelt_t *element;
385 dns_fixedname_t fixed;
391 dns_fixedname_init(&fixed);
392 name = dns_fixedname_name(&fixed);
393 for (element = cfg_list_first(mbs);
395 element = cfg_list_next(element))
397 obj = cfg_listelt_value(element);
398 str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
399 isc_buffer_init(&b, str, strlen(str));
400 isc_buffer_add(&b, strlen(str));
401 CHECK(dns_name_fromtext(name, &b, dns_rootname,
403 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
404 CHECK(dns_resolver_setmustbesecure(resolver, name, value));
407 result = ISC_R_SUCCESS;
414 * Get a dispatch appropriate for the resolver of a given view.
417 get_view_querysource_dispatch(cfg_obj_t **maps,
418 int af, dns_dispatch_t **dispatchp)
421 dns_dispatch_t *disp;
423 unsigned int attrs, attrmask;
424 cfg_obj_t *obj = NULL;
427 * Make compiler happy.
429 result = ISC_R_FAILURE;
433 result = ns_config_get(maps, "query-source", &obj);
434 INSIST(result == ISC_R_SUCCESS);
438 result = ns_config_get(maps, "query-source-v6", &obj);
439 INSIST(result == ISC_R_SUCCESS);
445 sa = *(cfg_obj_assockaddr(obj));
446 INSIST(isc_sockaddr_pf(&sa) == af);
449 * If we don't support this address family, we're done!
453 result = isc_net_probeipv4();
456 result = isc_net_probeipv6();
461 if (result != ISC_R_SUCCESS)
462 return (ISC_R_SUCCESS);
465 * Try to find a dispatcher that we can share.
468 attrs |= DNS_DISPATCHATTR_UDP;
471 attrs |= DNS_DISPATCHATTR_IPV4;
474 attrs |= DNS_DISPATCHATTR_IPV6;
478 attrmask |= DNS_DISPATCHATTR_UDP;
479 attrmask |= DNS_DISPATCHATTR_TCP;
480 attrmask |= DNS_DISPATCHATTR_IPV4;
481 attrmask |= DNS_DISPATCHATTR_IPV6;
484 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
485 ns_g_taskmgr, &sa, 4096,
486 1000, 32768, 16411, 16433,
487 attrs, attrmask, &disp);
488 if (result != ISC_R_SUCCESS) {
490 char buf[ISC_SOCKADDR_FORMATSIZE];
494 isc_sockaddr_any(&any);
497 isc_sockaddr_any6(&any);
500 if (isc_sockaddr_equal(&sa, &any))
501 return (ISC_R_SUCCESS);
502 isc_sockaddr_format(&sa, buf, sizeof(buf));
503 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
504 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
505 "could not get query source dispatcher (%s)",
512 return (ISC_R_SUCCESS);
516 configure_order(dns_order_t *order, cfg_obj_t *ent) {
517 dns_rdataclass_t rdclass;
518 dns_rdatatype_t rdtype;
520 dns_fixedname_t fixed;
521 unsigned int mode = 0;
525 isc_boolean_t addroot;
527 result = ns_config_getclass(cfg_tuple_get(ent, "class"),
528 dns_rdataclass_any, &rdclass);
529 if (result != ISC_R_SUCCESS)
532 result = ns_config_gettype(cfg_tuple_get(ent, "type"),
533 dns_rdatatype_any, &rdtype);
534 if (result != ISC_R_SUCCESS)
537 obj = cfg_tuple_get(ent, "name");
538 if (cfg_obj_isstring(obj))
539 str = cfg_obj_asstring(obj);
542 addroot = ISC_TF(strcmp(str, "*") == 0);
543 isc_buffer_init(&b, str, strlen(str));
544 isc_buffer_add(&b, strlen(str));
545 dns_fixedname_init(&fixed);
546 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
547 dns_rootname, ISC_FALSE, NULL);
548 if (result != ISC_R_SUCCESS)
551 obj = cfg_tuple_get(ent, "ordering");
552 INSIST(cfg_obj_isstring(obj));
553 str = cfg_obj_asstring(obj);
554 if (!strcasecmp(str, "fixed"))
555 mode = DNS_RDATASETATTR_FIXEDORDER;
556 else if (!strcasecmp(str, "random"))
557 mode = DNS_RDATASETATTR_RANDOMIZE;
558 else if (!strcasecmp(str, "cyclic"))
564 * "*" should match everything including the root (BIND 8 compat).
565 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a
566 * explict entry for "." when the name is "*".
569 result = dns_order_add(order, dns_rootname,
570 rdtype, rdclass, mode);
571 if (result != ISC_R_SUCCESS)
575 return (dns_order_add(order, dns_fixedname_name(&fixed),
576 rdtype, rdclass, mode));
580 configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
588 sa = cfg_obj_assockaddr(cfg_map_getname(cpeer));
589 isc_netaddr_fromsockaddr(&na, sa);
592 result = dns_peer_new(mctx, &na, &peer);
593 if (result != ISC_R_SUCCESS)
597 (void)cfg_map_get(cpeer, "bogus", &obj);
599 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
602 (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
604 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
607 (void)cfg_map_get(cpeer, "request-ixfr", &obj);
609 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
612 (void)cfg_map_get(cpeer, "edns", &obj);
614 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
617 (void)cfg_map_get(cpeer, "transfers", &obj);
619 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
622 (void)cfg_map_get(cpeer, "transfer-format", &obj);
624 str = cfg_obj_asstring(obj);
625 if (strcasecmp(str, "many-answers") == 0)
626 CHECK(dns_peer_settransferformat(peer,
628 else if (strcasecmp(str, "one-answer") == 0)
629 CHECK(dns_peer_settransferformat(peer,
636 (void)cfg_map_get(cpeer, "keys", &obj);
638 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
639 if (result != ISC_R_SUCCESS)
644 if (isc_sockaddr_pf(sa) == AF_INET)
645 (void)cfg_map_get(cpeer, "transfer-source", &obj);
647 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
649 result = dns_peer_settransfersource(peer,
650 cfg_obj_assockaddr(obj));
651 if (result != ISC_R_SUCCESS)
655 return (ISC_R_SUCCESS);
658 dns_peer_detach(&peer);
663 disable_algorithms(cfg_obj_t *disabled, dns_resolver_t *resolver) {
665 cfg_obj_t *algorithms;
666 cfg_listelt_t *element;
668 dns_fixedname_t fixed;
672 dns_fixedname_init(&fixed);
673 name = dns_fixedname_name(&fixed);
674 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
675 isc_buffer_init(&b, str, strlen(str));
676 isc_buffer_add(&b, strlen(str));
677 CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL));
679 algorithms = cfg_tuple_get(disabled, "algorithms");
680 for (element = cfg_list_first(algorithms);
682 element = cfg_list_next(element))
687 r.base = cfg_obj_asstring(cfg_listelt_value(element));
688 r.length = strlen(r.base);
690 result = dns_secalg_fromtext(&alg, &r);
691 if (result != ISC_R_SUCCESS) {
693 result = isc_parse_uint8(&ui, r.base, 10);
696 if (result != ISC_R_SUCCESS) {
697 cfg_obj_log(cfg_listelt_value(element),
698 ns_g_lctx, ISC_LOG_ERROR,
699 "invalid algorithm");
702 CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
709 * Configure 'view' according to 'vconfig', taking defaults from 'config'
710 * where values are missing in 'vconfig'.
712 * When configuring the default view, 'vconfig' will be NULL and the
713 * global defaults in 'config' used exclusively.
716 configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
717 isc_mem_t *mctx, ns_aclconfctx_t *actx,
718 isc_boolean_t need_hints)
721 cfg_obj_t *cfgmaps[3];
722 cfg_obj_t *options = NULL;
723 cfg_obj_t *voptions = NULL;
724 cfg_obj_t *forwardtype;
725 cfg_obj_t *forwarders;
726 cfg_obj_t *alternates;
730 cfg_listelt_t *element;
732 dns_cache_t *cache = NULL;
734 isc_uint32_t max_adb_size;
735 isc_uint32_t max_cache_size;
736 isc_uint32_t lame_ttl;
737 dns_tsig_keyring_t *ring;
738 dns_view_t *pview = NULL; /* Production view */
740 dns_dispatch_t *dispatch4 = NULL;
741 dns_dispatch_t *dispatch6 = NULL;
742 isc_boolean_t reused_cache = ISC_FALSE;
745 dns_order_t *order = NULL;
746 isc_uint32_t udpsize;
747 unsigned int check = 0;
749 REQUIRE(DNS_VIEW_VALID(view));
754 (void)cfg_map_get(config, "options", &options);
757 if (vconfig != NULL) {
758 voptions = cfg_tuple_get(vconfig, "options");
759 maps[i++] = voptions;
763 maps[i++] = ns_g_defaults;
767 if (voptions != NULL)
768 cfgmaps[i++] = voptions;
770 cfgmaps[i++] = config;
774 * Set the view's port number for outgoing queries.
776 CHECKM(ns_config_getport(config, &port), "port");
777 dns_view_setdstport(view, port);
780 * Configure the zones.
783 if (voptions != NULL)
784 (void)cfg_map_get(voptions, "zone", &zonelist);
786 (void)cfg_map_get(config, "zone", &zonelist);
787 for (element = cfg_list_first(zonelist);
789 element = cfg_list_next(element))
791 cfg_obj_t *zconfig = cfg_listelt_value(element);
792 CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
797 * Configure the view's cache. Try to reuse an existing
798 * cache if possible, otherwise create a new cache.
799 * Note that the ADB is not preserved in either case.
801 * XXX Determining when it is safe to reuse a cache is
802 * tricky. When the view's configuration changes, the cached
803 * data may become invalid because it reflects our old
804 * view of the world. As more view attributes become
805 * configurable, we will have to add code here to check
806 * whether they have changed in ways that could
807 * invalidate the cache.
809 result = dns_viewlist_find(&ns_g_server->viewlist,
810 view->name, view->rdclass,
812 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
815 INSIST(pview->cache != NULL);
816 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
817 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3),
818 "reusing existing cache");
819 reused_cache = ISC_TRUE;
820 dns_cache_attach(pview->cache, &cache);
821 dns_view_detach(&pview);
823 CHECK(isc_mem_create(0, 0, &cmctx));
824 CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr,
825 view->rdclass, "rbt", 0, NULL, &cache));
827 dns_view_setcache(view, cache);
830 * cache-file cannot be inherited if views are present, but this
831 * should be caught by the configuration checking stage.
834 result = ns_config_get(maps, "cache-file", &obj);
835 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) {
836 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj)));
838 CHECK(dns_cache_load(cache));
842 result = ns_config_get(maps, "cleaning-interval", &obj);
843 INSIST(result == ISC_R_SUCCESS);
844 dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60);
847 result = ns_config_get(maps, "max-cache-size", &obj);
848 INSIST(result == ISC_R_SUCCESS);
849 if (cfg_obj_isstring(obj)) {
850 str = cfg_obj_asstring(obj);
851 INSIST(strcasecmp(str, "unlimited") == 0);
852 max_cache_size = ISC_UINT32_MAX;
854 isc_resourcevalue_t value;
855 value = cfg_obj_asuint64(obj);
856 if (value > ISC_UINT32_MAX) {
857 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
859 "%" ISC_PRINT_QUADFORMAT "d' is too large",
861 result = ISC_R_RANGE;
864 max_cache_size = (isc_uint32_t)value;
866 dns_cache_setcachesize(cache, max_cache_size);
868 dns_cache_detach(&cache);
874 result = ns_checknames_get(maps, "response", &obj);
875 INSIST(result == ISC_R_SUCCESS);
877 str = cfg_obj_asstring(obj);
878 if (strcasecmp(str, "fail") == 0) {
879 check = DNS_RESOLVER_CHECKNAMES |
880 DNS_RESOLVER_CHECKNAMESFAIL;
881 view->checknames = ISC_TRUE;
882 } else if (strcasecmp(str, "warn") == 0) {
883 check = DNS_RESOLVER_CHECKNAMES;
884 view->checknames = ISC_FALSE;
885 } else if (strcasecmp(str, "ignore") == 0) {
887 view->checknames = ISC_FALSE;
894 * XXXRTH Hardwired number of tasks.
896 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4));
897 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6));
898 if (dispatch4 == NULL && dispatch6 == NULL) {
899 UNEXPECTED_ERROR(__FILE__, __LINE__,
900 "unable to obtain neither an IPv4 nor"
901 " an IPv6 dispatch");
902 result = ISC_R_UNEXPECTED;
905 CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
906 ns_g_socketmgr, ns_g_timermgr,
907 check, ns_g_dispatchmgr,
908 dispatch4, dispatch6));
911 * Set the ADB cache size to 1/8th of the max-cache-size.
914 if (max_cache_size != 0) {
915 max_adb_size = max_cache_size / 8;
916 if (max_adb_size == 0)
917 max_adb_size = 1; /* Force minimum. */
919 dns_adb_setadbsize(view->adb, max_adb_size);
922 * Set resolver's lame-ttl.
925 result = ns_config_get(maps, "lame-ttl", &obj);
926 INSIST(result == ISC_R_SUCCESS);
927 lame_ttl = cfg_obj_asuint32(obj);
930 dns_resolver_setlamettl(view->resolver, lame_ttl);
933 * Set the resolver's EDNS UDP size.
936 result = ns_config_get(maps, "edns-udp-size", &obj);
937 INSIST(result == ISC_R_SUCCESS);
938 udpsize = cfg_obj_asuint32(obj);
943 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize);
946 * Set supported DNSSEC algorithms.
948 dns_resolver_reset_algorithms(view->resolver);
950 (void)ns_config_get(maps, "disable-algorithms", &disabled);
951 if (disabled != NULL) {
952 for (element = cfg_list_first(disabled);
954 element = cfg_list_next(element))
955 CHECK(disable_algorithms(cfg_listelt_value(element),
960 * A global or view "forwarders" option, if present,
961 * creates an entry for "." in the forwarding table.
965 (void)ns_config_get(maps, "forward", &forwardtype);
966 (void)ns_config_get(maps, "forwarders", &forwarders);
967 if (forwarders != NULL)
968 CHECK(configure_forward(config, view, dns_rootname,
969 forwarders, forwardtype));
972 * Dual Stack Servers.
975 (void)ns_config_get(maps, "dual-stack-servers", &alternates);
976 if (alternates != NULL)
977 CHECK(configure_alternates(config, view, alternates));
980 * We have default hints for class IN if we need them.
982 if (view->rdclass == dns_rdataclass_in && view->hints == NULL)
983 dns_view_sethints(view, ns_g_server->in_roothints);
986 * If we still have no hints, this is a non-IN view with no
987 * "hints zone" configured. Issue a warning, except if this
988 * is a root server. Root servers never need to consult
989 * their hints, so it's no point requiring users to configure
992 if (view->hints == NULL) {
993 dns_zone_t *rootzone = NULL;
994 (void)dns_view_findzone(view, dns_rootname, &rootzone);
995 if (rootzone != NULL) {
996 dns_zone_detach(&rootzone);
997 need_hints = ISC_FALSE;
1000 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1001 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1002 "no root hints for view '%s'",
1007 * Configure the view's TSIG keys.
1010 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
1011 dns_view_setkeyring(view, ring);
1014 * Configure the view's peer list.
1017 cfg_obj_t *peers = NULL;
1018 cfg_listelt_t *element;
1019 dns_peerlist_t *newpeers = NULL;
1021 (void)ns_config_get(cfgmaps, "server", &peers);
1022 CHECK(dns_peerlist_new(mctx, &newpeers));
1023 for (element = cfg_list_first(peers);
1025 element = cfg_list_next(element))
1027 cfg_obj_t *cpeer = cfg_listelt_value(element);
1030 CHECK(configure_peer(cpeer, mctx, &peer));
1031 dns_peerlist_addpeer(newpeers, peer);
1032 dns_peer_detach(&peer);
1034 dns_peerlist_detach(&view->peers);
1035 view->peers = newpeers; /* Transfer ownership. */
1039 * Configure the views rrset-order.
1042 cfg_obj_t *rrsetorder = NULL;
1043 cfg_listelt_t *element;
1045 (void)ns_config_get(maps, "rrset-order", &rrsetorder);
1046 CHECK(dns_order_create(mctx, &order));
1047 for (element = cfg_list_first(rrsetorder);
1049 element = cfg_list_next(element))
1051 cfg_obj_t *ent = cfg_listelt_value(element);
1053 CHECK(configure_order(order, ent));
1055 if (view->order != NULL)
1056 dns_order_detach(&view->order);
1057 dns_order_attach(order, &view->order);
1058 dns_order_detach(&order);
1061 * Copy the aclenv object.
1063 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv);
1066 * Configure the "match-clients" and "match-destinations" ACL.
1068 CHECK(configure_view_acl(vconfig, config, "match-clients", actx,
1069 ns_g_mctx, &view->matchclients));
1070 CHECK(configure_view_acl(vconfig, config, "match-destinations", actx,
1071 ns_g_mctx, &view->matchdestinations));
1074 * Configure the "match-recursive-only" option.
1077 (void) ns_config_get(maps, "match-recursive-only", &obj);
1078 if (obj != NULL && cfg_obj_asboolean(obj))
1079 view->matchrecursiveonly = ISC_TRUE;
1081 view->matchrecursiveonly = ISC_FALSE;
1084 * Configure other configurable data.
1087 result = ns_config_get(maps, "recursion", &obj);
1088 INSIST(result == ISC_R_SUCCESS);
1089 view->recursion = cfg_obj_asboolean(obj);
1092 result = ns_config_get(maps, "auth-nxdomain", &obj);
1093 INSIST(result == ISC_R_SUCCESS);
1094 view->auth_nxdomain = cfg_obj_asboolean(obj);
1097 result = ns_config_get(maps, "minimal-responses", &obj);
1098 INSIST(result == ISC_R_SUCCESS);
1099 view->minimalresponses = cfg_obj_asboolean(obj);
1102 result = ns_config_get(maps, "transfer-format", &obj);
1103 INSIST(result == ISC_R_SUCCESS);
1104 str = cfg_obj_asstring(obj);
1105 if (strcasecmp(str, "many-answers") == 0)
1106 view->transfer_format = dns_many_answers;
1107 else if (strcasecmp(str, "one-answer") == 0)
1108 view->transfer_format = dns_one_answer;
1113 * Set sources where additional data and CNAME/DNAME
1114 * targets for authoritative answers may be found.
1117 result = ns_config_get(maps, "additional-from-auth", &obj);
1118 INSIST(result == ISC_R_SUCCESS);
1119 view->additionalfromauth = cfg_obj_asboolean(obj);
1120 if (view->recursion && ! view->additionalfromauth) {
1121 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1122 "'additional-from-auth no' is only supported "
1123 "with 'recursion no'");
1124 view->additionalfromauth = ISC_TRUE;
1128 result = ns_config_get(maps, "additional-from-cache", &obj);
1129 INSIST(result == ISC_R_SUCCESS);
1130 view->additionalfromcache = cfg_obj_asboolean(obj);
1131 if (view->recursion && ! view->additionalfromcache) {
1132 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1133 "'additional-from-cache no' is only supported "
1134 "with 'recursion no'");
1135 view->additionalfromcache = ISC_TRUE;
1138 CHECK(configure_view_acl(vconfig, config, "allow-query",
1139 actx, ns_g_mctx, &view->queryacl));
1141 if (strcmp(view->name, "_bind") != 0)
1142 CHECK(configure_view_acl(vconfig, config, "allow-recursion",
1143 actx, ns_g_mctx, &view->recursionacl));
1146 * Warning if both "recursion no;" and allow-recursion are active
1147 * except for "allow-recursion { none; };".
1149 if (!view->recursion && view->recursionacl != NULL &&
1150 (view->recursionacl->length != 1 ||
1151 view->recursionacl->elements[0].type != dns_aclelementtype_any ||
1152 view->recursionacl->elements[0].negative != ISC_TRUE)) {
1153 const char *forview = " for view ";
1154 const char *viewname = view->name;
1156 if (!strcmp(view->name, "_bind") ||
1157 !strcmp(view->name, "_default")) {
1161 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1162 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1163 "both \"recursion no;\" and \"allow-recursion\" "
1164 "active%s%s", forview, viewname);
1167 CHECK(configure_view_acl(vconfig, config, "sortlist",
1168 actx, ns_g_mctx, &view->sortlist));
1171 result = ns_config_get(maps, "request-ixfr", &obj);
1172 INSIST(result == ISC_R_SUCCESS);
1173 view->requestixfr = cfg_obj_asboolean(obj);
1176 result = ns_config_get(maps, "provide-ixfr", &obj);
1177 INSIST(result == ISC_R_SUCCESS);
1178 view->provideixfr = cfg_obj_asboolean(obj);
1181 result = ns_config_get(maps, "dnssec-enable", &obj);
1182 INSIST(result == ISC_R_SUCCESS);
1183 view->enablednssec = cfg_obj_asboolean(obj);
1186 result = ns_config_get(maps, "dnssec-lookaside", &obj);
1187 if (result == ISC_R_SUCCESS) {
1188 for (element = cfg_list_first(obj);
1190 element = cfg_list_next(element))
1196 obj = cfg_listelt_value(element);
1198 dns_fixedname_t fixed;
1202 * When we support multiple dnssec-lookaside
1203 * entries this is how to find the domain to be
1206 dns_fixedname_init(&fixed);
1207 name = dns_fixedname_name(&fixed);
1208 str = cfg_obj_asstring(cfg_tuple_get(obj,
1210 isc_buffer_init(&b, str, strlen(str));
1211 isc_buffer_add(&b, strlen(str));
1212 CHECK(dns_name_fromtext(name, &b, dns_rootname,
1215 str = cfg_obj_asstring(cfg_tuple_get(obj,
1217 isc_buffer_init(&b, str, strlen(str));
1218 isc_buffer_add(&b, strlen(str));
1219 dlv = dns_fixedname_name(&view->dlv_fixed);
1220 CHECK(dns_name_fromtext(dlv, &b, dns_rootname,
1222 view->dlv = dns_fixedname_name(&view->dlv_fixed);
1228 * For now, there is only one kind of trusted keys, the
1231 if (view->enablednssec) {
1232 CHECK(configure_view_dnsseckeys(vconfig, config, mctx,
1234 dns_resolver_resetmustbesecure(view->resolver);
1236 result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
1237 if (result == ISC_R_SUCCESS)
1238 CHECK(mustbesecure(obj, view->resolver));
1242 result = ns_config_get(maps, "max-cache-ttl", &obj);
1243 INSIST(result == ISC_R_SUCCESS);
1244 view->maxcachettl = cfg_obj_asuint32(obj);
1247 result = ns_config_get(maps, "max-ncache-ttl", &obj);
1248 INSIST(result == ISC_R_SUCCESS);
1249 view->maxncachettl = cfg_obj_asuint32(obj);
1250 if (view->maxncachettl > 7 * 24 * 3600)
1251 view->maxncachettl = 7 * 24 * 3600;
1254 result = ns_config_get(maps, "preferred-glue", &obj);
1255 if (result == ISC_R_SUCCESS) {
1256 str = cfg_obj_asstring(obj);
1257 if (strcasecmp(str, "a") == 0)
1258 view->preferred_glue = dns_rdatatype_a;
1259 else if (strcasecmp(str, "aaaa") == 0)
1260 view->preferred_glue = dns_rdatatype_aaaa;
1262 view->preferred_glue = 0;
1264 view->preferred_glue = 0;
1267 result = ns_config_get(maps, "root-delegation-only", &obj);
1268 if (result == ISC_R_SUCCESS) {
1269 dns_view_setrootdelonly(view, ISC_TRUE);
1270 if (!cfg_obj_isvoid(obj)) {
1271 dns_fixedname_t fixed;
1277 dns_fixedname_init(&fixed);
1278 name = dns_fixedname_name(&fixed);
1279 for (element = cfg_list_first(obj);
1281 element = cfg_list_next(element)) {
1282 exclude = cfg_listelt_value(element);
1283 str = cfg_obj_asstring(exclude);
1284 isc_buffer_init(&b, str, strlen(str));
1285 isc_buffer_add(&b, strlen(str));
1286 CHECK(dns_name_fromtext(name, &b, dns_rootname,
1288 CHECK(dns_view_excludedelegationonly(view,
1293 dns_view_setrootdelonly(view, ISC_FALSE);
1295 result = ISC_R_SUCCESS;
1298 if (dispatch4 != NULL)
1299 dns_dispatch_detach(&dispatch4);
1300 if (dispatch6 != NULL)
1301 dns_dispatch_detach(&dispatch6);
1303 dns_order_detach(&order);
1305 isc_mem_detach(&cmctx);
1308 dns_cache_detach(&cache);
1314 configure_hints(dns_view_t *view, const char *filename) {
1315 isc_result_t result;
1319 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db);
1320 if (result == ISC_R_SUCCESS) {
1321 dns_view_sethints(view, db);
1329 configure_alternates(cfg_obj_t *config, dns_view_t *view,
1330 cfg_obj_t *alternates)
1333 cfg_obj_t *addresses;
1334 cfg_listelt_t *element;
1335 isc_result_t result = ISC_R_SUCCESS;
1339 * Determine which port to send requests to.
1341 if (ns_g_lwresdonly && ns_g_port != 0)
1344 CHECKM(ns_config_getport(config, &port), "port");
1346 if (alternates != NULL) {
1347 portobj = cfg_tuple_get(alternates, "port");
1348 if (cfg_obj_isuint32(portobj)) {
1349 isc_uint32_t val = cfg_obj_asuint32(portobj);
1350 if (val > ISC_UINT16_MAX) {
1351 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
1352 "port '%u' out of range", val);
1353 return (ISC_R_RANGE);
1355 port = (in_port_t) val;
1360 if (alternates != NULL)
1361 addresses = cfg_tuple_get(alternates, "addresses");
1363 for (element = cfg_list_first(addresses);
1365 element = cfg_list_next(element))
1367 cfg_obj_t *alternate = cfg_listelt_value(element);
1370 if (!cfg_obj_issockaddr(alternate)) {
1371 dns_fixedname_t fixed;
1373 char *str = cfg_obj_asstring(cfg_tuple_get(alternate,
1375 isc_buffer_t buffer;
1376 in_port_t myport = port;
1378 isc_buffer_init(&buffer, str, strlen(str));
1379 isc_buffer_add(&buffer, strlen(str));
1380 dns_fixedname_init(&fixed);
1381 name = dns_fixedname_name(&fixed);
1382 CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
1385 portobj = cfg_tuple_get(alternate, "port");
1386 if (cfg_obj_isuint32(portobj)) {
1387 isc_uint32_t val = cfg_obj_asuint32(portobj);
1388 if (val > ISC_UINT16_MAX) {
1389 cfg_obj_log(portobj, ns_g_lctx,
1391 "port '%u' out of range",
1393 return (ISC_R_RANGE);
1395 myport = (in_port_t) val;
1397 CHECK(dns_resolver_addalternate(view->resolver, NULL,
1402 sa = *cfg_obj_assockaddr(alternate);
1403 if (isc_sockaddr_getport(&sa) == 0)
1404 isc_sockaddr_setport(&sa, port);
1405 CHECK(dns_resolver_addalternate(view->resolver, &sa,
1414 configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
1415 cfg_obj_t *forwarders, cfg_obj_t *forwardtype)
1418 cfg_obj_t *faddresses;
1419 cfg_listelt_t *element;
1420 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
1421 isc_sockaddrlist_t addresses;
1423 isc_result_t result;
1427 * Determine which port to send forwarded requests to.
1429 if (ns_g_lwresdonly && ns_g_port != 0)
1432 CHECKM(ns_config_getport(config, &port), "port");
1434 if (forwarders != NULL) {
1435 portobj = cfg_tuple_get(forwarders, "port");
1436 if (cfg_obj_isuint32(portobj)) {
1437 isc_uint32_t val = cfg_obj_asuint32(portobj);
1438 if (val > ISC_UINT16_MAX) {
1439 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
1440 "port '%u' out of range", val);
1441 return (ISC_R_RANGE);
1443 port = (in_port_t) val;
1448 if (forwarders != NULL)
1449 faddresses = cfg_tuple_get(forwarders, "addresses");
1451 ISC_LIST_INIT(addresses);
1453 for (element = cfg_list_first(faddresses);
1455 element = cfg_list_next(element))
1457 cfg_obj_t *forwarder = cfg_listelt_value(element);
1458 sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t));
1460 result = ISC_R_NOMEMORY;
1463 *sa = *cfg_obj_assockaddr(forwarder);
1464 if (isc_sockaddr_getport(sa) == 0)
1465 isc_sockaddr_setport(sa, port);
1466 ISC_LINK_INIT(sa, link);
1467 ISC_LIST_APPEND(addresses, sa, link);
1470 if (ISC_LIST_EMPTY(addresses)) {
1471 if (forwardtype != NULL)
1472 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
1473 "no forwarders seen; disabling "
1475 fwdpolicy = dns_fwdpolicy_none;
1477 if (forwardtype == NULL)
1478 fwdpolicy = dns_fwdpolicy_first;
1480 char *forwardstr = cfg_obj_asstring(forwardtype);
1481 if (strcasecmp(forwardstr, "first") == 0)
1482 fwdpolicy = dns_fwdpolicy_first;
1483 else if (strcasecmp(forwardstr, "only") == 0)
1484 fwdpolicy = dns_fwdpolicy_only;
1490 result = dns_fwdtable_add(view->fwdtable, origin, &addresses,
1492 if (result != ISC_R_SUCCESS) {
1493 char namebuf[DNS_NAME_FORMATSIZE];
1494 dns_name_format(origin, namebuf, sizeof(namebuf));
1495 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
1496 "could not set up forwarding for domain '%s': %s",
1497 namebuf, isc_result_totext(result));
1501 result = ISC_R_SUCCESS;
1505 while (!ISC_LIST_EMPTY(addresses)) {
1506 sa = ISC_LIST_HEAD(addresses);
1507 ISC_LIST_UNLINK(addresses, sa, link);
1508 isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t));
1515 * Create a new view and add it to the list.
1517 * If 'vconfig' is NULL, create the default view.
1519 * The view created is attached to '*viewp'.
1522 create_view(cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) {
1523 isc_result_t result;
1524 const char *viewname;
1525 dns_rdataclass_t viewclass;
1526 dns_view_t *view = NULL;
1528 if (vconfig != NULL) {
1529 cfg_obj_t *classobj = NULL;
1531 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
1532 classobj = cfg_tuple_get(vconfig, "class");
1533 result = ns_config_getclass(classobj, dns_rdataclass_in,
1536 viewname = "_default";
1537 viewclass = dns_rdataclass_in;
1539 result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
1540 if (result == ISC_R_SUCCESS)
1541 return (ISC_R_EXISTS);
1542 if (result != ISC_R_NOTFOUND)
1544 INSIST(view == NULL);
1546 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view);
1547 if (result != ISC_R_SUCCESS)
1550 ISC_LIST_APPEND(*viewlist, view, link);
1551 dns_view_attach(view, viewp);
1552 return (ISC_R_SUCCESS);
1556 * Configure or reconfigure a zone.
1559 configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
1560 isc_mem_t *mctx, dns_view_t *view,
1561 ns_aclconfctx_t *aclconf)
1563 dns_view_t *pview = NULL; /* Production view */
1564 dns_zone_t *zone = NULL; /* New or reused zone */
1565 dns_zone_t *dupzone = NULL;
1566 cfg_obj_t *options = NULL;
1567 cfg_obj_t *zoptions = NULL;
1568 cfg_obj_t *typeobj = NULL;
1569 cfg_obj_t *forwarders = NULL;
1570 cfg_obj_t *forwardtype = NULL;
1571 cfg_obj_t *only = NULL;
1572 isc_result_t result;
1573 isc_result_t tresult;
1574 isc_buffer_t buffer;
1575 dns_fixedname_t fixorigin;
1578 dns_rdataclass_t zclass;
1579 const char *ztypestr;
1582 (void)cfg_map_get(config, "options", &options);
1584 zoptions = cfg_tuple_get(zconfig, "options");
1587 * Get the zone origin as a dns_name_t.
1589 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
1590 isc_buffer_init(&buffer, zname, strlen(zname));
1591 isc_buffer_add(&buffer, strlen(zname));
1592 dns_fixedname_init(&fixorigin);
1593 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin),
1594 &buffer, dns_rootname, ISC_FALSE, NULL));
1595 origin = dns_fixedname_name(&fixorigin);
1597 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
1598 view->rdclass, &zclass));
1599 if (zclass != view->rdclass) {
1600 const char *vname = NULL;
1601 if (vconfig != NULL)
1602 vname = cfg_obj_asstring(cfg_tuple_get(vconfig,
1605 vname = "<default view>";
1607 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1608 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
1609 "zone '%s': wrong class for view '%s'",
1611 result = ISC_R_FAILURE;
1615 (void)cfg_map_get(zoptions, "type", &typeobj);
1616 if (typeobj == NULL) {
1617 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
1618 "zone '%s' 'type' not specified", zname);
1619 return (ISC_R_FAILURE);
1621 ztypestr = cfg_obj_asstring(typeobj);
1624 * "hints zones" aren't zones. If we've got one,
1625 * configure it and return.
1627 if (strcasecmp(ztypestr, "hint") == 0) {
1628 cfg_obj_t *fileobj = NULL;
1629 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
1630 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1631 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
1632 "zone '%s': 'file' not specified",
1634 result = ISC_R_FAILURE;
1637 if (dns_name_equal(origin, dns_rootname)) {
1638 char *hintsfile = cfg_obj_asstring(fileobj);
1640 result = configure_hints(view, hintsfile);
1641 if (result != ISC_R_SUCCESS) {
1642 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1643 NS_LOGMODULE_SERVER,
1645 "could not configure root hints "
1646 "from '%s': %s", hintsfile,
1647 isc_result_totext(result));
1651 * Hint zones may also refer to delegation only points.
1654 tresult = cfg_map_get(zoptions, "delegation-only",
1656 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
1657 CHECK(dns_view_adddelegationonly(view, origin));
1659 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1660 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1661 "ignoring non-root hint zone '%s'",
1663 result = ISC_R_SUCCESS;
1665 /* Skip ordinary zone processing. */
1670 * "forward zones" aren't zones either. Translate this syntax into
1671 * the appropriate selective forwarding configuration and return.
1673 if (strcasecmp(ztypestr, "forward") == 0) {
1677 (void)cfg_map_get(zoptions, "forward", &forwardtype);
1678 (void)cfg_map_get(zoptions, "forwarders", &forwarders);
1679 result = configure_forward(config, view, origin, forwarders,
1685 * "delegation-only zones" aren't zones either.
1687 if (strcasecmp(ztypestr, "delegation-only") == 0) {
1688 result = dns_view_adddelegationonly(view, origin);
1693 * Check for duplicates in the new zone table.
1695 result = dns_view_findzone(view, origin, &dupzone);
1696 if (result == ISC_R_SUCCESS) {
1698 * We already have this zone!
1700 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
1701 "zone '%s' already exists", zname);
1702 dns_zone_detach(&dupzone);
1703 result = ISC_R_EXISTS;
1706 INSIST(dupzone == NULL);
1709 * See if we can reuse an existing zone. This is
1710 * only possible if all of these are true:
1711 * - The zone's view exists
1712 * - A zone with the right name exists in the view
1713 * - The zone is compatible with the config
1714 * options (e.g., an existing master zone cannot
1715 * be reused if the options specify a slave zone)
1717 result = dns_viewlist_find(&ns_g_server->viewlist,
1718 view->name, view->rdclass,
1720 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
1723 result = dns_view_findzone(pview, origin, &zone);
1724 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
1727 if (! ns_zone_reusable(zone, zconfig))
1728 dns_zone_detach(&zone);
1733 * We found a reusable zone. Make it use the
1736 dns_zone_setview(zone, view);
1739 * We cannot reuse an existing zone, we have
1740 * to create a new one.
1742 CHECK(dns_zone_create(&zone, mctx));
1743 CHECK(dns_zone_setorigin(zone, origin));
1744 dns_zone_setview(zone, view);
1745 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
1749 * If the zone contains a 'forwarders' statement, configure
1750 * selective forwarding.
1753 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS)
1756 (void)cfg_map_get(zoptions, "forward", &forwardtype);
1757 CHECK(configure_forward(config, view, origin, forwarders,
1762 * Stub and forward zones may also refer to delegation only points.
1765 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS)
1767 if (cfg_obj_asboolean(only))
1768 CHECK(dns_view_adddelegationonly(view, origin));
1772 * Configure the zone.
1774 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone));
1777 * Add the zone to its view in the new view list.
1779 CHECK(dns_view_addzone(view, zone));
1783 dns_zone_detach(&zone);
1785 dns_view_detach(&pview);
1791 * Configure a single server quota.
1794 configure_server_quota(cfg_obj_t **maps, const char *name, isc_quota_t *quota)
1796 cfg_obj_t *obj = NULL;
1797 isc_result_t result;
1799 result = ns_config_get(maps, name, &obj);
1800 INSIST(result == ISC_R_SUCCESS);
1801 quota->max = cfg_obj_asuint32(obj);
1805 * This function is called as soon as the 'directory' statement has been
1806 * parsed. This can be extended to support other options if necessary.
1809 directory_callback(const char *clausename, cfg_obj_t *obj, void *arg) {
1810 isc_result_t result;
1813 REQUIRE(strcasecmp("directory", clausename) == 0);
1821 directory = cfg_obj_asstring(obj);
1823 if (! isc_file_ischdiridempotent(directory))
1824 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1825 "option 'directory' contains relative path '%s'",
1828 result = isc_dir_chdir(directory);
1829 if (result != ISC_R_SUCCESS) {
1830 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
1831 "change directory to '%s' failed: %s",
1832 directory, isc_result_totext(result));
1836 return (ISC_R_SUCCESS);
1840 scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
1841 isc_boolean_t match_mapped = server->aclenv.match_mapped;
1843 ns_interfacemgr_scan(server->interfacemgr, verbose);
1845 * Update the "localhost" and "localnets" ACLs to match the
1846 * current set of network interfaces.
1848 dns_aclenv_copy(&server->aclenv,
1849 ns_interfacemgr_getaclenv(server->interfacemgr));
1851 server->aclenv.match_mapped = match_mapped;
1855 add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr) {
1856 ns_listenelt_t *lelt = NULL;
1857 dns_acl_t *src_acl = NULL;
1858 dns_aclelement_t aelt;
1859 isc_result_t result;
1860 isc_sockaddr_t any_sa6;
1862 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
1864 isc_sockaddr_any6(&any_sa6);
1865 if (!isc_sockaddr_equal(&any_sa6, addr)) {
1866 aelt.type = dns_aclelementtype_ipprefix;
1867 aelt.negative = ISC_FALSE;
1868 aelt.u.ip_prefix.prefixlen = 128;
1869 isc_netaddr_fromin6(&aelt.u.ip_prefix.address,
1870 &addr->type.sin6.sin6_addr);
1872 result = dns_acl_create(mctx, 1, &src_acl);
1873 if (result != ISC_R_SUCCESS)
1875 result = dns_acl_appendelement(src_acl, &aelt);
1876 if (result != ISC_R_SUCCESS)
1879 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
1881 if (result != ISC_R_SUCCESS)
1883 ISC_LIST_APPEND(list->elts, lelt, link);
1886 return (ISC_R_SUCCESS);
1889 INSIST(lelt == NULL);
1890 if (src_acl != NULL)
1891 dns_acl_detach(&src_acl);
1897 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust()
1898 * to update the listening interfaces accordingly.
1899 * We currently only consider IPv6, because this only affects IPv6 wildcard
1903 adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
1904 isc_result_t result;
1905 ns_listenlist_t *list = NULL;
1907 dns_zone_t *zone, *next;
1908 isc_sockaddr_t addr, *addrp;
1910 result = ns_listenlist_create(mctx, &list);
1911 if (result != ISC_R_SUCCESS)
1914 for (view = ISC_LIST_HEAD(server->viewlist);
1916 view = ISC_LIST_NEXT(view, link)) {
1917 dns_dispatch_t *dispatch6;
1919 dispatch6 = dns_resolver_dispatchv6(view->resolver);
1920 if (dispatch6 == NULL)
1922 result = dns_dispatch_getlocaladdress(dispatch6, &addr);
1923 if (result != ISC_R_SUCCESS)
1925 result = add_listenelt(mctx, list, &addr);
1926 if (result != ISC_R_SUCCESS)
1931 for (result = dns_zone_first(server->zonemgr, &zone);
1932 result == ISC_R_SUCCESS;
1933 next = NULL, result = dns_zone_next(zone, &next), zone = next) {
1934 dns_view_t *zoneview;
1937 * At this point the zone list may contain a stale zone
1938 * just removed from the configuration. To see the validity,
1939 * check if the corresponding view is in our current view list.
1941 zoneview = dns_zone_getview(zone);
1942 INSIST(zoneview != NULL);
1943 for (view = ISC_LIST_HEAD(server->viewlist);
1944 view != NULL && view != zoneview;
1945 view = ISC_LIST_NEXT(view, link))
1950 addrp = dns_zone_getnotifysrc6(zone);
1951 result = add_listenelt(mctx, list, addrp);
1952 if (result != ISC_R_SUCCESS)
1955 addrp = dns_zone_getxfrsource6(zone);
1956 result = add_listenelt(mctx, list, addrp);
1957 if (result != ISC_R_SUCCESS)
1961 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE);
1964 ns_listenlist_detach(&list);
1969 * Even when we failed the procedure, most of other interfaces
1970 * should work correctly. We therefore just warn it.
1972 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1973 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1974 "could not adjust the listen-on list; "
1975 "some interfaces may not work");
1980 * This event callback is invoked to do periodic network
1981 * interface scanning.
1984 interface_timer_tick(isc_task_t *task, isc_event_t *event) {
1985 isc_result_t result;
1986 ns_server_t *server = (ns_server_t *) event->ev_arg;
1987 INSIST(task == server->task);
1989 isc_event_free(&event);
1991 * XXX should scan interfaces unlocked and get exclusive access
1992 * only to replace ACLs.
1994 result = isc_task_beginexclusive(server->task);
1995 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1996 scan_interfaces(server, ISC_FALSE);
1997 isc_task_endexclusive(server->task);
2001 heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
2002 ns_server_t *server = (ns_server_t *) event->ev_arg;
2006 isc_event_free(&event);
2007 view = ISC_LIST_HEAD(server->viewlist);
2008 while (view != NULL) {
2009 dns_view_dialup(view);
2010 view = ISC_LIST_NEXT(view, link);
2015 * Replace the current value of '*field', a dynamically allocated
2016 * string or NULL, with a dynamically allocated copy of the
2017 * null-terminated string pointed to by 'value', or NULL.
2020 setstring(ns_server_t *server, char **field, const char *value) {
2023 if (value != NULL) {
2024 copy = isc_mem_strdup(server->mctx, value);
2026 return (ISC_R_NOMEMORY);
2032 isc_mem_free(server->mctx, *field);
2035 return (ISC_R_SUCCESS);
2039 * Replace the current value of '*field', a dynamically allocated
2040 * string or NULL, with another dynamically allocated string
2041 * or NULL if whether 'obj' is a string or void value, respectively.
2044 setoptstring(ns_server_t *server, char **field, cfg_obj_t *obj) {
2045 if (cfg_obj_isvoid(obj))
2046 return (setstring(server, field, NULL));
2048 return (setstring(server, field, cfg_obj_asstring(obj)));
2052 set_limit(cfg_obj_t **maps, const char *configname, const char *description,
2053 isc_resource_t resourceid, isc_resourcevalue_t defaultvalue)
2055 cfg_obj_t *obj = NULL;
2057 isc_resourcevalue_t value;
2058 isc_result_t result;
2060 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS)
2063 if (cfg_obj_isstring(obj)) {
2064 resource = cfg_obj_asstring(obj);
2065 if (strcasecmp(resource, "unlimited") == 0)
2066 value = ISC_RESOURCE_UNLIMITED;
2068 INSIST(strcasecmp(resource, "default") == 0);
2069 value = defaultvalue;
2072 value = cfg_obj_asuint64(obj);
2074 result = isc_resource_setlimit(resourceid, value);
2075 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2076 result == ISC_R_SUCCESS ?
2077 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
2078 "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s",
2079 description, value, isc_result_totext(result));
2082 #define SETLIMIT(cfgvar, resource, description) \
2083 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \
2084 ns_g_init ## resource)
2087 set_limits(cfg_obj_t **maps) {
2088 SETLIMIT("stacksize", stacksize, "stack size");
2089 SETLIMIT("datasize", datasize, "data size");
2090 SETLIMIT("coresize", coresize, "core size");
2091 SETLIMIT("files", openfiles, "open files");
2095 portlist_fromconf(dns_portlist_t *portlist, unsigned int family,
2098 cfg_listelt_t *element;
2099 isc_result_t result = ISC_R_SUCCESS;
2101 for (element = cfg_list_first(ports);
2103 element = cfg_list_next(element)) {
2104 cfg_obj_t *obj = cfg_listelt_value(element);
2105 in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
2107 result = dns_portlist_add(portlist, family, port);
2108 if (result != ISC_R_SUCCESS)
2115 load_configuration(const char *filename, ns_server_t *server,
2116 isc_boolean_t first_time)
2118 isc_result_t result;
2119 cfg_parser_t *parser = NULL;
2124 cfg_obj_t *v4ports, *v6ports;
2126 cfg_obj_t *builtin_views;
2127 cfg_listelt_t *element;
2128 dns_view_t *view = NULL;
2129 dns_view_t *view_next;
2130 dns_viewlist_t viewlist;
2131 dns_viewlist_t tmpviewlist;
2132 ns_aclconfctx_t aclconfctx;
2133 isc_uint32_t interface_interval;
2134 isc_uint32_t heartbeat_interval;
2135 isc_uint32_t udpsize;
2136 in_port_t listen_port;
2139 ns_aclconfctx_init(&aclconfctx);
2140 ISC_LIST_INIT(viewlist);
2142 /* Ensure exclusive access to configuration data. */
2143 result = isc_task_beginexclusive(server->task);
2144 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2147 * Parse the global default pseudo-config file.
2150 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config));
2151 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options",
2157 * Parse the configuration file using the new config code.
2159 result = ISC_R_FAILURE;
2163 * Unless this is lwresd with the -C option, parse the config file.
2165 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) {
2166 isc_log_write(ns_g_lctx,
2167 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2168 ISC_LOG_INFO, "loading configuration from '%s'",
2170 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
2171 cfg_parser_setcallback(parser, directory_callback, NULL);
2172 result = cfg_parse_file(parser, filename, &cfg_type_namedconf,
2177 * If this is lwresd with the -C option, or lwresd with no -C or -c
2178 * option where the above parsing failed, parse resolv.conf.
2180 if (ns_g_lwresdonly &&
2181 (lwresd_g_useresolvconf ||
2182 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND)))
2184 isc_log_write(ns_g_lctx,
2185 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2186 ISC_LOG_INFO, "loading configuration from '%s'",
2187 lwresd_g_resolvconffile);
2189 cfg_parser_destroy(&parser);
2190 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
2191 result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser,
2197 * Check the validity of the configuration.
2199 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx));
2202 * Fill in the maps array, used for resolving defaults.
2206 result = cfg_map_get(config, "options", &options);
2207 if (result == ISC_R_SUCCESS)
2208 maps[i++] = options;
2209 maps[i++] = ns_g_defaults;
2213 * Set process limits, which (usually) needs to be done as root.
2218 * Configure various server options.
2220 configure_server_quota(maps, "transfers-out", &server->xfroutquota);
2221 configure_server_quota(maps, "tcp-clients", &server->tcpquota);
2222 configure_server_quota(maps, "recursive-clients",
2223 &server->recursionquota);
2225 CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
2226 ns_g_mctx, &server->blackholeacl));
2227 if (server->blackholeacl != NULL)
2228 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
2229 server->blackholeacl);
2232 result = ns_config_get(maps, "match-mapped-addresses", &obj);
2233 INSIST(result == ISC_R_SUCCESS);
2234 server->aclenv.match_mapped = cfg_obj_asboolean(obj);
2238 (void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports);
2239 (void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports);
2240 if (v4ports != NULL || v6ports != NULL) {
2241 dns_portlist_t *portlist = NULL;
2242 result = dns_portlist_create(ns_g_mctx, &portlist);
2243 if (result == ISC_R_SUCCESS && v4ports != NULL)
2244 result = portlist_fromconf(portlist, AF_INET, v4ports);
2245 if (result == ISC_R_SUCCESS && v6ports != NULL)
2246 portlist_fromconf(portlist, AF_INET6, v6ports);
2247 if (result == ISC_R_SUCCESS)
2248 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist);
2249 if (portlist != NULL)
2250 dns_portlist_detach(&portlist);
2253 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL);
2256 * Set the EDNS UDP size when we don't match a view.
2259 result = ns_config_get(maps, "edns-udp-size", &obj);
2260 INSIST(result == ISC_R_SUCCESS);
2261 udpsize = cfg_obj_asuint32(obj);
2266 ns_g_udpsize = (isc_uint16_t)udpsize;
2269 * Configure the zone manager.
2272 result = ns_config_get(maps, "transfers-in", &obj);
2273 INSIST(result == ISC_R_SUCCESS);
2274 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
2277 result = ns_config_get(maps, "transfers-per-ns", &obj);
2278 INSIST(result == ISC_R_SUCCESS);
2279 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
2282 result = ns_config_get(maps, "serial-query-rate", &obj);
2283 INSIST(result == ISC_R_SUCCESS);
2284 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj));
2287 * Determine which port to use for listening for incoming connections.
2290 listen_port = ns_g_port;
2292 CHECKM(ns_config_getport(config, &listen_port), "port");
2295 * Find the listen queue depth.
2298 result = ns_config_get(maps, "tcp-listen-queue", &obj);
2299 INSIST(result == ISC_R_SUCCESS);
2300 ns_g_listen = cfg_obj_asuint32(obj);
2301 if (ns_g_listen < 3)
2305 * Configure the interface manager according to the "listen-on"
2309 cfg_obj_t *clistenon = NULL;
2310 ns_listenlist_t *listenon = NULL;
2314 * Even though listen-on is present in the default
2315 * configuration, we can't use it here, since it isn't
2316 * used if we're in lwresd mode. This way is easier.
2318 if (options != NULL)
2319 (void)cfg_map_get(options, "listen-on", &clistenon);
2320 if (clistenon != NULL) {
2321 result = ns_listenlist_fromconfig(clistenon,
2326 } else if (!ns_g_lwresdonly) {
2328 * Not specified, use default.
2330 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
2331 ISC_TRUE, &listenon));
2333 if (listenon != NULL) {
2334 ns_interfacemgr_setlistenon4(server->interfacemgr,
2336 ns_listenlist_detach(&listenon);
2343 cfg_obj_t *clistenon = NULL;
2344 ns_listenlist_t *listenon = NULL;
2346 if (options != NULL)
2347 (void)cfg_map_get(options, "listen-on-v6", &clistenon);
2348 if (clistenon != NULL) {
2349 result = ns_listenlist_fromconfig(clistenon,
2354 } else if (!ns_g_lwresdonly) {
2356 * Not specified, use default.
2358 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
2359 ISC_FALSE, &listenon));
2361 if (listenon != NULL) {
2362 ns_interfacemgr_setlistenon6(server->interfacemgr,
2364 ns_listenlist_detach(&listenon);
2369 * Rescan the interface list to pick up changes in the
2370 * listen-on option. It's important that we do this before we try
2371 * to configure the query source, since the dispatcher we use might
2372 * be shared with an interface.
2374 scan_interfaces(server, ISC_TRUE);
2377 * Arrange for further interface scanning to occur periodically
2378 * as specified by the "interface-interval" option.
2381 result = ns_config_get(maps, "interface-interval", &obj);
2382 INSIST(result == ISC_R_SUCCESS);
2383 interface_interval = cfg_obj_asuint32(obj) * 60;
2384 if (interface_interval == 0) {
2385 CHECK(isc_timer_reset(server->interface_timer,
2386 isc_timertype_inactive,
2387 NULL, NULL, ISC_TRUE));
2388 } else if (server->interface_interval != interface_interval) {
2389 isc_interval_t interval;
2390 isc_interval_set(&interval, interface_interval, 0);
2391 CHECK(isc_timer_reset(server->interface_timer,
2392 isc_timertype_ticker,
2393 NULL, &interval, ISC_FALSE));
2395 server->interface_interval = interface_interval;
2398 * Configure the dialup heartbeat timer.
2401 result = ns_config_get(maps, "heartbeat-interval", &obj);
2402 INSIST(result == ISC_R_SUCCESS);
2403 heartbeat_interval = cfg_obj_asuint32(obj) * 60;
2404 if (heartbeat_interval == 0) {
2405 CHECK(isc_timer_reset(server->heartbeat_timer,
2406 isc_timertype_inactive,
2407 NULL, NULL, ISC_TRUE));
2408 } else if (server->heartbeat_interval != heartbeat_interval) {
2409 isc_interval_t interval;
2410 isc_interval_set(&interval, heartbeat_interval, 0);
2411 CHECK(isc_timer_reset(server->heartbeat_timer,
2412 isc_timertype_ticker,
2413 NULL, &interval, ISC_FALSE));
2415 server->heartbeat_interval = heartbeat_interval;
2418 * Configure and freeze all explicit views. Explicit
2419 * views that have zones were already created at parsing
2420 * time, but views with no zones must be created here.
2423 (void)cfg_map_get(config, "view", &views);
2424 for (element = cfg_list_first(views);
2426 element = cfg_list_next(element))
2428 cfg_obj_t *vconfig = cfg_listelt_value(element);
2431 CHECK(create_view(vconfig, &viewlist, &view));
2432 INSIST(view != NULL);
2433 CHECK(configure_view(view, config, vconfig,
2434 ns_g_mctx, &aclconfctx, ISC_TRUE));
2435 dns_view_freeze(view);
2436 dns_view_detach(&view);
2440 * Make sure we have a default view if and only if there
2441 * were no explicit views.
2443 if (views == NULL) {
2445 * No explicit views; there ought to be a default view.
2446 * There may already be one created as a side effect
2447 * of zone statements, or we may have to create one.
2448 * In either case, we need to configure and freeze it.
2450 CHECK(create_view(NULL, &viewlist, &view));
2451 CHECK(configure_view(view, config, NULL, ns_g_mctx,
2452 &aclconfctx, ISC_TRUE));
2453 dns_view_freeze(view);
2454 dns_view_detach(&view);
2458 * Create (or recreate) the built-in views. Currently
2459 * there is only one, the _bind view.
2461 builtin_views = NULL;
2462 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
2463 &builtin_views) == ISC_R_SUCCESS);
2464 for (element = cfg_list_first(builtin_views);
2466 element = cfg_list_next(element))
2468 cfg_obj_t *vconfig = cfg_listelt_value(element);
2469 CHECK(create_view(vconfig, &viewlist, &view));
2470 CHECK(configure_view(view, config, vconfig, ns_g_mctx,
2471 &aclconfctx, ISC_FALSE));
2472 dns_view_freeze(view);
2473 dns_view_detach(&view);
2478 * Swap our new view list with the production one.
2480 tmpviewlist = server->viewlist;
2481 server->viewlist = viewlist;
2482 viewlist = tmpviewlist;
2485 * Load the TKEY information from the configuration.
2487 if (options != NULL) {
2488 dns_tkeyctx_t *t = NULL;
2489 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
2491 "configuring TKEY");
2492 if (server->tkeyctx != NULL)
2493 dns_tkeyctx_destroy(&server->tkeyctx);
2494 server->tkeyctx = t;
2498 * Bind the control port(s).
2500 CHECKM(ns_controls_configure(ns_g_server->controls, config,
2502 "binding control channel(s)");
2505 * Bind the lwresd port(s).
2507 CHECKM(ns_lwresd_configure(ns_g_mctx, config),
2508 "binding lightweight resolver ports");
2511 * Open the source of entropy.
2515 result = ns_config_get(maps, "random-device", &obj);
2516 if (result != ISC_R_SUCCESS) {
2517 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2518 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
2519 "no source of entropy found");
2521 const char *randomdev = cfg_obj_asstring(obj);
2522 result = isc_entropy_createfilesource(ns_g_entropy,
2524 if (result != ISC_R_SUCCESS)
2525 isc_log_write(ns_g_lctx,
2526 NS_LOGCATEGORY_GENERAL,
2527 NS_LOGMODULE_SERVER,
2529 "could not open entropy source "
2532 isc_result_totext(result));
2533 #ifdef PATH_RANDOMDEV
2534 if (ns_g_fallbackentropy != NULL) {
2535 if (result != ISC_R_SUCCESS) {
2536 isc_log_write(ns_g_lctx,
2537 NS_LOGCATEGORY_GENERAL,
2538 NS_LOGMODULE_SERVER,
2540 "using pre-chroot entropy source "
2543 isc_entropy_detach(&ns_g_entropy);
2544 isc_entropy_attach(ns_g_fallbackentropy,
2547 isc_entropy_detach(&ns_g_fallbackentropy);
2554 * Relinquish root privileges.
2560 * Configure the logging system.
2562 * Do this after changing UID to make sure that any log
2563 * files specified in named.conf get created by the
2564 * unprivileged user, not root.
2566 if (ns_g_logstderr) {
2567 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2568 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
2569 "ignoring config file logging "
2570 "statement due to -g option");
2572 cfg_obj_t *logobj = NULL;
2573 isc_logconfig_t *logc = NULL;
2575 CHECKM(isc_logconfig_create(ns_g_lctx, &logc),
2576 "creating new logging configuration");
2579 (void)cfg_map_get(config, "logging", &logobj);
2580 if (logobj != NULL) {
2581 CHECKM(ns_log_configure(logc, logobj),
2582 "configuring logging");
2584 CHECKM(ns_log_setdefaultchannels(logc),
2585 "setting up default logging channels");
2586 CHECKM(ns_log_setunmatchedcategory(logc),
2587 "setting up default 'category unmatched'");
2588 CHECKM(ns_log_setdefaultcategory(logc),
2589 "setting up default 'category default'");
2592 result = isc_logconfig_use(ns_g_lctx, logc);
2593 if (result != ISC_R_SUCCESS) {
2594 isc_logconfig_destroy(&logc);
2595 CHECKM(result, "installing logging configuration");
2598 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2599 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
2600 "now using logging configuration from "
2605 * Set the default value of the query logging flag depending
2606 * whether a "queries" category has been defined. This is
2607 * a disgusting hack, but we need to do this for BIND 8
2611 cfg_obj_t *logobj = NULL;
2612 cfg_obj_t *categories = NULL;
2615 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
2616 server->log_queries = cfg_obj_asboolean(obj);
2619 (void)cfg_map_get(config, "logging", &logobj);
2621 (void)cfg_map_get(logobj, "category",
2623 if (categories != NULL) {
2624 cfg_listelt_t *element;
2625 for (element = cfg_list_first(categories);
2627 element = cfg_list_next(element))
2632 obj = cfg_listelt_value(element);
2633 catobj = cfg_tuple_get(obj, "name");
2634 str = cfg_obj_asstring(catobj);
2635 if (strcasecmp(str, "queries") == 0)
2636 server->log_queries = ISC_TRUE;
2643 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)
2644 if (cfg_obj_isvoid(obj))
2645 ns_os_writepidfile(NULL, first_time);
2647 ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
2648 else if (ns_g_lwresdonly)
2649 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
2651 ns_os_writepidfile(ns_g_defaultpidfile, first_time);
2654 if (options != NULL &&
2655 cfg_map_get(options, "memstatistics-file", &obj) == ISC_R_SUCCESS)
2656 ns_main_setmemstats(cfg_obj_asstring(obj));
2658 ns_main_setmemstats(NULL);
2661 result = ns_config_get(maps, "statistics-file", &obj);
2662 INSIST(result == ISC_R_SUCCESS);
2663 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
2667 result = ns_config_get(maps, "dump-file", &obj);
2668 INSIST(result == ISC_R_SUCCESS);
2669 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),
2673 result = ns_config_get(maps, "recursing-file", &obj);
2674 INSIST(result == ISC_R_SUCCESS);
2675 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
2679 result = ns_config_get(maps, "version", &obj);
2680 if (result == ISC_R_SUCCESS) {
2681 CHECKM(setoptstring(server, &server->version, obj), "strdup");
2682 server->version_set = ISC_TRUE;
2684 server->version_set = ISC_FALSE;
2688 result = ns_config_get(maps, "hostname", &obj);
2689 if (result == ISC_R_SUCCESS) {
2690 CHECKM(setoptstring(server, &server->hostname, obj), "strdup");
2691 server->hostname_set = ISC_TRUE;
2693 server->hostname_set = ISC_FALSE;
2697 result = ns_config_get(maps, "server-id", &obj);
2698 server->server_usehostname = ISC_FALSE;
2699 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
2700 server->server_usehostname = ISC_TRUE;
2701 } else if (result == ISC_R_SUCCESS) {
2702 CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
2704 result = setoptstring(server, &server->server_id, NULL);
2705 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2709 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj);
2710 if (result == ISC_R_SUCCESS) {
2711 server->flushonshutdown = cfg_obj_asboolean(obj);
2713 server->flushonshutdown = ISC_FALSE;
2716 result = ISC_R_SUCCESS;
2719 ns_aclconfctx_destroy(&aclconfctx);
2721 if (parser != NULL) {
2723 cfg_obj_destroy(parser, &config);
2724 cfg_parser_destroy(&parser);
2728 dns_view_detach(&view);
2731 * This cleans up either the old production view list
2732 * or our temporary list depending on whether they
2733 * were swapped above or not.
2735 for (view = ISC_LIST_HEAD(viewlist);
2738 view_next = ISC_LIST_NEXT(view, link);
2739 ISC_LIST_UNLINK(viewlist, view, link);
2740 dns_view_detach(&view);
2745 * Adjust the listening interfaces in accordance with the source
2746 * addresses specified in views and zones.
2748 if (isc_net_probeipv6() == ISC_R_SUCCESS)
2749 adjust_interfaces(server, ns_g_mctx);
2751 /* Relinquish exclusive access to configuration data. */
2752 isc_task_endexclusive(server->task);
2754 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2755 ISC_LOG_DEBUG(1), "load_configuration: %s",
2756 isc_result_totext(result));
2762 load_zones(ns_server_t *server, isc_boolean_t stop) {
2763 isc_result_t result;
2766 result = isc_task_beginexclusive(server->task);
2767 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2770 * Load zone data from disk.
2772 for (view = ISC_LIST_HEAD(server->viewlist);
2774 view = ISC_LIST_NEXT(view, link))
2776 CHECK(dns_view_load(view, stop));
2780 * Force zone maintenance. Do this after loading
2781 * so that we know when we need to force AXFR of
2782 * slave zones whose master files are missing.
2784 CHECK(dns_zonemgr_forcemaint(server->zonemgr));
2786 isc_task_endexclusive(server->task);
2791 load_new_zones(ns_server_t *server, isc_boolean_t stop) {
2792 isc_result_t result;
2795 result = isc_task_beginexclusive(server->task);
2796 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2799 * Load zone data from disk.
2801 for (view = ISC_LIST_HEAD(server->viewlist);
2803 view = ISC_LIST_NEXT(view, link))
2805 CHECK(dns_view_loadnew(view, stop));
2808 * Force zone maintenance. Do this after loading
2809 * so that we know when we need to force AXFR of
2810 * slave zones whose master files are missing.
2812 dns_zonemgr_resumexfrs(server->zonemgr);
2814 isc_task_endexclusive(server->task);
2819 run_server(isc_task_t *task, isc_event_t *event) {
2820 isc_result_t result;
2821 ns_server_t *server = (ns_server_t *)event->ev_arg;
2823 INSIST(task == server->task);
2825 isc_event_free(&event);
2827 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy,
2829 "creating dispatch manager");
2831 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
2832 ns_g_socketmgr, ns_g_dispatchmgr,
2833 &server->interfacemgr),
2834 "creating interface manager");
2836 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
2837 NULL, NULL, server->task,
2838 interface_timer_tick,
2839 server, &server->interface_timer),
2840 "creating interface timer");
2842 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
2843 NULL, NULL, server->task,
2844 heartbeat_timer_tick,
2845 server, &server->heartbeat_timer),
2846 "creating heartbeat timer");
2848 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser),
2849 "creating default configuration parser");
2851 if (ns_g_lwresdonly)
2852 CHECKFATAL(load_configuration(lwresd_g_conffile, server,
2854 "loading configuration");
2856 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE),
2857 "loading configuration");
2861 CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones");
2864 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2865 ISC_LOG_NOTICE, "running");
2869 ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) {
2871 REQUIRE(NS_SERVER_VALID(server));
2873 server->flushonshutdown = flush;
2877 shutdown_server(isc_task_t *task, isc_event_t *event) {
2878 isc_result_t result;
2879 dns_view_t *view, *view_next;
2880 ns_server_t *server = (ns_server_t *)event->ev_arg;
2881 isc_boolean_t flush = server->flushonshutdown;
2884 INSIST(task == server->task);
2886 result = isc_task_beginexclusive(server->task);
2887 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2889 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2890 ISC_LOG_INFO, "shutting down%s",
2891 flush ? ": flushing changes" : "");
2893 ns_controls_shutdown(server->controls);
2894 end_reserved_dispatches(server, ISC_TRUE);
2896 cfg_obj_destroy(ns_g_parser, &ns_g_config);
2897 cfg_parser_destroy(&ns_g_parser);
2899 for (view = ISC_LIST_HEAD(server->viewlist);
2902 view_next = ISC_LIST_NEXT(view, link);
2903 ISC_LIST_UNLINK(server->viewlist, view, link);
2905 dns_view_flushanddetach(&view);
2907 dns_view_detach(&view);
2910 isc_timer_detach(&server->interface_timer);
2911 isc_timer_detach(&server->heartbeat_timer);
2913 ns_interfacemgr_shutdown(server->interfacemgr);
2914 ns_interfacemgr_detach(&server->interfacemgr);
2916 dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
2918 dns_zonemgr_shutdown(server->zonemgr);
2920 if (server->blackholeacl != NULL)
2921 dns_acl_detach(&server->blackholeacl);
2923 dns_db_detach(&server->in_roothints);
2925 isc_task_endexclusive(server->task);
2927 isc_task_detach(&server->task);
2929 isc_event_free(&event);
2933 ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
2934 isc_result_t result;
2936 ns_server_t *server = isc_mem_get(mctx, sizeof(*server));
2938 fatal("allocating server object", ISC_R_NOMEMORY);
2940 server->mctx = mctx;
2941 server->task = NULL;
2943 /* Initialize configuration data with default values. */
2945 result = isc_quota_init(&server->xfroutquota, 10);
2946 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2947 result = isc_quota_init(&server->tcpquota, 10);
2948 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2949 result = isc_quota_init(&server->recursionquota, 100);
2950 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2951 isc_quota_soft(&server->recursionquota, ISC_FALSE);
2953 result = dns_aclenv_init(mctx, &server->aclenv);
2954 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2956 /* Initialize server data structures. */
2957 server->zonemgr = NULL;
2958 server->interfacemgr = NULL;
2959 ISC_LIST_INIT(server->viewlist);
2960 server->in_roothints = NULL;
2961 server->blackholeacl = NULL;
2963 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
2964 &server->in_roothints),
2965 "setting up root hints");
2967 CHECKFATAL(isc_mutex_init(&server->reload_event_lock),
2968 "initializing reload event lock");
2969 server->reload_event =
2970 isc_event_allocate(ns_g_mctx, server,
2974 sizeof(isc_event_t));
2975 CHECKFATAL(server->reload_event == NULL ?
2976 ISC_R_NOMEMORY : ISC_R_SUCCESS,
2977 "allocating reload event");
2979 CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY),
2980 "initializing DST");
2982 server->tkeyctx = NULL;
2983 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
2985 "creating TKEY context");
2988 * Setup the server task, which is responsible for coordinating
2989 * startup and shutdown of the server.
2991 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),
2992 "creating server task");
2993 isc_task_setname(server->task, "server", server);
2994 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
2995 "isc_task_onshutdown");
2996 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
2999 server->interface_timer = NULL;
3000 server->heartbeat_timer = NULL;
3002 server->interface_interval = 0;
3003 server->heartbeat_interval = 0;
3005 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
3006 ns_g_socketmgr, &server->zonemgr),
3007 "dns_zonemgr_create");
3009 server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
3010 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
3012 server->querystats = NULL;
3014 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
3015 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
3018 server->recfile = isc_mem_strdup(server->mctx, "named.recursing");
3019 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
3022 server->hostname_set = ISC_FALSE;
3023 server->hostname = NULL;
3024 server->version_set = ISC_FALSE;
3025 server->version = NULL;
3026 server->server_usehostname = ISC_FALSE;
3027 server->server_id = NULL;
3029 CHECKFATAL(dns_stats_alloccounters(ns_g_mctx, &server->querystats),
3030 "dns_stats_alloccounters");
3032 server->flushonshutdown = ISC_FALSE;
3033 server->log_queries = ISC_FALSE;
3035 server->controls = NULL;
3036 CHECKFATAL(ns_controls_create(server, &server->controls),
3037 "ns_controls_create");
3038 server->dispatchgen = 0;
3039 ISC_LIST_INIT(server->dispatches);
3041 server->magic = NS_SERVER_MAGIC;
3046 ns_server_destroy(ns_server_t **serverp) {
3047 ns_server_t *server = *serverp;
3048 REQUIRE(NS_SERVER_VALID(server));
3050 ns_controls_destroy(&server->controls);
3052 dns_stats_freecounters(server->mctx, &server->querystats);
3054 isc_mem_free(server->mctx, server->statsfile);
3055 isc_mem_free(server->mctx, server->dumpfile);
3056 isc_mem_free(server->mctx, server->recfile);
3058 if (server->version != NULL)
3059 isc_mem_free(server->mctx, server->version);
3060 if (server->hostname != NULL)
3061 isc_mem_free(server->mctx, server->hostname);
3062 if (server->server_id != NULL)
3063 isc_mem_free(server->mctx, server->server_id);
3065 dns_zonemgr_detach(&server->zonemgr);
3067 if (server->tkeyctx != NULL)
3068 dns_tkeyctx_destroy(&server->tkeyctx);
3072 isc_event_free(&server->reload_event);
3074 INSIST(ISC_LIST_EMPTY(server->viewlist));
3076 dns_aclenv_destroy(&server->aclenv);
3078 isc_quota_destroy(&server->recursionquota);
3079 isc_quota_destroy(&server->tcpquota);
3080 isc_quota_destroy(&server->xfroutquota);
3083 isc_mem_put(server->mctx, server, sizeof(*server));
3088 fatal(const char *msg, isc_result_t result) {
3089 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3090 ISC_LOG_CRITICAL, "%s: %s", msg,
3091 isc_result_totext(result));
3092 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3093 ISC_LOG_CRITICAL, "exiting (due to fatal error)");
3098 start_reserved_dispatches(ns_server_t *server) {
3100 REQUIRE(NS_SERVER_VALID(server));
3102 server->dispatchgen++;
3106 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) {
3107 ns_dispatch_t *dispatch, *nextdispatch;
3109 REQUIRE(NS_SERVER_VALID(server));
3111 for (dispatch = ISC_LIST_HEAD(server->dispatches);
3113 dispatch = nextdispatch) {
3114 nextdispatch = ISC_LIST_NEXT(dispatch, link);
3115 if (!all && server->dispatchgen == dispatch-> dispatchgen)
3117 ISC_LIST_UNLINK(server->dispatches, dispatch, link);
3118 dns_dispatch_detach(&dispatch->dispatch);
3119 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
3124 ns_add_reserved_dispatch(ns_server_t *server, isc_sockaddr_t *addr) {
3125 ns_dispatch_t *dispatch;
3127 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3128 isc_result_t result;
3129 unsigned int attrs, attrmask;
3131 REQUIRE(NS_SERVER_VALID(server));
3133 port = isc_sockaddr_getport(addr);
3134 if (port == 0 || port >= 1024)
3137 for (dispatch = ISC_LIST_HEAD(server->dispatches);
3139 dispatch = ISC_LIST_NEXT(dispatch, link)) {
3140 if (isc_sockaddr_equal(&dispatch->addr, addr))
3143 if (dispatch != NULL) {
3144 dispatch->dispatchgen = server->dispatchgen;
3148 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch));
3149 if (dispatch == NULL) {
3150 result = ISC_R_NOMEMORY;
3154 dispatch->addr = *addr;
3155 dispatch->dispatchgen = server->dispatchgen;
3156 dispatch->dispatch = NULL;
3159 attrs |= DNS_DISPATCHATTR_UDP;
3160 switch (isc_sockaddr_pf(addr)) {
3162 attrs |= DNS_DISPATCHATTR_IPV4;
3165 attrs |= DNS_DISPATCHATTR_IPV6;
3168 result = ISC_R_NOTIMPLEMENTED;
3172 attrmask |= DNS_DISPATCHATTR_UDP;
3173 attrmask |= DNS_DISPATCHATTR_TCP;
3174 attrmask |= DNS_DISPATCHATTR_IPV4;
3175 attrmask |= DNS_DISPATCHATTR_IPV6;
3177 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
3178 ns_g_taskmgr, &dispatch->addr, 4096,
3179 1000, 32768, 16411, 16433,
3180 attrs, attrmask, &dispatch->dispatch);
3181 if (result != ISC_R_SUCCESS)
3184 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
3189 if (dispatch != NULL)
3190 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
3191 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
3192 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3193 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
3194 "unable to create dispatch for reserved port %s: %s",
3195 addrbuf, isc_result_totext(result));
3200 loadconfig(ns_server_t *server) {
3201 isc_result_t result;
3202 start_reserved_dispatches(server);
3203 result = load_configuration(ns_g_lwresdonly ?
3204 lwresd_g_conffile : ns_g_conffile,
3206 if (result == ISC_R_SUCCESS)
3207 end_reserved_dispatches(server, ISC_FALSE);
3209 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3210 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3211 "reloading configuration failed: %s",
3212 isc_result_totext(result));
3217 reload(ns_server_t *server) {
3218 isc_result_t result;
3219 CHECK(loadconfig(server));
3221 result = load_zones(server, ISC_FALSE);
3222 if (result != ISC_R_SUCCESS) {
3223 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3224 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3225 "reloading zones failed: %s",
3226 isc_result_totext(result));
3233 reconfig(ns_server_t *server) {
3234 isc_result_t result;
3235 CHECK(loadconfig(server));
3237 result = load_new_zones(server, ISC_FALSE);
3238 if (result != ISC_R_SUCCESS) {
3239 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3240 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3241 "loading new zones failed: %s",
3242 isc_result_totext(result));
3248 * Handle a reload event (from SIGHUP).
3251 ns_server_reload(isc_task_t *task, isc_event_t *event) {
3252 ns_server_t *server = (ns_server_t *)event->ev_arg;
3254 INSIST(task = server->task);
3257 (void)reload(server);
3259 LOCK(&server->reload_event_lock);
3260 INSIST(server->reload_event == NULL);
3261 server->reload_event = event;
3262 UNLOCK(&server->reload_event_lock);
3266 ns_server_reloadwanted(ns_server_t *server) {
3267 LOCK(&server->reload_event_lock);
3268 if (server->reload_event != NULL)
3269 isc_task_send(server->task, &server->reload_event);
3270 UNLOCK(&server->reload_event_lock);
3274 next_token(char **stringp, const char *delim) {
3278 res = strsep(stringp, delim);
3281 } while (*res == '\0');
3286 * Find the zone specified in the control channel command 'args',
3287 * if any. If a zone is specified, point '*zonep' at it, otherwise
3288 * set '*zonep' to NULL.
3291 zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
3293 const char *zonetxt;
3295 const char *viewtxt = NULL;
3296 dns_fixedname_t name;
3297 isc_result_t result;
3299 dns_view_t *view = NULL;
3300 dns_rdataclass_t rdclass;
3302 REQUIRE(zonep != NULL && *zonep == NULL);
3306 /* Skip the command name. */
3307 ptr = next_token(&input, " \t");
3309 return (ISC_R_UNEXPECTEDEND);
3311 /* Look for the zone name. */
3312 zonetxt = next_token(&input, " \t");
3313 if (zonetxt == NULL)
3314 return (ISC_R_SUCCESS);
3316 /* Look for the optional class name. */
3317 classtxt = next_token(&input, " \t");
3318 if (classtxt != NULL) {
3319 /* Look for the optional view name. */
3320 viewtxt = next_token(&input, " \t");
3323 isc_buffer_init(&buf, zonetxt, strlen(zonetxt));
3324 isc_buffer_add(&buf, strlen(zonetxt));
3325 dns_fixedname_init(&name);
3326 result = dns_name_fromtext(dns_fixedname_name(&name),
3327 &buf, dns_rootname, ISC_FALSE, NULL);
3328 if (result != ISC_R_SUCCESS)
3331 if (classtxt != NULL) {
3334 r.length = strlen(classtxt);
3335 result = dns_rdataclass_fromtext(&rdclass, &r);
3336 if (result != ISC_R_SUCCESS)
3339 rdclass = dns_rdataclass_in;
3342 if (viewtxt == NULL)
3343 viewtxt = "_default";
3344 result = dns_viewlist_find(&server->viewlist, viewtxt,
3346 if (result != ISC_R_SUCCESS)
3349 result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
3351 /* Partial match? */
3352 if (result != ISC_R_SUCCESS && *zonep != NULL)
3353 dns_zone_detach(zonep);
3354 dns_view_detach(&view);
3360 * Act on a "retransfer" command from the command channel.
3363 ns_server_retransfercommand(ns_server_t *server, char *args) {
3364 isc_result_t result;
3365 dns_zone_t *zone = NULL;
3366 dns_zonetype_t type;
3368 result = zone_from_args(server, args, &zone);
3369 if (result != ISC_R_SUCCESS)
3372 return (ISC_R_UNEXPECTEDEND);
3373 type = dns_zone_gettype(zone);
3374 if (type == dns_zone_slave || type == dns_zone_stub)
3375 dns_zone_forcereload(zone);
3377 result = ISC_R_NOTFOUND;
3378 dns_zone_detach(&zone);
3383 * Act on a "reload" command from the command channel.
3386 ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
3387 isc_result_t result;
3388 dns_zone_t *zone = NULL;
3389 dns_zonetype_t type;
3390 const char *msg = NULL;
3392 result = zone_from_args(server, args, &zone);
3393 if (result != ISC_R_SUCCESS)
3396 result = reload(server);
3397 if (result == ISC_R_SUCCESS)
3398 msg = "server reload successful";
3400 type = dns_zone_gettype(zone);
3401 if (type == dns_zone_slave || type == dns_zone_stub) {
3402 dns_zone_refresh(zone);
3403 msg = "zone refresh queued";
3405 result = dns_zone_load(zone);
3406 dns_zone_detach(&zone);
3409 msg = "zone reload successful";
3411 case DNS_R_CONTINUE:
3412 msg = "zone reload queued";
3413 result = ISC_R_SUCCESS;
3415 case DNS_R_UPTODATE:
3416 msg = "zone reload up-to-date";
3417 result = ISC_R_SUCCESS;
3420 /* failure message will be generated by rndc */
3425 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
3426 isc_buffer_putmem(text, (const unsigned char *)msg,
3432 * Act on a "reconfig" command from the command channel.
3435 ns_server_reconfigcommand(ns_server_t *server, char *args) {
3439 return (ISC_R_SUCCESS);
3443 * Act on a "refresh" command from the command channel.
3446 ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
3447 isc_result_t result;
3448 dns_zone_t *zone = NULL;
3449 const unsigned char msg[] = "zone refresh queued";
3451 result = zone_from_args(server, args, &zone);
3452 if (result != ISC_R_SUCCESS)
3455 return (ISC_R_UNEXPECTEDEND);
3457 dns_zone_refresh(zone);
3458 dns_zone_detach(&zone);
3459 if (sizeof(msg) <= isc_buffer_availablelength(text))
3460 isc_buffer_putmem(text, msg, sizeof(msg));
3462 return (ISC_R_SUCCESS);
3466 ns_server_togglequerylog(ns_server_t *server) {
3467 server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE;
3469 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3470 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3471 "query logging is now %s",
3472 server->log_queries ? "on" : "off");
3473 return (ISC_R_SUCCESS);
3477 ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config,
3478 ns_aclconfctx_t *actx,
3479 isc_mem_t *mctx, ns_listenlist_t **target)
3481 isc_result_t result;
3482 cfg_listelt_t *element;
3483 ns_listenlist_t *dlist = NULL;
3485 REQUIRE(target != NULL && *target == NULL);
3487 result = ns_listenlist_create(mctx, &dlist);
3488 if (result != ISC_R_SUCCESS)
3491 for (element = cfg_list_first(listenlist);
3493 element = cfg_list_next(element))
3495 ns_listenelt_t *delt = NULL;
3496 cfg_obj_t *listener = cfg_listelt_value(element);
3497 result = ns_listenelt_fromconfig(listener, config, actx,
3499 if (result != ISC_R_SUCCESS)
3501 ISC_LIST_APPEND(dlist->elts, delt, link);
3504 return (ISC_R_SUCCESS);
3507 ns_listenlist_detach(&dlist);
3512 * Create a listen list from the corresponding configuration
3516 ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config,
3517 ns_aclconfctx_t *actx,
3518 isc_mem_t *mctx, ns_listenelt_t **target)
3520 isc_result_t result;
3523 ns_listenelt_t *delt = NULL;
3524 REQUIRE(target != NULL && *target == NULL);
3526 portobj = cfg_tuple_get(listener, "port");
3527 if (!cfg_obj_isuint32(portobj)) {
3528 if (ns_g_port != 0) {
3531 result = ns_config_getport(config, &port);
3532 if (result != ISC_R_SUCCESS)
3536 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
3537 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
3538 "port value '%u' is out of range",
3539 cfg_obj_asuint32(portobj));
3540 return (ISC_R_RANGE);
3542 port = (in_port_t)cfg_obj_asuint32(portobj);
3545 result = ns_listenelt_create(mctx, port, NULL, &delt);
3546 if (result != ISC_R_SUCCESS)
3549 result = ns_acl_fromconfig(cfg_tuple_get(listener, "acl"),
3550 config, actx, mctx, &delt->acl);
3551 if (result != ISC_R_SUCCESS) {
3552 ns_listenelt_destroy(delt);
3556 return (ISC_R_SUCCESS);
3560 ns_server_dumpstats(ns_server_t *server) {
3561 isc_result_t result;
3562 dns_zone_t *zone, *next;
3568 isc_stdtime_get(&now);
3570 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
3571 "could not open statistics dump file", server->statsfile);
3573 ncounters = DNS_STATS_NCOUNTERS;
3574 fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
3576 for (i = 0; i < ncounters; i++)
3577 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT "u\n",
3578 dns_statscounter_names[i],
3579 server->querystats[i]);
3582 for (result = dns_zone_first(server->zonemgr, &zone);
3583 result == ISC_R_SUCCESS;
3584 next = NULL, result = dns_zone_next(zone, &next), zone = next)
3586 isc_uint64_t *zonestats = dns_zone_getstatscounters(zone);
3587 if (zonestats != NULL) {
3588 char zonename[DNS_NAME_FORMATSIZE];
3592 dns_name_format(dns_zone_getorigin(zone),
3593 zonename, sizeof(zonename));
3594 view = dns_zone_getview(zone);
3595 viewname = view->name;
3596 for (i = 0; i < ncounters; i++) {
3597 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT
3599 dns_statscounter_names[i],
3602 if (strcmp(viewname, "_default") != 0)
3603 fprintf(fp, " %s", viewname);
3608 if (result == ISC_R_NOMORE)
3609 result = ISC_R_SUCCESS;
3612 fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
3616 (void)isc_stdio_close(fp);
3621 add_zone_tolist(dns_zone_t *zone, void *uap) {
3622 struct dumpcontext *dctx = uap;
3623 struct zonelistentry *zle;
3625 zle = isc_mem_get(dctx->mctx, sizeof *zle);
3627 return (ISC_R_NOMEMORY);
3629 dns_zone_attach(zone, &zle->zone);
3630 ISC_LINK_INIT(zle, link);
3631 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
3632 return (ISC_R_SUCCESS);
3636 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
3637 struct viewlistentry *vle;
3638 isc_result_t result = ISC_R_SUCCESS;
3640 vle = isc_mem_get(dctx->mctx, sizeof *vle);
3642 return (ISC_R_NOMEMORY);
3644 dns_view_attach(view, &vle->view);
3645 ISC_LINK_INIT(vle, link);
3646 ISC_LIST_INIT(vle->zonelist);
3647 ISC_LIST_APPEND(dctx->viewlist, vle, link);
3648 if (dctx->dumpzones)
3649 result = dns_zt_apply(view->zonetable, ISC_TRUE,
3650 add_zone_tolist, dctx);
3655 dumpcontext_destroy(struct dumpcontext *dctx) {
3656 struct viewlistentry *vle;
3657 struct zonelistentry *zle;
3659 vle = ISC_LIST_HEAD(dctx->viewlist);
3660 while (vle != NULL) {
3661 ISC_LIST_UNLINK(dctx->viewlist, vle, link);
3662 zle = ISC_LIST_HEAD(vle->zonelist);
3663 while (zle != NULL) {
3664 ISC_LIST_UNLINK(vle->zonelist, zle, link);
3665 dns_zone_detach(&zle->zone);
3666 isc_mem_put(dctx->mctx, zle, sizeof *zle);
3667 zle = ISC_LIST_HEAD(vle->zonelist);
3669 dns_view_detach(&vle->view);
3670 isc_mem_put(dctx->mctx, vle, sizeof *vle);
3671 vle = ISC_LIST_HEAD(dctx->viewlist);
3673 if (dctx->version != NULL)
3674 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
3675 if (dctx->db != NULL)
3676 dns_db_detach(&dctx->db);
3677 if (dctx->cache != NULL)
3678 dns_db_detach(&dctx->cache);
3679 if (dctx->task != NULL)
3680 isc_task_detach(&dctx->task);
3681 if (dctx->fp != NULL)
3682 (void)isc_stdio_close(dctx->fp);
3683 if (dctx->mdctx != NULL)
3684 dns_dumpctx_detach(&dctx->mdctx);
3685 isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
3689 dumpdone(void *arg, isc_result_t result) {
3690 struct dumpcontext *dctx = arg;
3692 const dns_master_style_t *style;
3694 if (result != ISC_R_SUCCESS)
3696 if (dctx->mdctx != NULL)
3697 dns_dumpctx_detach(&dctx->mdctx);
3698 if (dctx->view == NULL) {
3699 dctx->view = ISC_LIST_HEAD(dctx->viewlist);
3700 if (dctx->view == NULL)
3702 INSIST(dctx->zone == NULL);
3705 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
3706 if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) {
3707 style = &dns_master_style_cache;
3708 /* start cache dump */
3709 if (dctx->view->view->cachedb != NULL)
3710 dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
3711 if (dctx->cache != NULL) {
3713 fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n",
3714 dctx->view->view->name);
3715 result = dns_master_dumptostreaminc(dctx->mctx,
3721 if (result == DNS_R_CONTINUE)
3723 if (result == ISC_R_NOTIMPLEMENTED)
3724 fprintf(dctx->fp, "; %s\n",
3725 dns_result_totext(result));
3726 else if (result != ISC_R_SUCCESS)
3730 if (dctx->cache != NULL) {
3731 dns_adb_dump(dctx->view->view->adb, dctx->fp);
3732 dns_db_detach(&dctx->cache);
3734 if (dctx->dumpzones) {
3735 style = &dns_master_style_full;
3737 if (dctx->version != NULL)
3738 dns_db_closeversion(dctx->db, &dctx->version,
3740 if (dctx->db != NULL)
3741 dns_db_detach(&dctx->db);
3742 if (dctx->zone == NULL)
3743 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
3745 dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
3746 if (dctx->zone != NULL) {
3747 /* start zone dump */
3748 dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
3749 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
3750 result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
3751 if (result != ISC_R_SUCCESS) {
3752 fprintf(dctx->fp, "; %s\n",
3753 dns_result_totext(result));
3756 dns_db_currentversion(dctx->db, &dctx->version);
3757 result = dns_master_dumptostreaminc(dctx->mctx,
3764 if (result == DNS_R_CONTINUE)
3766 if (result == ISC_R_NOTIMPLEMENTED)
3767 fprintf(dctx->fp, "; %s\n",
3768 dns_result_totext(result));
3769 if (result != ISC_R_SUCCESS)
3773 if (dctx->view != NULL)
3774 dctx->view = ISC_LIST_NEXT(dctx->view, link);
3775 if (dctx->view != NULL)
3778 fprintf(dctx->fp, "; Dump complete\n");
3779 result = isc_stdio_flush(dctx->fp);
3780 if (result == ISC_R_SUCCESS)
3781 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3782 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3785 if (result != ISC_R_SUCCESS)
3786 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3787 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3788 "dumpdb failed: %s", dns_result_totext(result));
3789 dumpcontext_destroy(dctx);
3794 ns_server_dumpdb(ns_server_t *server, char *args) {
3795 struct dumpcontext *dctx = NULL;
3797 isc_result_t result;
3801 dctx = isc_mem_get(server->mctx, sizeof(*dctx));
3803 return (ISC_R_NOMEMORY);
3805 dctx->mctx = server->mctx;
3806 dctx->dumpcache = ISC_TRUE;
3807 dctx->dumpzones = ISC_FALSE;
3809 ISC_LIST_INIT(dctx->viewlist);
3817 dctx->version = NULL;
3818 isc_task_attach(server->task, &dctx->task);
3820 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
3821 "could not open dump file", server->dumpfile);
3823 /* Skip the command name. */
3824 ptr = next_token(&args, " \t");
3826 return (ISC_R_UNEXPECTEDEND);
3828 sep = (args == NULL) ? "" : ": ";
3829 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3830 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3831 "dumpdb started%s%s", sep, (args != NULL) ? args : "");
3833 ptr = next_token(&args, " \t");
3834 if (ptr != NULL && strcmp(ptr, "-all") == 0) {
3835 dctx->dumpzones = ISC_TRUE;
3836 dctx->dumpcache = ISC_TRUE;
3837 ptr = next_token(&args, " \t");
3838 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
3839 dctx->dumpzones = ISC_FALSE;
3840 dctx->dumpcache = ISC_TRUE;
3841 ptr = next_token(&args, " \t");
3842 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
3843 dctx->dumpzones = ISC_TRUE;
3844 dctx->dumpcache = ISC_FALSE;
3845 ptr = next_token(&args, " \t");
3848 for (view = ISC_LIST_HEAD(server->viewlist);
3850 view = ISC_LIST_NEXT(view, link))
3852 if (ptr != NULL && strcmp(view->name, ptr) != 0)
3854 CHECK(add_view_tolist(dctx, view));
3856 dumpdone(dctx, ISC_R_SUCCESS);
3857 return (ISC_R_SUCCESS);
3861 dumpcontext_destroy(dctx);
3866 ns_server_dumprecursing(ns_server_t *server) {
3868 isc_result_t result;
3870 CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
3871 "could not open dump file", server->recfile);
3872 fprintf(fp,";\n; Recursing Queries\n;\n");
3873 ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
3874 fprintf(fp, "; Dump complete\n");
3878 result = isc_stdio_close(fp);
3883 ns_server_setdebuglevel(ns_server_t *server, char *args) {
3891 /* Skip the command name. */
3892 ptr = next_token(&args, " \t");
3894 return (ISC_R_UNEXPECTEDEND);
3896 /* Look for the new level name. */
3897 levelstr = next_token(&args, " \t");
3898 if (levelstr == NULL) {
3899 if (ns_g_debuglevel < 99)
3902 newlevel = strtol(levelstr, &endp, 10);
3903 if (*endp != '\0' || newlevel < 0 || newlevel > 99)
3904 return (ISC_R_RANGE);
3905 ns_g_debuglevel = (unsigned int)newlevel;
3907 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
3908 return (ISC_R_SUCCESS);
3912 ns_server_flushcache(ns_server_t *server, char *args) {
3913 char *ptr, *viewname;
3915 isc_boolean_t flushed = ISC_FALSE;
3916 isc_result_t result;
3918 /* Skip the command name. */
3919 ptr = next_token(&args, " \t");
3921 return (ISC_R_UNEXPECTEDEND);
3923 /* Look for the view name. */
3924 viewname = next_token(&args, " \t");
3926 result = isc_task_beginexclusive(server->task);
3927 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3928 for (view = ISC_LIST_HEAD(server->viewlist);
3930 view = ISC_LIST_NEXT(view, link))
3932 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
3934 result = dns_view_flushcache(view);
3935 if (result != ISC_R_SUCCESS)
3940 result = ISC_R_SUCCESS;
3942 result = ISC_R_FAILURE;
3944 isc_task_endexclusive(server->task);
3949 ns_server_flushname(ns_server_t *server, char *args) {
3950 char *ptr, *target, *viewname;
3952 isc_boolean_t flushed = ISC_FALSE;
3953 isc_result_t result;
3955 dns_fixedname_t fixed;
3958 /* Skip the command name. */
3959 ptr = next_token(&args, " \t");
3961 return (ISC_R_UNEXPECTEDEND);
3963 /* Find the domain name to flush. */
3964 target = next_token(&args, " \t");
3966 return (ISC_R_UNEXPECTEDEND);
3968 isc_buffer_init(&b, target, strlen(target));
3969 isc_buffer_add(&b, strlen(target));
3970 dns_fixedname_init(&fixed);
3971 name = dns_fixedname_name(&fixed);
3972 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
3973 if (result != ISC_R_SUCCESS)
3976 /* Look for the view name. */
3977 viewname = next_token(&args, " \t");
3979 result = isc_task_beginexclusive(server->task);
3980 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3982 for (view = ISC_LIST_HEAD(server->viewlist);
3984 view = ISC_LIST_NEXT(view, link))
3986 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
3988 result = dns_view_flushname(view, name);
3989 if (result != ISC_R_SUCCESS)
3990 flushed = ISC_FALSE;
3993 result = ISC_R_SUCCESS;
3995 result = ISC_R_FAILURE;
3996 isc_task_endexclusive(server->task);
4001 ns_server_status(ns_server_t *server, isc_buffer_t *text) {
4002 int zonecount, xferrunning, xferdeferred, soaqueries;
4005 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
4006 xferrunning = dns_zonemgr_getcount(server->zonemgr,
4007 DNS_ZONESTATE_XFERRUNNING);
4008 xferdeferred = dns_zonemgr_getcount(server->zonemgr,
4009 DNS_ZONESTATE_XFERDEFERRED);
4010 soaqueries = dns_zonemgr_getcount(server->zonemgr,
4011 DNS_ZONESTATE_SOAQUERY);
4012 n = snprintf((char *)isc_buffer_used(text),
4013 isc_buffer_availablelength(text),
4014 "number of zones: %u\n"
4016 "xfers running: %u\n"
4017 "xfers deferred: %u\n"
4018 "soa queries in progress: %u\n"
4019 "query logging is %s\n"
4020 "recursive clients: %d/%d\n"
4021 "tcp clients: %d/%d\n"
4022 "server is up and running",
4023 zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
4024 soaqueries, server->log_queries ? "ON" : "OFF",
4025 server->recursionquota.used, server->recursionquota.max,
4026 server->tcpquota.used, server->tcpquota.max);
4027 if (n >= isc_buffer_availablelength(text))
4028 return (ISC_R_NOSPACE);
4029 isc_buffer_add(text, n);
4030 return (ISC_R_SUCCESS);
4034 * Act on a "freeze" or "unfreeze" command from the command channel.
4037 ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) {
4038 isc_result_t result;
4039 dns_zone_t *zone = NULL;
4040 dns_zonetype_t type;
4041 char classstr[DNS_RDATACLASS_FORMATSIZE];
4042 char zonename[DNS_NAME_FORMATSIZE];
4045 const char *vname, *sep;
4046 isc_boolean_t frozen;
4048 result = zone_from_args(server, args, &zone);
4049 if (result != ISC_R_SUCCESS)
4052 return (ISC_R_UNEXPECTEDEND);
4053 type = dns_zone_gettype(zone);
4054 if (type != dns_zone_master) {
4055 dns_zone_detach(&zone);
4056 return (ISC_R_NOTFOUND);
4059 frozen = dns_zone_getupdatedisabled(zone);
4062 result = DNS_R_FROZEN;
4063 if (result == ISC_R_SUCCESS)
4064 result = dns_zone_flush(zone);
4065 if (result == ISC_R_SUCCESS) {
4066 journal = dns_zone_getjournal(zone);
4067 if (journal != NULL)
4068 (void)isc_file_remove(journal);
4072 result = dns_zone_load(zone);
4073 if (result == DNS_R_CONTINUE ||
4074 result == DNS_R_UPTODATE)
4075 result = ISC_R_SUCCESS;
4078 if (result == ISC_R_SUCCESS)
4079 dns_zone_setupdatedisabled(zone, freeze);
4081 view = dns_zone_getview(zone);
4082 if (strcmp(view->name, "_bind") == 0 ||
4083 strcmp(view->name, "_default") == 0)
4091 dns_rdataclass_format(dns_zone_getclass(zone), classstr,
4093 dns_name_format(dns_zone_getorigin(zone),
4094 zonename, sizeof(zonename));
4095 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4096 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4097 "%s zone '%s/%s'%s%s: %s",
4098 freeze ? "freezing" : "unfreezing",
4099 zonename, classstr, sep, vname,
4100 isc_result_totext(result));
4101 dns_zone_detach(&zone);