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.56 2004/06/18 04:39:48 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;
526 result = ns_config_getclass(cfg_tuple_get(ent, "class"),
527 dns_rdataclass_any, &rdclass);
528 if (result != ISC_R_SUCCESS)
531 result = ns_config_gettype(cfg_tuple_get(ent, "type"),
532 dns_rdatatype_any, &rdtype);
533 if (result != ISC_R_SUCCESS)
536 obj = cfg_tuple_get(ent, "name");
537 if (cfg_obj_isstring(obj))
538 str = cfg_obj_asstring(obj);
541 isc_buffer_init(&b, str, strlen(str));
542 isc_buffer_add(&b, strlen(str));
543 dns_fixedname_init(&fixed);
544 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
545 dns_rootname, ISC_FALSE, NULL);
546 if (result != ISC_R_SUCCESS)
549 obj = cfg_tuple_get(ent, "ordering");
550 INSIST(cfg_obj_isstring(obj));
551 str = cfg_obj_asstring(obj);
552 if (!strcasecmp(str, "fixed"))
553 mode = DNS_RDATASETATTR_FIXEDORDER;
554 else if (!strcasecmp(str, "random"))
555 mode = DNS_RDATASETATTR_RANDOMIZE;
556 else if (!strcasecmp(str, "cyclic"))
561 return (dns_order_add(order, dns_fixedname_name(&fixed),
562 rdtype, rdclass, mode));
566 configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
574 sa = cfg_obj_assockaddr(cfg_map_getname(cpeer));
575 isc_netaddr_fromsockaddr(&na, sa);
578 result = dns_peer_new(mctx, &na, &peer);
579 if (result != ISC_R_SUCCESS)
583 (void)cfg_map_get(cpeer, "bogus", &obj);
585 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
588 (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
590 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
593 (void)cfg_map_get(cpeer, "request-ixfr", &obj);
595 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
598 (void)cfg_map_get(cpeer, "edns", &obj);
600 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
603 (void)cfg_map_get(cpeer, "transfers", &obj);
605 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
608 (void)cfg_map_get(cpeer, "transfer-format", &obj);
610 str = cfg_obj_asstring(obj);
611 if (strcasecmp(str, "many-answers") == 0)
612 CHECK(dns_peer_settransferformat(peer,
614 else if (strcasecmp(str, "one-answer") == 0)
615 CHECK(dns_peer_settransferformat(peer,
622 (void)cfg_map_get(cpeer, "keys", &obj);
624 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
625 if (result != ISC_R_SUCCESS)
630 if (isc_sockaddr_pf(sa) == AF_INET)
631 (void)cfg_map_get(cpeer, "transfer-source", &obj);
633 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
635 result = dns_peer_settransfersource(peer,
636 cfg_obj_assockaddr(obj));
637 if (result != ISC_R_SUCCESS)
641 return (ISC_R_SUCCESS);
644 dns_peer_detach(&peer);
649 disable_algorithms(cfg_obj_t *disabled, dns_resolver_t *resolver) {
651 cfg_obj_t *algorithms;
652 cfg_listelt_t *element;
654 dns_fixedname_t fixed;
658 dns_fixedname_init(&fixed);
659 name = dns_fixedname_name(&fixed);
660 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
661 isc_buffer_init(&b, str, strlen(str));
662 isc_buffer_add(&b, strlen(str));
663 CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL));
665 algorithms = cfg_tuple_get(disabled, "algorithms");
666 for (element = cfg_list_first(algorithms);
668 element = cfg_list_next(element))
673 r.base = cfg_obj_asstring(cfg_listelt_value(element));
674 r.length = strlen(r.base);
676 result = dns_secalg_fromtext(&alg, &r);
677 if (result != ISC_R_SUCCESS) {
679 result = isc_parse_uint8(&ui, r.base, 10);
682 if (result != ISC_R_SUCCESS) {
683 cfg_obj_log(cfg_listelt_value(element),
684 ns_g_lctx, ISC_LOG_ERROR,
685 "invalid algorithm");
688 CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
695 * Configure 'view' according to 'vconfig', taking defaults from 'config'
696 * where values are missing in 'vconfig'.
698 * When configuring the default view, 'vconfig' will be NULL and the
699 * global defaults in 'config' used exclusively.
702 configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
703 isc_mem_t *mctx, ns_aclconfctx_t *actx,
704 isc_boolean_t need_hints)
707 cfg_obj_t *cfgmaps[3];
708 cfg_obj_t *options = NULL;
709 cfg_obj_t *voptions = NULL;
710 cfg_obj_t *forwardtype;
711 cfg_obj_t *forwarders;
712 cfg_obj_t *alternates;
716 cfg_listelt_t *element;
718 dns_cache_t *cache = NULL;
720 isc_uint32_t max_adb_size;
721 isc_uint32_t max_cache_size;
722 isc_uint32_t lame_ttl;
723 dns_tsig_keyring_t *ring;
724 dns_view_t *pview = NULL; /* Production view */
726 dns_dispatch_t *dispatch4 = NULL;
727 dns_dispatch_t *dispatch6 = NULL;
728 isc_boolean_t reused_cache = ISC_FALSE;
731 dns_order_t *order = NULL;
732 isc_uint32_t udpsize;
733 unsigned int check = 0;
735 REQUIRE(DNS_VIEW_VALID(view));
740 (void)cfg_map_get(config, "options", &options);
743 if (vconfig != NULL) {
744 voptions = cfg_tuple_get(vconfig, "options");
745 maps[i++] = voptions;
749 maps[i++] = ns_g_defaults;
753 if (voptions != NULL)
754 cfgmaps[i++] = voptions;
756 cfgmaps[i++] = config;
760 * Set the view's port number for outgoing queries.
762 CHECKM(ns_config_getport(config, &port), "port");
763 dns_view_setdstport(view, port);
766 * Configure the zones.
769 if (voptions != NULL)
770 (void)cfg_map_get(voptions, "zone", &zonelist);
772 (void)cfg_map_get(config, "zone", &zonelist);
773 for (element = cfg_list_first(zonelist);
775 element = cfg_list_next(element))
777 cfg_obj_t *zconfig = cfg_listelt_value(element);
778 CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
783 * Configure the view's cache. Try to reuse an existing
784 * cache if possible, otherwise create a new cache.
785 * Note that the ADB is not preserved in either case.
787 * XXX Determining when it is safe to reuse a cache is
788 * tricky. When the view's configuration changes, the cached
789 * data may become invalid because it reflects our old
790 * view of the world. As more view attributes become
791 * configurable, we will have to add code here to check
792 * whether they have changed in ways that could
793 * invalidate the cache.
795 result = dns_viewlist_find(&ns_g_server->viewlist,
796 view->name, view->rdclass,
798 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
801 INSIST(pview->cache != NULL);
802 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
803 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3),
804 "reusing existing cache");
805 reused_cache = ISC_TRUE;
806 dns_cache_attach(pview->cache, &cache);
807 dns_view_detach(&pview);
809 CHECK(isc_mem_create(0, 0, &cmctx));
810 CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr,
811 view->rdclass, "rbt", 0, NULL, &cache));
813 dns_view_setcache(view, cache);
816 * cache-file cannot be inherited if views are present, but this
817 * should be caught by the configuration checking stage.
820 result = ns_config_get(maps, "cache-file", &obj);
821 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) {
822 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj)));
824 CHECK(dns_cache_load(cache));
828 result = ns_config_get(maps, "cleaning-interval", &obj);
829 INSIST(result == ISC_R_SUCCESS);
830 dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60);
833 result = ns_config_get(maps, "max-cache-size", &obj);
834 INSIST(result == ISC_R_SUCCESS);
835 if (cfg_obj_isstring(obj)) {
836 str = cfg_obj_asstring(obj);
837 INSIST(strcasecmp(str, "unlimited") == 0);
838 max_cache_size = ISC_UINT32_MAX;
840 isc_resourcevalue_t value;
841 value = cfg_obj_asuint64(obj);
842 if (value > ISC_UINT32_MAX) {
843 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
845 "%" ISC_PRINT_QUADFORMAT "d' is too large",
847 result = ISC_R_RANGE;
850 max_cache_size = (isc_uint32_t)value;
852 dns_cache_setcachesize(cache, max_cache_size);
854 dns_cache_detach(&cache);
860 result = ns_checknames_get(maps, "response", &obj);
861 INSIST(result == ISC_R_SUCCESS);
863 str = cfg_obj_asstring(obj);
864 if (strcasecmp(str, "fail") == 0) {
865 check = DNS_RESOLVER_CHECKNAMES |
866 DNS_RESOLVER_CHECKNAMESFAIL;
867 view->checknames = ISC_TRUE;
868 } else if (strcasecmp(str, "warn") == 0) {
869 check = DNS_RESOLVER_CHECKNAMES;
870 view->checknames = ISC_FALSE;
871 } else if (strcasecmp(str, "ignore") == 0) {
873 view->checknames = ISC_FALSE;
880 * XXXRTH Hardwired number of tasks.
882 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4));
883 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6));
884 if (dispatch4 == NULL && dispatch6 == NULL) {
885 UNEXPECTED_ERROR(__FILE__, __LINE__,
886 "unable to obtain neither an IPv4 nor"
887 " an IPv6 dispatch");
888 result = ISC_R_UNEXPECTED;
891 CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
892 ns_g_socketmgr, ns_g_timermgr,
893 check, ns_g_dispatchmgr,
894 dispatch4, dispatch6));
897 * Set the ADB cache size to 1/8th of the max-cache-size.
900 if (max_cache_size != 0) {
901 max_adb_size = max_cache_size / 8;
902 if (max_adb_size == 0)
903 max_adb_size = 1; /* Force minimum. */
905 dns_adb_setadbsize(view->adb, max_adb_size);
908 * Set resolver's lame-ttl.
911 result = ns_config_get(maps, "lame-ttl", &obj);
912 INSIST(result == ISC_R_SUCCESS);
913 lame_ttl = cfg_obj_asuint32(obj);
916 dns_resolver_setlamettl(view->resolver, lame_ttl);
919 * Set the resolver's EDNS UDP size.
922 result = ns_config_get(maps, "edns-udp-size", &obj);
923 INSIST(result == ISC_R_SUCCESS);
924 udpsize = cfg_obj_asuint32(obj);
929 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize);
932 * Set supported DNSSEC algorithms.
934 dns_resolver_reset_algorithms(view->resolver);
936 (void)ns_config_get(maps, "disable-algorithms", &disabled);
937 if (disabled != NULL) {
938 for (element = cfg_list_first(disabled);
940 element = cfg_list_next(element))
941 CHECK(disable_algorithms(cfg_listelt_value(element),
946 * A global or view "forwarders" option, if present,
947 * creates an entry for "." in the forwarding table.
951 (void)ns_config_get(maps, "forward", &forwardtype);
952 (void)ns_config_get(maps, "forwarders", &forwarders);
953 if (forwarders != NULL)
954 CHECK(configure_forward(config, view, dns_rootname,
955 forwarders, forwardtype));
958 * Dual Stack Servers.
961 (void)ns_config_get(maps, "dual-stack-servers", &alternates);
962 if (alternates != NULL)
963 CHECK(configure_alternates(config, view, alternates));
966 * We have default hints for class IN if we need them.
968 if (view->rdclass == dns_rdataclass_in && view->hints == NULL)
969 dns_view_sethints(view, ns_g_server->in_roothints);
972 * If we still have no hints, this is a non-IN view with no
973 * "hints zone" configured. Issue a warning, except if this
974 * is a root server. Root servers never need to consult
975 * their hints, so it's no point requiring users to configure
978 if (view->hints == NULL) {
979 dns_zone_t *rootzone = NULL;
980 (void)dns_view_findzone(view, dns_rootname, &rootzone);
981 if (rootzone != NULL) {
982 dns_zone_detach(&rootzone);
983 need_hints = ISC_FALSE;
986 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
987 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
988 "no root hints for view '%s'",
993 * Configure the view's TSIG keys.
996 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
997 dns_view_setkeyring(view, ring);
1000 * Configure the view's peer list.
1003 cfg_obj_t *peers = NULL;
1004 cfg_listelt_t *element;
1005 dns_peerlist_t *newpeers = NULL;
1007 (void)ns_config_get(cfgmaps, "server", &peers);
1008 CHECK(dns_peerlist_new(mctx, &newpeers));
1009 for (element = cfg_list_first(peers);
1011 element = cfg_list_next(element))
1013 cfg_obj_t *cpeer = cfg_listelt_value(element);
1016 CHECK(configure_peer(cpeer, mctx, &peer));
1017 dns_peerlist_addpeer(newpeers, peer);
1018 dns_peer_detach(&peer);
1020 dns_peerlist_detach(&view->peers);
1021 view->peers = newpeers; /* Transfer ownership. */
1025 * Configure the views rrset-order.
1028 cfg_obj_t *rrsetorder = NULL;
1029 cfg_listelt_t *element;
1031 (void)ns_config_get(maps, "rrset-order", &rrsetorder);
1032 CHECK(dns_order_create(mctx, &order));
1033 for (element = cfg_list_first(rrsetorder);
1035 element = cfg_list_next(element))
1037 cfg_obj_t *ent = cfg_listelt_value(element);
1039 CHECK(configure_order(order, ent));
1041 if (view->order != NULL)
1042 dns_order_detach(&view->order);
1043 dns_order_attach(order, &view->order);
1044 dns_order_detach(&order);
1047 * Copy the aclenv object.
1049 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv);
1052 * Configure the "match-clients" and "match-destinations" ACL.
1054 CHECK(configure_view_acl(vconfig, config, "match-clients", actx,
1055 ns_g_mctx, &view->matchclients));
1056 CHECK(configure_view_acl(vconfig, config, "match-destinations", actx,
1057 ns_g_mctx, &view->matchdestinations));
1060 * Configure the "match-recursive-only" option.
1063 (void) ns_config_get(maps, "match-recursive-only", &obj);
1064 if (obj != NULL && cfg_obj_asboolean(obj))
1065 view->matchrecursiveonly = ISC_TRUE;
1067 view->matchrecursiveonly = ISC_FALSE;
1070 * Configure other configurable data.
1073 result = ns_config_get(maps, "recursion", &obj);
1074 INSIST(result == ISC_R_SUCCESS);
1075 view->recursion = cfg_obj_asboolean(obj);
1078 result = ns_config_get(maps, "auth-nxdomain", &obj);
1079 INSIST(result == ISC_R_SUCCESS);
1080 view->auth_nxdomain = cfg_obj_asboolean(obj);
1083 result = ns_config_get(maps, "minimal-responses", &obj);
1084 INSIST(result == ISC_R_SUCCESS);
1085 view->minimalresponses = cfg_obj_asboolean(obj);
1088 result = ns_config_get(maps, "transfer-format", &obj);
1089 INSIST(result == ISC_R_SUCCESS);
1090 str = cfg_obj_asstring(obj);
1091 if (strcasecmp(str, "many-answers") == 0)
1092 view->transfer_format = dns_many_answers;
1093 else if (strcasecmp(str, "one-answer") == 0)
1094 view->transfer_format = dns_one_answer;
1099 * Set sources where additional data and CNAME/DNAME
1100 * targets for authoritative answers may be found.
1103 result = ns_config_get(maps, "additional-from-auth", &obj);
1104 INSIST(result == ISC_R_SUCCESS);
1105 view->additionalfromauth = cfg_obj_asboolean(obj);
1106 if (view->recursion && ! view->additionalfromauth) {
1107 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1108 "'additional-from-auth no' is only supported "
1109 "with 'recursion no'");
1110 view->additionalfromauth = ISC_TRUE;
1114 result = ns_config_get(maps, "additional-from-cache", &obj);
1115 INSIST(result == ISC_R_SUCCESS);
1116 view->additionalfromcache = cfg_obj_asboolean(obj);
1117 if (view->recursion && ! view->additionalfromcache) {
1118 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1119 "'additional-from-cache no' is only supported "
1120 "with 'recursion no'");
1121 view->additionalfromcache = ISC_TRUE;
1124 CHECK(configure_view_acl(vconfig, config, "allow-query",
1125 actx, ns_g_mctx, &view->queryacl));
1127 if (strcmp(view->name, "_bind") != 0)
1128 CHECK(configure_view_acl(vconfig, config, "allow-recursion",
1129 actx, ns_g_mctx, &view->recursionacl));
1132 * Warning if both "recursion no;" and allow-recursion are active
1133 * except for "allow-recursion { none; };".
1135 if (!view->recursion && view->recursionacl != NULL &&
1136 (view->recursionacl->length != 1 ||
1137 view->recursionacl->elements[0].type != dns_aclelementtype_any ||
1138 view->recursionacl->elements[0].negative != ISC_TRUE)) {
1139 const char *forview = " for view ";
1140 const char *viewname = view->name;
1142 if (!strcmp(view->name, "_bind") ||
1143 !strcmp(view->name, "_default")) {
1147 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1148 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1149 "both \"recursion no;\" and \"allow-recursion\" "
1150 "active%s%s", forview, viewname);
1153 CHECK(configure_view_acl(vconfig, config, "sortlist",
1154 actx, ns_g_mctx, &view->sortlist));
1157 result = ns_config_get(maps, "request-ixfr", &obj);
1158 INSIST(result == ISC_R_SUCCESS);
1159 view->requestixfr = cfg_obj_asboolean(obj);
1162 result = ns_config_get(maps, "provide-ixfr", &obj);
1163 INSIST(result == ISC_R_SUCCESS);
1164 view->provideixfr = cfg_obj_asboolean(obj);
1167 result = ns_config_get(maps, "dnssec-enable", &obj);
1168 INSIST(result == ISC_R_SUCCESS);
1169 view->enablednssec = cfg_obj_asboolean(obj);
1172 result = ns_config_get(maps, "dnssec-lookaside", &obj);
1173 if (result == ISC_R_SUCCESS) {
1174 for (element = cfg_list_first(obj);
1176 element = cfg_list_next(element))
1182 obj = cfg_listelt_value(element);
1184 dns_fixedname_t fixed;
1188 * When we support multiple dnssec-lookaside
1189 * entries this is how to find the domain to be
1192 dns_fixedname_init(&fixed);
1193 name = dns_fixedname_name(&fixed);
1194 str = cfg_obj_asstring(cfg_tuple_get(obj,
1196 isc_buffer_init(&b, str, strlen(str));
1197 isc_buffer_add(&b, strlen(str));
1198 CHECK(dns_name_fromtext(name, &b, dns_rootname,
1201 str = cfg_obj_asstring(cfg_tuple_get(obj,
1203 isc_buffer_init(&b, str, strlen(str));
1204 isc_buffer_add(&b, strlen(str));
1205 dlv = dns_fixedname_name(&view->dlv_fixed);
1206 CHECK(dns_name_fromtext(dlv, &b, dns_rootname,
1208 view->dlv = dns_fixedname_name(&view->dlv_fixed);
1214 * For now, there is only one kind of trusted keys, the
1217 if (view->enablednssec) {
1218 CHECK(configure_view_dnsseckeys(vconfig, config, mctx,
1220 dns_resolver_resetmustbesecure(view->resolver);
1222 result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
1223 if (result == ISC_R_SUCCESS)
1224 CHECK(mustbesecure(obj, view->resolver));
1228 result = ns_config_get(maps, "max-cache-ttl", &obj);
1229 INSIST(result == ISC_R_SUCCESS);
1230 view->maxcachettl = cfg_obj_asuint32(obj);
1233 result = ns_config_get(maps, "max-ncache-ttl", &obj);
1234 INSIST(result == ISC_R_SUCCESS);
1235 view->maxncachettl = cfg_obj_asuint32(obj);
1236 if (view->maxncachettl > 7 * 24 * 3600)
1237 view->maxncachettl = 7 * 24 * 3600;
1240 result = ns_config_get(maps, "preferred-glue", &obj);
1241 if (result == ISC_R_SUCCESS) {
1242 str = cfg_obj_asstring(obj);
1243 if (strcasecmp(str, "a") == 0)
1244 view->preferred_glue = dns_rdatatype_a;
1245 else if (strcasecmp(str, "aaaa") == 0)
1246 view->preferred_glue = dns_rdatatype_aaaa;
1248 view->preferred_glue = 0;
1250 view->preferred_glue = 0;
1253 result = ns_config_get(maps, "root-delegation-only", &obj);
1254 if (result == ISC_R_SUCCESS) {
1255 dns_view_setrootdelonly(view, ISC_TRUE);
1256 if (!cfg_obj_isvoid(obj)) {
1257 dns_fixedname_t fixed;
1263 dns_fixedname_init(&fixed);
1264 name = dns_fixedname_name(&fixed);
1265 for (element = cfg_list_first(obj);
1267 element = cfg_list_next(element)) {
1268 exclude = cfg_listelt_value(element);
1269 str = cfg_obj_asstring(exclude);
1270 isc_buffer_init(&b, str, strlen(str));
1271 isc_buffer_add(&b, strlen(str));
1272 CHECK(dns_name_fromtext(name, &b, dns_rootname,
1274 CHECK(dns_view_excludedelegationonly(view,
1279 dns_view_setrootdelonly(view, ISC_FALSE);
1281 result = ISC_R_SUCCESS;
1284 if (dispatch4 != NULL)
1285 dns_dispatch_detach(&dispatch4);
1286 if (dispatch6 != NULL)
1287 dns_dispatch_detach(&dispatch6);
1289 dns_order_detach(&order);
1291 isc_mem_detach(&cmctx);
1294 dns_cache_detach(&cache);
1300 configure_hints(dns_view_t *view, const char *filename) {
1301 isc_result_t result;
1305 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db);
1306 if (result == ISC_R_SUCCESS) {
1307 dns_view_sethints(view, db);
1315 configure_alternates(cfg_obj_t *config, dns_view_t *view,
1316 cfg_obj_t *alternates)
1319 cfg_obj_t *addresses;
1320 cfg_listelt_t *element;
1321 isc_result_t result = ISC_R_SUCCESS;
1325 * Determine which port to send requests to.
1327 if (ns_g_lwresdonly && ns_g_port != 0)
1330 CHECKM(ns_config_getport(config, &port), "port");
1332 if (alternates != NULL) {
1333 portobj = cfg_tuple_get(alternates, "port");
1334 if (cfg_obj_isuint32(portobj)) {
1335 isc_uint32_t val = cfg_obj_asuint32(portobj);
1336 if (val > ISC_UINT16_MAX) {
1337 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
1338 "port '%u' out of range", val);
1339 return (ISC_R_RANGE);
1341 port = (in_port_t) val;
1346 if (alternates != NULL)
1347 addresses = cfg_tuple_get(alternates, "addresses");
1349 for (element = cfg_list_first(addresses);
1351 element = cfg_list_next(element))
1353 cfg_obj_t *alternate = cfg_listelt_value(element);
1356 if (!cfg_obj_issockaddr(alternate)) {
1357 dns_fixedname_t fixed;
1359 char *str = cfg_obj_asstring(cfg_tuple_get(alternate,
1361 isc_buffer_t buffer;
1362 in_port_t myport = port;
1364 isc_buffer_init(&buffer, str, strlen(str));
1365 isc_buffer_add(&buffer, strlen(str));
1366 dns_fixedname_init(&fixed);
1367 name = dns_fixedname_name(&fixed);
1368 CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
1371 portobj = cfg_tuple_get(alternate, "port");
1372 if (cfg_obj_isuint32(portobj)) {
1373 isc_uint32_t val = cfg_obj_asuint32(portobj);
1374 if (val > ISC_UINT16_MAX) {
1375 cfg_obj_log(portobj, ns_g_lctx,
1377 "port '%u' out of range",
1379 return (ISC_R_RANGE);
1381 myport = (in_port_t) val;
1383 CHECK(dns_resolver_addalternate(view->resolver, NULL,
1388 sa = *cfg_obj_assockaddr(alternate);
1389 if (isc_sockaddr_getport(&sa) == 0)
1390 isc_sockaddr_setport(&sa, port);
1391 CHECK(dns_resolver_addalternate(view->resolver, &sa,
1400 configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
1401 cfg_obj_t *forwarders, cfg_obj_t *forwardtype)
1404 cfg_obj_t *faddresses;
1405 cfg_listelt_t *element;
1406 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
1407 isc_sockaddrlist_t addresses;
1409 isc_result_t result;
1413 * Determine which port to send forwarded requests to.
1415 if (ns_g_lwresdonly && ns_g_port != 0)
1418 CHECKM(ns_config_getport(config, &port), "port");
1420 if (forwarders != NULL) {
1421 portobj = cfg_tuple_get(forwarders, "port");
1422 if (cfg_obj_isuint32(portobj)) {
1423 isc_uint32_t val = cfg_obj_asuint32(portobj);
1424 if (val > ISC_UINT16_MAX) {
1425 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
1426 "port '%u' out of range", val);
1427 return (ISC_R_RANGE);
1429 port = (in_port_t) val;
1434 if (forwarders != NULL)
1435 faddresses = cfg_tuple_get(forwarders, "addresses");
1437 ISC_LIST_INIT(addresses);
1439 for (element = cfg_list_first(faddresses);
1441 element = cfg_list_next(element))
1443 cfg_obj_t *forwarder = cfg_listelt_value(element);
1444 sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t));
1446 result = ISC_R_NOMEMORY;
1449 *sa = *cfg_obj_assockaddr(forwarder);
1450 if (isc_sockaddr_getport(sa) == 0)
1451 isc_sockaddr_setport(sa, port);
1452 ISC_LINK_INIT(sa, link);
1453 ISC_LIST_APPEND(addresses, sa, link);
1456 if (ISC_LIST_EMPTY(addresses)) {
1457 if (forwardtype != NULL)
1458 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
1459 "no forwarders seen; disabling "
1461 fwdpolicy = dns_fwdpolicy_none;
1463 if (forwardtype == NULL)
1464 fwdpolicy = dns_fwdpolicy_first;
1466 char *forwardstr = cfg_obj_asstring(forwardtype);
1467 if (strcasecmp(forwardstr, "first") == 0)
1468 fwdpolicy = dns_fwdpolicy_first;
1469 else if (strcasecmp(forwardstr, "only") == 0)
1470 fwdpolicy = dns_fwdpolicy_only;
1476 result = dns_fwdtable_add(view->fwdtable, origin, &addresses,
1478 if (result != ISC_R_SUCCESS) {
1479 char namebuf[DNS_NAME_FORMATSIZE];
1480 dns_name_format(origin, namebuf, sizeof(namebuf));
1481 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
1482 "could not set up forwarding for domain '%s': %s",
1483 namebuf, isc_result_totext(result));
1487 result = ISC_R_SUCCESS;
1491 while (!ISC_LIST_EMPTY(addresses)) {
1492 sa = ISC_LIST_HEAD(addresses);
1493 ISC_LIST_UNLINK(addresses, sa, link);
1494 isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t));
1501 * Create a new view and add it to the list.
1503 * If 'vconfig' is NULL, create the default view.
1505 * The view created is attached to '*viewp'.
1508 create_view(cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) {
1509 isc_result_t result;
1510 const char *viewname;
1511 dns_rdataclass_t viewclass;
1512 dns_view_t *view = NULL;
1514 if (vconfig != NULL) {
1515 cfg_obj_t *classobj = NULL;
1517 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
1518 classobj = cfg_tuple_get(vconfig, "class");
1519 result = ns_config_getclass(classobj, dns_rdataclass_in,
1522 viewname = "_default";
1523 viewclass = dns_rdataclass_in;
1525 result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
1526 if (result == ISC_R_SUCCESS)
1527 return (ISC_R_EXISTS);
1528 if (result != ISC_R_NOTFOUND)
1530 INSIST(view == NULL);
1532 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view);
1533 if (result != ISC_R_SUCCESS)
1536 ISC_LIST_APPEND(*viewlist, view, link);
1537 dns_view_attach(view, viewp);
1538 return (ISC_R_SUCCESS);
1542 * Configure or reconfigure a zone.
1545 configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
1546 isc_mem_t *mctx, dns_view_t *view,
1547 ns_aclconfctx_t *aclconf)
1549 dns_view_t *pview = NULL; /* Production view */
1550 dns_zone_t *zone = NULL; /* New or reused zone */
1551 dns_zone_t *dupzone = NULL;
1552 cfg_obj_t *options = NULL;
1553 cfg_obj_t *zoptions = NULL;
1554 cfg_obj_t *typeobj = NULL;
1555 cfg_obj_t *forwarders = NULL;
1556 cfg_obj_t *forwardtype = NULL;
1557 cfg_obj_t *only = NULL;
1558 isc_result_t result;
1559 isc_result_t tresult;
1560 isc_buffer_t buffer;
1561 dns_fixedname_t fixorigin;
1564 dns_rdataclass_t zclass;
1565 const char *ztypestr;
1568 (void)cfg_map_get(config, "options", &options);
1570 zoptions = cfg_tuple_get(zconfig, "options");
1573 * Get the zone origin as a dns_name_t.
1575 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
1576 isc_buffer_init(&buffer, zname, strlen(zname));
1577 isc_buffer_add(&buffer, strlen(zname));
1578 dns_fixedname_init(&fixorigin);
1579 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin),
1580 &buffer, dns_rootname, ISC_FALSE, NULL));
1581 origin = dns_fixedname_name(&fixorigin);
1583 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
1584 view->rdclass, &zclass));
1585 if (zclass != view->rdclass) {
1586 const char *vname = NULL;
1587 if (vconfig != NULL)
1588 vname = cfg_obj_asstring(cfg_tuple_get(vconfig,
1591 vname = "<default view>";
1593 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1594 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
1595 "zone '%s': wrong class for view '%s'",
1597 result = ISC_R_FAILURE;
1601 (void)cfg_map_get(zoptions, "type", &typeobj);
1602 if (typeobj == NULL) {
1603 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
1604 "zone '%s' 'type' not specified", zname);
1605 return (ISC_R_FAILURE);
1607 ztypestr = cfg_obj_asstring(typeobj);
1610 * "hints zones" aren't zones. If we've got one,
1611 * configure it and return.
1613 if (strcasecmp(ztypestr, "hint") == 0) {
1614 cfg_obj_t *fileobj = NULL;
1615 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
1616 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1617 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
1618 "zone '%s': 'file' not specified",
1620 result = ISC_R_FAILURE;
1623 if (dns_name_equal(origin, dns_rootname)) {
1624 char *hintsfile = cfg_obj_asstring(fileobj);
1626 result = configure_hints(view, hintsfile);
1627 if (result != ISC_R_SUCCESS) {
1628 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1629 NS_LOGMODULE_SERVER,
1631 "could not configure root hints "
1632 "from '%s': %s", hintsfile,
1633 isc_result_totext(result));
1637 * Hint zones may also refer to delegation only points.
1640 tresult = cfg_map_get(zoptions, "delegation-only",
1642 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
1643 CHECK(dns_view_adddelegationonly(view, origin));
1645 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1646 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1647 "ignoring non-root hint zone '%s'",
1649 result = ISC_R_SUCCESS;
1651 /* Skip ordinary zone processing. */
1656 * "forward zones" aren't zones either. Translate this syntax into
1657 * the appropriate selective forwarding configuration and return.
1659 if (strcasecmp(ztypestr, "forward") == 0) {
1663 (void)cfg_map_get(zoptions, "forward", &forwardtype);
1664 (void)cfg_map_get(zoptions, "forwarders", &forwarders);
1665 result = configure_forward(config, view, origin, forwarders,
1671 * "delegation-only zones" aren't zones either.
1673 if (strcasecmp(ztypestr, "delegation-only") == 0) {
1674 result = dns_view_adddelegationonly(view, origin);
1679 * Check for duplicates in the new zone table.
1681 result = dns_view_findzone(view, origin, &dupzone);
1682 if (result == ISC_R_SUCCESS) {
1684 * We already have this zone!
1686 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
1687 "zone '%s' already exists", zname);
1688 dns_zone_detach(&dupzone);
1689 result = ISC_R_EXISTS;
1692 INSIST(dupzone == NULL);
1695 * See if we can reuse an existing zone. This is
1696 * only possible if all of these are true:
1697 * - The zone's view exists
1698 * - A zone with the right name exists in the view
1699 * - The zone is compatible with the config
1700 * options (e.g., an existing master zone cannot
1701 * be reused if the options specify a slave zone)
1703 result = dns_viewlist_find(&ns_g_server->viewlist,
1704 view->name, view->rdclass,
1706 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
1709 result = dns_view_findzone(pview, origin, &zone);
1710 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
1713 if (! ns_zone_reusable(zone, zconfig))
1714 dns_zone_detach(&zone);
1719 * We found a reusable zone. Make it use the
1722 dns_zone_setview(zone, view);
1725 * We cannot reuse an existing zone, we have
1726 * to create a new one.
1728 CHECK(dns_zone_create(&zone, mctx));
1729 CHECK(dns_zone_setorigin(zone, origin));
1730 dns_zone_setview(zone, view);
1731 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
1735 * If the zone contains a 'forwarders' statement, configure
1736 * selective forwarding.
1739 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS)
1742 (void)cfg_map_get(zoptions, "forward", &forwardtype);
1743 CHECK(configure_forward(config, view, origin, forwarders,
1748 * Stub and forward zones may also refer to delegation only points.
1751 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS)
1753 if (cfg_obj_asboolean(only))
1754 CHECK(dns_view_adddelegationonly(view, origin));
1758 * Configure the zone.
1760 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone));
1763 * Add the zone to its view in the new view list.
1765 CHECK(dns_view_addzone(view, zone));
1769 dns_zone_detach(&zone);
1771 dns_view_detach(&pview);
1777 * Configure a single server quota.
1780 configure_server_quota(cfg_obj_t **maps, const char *name, isc_quota_t *quota)
1782 cfg_obj_t *obj = NULL;
1783 isc_result_t result;
1785 result = ns_config_get(maps, name, &obj);
1786 INSIST(result == ISC_R_SUCCESS);
1787 quota->max = cfg_obj_asuint32(obj);
1791 * This function is called as soon as the 'directory' statement has been
1792 * parsed. This can be extended to support other options if necessary.
1795 directory_callback(const char *clausename, cfg_obj_t *obj, void *arg) {
1796 isc_result_t result;
1799 REQUIRE(strcasecmp("directory", clausename) == 0);
1807 directory = cfg_obj_asstring(obj);
1809 if (! isc_file_ischdiridempotent(directory))
1810 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1811 "option 'directory' contains relative path '%s'",
1814 result = isc_dir_chdir(directory);
1815 if (result != ISC_R_SUCCESS) {
1816 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
1817 "change directory to '%s' failed: %s",
1818 directory, isc_result_totext(result));
1822 return (ISC_R_SUCCESS);
1826 scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
1827 isc_boolean_t match_mapped = server->aclenv.match_mapped;
1829 ns_interfacemgr_scan(server->interfacemgr, verbose);
1831 * Update the "localhost" and "localnets" ACLs to match the
1832 * current set of network interfaces.
1834 dns_aclenv_copy(&server->aclenv,
1835 ns_interfacemgr_getaclenv(server->interfacemgr));
1837 server->aclenv.match_mapped = match_mapped;
1841 add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr) {
1842 ns_listenelt_t *lelt = NULL;
1843 dns_acl_t *src_acl = NULL;
1844 dns_aclelement_t aelt;
1845 isc_result_t result;
1846 isc_sockaddr_t any_sa6;
1848 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
1850 isc_sockaddr_any6(&any_sa6);
1851 if (!isc_sockaddr_equal(&any_sa6, addr)) {
1852 aelt.type = dns_aclelementtype_ipprefix;
1853 aelt.negative = ISC_FALSE;
1854 aelt.u.ip_prefix.prefixlen = 128;
1855 isc_netaddr_fromin6(&aelt.u.ip_prefix.address,
1856 &addr->type.sin6.sin6_addr);
1858 result = dns_acl_create(mctx, 1, &src_acl);
1859 if (result != ISC_R_SUCCESS)
1861 result = dns_acl_appendelement(src_acl, &aelt);
1862 if (result != ISC_R_SUCCESS)
1865 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
1867 if (result != ISC_R_SUCCESS)
1869 ISC_LIST_APPEND(list->elts, lelt, link);
1872 return (ISC_R_SUCCESS);
1875 INSIST(lelt == NULL);
1876 if (src_acl != NULL)
1877 dns_acl_detach(&src_acl);
1883 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust()
1884 * to update the listening interfaces accordingly.
1885 * We currently only consider IPv6, because this only affects IPv6 wildcard
1889 adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
1890 isc_result_t result;
1891 ns_listenlist_t *list = NULL;
1893 dns_zone_t *zone, *next;
1894 isc_sockaddr_t addr, *addrp;
1896 result = ns_listenlist_create(mctx, &list);
1897 if (result != ISC_R_SUCCESS)
1900 for (view = ISC_LIST_HEAD(server->viewlist);
1902 view = ISC_LIST_NEXT(view, link)) {
1903 dns_dispatch_t *dispatch6;
1905 dispatch6 = dns_resolver_dispatchv6(view->resolver);
1906 INSIST(dispatch6 != NULL);
1907 result = dns_dispatch_getlocaladdress(dispatch6, &addr);
1908 if (result != ISC_R_SUCCESS)
1910 result = add_listenelt(mctx, list, &addr);
1911 if (result != ISC_R_SUCCESS)
1916 for (result = dns_zone_first(server->zonemgr, &zone);
1917 result == ISC_R_SUCCESS;
1918 next = NULL, result = dns_zone_next(zone, &next), zone = next) {
1919 dns_view_t *zoneview;
1922 * At this point the zone list may contain a stale zone
1923 * just removed from the configuration. To see the validity,
1924 * check if the corresponding view is in our current view list.
1926 zoneview = dns_zone_getview(zone);
1927 INSIST(zoneview != NULL);
1928 for (view = ISC_LIST_HEAD(server->viewlist);
1929 view != NULL && view != zoneview;
1930 view = ISC_LIST_NEXT(view, link))
1935 addrp = dns_zone_getnotifysrc6(zone);
1936 result = add_listenelt(mctx, list, addrp);
1937 if (result != ISC_R_SUCCESS)
1940 addrp = dns_zone_getxfrsource6(zone);
1941 result = add_listenelt(mctx, list, addrp);
1942 if (result != ISC_R_SUCCESS)
1946 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE);
1949 ns_listenlist_detach(&list);
1954 * Even when we failed the procedure, most of other interfaces
1955 * should work correctly. We therefore just warn it.
1957 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1958 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1959 "could not adjust the listen-on list; "
1960 "some interfaces may not work");
1965 * This event callback is invoked to do periodic network
1966 * interface scanning.
1969 interface_timer_tick(isc_task_t *task, isc_event_t *event) {
1970 isc_result_t result;
1971 ns_server_t *server = (ns_server_t *) event->ev_arg;
1972 INSIST(task == server->task);
1974 isc_event_free(&event);
1976 * XXX should scan interfaces unlocked and get exclusive access
1977 * only to replace ACLs.
1979 result = isc_task_beginexclusive(server->task);
1980 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1981 scan_interfaces(server, ISC_FALSE);
1982 isc_task_endexclusive(server->task);
1986 heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
1987 ns_server_t *server = (ns_server_t *) event->ev_arg;
1991 isc_event_free(&event);
1992 view = ISC_LIST_HEAD(server->viewlist);
1993 while (view != NULL) {
1994 dns_view_dialup(view);
1995 view = ISC_LIST_NEXT(view, link);
2000 * Replace the current value of '*field', a dynamically allocated
2001 * string or NULL, with a dynamically allocated copy of the
2002 * null-terminated string pointed to by 'value', or NULL.
2005 setstring(ns_server_t *server, char **field, const char *value) {
2008 if (value != NULL) {
2009 copy = isc_mem_strdup(server->mctx, value);
2011 return (ISC_R_NOMEMORY);
2017 isc_mem_free(server->mctx, *field);
2020 return (ISC_R_SUCCESS);
2024 * Replace the current value of '*field', a dynamically allocated
2025 * string or NULL, with another dynamically allocated string
2026 * or NULL if whether 'obj' is a string or void value, respectively.
2029 setoptstring(ns_server_t *server, char **field, cfg_obj_t *obj) {
2030 if (cfg_obj_isvoid(obj))
2031 return (setstring(server, field, NULL));
2033 return (setstring(server, field, cfg_obj_asstring(obj)));
2037 set_limit(cfg_obj_t **maps, const char *configname, const char *description,
2038 isc_resource_t resourceid, isc_resourcevalue_t defaultvalue)
2040 cfg_obj_t *obj = NULL;
2042 isc_resourcevalue_t value;
2043 isc_result_t result;
2045 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS)
2048 if (cfg_obj_isstring(obj)) {
2049 resource = cfg_obj_asstring(obj);
2050 if (strcasecmp(resource, "unlimited") == 0)
2051 value = ISC_RESOURCE_UNLIMITED;
2053 INSIST(strcasecmp(resource, "default") == 0);
2054 value = defaultvalue;
2057 value = cfg_obj_asuint64(obj);
2059 result = isc_resource_setlimit(resourceid, value);
2060 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2061 result == ISC_R_SUCCESS ?
2062 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
2063 "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s",
2064 description, value, isc_result_totext(result));
2067 #define SETLIMIT(cfgvar, resource, description) \
2068 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \
2069 ns_g_init ## resource)
2072 set_limits(cfg_obj_t **maps) {
2073 SETLIMIT("stacksize", stacksize, "stack size");
2074 SETLIMIT("datasize", datasize, "data size");
2075 SETLIMIT("coresize", coresize, "core size");
2076 SETLIMIT("files", openfiles, "open files");
2080 portlist_fromconf(dns_portlist_t *portlist, unsigned int family,
2083 cfg_listelt_t *element;
2084 isc_result_t result = ISC_R_SUCCESS;
2086 for (element = cfg_list_first(ports);
2088 element = cfg_list_next(element)) {
2089 cfg_obj_t *obj = cfg_listelt_value(element);
2090 in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
2092 result = dns_portlist_add(portlist, family, port);
2093 if (result != ISC_R_SUCCESS)
2100 load_configuration(const char *filename, ns_server_t *server,
2101 isc_boolean_t first_time)
2103 isc_result_t result;
2104 cfg_parser_t *parser = NULL;
2109 cfg_obj_t *v4ports, *v6ports;
2111 cfg_obj_t *builtin_views;
2112 cfg_listelt_t *element;
2113 dns_view_t *view = NULL;
2114 dns_view_t *view_next;
2115 dns_viewlist_t viewlist;
2116 dns_viewlist_t tmpviewlist;
2117 ns_aclconfctx_t aclconfctx;
2118 isc_uint32_t interface_interval;
2119 isc_uint32_t heartbeat_interval;
2120 isc_uint32_t udpsize;
2121 in_port_t listen_port;
2124 ns_aclconfctx_init(&aclconfctx);
2125 ISC_LIST_INIT(viewlist);
2127 /* Ensure exclusive access to configuration data. */
2128 result = isc_task_beginexclusive(server->task);
2129 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2132 * Parse the global default pseudo-config file.
2135 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config));
2136 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options",
2142 * Parse the configuration file using the new config code.
2144 result = ISC_R_FAILURE;
2148 * Unless this is lwresd with the -C option, parse the config file.
2150 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) {
2151 isc_log_write(ns_g_lctx,
2152 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2153 ISC_LOG_INFO, "loading configuration from '%s'",
2155 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
2156 cfg_parser_setcallback(parser, directory_callback, NULL);
2157 result = cfg_parse_file(parser, filename, &cfg_type_namedconf,
2162 * If this is lwresd with the -C option, or lwresd with no -C or -c
2163 * option where the above parsing failed, parse resolv.conf.
2165 if (ns_g_lwresdonly &&
2166 (lwresd_g_useresolvconf ||
2167 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND)))
2169 isc_log_write(ns_g_lctx,
2170 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2171 ISC_LOG_INFO, "loading configuration from '%s'",
2172 lwresd_g_resolvconffile);
2174 cfg_parser_destroy(&parser);
2175 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
2176 result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser,
2182 * Check the validity of the configuration.
2184 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx));
2187 * Fill in the maps array, used for resolving defaults.
2191 result = cfg_map_get(config, "options", &options);
2192 if (result == ISC_R_SUCCESS)
2193 maps[i++] = options;
2194 maps[i++] = ns_g_defaults;
2198 * Set process limits, which (usually) needs to be done as root.
2203 * Configure various server options.
2205 configure_server_quota(maps, "transfers-out", &server->xfroutquota);
2206 configure_server_quota(maps, "tcp-clients", &server->tcpquota);
2207 configure_server_quota(maps, "recursive-clients",
2208 &server->recursionquota);
2210 CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
2211 ns_g_mctx, &server->blackholeacl));
2212 if (server->blackholeacl != NULL)
2213 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
2214 server->blackholeacl);
2217 result = ns_config_get(maps, "match-mapped-addresses", &obj);
2218 INSIST(result == ISC_R_SUCCESS);
2219 server->aclenv.match_mapped = cfg_obj_asboolean(obj);
2223 (void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports);
2224 (void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports);
2225 if (v4ports != NULL || v6ports != NULL) {
2226 dns_portlist_t *portlist = NULL;
2227 result = dns_portlist_create(ns_g_mctx, &portlist);
2228 if (result == ISC_R_SUCCESS && v4ports != NULL)
2229 result = portlist_fromconf(portlist, AF_INET, v4ports);
2230 if (result == ISC_R_SUCCESS && v6ports != NULL)
2231 portlist_fromconf(portlist, AF_INET6, v6ports);
2232 if (result == ISC_R_SUCCESS)
2233 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist);
2234 if (portlist != NULL)
2235 dns_portlist_detach(&portlist);
2238 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL);
2241 * Set the EDNS UDP size when we don't match a view.
2244 result = ns_config_get(maps, "edns-udp-size", &obj);
2245 INSIST(result == ISC_R_SUCCESS);
2246 udpsize = cfg_obj_asuint32(obj);
2251 ns_g_udpsize = (isc_uint16_t)udpsize;
2254 * Configure the zone manager.
2257 result = ns_config_get(maps, "transfers-in", &obj);
2258 INSIST(result == ISC_R_SUCCESS);
2259 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
2262 result = ns_config_get(maps, "transfers-per-ns", &obj);
2263 INSIST(result == ISC_R_SUCCESS);
2264 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
2267 result = ns_config_get(maps, "serial-query-rate", &obj);
2268 INSIST(result == ISC_R_SUCCESS);
2269 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj));
2272 * Determine which port to use for listening for incoming connections.
2275 listen_port = ns_g_port;
2277 CHECKM(ns_config_getport(config, &listen_port), "port");
2280 * Find the listen queue depth.
2283 result = ns_config_get(maps, "tcp-listen-queue", &obj);
2284 INSIST(result == ISC_R_SUCCESS);
2285 ns_g_listen = cfg_obj_asuint32(obj);
2286 if (ns_g_listen < 3)
2290 * Configure the interface manager according to the "listen-on"
2294 cfg_obj_t *clistenon = NULL;
2295 ns_listenlist_t *listenon = NULL;
2299 * Even though listen-on is present in the default
2300 * configuration, we can't use it here, since it isn't
2301 * used if we're in lwresd mode. This way is easier.
2303 if (options != NULL)
2304 (void)cfg_map_get(options, "listen-on", &clistenon);
2305 if (clistenon != NULL) {
2306 result = ns_listenlist_fromconfig(clistenon,
2311 } else if (!ns_g_lwresdonly) {
2313 * Not specified, use default.
2315 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
2316 ISC_TRUE, &listenon));
2318 if (listenon != NULL) {
2319 ns_interfacemgr_setlistenon4(server->interfacemgr,
2321 ns_listenlist_detach(&listenon);
2328 cfg_obj_t *clistenon = NULL;
2329 ns_listenlist_t *listenon = NULL;
2331 if (options != NULL)
2332 (void)cfg_map_get(options, "listen-on-v6", &clistenon);
2333 if (clistenon != NULL) {
2334 result = ns_listenlist_fromconfig(clistenon,
2339 } else if (!ns_g_lwresdonly) {
2341 * Not specified, use default.
2343 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
2344 ISC_FALSE, &listenon));
2346 if (listenon != NULL) {
2347 ns_interfacemgr_setlistenon6(server->interfacemgr,
2349 ns_listenlist_detach(&listenon);
2354 * Rescan the interface list to pick up changes in the
2355 * listen-on option. It's important that we do this before we try
2356 * to configure the query source, since the dispatcher we use might
2357 * be shared with an interface.
2359 scan_interfaces(server, ISC_TRUE);
2362 * Arrange for further interface scanning to occur periodically
2363 * as specified by the "interface-interval" option.
2366 result = ns_config_get(maps, "interface-interval", &obj);
2367 INSIST(result == ISC_R_SUCCESS);
2368 interface_interval = cfg_obj_asuint32(obj) * 60;
2369 if (interface_interval == 0) {
2370 CHECK(isc_timer_reset(server->interface_timer,
2371 isc_timertype_inactive,
2372 NULL, NULL, ISC_TRUE));
2373 } else if (server->interface_interval != interface_interval) {
2374 isc_interval_t interval;
2375 isc_interval_set(&interval, interface_interval, 0);
2376 CHECK(isc_timer_reset(server->interface_timer,
2377 isc_timertype_ticker,
2378 NULL, &interval, ISC_FALSE));
2380 server->interface_interval = interface_interval;
2383 * Configure the dialup heartbeat timer.
2386 result = ns_config_get(maps, "heartbeat-interval", &obj);
2387 INSIST(result == ISC_R_SUCCESS);
2388 heartbeat_interval = cfg_obj_asuint32(obj) * 60;
2389 if (heartbeat_interval == 0) {
2390 CHECK(isc_timer_reset(server->heartbeat_timer,
2391 isc_timertype_inactive,
2392 NULL, NULL, ISC_TRUE));
2393 } else if (server->heartbeat_interval != heartbeat_interval) {
2394 isc_interval_t interval;
2395 isc_interval_set(&interval, heartbeat_interval, 0);
2396 CHECK(isc_timer_reset(server->heartbeat_timer,
2397 isc_timertype_ticker,
2398 NULL, &interval, ISC_FALSE));
2400 server->heartbeat_interval = heartbeat_interval;
2403 * Configure and freeze all explicit views. Explicit
2404 * views that have zones were already created at parsing
2405 * time, but views with no zones must be created here.
2408 (void)cfg_map_get(config, "view", &views);
2409 for (element = cfg_list_first(views);
2411 element = cfg_list_next(element))
2413 cfg_obj_t *vconfig = cfg_listelt_value(element);
2416 CHECK(create_view(vconfig, &viewlist, &view));
2417 INSIST(view != NULL);
2418 CHECK(configure_view(view, config, vconfig,
2419 ns_g_mctx, &aclconfctx, ISC_TRUE));
2420 dns_view_freeze(view);
2421 dns_view_detach(&view);
2425 * Make sure we have a default view if and only if there
2426 * were no explicit views.
2428 if (views == NULL) {
2430 * No explicit views; there ought to be a default view.
2431 * There may already be one created as a side effect
2432 * of zone statements, or we may have to create one.
2433 * In either case, we need to configure and freeze it.
2435 CHECK(create_view(NULL, &viewlist, &view));
2436 CHECK(configure_view(view, config, NULL, ns_g_mctx,
2437 &aclconfctx, ISC_TRUE));
2438 dns_view_freeze(view);
2439 dns_view_detach(&view);
2443 * Create (or recreate) the built-in views. Currently
2444 * there is only one, the _bind view.
2446 builtin_views = NULL;
2447 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
2448 &builtin_views) == ISC_R_SUCCESS);
2449 for (element = cfg_list_first(builtin_views);
2451 element = cfg_list_next(element))
2453 cfg_obj_t *vconfig = cfg_listelt_value(element);
2454 CHECK(create_view(vconfig, &viewlist, &view));
2455 CHECK(configure_view(view, config, vconfig, ns_g_mctx,
2456 &aclconfctx, ISC_FALSE));
2457 dns_view_freeze(view);
2458 dns_view_detach(&view);
2463 * Swap our new view list with the production one.
2465 tmpviewlist = server->viewlist;
2466 server->viewlist = viewlist;
2467 viewlist = tmpviewlist;
2470 * Load the TKEY information from the configuration.
2472 if (options != NULL) {
2473 dns_tkeyctx_t *t = NULL;
2474 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
2476 "configuring TKEY");
2477 if (server->tkeyctx != NULL)
2478 dns_tkeyctx_destroy(&server->tkeyctx);
2479 server->tkeyctx = t;
2483 * Bind the control port(s).
2485 CHECKM(ns_controls_configure(ns_g_server->controls, config,
2487 "binding control channel(s)");
2490 * Bind the lwresd port(s).
2492 CHECKM(ns_lwresd_configure(ns_g_mctx, config),
2493 "binding lightweight resolver ports");
2496 * Open the source of entropy.
2500 result = ns_config_get(maps, "random-device", &obj);
2501 if (result != ISC_R_SUCCESS) {
2502 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2503 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
2504 "no source of entropy found");
2506 const char *randomdev = cfg_obj_asstring(obj);
2507 result = isc_entropy_createfilesource(ns_g_entropy,
2509 if (result != ISC_R_SUCCESS)
2510 isc_log_write(ns_g_lctx,
2511 NS_LOGCATEGORY_GENERAL,
2512 NS_LOGMODULE_SERVER,
2514 "could not open entropy source "
2517 isc_result_totext(result));
2518 #ifdef PATH_RANDOMDEV
2519 if (ns_g_fallbackentropy != NULL) {
2520 if (result != ISC_R_SUCCESS) {
2521 isc_log_write(ns_g_lctx,
2522 NS_LOGCATEGORY_GENERAL,
2523 NS_LOGMODULE_SERVER,
2525 "using pre-chroot entropy source "
2528 isc_entropy_detach(&ns_g_entropy);
2529 isc_entropy_attach(ns_g_fallbackentropy,
2532 isc_entropy_detach(&ns_g_fallbackentropy);
2539 * Relinquish root privileges.
2545 * Configure the logging system.
2547 * Do this after changing UID to make sure that any log
2548 * files specified in named.conf get created by the
2549 * unprivileged user, not root.
2551 if (ns_g_logstderr) {
2552 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2553 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
2554 "ignoring config file logging "
2555 "statement due to -g option");
2557 cfg_obj_t *logobj = NULL;
2558 isc_logconfig_t *logc = NULL;
2560 CHECKM(isc_logconfig_create(ns_g_lctx, &logc),
2561 "creating new logging configuration");
2564 (void)cfg_map_get(config, "logging", &logobj);
2565 if (logobj != NULL) {
2566 CHECKM(ns_log_configure(logc, logobj),
2567 "configuring logging");
2569 CHECKM(ns_log_setdefaultchannels(logc),
2570 "setting up default logging channels");
2571 CHECKM(ns_log_setunmatchedcategory(logc),
2572 "setting up default 'category unmatched'");
2573 CHECKM(ns_log_setdefaultcategory(logc),
2574 "setting up default 'category default'");
2577 result = isc_logconfig_use(ns_g_lctx, logc);
2578 if (result != ISC_R_SUCCESS) {
2579 isc_logconfig_destroy(&logc);
2580 CHECKM(result, "installing logging configuration");
2583 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2584 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
2585 "now using logging configuration from "
2590 * Set the default value of the query logging flag depending
2591 * whether a "queries" category has been defined. This is
2592 * a disgusting hack, but we need to do this for BIND 8
2596 cfg_obj_t *logobj = NULL;
2597 cfg_obj_t *categories = NULL;
2600 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
2601 server->log_queries = cfg_obj_asboolean(obj);
2604 (void)cfg_map_get(config, "logging", &logobj);
2606 (void)cfg_map_get(logobj, "category",
2608 if (categories != NULL) {
2609 cfg_listelt_t *element;
2610 for (element = cfg_list_first(categories);
2612 element = cfg_list_next(element))
2617 obj = cfg_listelt_value(element);
2618 catobj = cfg_tuple_get(obj, "name");
2619 str = cfg_obj_asstring(catobj);
2620 if (strcasecmp(str, "queries") == 0)
2621 server->log_queries = ISC_TRUE;
2628 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)
2629 if (cfg_obj_isvoid(obj))
2630 ns_os_writepidfile(NULL, first_time);
2632 ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
2633 else if (ns_g_lwresdonly)
2634 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
2636 ns_os_writepidfile(ns_g_defaultpidfile, first_time);
2639 if (options != NULL &&
2640 cfg_map_get(options, "memstatistics-file", &obj) == ISC_R_SUCCESS)
2641 ns_main_setmemstats(cfg_obj_asstring(obj));
2643 ns_main_setmemstats(NULL);
2646 result = ns_config_get(maps, "statistics-file", &obj);
2647 INSIST(result == ISC_R_SUCCESS);
2648 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
2652 result = ns_config_get(maps, "dump-file", &obj);
2653 INSIST(result == ISC_R_SUCCESS);
2654 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),
2658 result = ns_config_get(maps, "recursing-file", &obj);
2659 INSIST(result == ISC_R_SUCCESS);
2660 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
2664 result = ns_config_get(maps, "version", &obj);
2665 if (result == ISC_R_SUCCESS) {
2666 CHECKM(setoptstring(server, &server->version, obj), "strdup");
2667 server->version_set = ISC_TRUE;
2669 server->version_set = ISC_FALSE;
2673 result = ns_config_get(maps, "hostname", &obj);
2674 if (result == ISC_R_SUCCESS) {
2675 CHECKM(setoptstring(server, &server->hostname, obj), "strdup");
2676 server->hostname_set = ISC_TRUE;
2678 server->hostname_set = ISC_FALSE;
2682 result = ns_config_get(maps, "server-id", &obj);
2683 server->server_usehostname = ISC_FALSE;
2684 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
2685 server->server_usehostname = ISC_TRUE;
2686 } else if (result == ISC_R_SUCCESS) {
2687 CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
2689 result = setoptstring(server, &server->server_id, NULL);
2690 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2694 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj);
2695 if (result == ISC_R_SUCCESS) {
2696 server->flushonshutdown = cfg_obj_asboolean(obj);
2698 server->flushonshutdown = ISC_FALSE;
2701 result = ISC_R_SUCCESS;
2704 ns_aclconfctx_destroy(&aclconfctx);
2706 if (parser != NULL) {
2708 cfg_obj_destroy(parser, &config);
2709 cfg_parser_destroy(&parser);
2713 dns_view_detach(&view);
2716 * This cleans up either the old production view list
2717 * or our temporary list depending on whether they
2718 * were swapped above or not.
2720 for (view = ISC_LIST_HEAD(viewlist);
2723 view_next = ISC_LIST_NEXT(view, link);
2724 ISC_LIST_UNLINK(viewlist, view, link);
2725 dns_view_detach(&view);
2730 * Adjust the listening interfaces in accordance with the source
2731 * addresses specified in views and zones.
2733 if (isc_net_probeipv6() == ISC_R_SUCCESS)
2734 adjust_interfaces(server, ns_g_mctx);
2736 /* Relinquish exclusive access to configuration data. */
2737 isc_task_endexclusive(server->task);
2739 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2740 ISC_LOG_DEBUG(1), "load_configuration: %s",
2741 isc_result_totext(result));
2747 load_zones(ns_server_t *server, isc_boolean_t stop) {
2748 isc_result_t result;
2751 result = isc_task_beginexclusive(server->task);
2752 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2755 * Load zone data from disk.
2757 for (view = ISC_LIST_HEAD(server->viewlist);
2759 view = ISC_LIST_NEXT(view, link))
2761 CHECK(dns_view_load(view, stop));
2765 * Force zone maintenance. Do this after loading
2766 * so that we know when we need to force AXFR of
2767 * slave zones whose master files are missing.
2769 CHECK(dns_zonemgr_forcemaint(server->zonemgr));
2771 isc_task_endexclusive(server->task);
2776 load_new_zones(ns_server_t *server, isc_boolean_t stop) {
2777 isc_result_t result;
2780 result = isc_task_beginexclusive(server->task);
2781 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2784 * Load zone data from disk.
2786 for (view = ISC_LIST_HEAD(server->viewlist);
2788 view = ISC_LIST_NEXT(view, link))
2790 CHECK(dns_view_loadnew(view, stop));
2793 * Force zone maintenance. Do this after loading
2794 * so that we know when we need to force AXFR of
2795 * slave zones whose master files are missing.
2797 dns_zonemgr_resumexfrs(server->zonemgr);
2799 isc_task_endexclusive(server->task);
2804 run_server(isc_task_t *task, isc_event_t *event) {
2805 isc_result_t result;
2806 ns_server_t *server = (ns_server_t *)event->ev_arg;
2810 isc_event_free(&event);
2812 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy,
2814 "creating dispatch manager");
2816 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
2817 ns_g_socketmgr, ns_g_dispatchmgr,
2818 &server->interfacemgr),
2819 "creating interface manager");
2821 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
2822 NULL, NULL, server->task,
2823 interface_timer_tick,
2824 server, &server->interface_timer),
2825 "creating interface timer");
2827 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
2828 NULL, NULL, server->task,
2829 heartbeat_timer_tick,
2830 server, &server->heartbeat_timer),
2831 "creating heartbeat timer");
2833 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser),
2834 "creating default configuration parser");
2836 if (ns_g_lwresdonly)
2837 CHECKFATAL(load_configuration(lwresd_g_conffile, server,
2839 "loading configuration");
2841 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE),
2842 "loading configuration");
2846 CHECKFATAL(load_zones(server, ISC_FALSE),
2849 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2850 ISC_LOG_INFO, "running");
2854 ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) {
2856 REQUIRE(NS_SERVER_VALID(server));
2858 server->flushonshutdown = flush;
2862 shutdown_server(isc_task_t *task, isc_event_t *event) {
2863 isc_result_t result;
2864 dns_view_t *view, *view_next;
2865 ns_server_t *server = (ns_server_t *)event->ev_arg;
2866 isc_boolean_t flush = server->flushonshutdown;
2869 INSIST(task == server->task);
2871 result = isc_task_beginexclusive(server->task);
2872 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2874 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2875 ISC_LOG_INFO, "shutting down%s",
2876 flush ? ": flushing changes" : "");
2878 ns_controls_shutdown(server->controls);
2879 end_reserved_dispatches(server, ISC_TRUE);
2881 cfg_obj_destroy(ns_g_parser, &ns_g_config);
2882 cfg_parser_destroy(&ns_g_parser);
2884 for (view = ISC_LIST_HEAD(server->viewlist);
2887 view_next = ISC_LIST_NEXT(view, link);
2888 ISC_LIST_UNLINK(server->viewlist, view, link);
2890 dns_view_flushanddetach(&view);
2892 dns_view_detach(&view);
2895 isc_timer_detach(&server->interface_timer);
2896 isc_timer_detach(&server->heartbeat_timer);
2898 ns_interfacemgr_shutdown(server->interfacemgr);
2899 ns_interfacemgr_detach(&server->interfacemgr);
2901 dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
2903 dns_zonemgr_shutdown(server->zonemgr);
2905 if (server->blackholeacl != NULL)
2906 dns_acl_detach(&server->blackholeacl);
2908 dns_db_detach(&server->in_roothints);
2910 isc_task_endexclusive(server->task);
2912 isc_task_detach(&server->task);
2914 isc_event_free(&event);
2918 ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
2919 isc_result_t result;
2921 ns_server_t *server = isc_mem_get(mctx, sizeof(*server));
2923 fatal("allocating server object", ISC_R_NOMEMORY);
2925 server->mctx = mctx;
2926 server->task = NULL;
2928 /* Initialize configuration data with default values. */
2930 result = isc_quota_init(&server->xfroutquota, 10);
2931 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2932 result = isc_quota_init(&server->tcpquota, 10);
2933 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2934 result = isc_quota_init(&server->recursionquota, 100);
2935 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2936 isc_quota_soft(&server->recursionquota, ISC_FALSE);
2938 result = dns_aclenv_init(mctx, &server->aclenv);
2939 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2941 /* Initialize server data structures. */
2942 server->zonemgr = NULL;
2943 server->interfacemgr = NULL;
2944 ISC_LIST_INIT(server->viewlist);
2945 server->in_roothints = NULL;
2946 server->blackholeacl = NULL;
2948 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
2949 &server->in_roothints),
2950 "setting up root hints");
2952 CHECKFATAL(isc_mutex_init(&server->reload_event_lock),
2953 "initializing reload event lock");
2954 server->reload_event =
2955 isc_event_allocate(ns_g_mctx, server,
2959 sizeof(isc_event_t));
2960 CHECKFATAL(server->reload_event == NULL ?
2961 ISC_R_NOMEMORY : ISC_R_SUCCESS,
2962 "allocating reload event");
2964 CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY),
2965 "initializing DST");
2967 server->tkeyctx = NULL;
2968 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
2970 "creating TKEY context");
2973 * Setup the server task, which is responsible for coordinating
2974 * startup and shutdown of the server.
2976 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),
2977 "creating server task");
2978 isc_task_setname(server->task, "server", server);
2979 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
2980 "isc_task_onshutdown");
2981 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
2984 server->interface_timer = NULL;
2985 server->heartbeat_timer = NULL;
2987 server->interface_interval = 0;
2988 server->heartbeat_interval = 0;
2990 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
2991 ns_g_socketmgr, &server->zonemgr),
2992 "dns_zonemgr_create");
2994 server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
2995 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
2997 server->querystats = NULL;
2999 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
3000 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
3003 server->recfile = isc_mem_strdup(server->mctx, "named.recursing");
3004 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
3007 server->hostname_set = ISC_FALSE;
3008 server->hostname = NULL;
3009 server->version_set = ISC_FALSE;
3010 server->version = NULL;
3011 server->server_usehostname = ISC_FALSE;
3012 server->server_id = NULL;
3014 CHECKFATAL(dns_stats_alloccounters(ns_g_mctx, &server->querystats),
3015 "dns_stats_alloccounters");
3017 server->flushonshutdown = ISC_FALSE;
3018 server->log_queries = ISC_FALSE;
3020 server->controls = NULL;
3021 CHECKFATAL(ns_controls_create(server, &server->controls),
3022 "ns_controls_create");
3023 server->dispatchgen = 0;
3024 ISC_LIST_INIT(server->dispatches);
3026 server->magic = NS_SERVER_MAGIC;
3031 ns_server_destroy(ns_server_t **serverp) {
3032 ns_server_t *server = *serverp;
3033 REQUIRE(NS_SERVER_VALID(server));
3035 ns_controls_destroy(&server->controls);
3037 dns_stats_freecounters(server->mctx, &server->querystats);
3039 isc_mem_free(server->mctx, server->statsfile);
3040 isc_mem_free(server->mctx, server->dumpfile);
3041 isc_mem_free(server->mctx, server->recfile);
3043 if (server->version != NULL)
3044 isc_mem_free(server->mctx, server->version);
3045 if (server->hostname != NULL)
3046 isc_mem_free(server->mctx, server->hostname);
3047 if (server->server_id != NULL)
3048 isc_mem_free(server->mctx, server->server_id);
3050 dns_zonemgr_detach(&server->zonemgr);
3052 if (server->tkeyctx != NULL)
3053 dns_tkeyctx_destroy(&server->tkeyctx);
3057 isc_event_free(&server->reload_event);
3059 INSIST(ISC_LIST_EMPTY(server->viewlist));
3061 dns_aclenv_destroy(&server->aclenv);
3063 isc_quota_destroy(&server->recursionquota);
3064 isc_quota_destroy(&server->tcpquota);
3065 isc_quota_destroy(&server->xfroutquota);
3068 isc_mem_put(server->mctx, server, sizeof(*server));
3073 fatal(const char *msg, isc_result_t result) {
3074 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3075 ISC_LOG_CRITICAL, "%s: %s", msg,
3076 isc_result_totext(result));
3077 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3078 ISC_LOG_CRITICAL, "exiting (due to fatal error)");
3083 start_reserved_dispatches(ns_server_t *server) {
3085 REQUIRE(NS_SERVER_VALID(server));
3087 server->dispatchgen++;
3091 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) {
3092 ns_dispatch_t *dispatch, *nextdispatch;
3094 REQUIRE(NS_SERVER_VALID(server));
3096 for (dispatch = ISC_LIST_HEAD(server->dispatches);
3098 dispatch = nextdispatch) {
3099 nextdispatch = ISC_LIST_NEXT(dispatch, link);
3100 if (!all && server->dispatchgen == dispatch-> dispatchgen)
3102 ISC_LIST_UNLINK(server->dispatches, dispatch, link);
3103 dns_dispatch_detach(&dispatch->dispatch);
3104 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
3109 ns_add_reserved_dispatch(ns_server_t *server, isc_sockaddr_t *addr) {
3110 ns_dispatch_t *dispatch;
3112 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3113 isc_result_t result;
3114 unsigned int attrs, attrmask;
3116 REQUIRE(NS_SERVER_VALID(server));
3118 port = isc_sockaddr_getport(addr);
3119 if (port == 0 || port >= 1024)
3122 for (dispatch = ISC_LIST_HEAD(server->dispatches);
3124 dispatch = ISC_LIST_NEXT(dispatch, link)) {
3125 if (isc_sockaddr_equal(&dispatch->addr, addr))
3128 if (dispatch != NULL) {
3129 dispatch->dispatchgen = server->dispatchgen;
3133 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch));
3134 if (dispatch == NULL) {
3135 result = ISC_R_NOMEMORY;
3139 dispatch->addr = *addr;
3140 dispatch->dispatchgen = server->dispatchgen;
3141 dispatch->dispatch = NULL;
3144 attrs |= DNS_DISPATCHATTR_UDP;
3145 switch (isc_sockaddr_pf(addr)) {
3147 attrs |= DNS_DISPATCHATTR_IPV4;
3150 attrs |= DNS_DISPATCHATTR_IPV6;
3153 result = ISC_R_NOTIMPLEMENTED;
3157 attrmask |= DNS_DISPATCHATTR_UDP;
3158 attrmask |= DNS_DISPATCHATTR_TCP;
3159 attrmask |= DNS_DISPATCHATTR_IPV4;
3160 attrmask |= DNS_DISPATCHATTR_IPV6;
3162 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
3163 ns_g_taskmgr, &dispatch->addr, 4096,
3164 1000, 32768, 16411, 16433,
3165 attrs, attrmask, &dispatch->dispatch);
3166 if (result != ISC_R_SUCCESS)
3169 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
3174 if (dispatch != NULL)
3175 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
3176 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
3177 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3178 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
3179 "unable to create dispatch for reserved port %s: %s",
3180 addrbuf, isc_result_totext(result));
3185 loadconfig(ns_server_t *server) {
3186 isc_result_t result;
3187 start_reserved_dispatches(server);
3188 result = load_configuration(ns_g_lwresdonly ?
3189 lwresd_g_conffile : ns_g_conffile,
3192 if (result == ISC_R_SUCCESS)
3193 end_reserved_dispatches(server, ISC_FALSE);
3195 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3196 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3197 "reloading configuration failed: %s",
3198 isc_result_totext(result));
3203 reload(ns_server_t *server) {
3204 isc_result_t result;
3205 CHECK(loadconfig(server));
3207 result = load_zones(server, ISC_FALSE);
3208 if (result != ISC_R_SUCCESS) {
3209 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3210 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3211 "reloading zones failed: %s",
3212 isc_result_totext(result));
3219 reconfig(ns_server_t *server) {
3220 isc_result_t result;
3221 CHECK(loadconfig(server));
3223 result = load_new_zones(server, ISC_FALSE);
3224 if (result != ISC_R_SUCCESS) {
3225 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3226 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3227 "loading new zones failed: %s",
3228 isc_result_totext(result));
3234 * Handle a reload event (from SIGHUP).
3237 ns_server_reload(isc_task_t *task, isc_event_t *event) {
3238 ns_server_t *server = (ns_server_t *)event->ev_arg;
3240 INSIST(task = server->task);
3243 (void)reload(server);
3245 LOCK(&server->reload_event_lock);
3246 INSIST(server->reload_event == NULL);
3247 server->reload_event = event;
3248 UNLOCK(&server->reload_event_lock);
3252 ns_server_reloadwanted(ns_server_t *server) {
3253 LOCK(&server->reload_event_lock);
3254 if (server->reload_event != NULL)
3255 isc_task_send(server->task, &server->reload_event);
3256 UNLOCK(&server->reload_event_lock);
3260 next_token(char **stringp, const char *delim) {
3264 res = strsep(stringp, delim);
3267 } while (*res == '\0');
3272 * Find the zone specified in the control channel command 'args',
3273 * if any. If a zone is specified, point '*zonep' at it, otherwise
3274 * set '*zonep' to NULL.
3277 zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
3279 const char *zonetxt;
3281 const char *viewtxt = NULL;
3282 dns_fixedname_t name;
3283 isc_result_t result;
3285 dns_view_t *view = NULL;
3286 dns_rdataclass_t rdclass;
3288 REQUIRE(zonep != NULL && *zonep == NULL);
3292 /* Skip the command name. */
3293 ptr = next_token(&input, " \t");
3295 return (ISC_R_UNEXPECTEDEND);
3297 /* Look for the zone name. */
3298 zonetxt = next_token(&input, " \t");
3299 if (zonetxt == NULL)
3300 return (ISC_R_SUCCESS);
3302 /* Look for the optional class name. */
3303 classtxt = next_token(&input, " \t");
3304 if (classtxt != NULL) {
3305 /* Look for the optional view name. */
3306 viewtxt = next_token(&input, " \t");
3309 isc_buffer_init(&buf, zonetxt, strlen(zonetxt));
3310 isc_buffer_add(&buf, strlen(zonetxt));
3311 dns_fixedname_init(&name);
3312 result = dns_name_fromtext(dns_fixedname_name(&name),
3313 &buf, dns_rootname, ISC_FALSE, NULL);
3314 if (result != ISC_R_SUCCESS)
3317 if (classtxt != NULL) {
3320 r.length = strlen(classtxt);
3321 result = dns_rdataclass_fromtext(&rdclass, &r);
3322 if (result != ISC_R_SUCCESS)
3325 rdclass = dns_rdataclass_in;
3328 if (viewtxt == NULL)
3329 viewtxt = "_default";
3330 result = dns_viewlist_find(&server->viewlist, viewtxt,
3332 if (result != ISC_R_SUCCESS)
3335 result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
3337 /* Partial match? */
3338 if (result != ISC_R_SUCCESS && *zonep != NULL)
3339 dns_zone_detach(zonep);
3340 dns_view_detach(&view);
3346 * Act on a "retransfer" command from the command channel.
3349 ns_server_retransfercommand(ns_server_t *server, char *args) {
3350 isc_result_t result;
3351 dns_zone_t *zone = NULL;
3352 dns_zonetype_t type;
3354 result = zone_from_args(server, args, &zone);
3355 if (result != ISC_R_SUCCESS)
3358 return (ISC_R_UNEXPECTEDEND);
3359 type = dns_zone_gettype(zone);
3360 if (type == dns_zone_slave || type == dns_zone_stub)
3361 dns_zone_forcereload(zone);
3363 result = ISC_R_NOTFOUND;
3364 dns_zone_detach(&zone);
3369 * Act on a "reload" command from the command channel.
3372 ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
3373 isc_result_t result;
3374 dns_zone_t *zone = NULL;
3375 dns_zonetype_t type;
3376 const char *msg = NULL;
3378 result = zone_from_args(server, args, &zone);
3379 if (result != ISC_R_SUCCESS)
3382 result = reload(server);
3383 if (result == ISC_R_SUCCESS)
3384 msg = "server reload successful";
3386 type = dns_zone_gettype(zone);
3387 if (type == dns_zone_slave || type == dns_zone_stub) {
3388 dns_zone_refresh(zone);
3389 msg = "zone refresh queued";
3391 result = dns_zone_load(zone);
3392 dns_zone_detach(&zone);
3395 msg = "zone reload successful";
3397 case DNS_R_CONTINUE:
3398 msg = "zone reload queued";
3399 result = ISC_R_SUCCESS;
3401 case DNS_R_UPTODATE:
3402 msg = "zone reload up-to-date";
3403 result = ISC_R_SUCCESS;
3406 /* failure message will be generated by rndc */
3411 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
3412 isc_buffer_putmem(text, (const unsigned char *)msg,
3418 * Act on a "reconfig" command from the command channel.
3421 ns_server_reconfigcommand(ns_server_t *server, char *args) {
3425 return (ISC_R_SUCCESS);
3429 * Act on a "refresh" command from the command channel.
3432 ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
3433 isc_result_t result;
3434 dns_zone_t *zone = NULL;
3435 const unsigned char msg[] = "zone refresh queued";
3437 result = zone_from_args(server, args, &zone);
3438 if (result != ISC_R_SUCCESS)
3441 return (ISC_R_UNEXPECTEDEND);
3443 dns_zone_refresh(zone);
3444 dns_zone_detach(&zone);
3445 if (sizeof(msg) <= isc_buffer_availablelength(text))
3446 isc_buffer_putmem(text, msg, sizeof(msg));
3448 return (ISC_R_SUCCESS);
3452 ns_server_togglequerylog(ns_server_t *server) {
3453 server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE;
3455 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3456 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3457 "query logging is now %s",
3458 server->log_queries ? "on" : "off");
3459 return (ISC_R_SUCCESS);
3463 ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config,
3464 ns_aclconfctx_t *actx,
3465 isc_mem_t *mctx, ns_listenlist_t **target)
3467 isc_result_t result;
3468 cfg_listelt_t *element;
3469 ns_listenlist_t *dlist = NULL;
3471 REQUIRE(target != NULL && *target == NULL);
3473 result = ns_listenlist_create(mctx, &dlist);
3474 if (result != ISC_R_SUCCESS)
3477 for (element = cfg_list_first(listenlist);
3479 element = cfg_list_next(element))
3481 ns_listenelt_t *delt = NULL;
3482 cfg_obj_t *listener = cfg_listelt_value(element);
3483 result = ns_listenelt_fromconfig(listener, config, actx,
3485 if (result != ISC_R_SUCCESS)
3487 ISC_LIST_APPEND(dlist->elts, delt, link);
3490 return (ISC_R_SUCCESS);
3493 ns_listenlist_detach(&dlist);
3498 * Create a listen list from the corresponding configuration
3502 ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config,
3503 ns_aclconfctx_t *actx,
3504 isc_mem_t *mctx, ns_listenelt_t **target)
3506 isc_result_t result;
3509 ns_listenelt_t *delt = NULL;
3510 REQUIRE(target != NULL && *target == NULL);
3512 portobj = cfg_tuple_get(listener, "port");
3513 if (!cfg_obj_isuint32(portobj)) {
3514 if (ns_g_port != 0) {
3517 result = ns_config_getport(config, &port);
3518 if (result != ISC_R_SUCCESS)
3522 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
3523 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
3524 "port value '%u' is out of range",
3525 cfg_obj_asuint32(portobj));
3526 return (ISC_R_RANGE);
3528 port = (in_port_t)cfg_obj_asuint32(portobj);
3531 result = ns_listenelt_create(mctx, port, NULL, &delt);
3532 if (result != ISC_R_SUCCESS)
3535 result = ns_acl_fromconfig(cfg_tuple_get(listener, "acl"),
3536 config, actx, mctx, &delt->acl);
3537 if (result != ISC_R_SUCCESS) {
3538 ns_listenelt_destroy(delt);
3542 return (ISC_R_SUCCESS);
3546 ns_server_dumpstats(ns_server_t *server) {
3547 isc_result_t result;
3548 dns_zone_t *zone, *next;
3554 isc_stdtime_get(&now);
3556 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
3557 "could not open statistics dump file", server->statsfile);
3559 ncounters = DNS_STATS_NCOUNTERS;
3560 fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
3562 for (i = 0; i < ncounters; i++)
3563 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT "u\n",
3564 dns_statscounter_names[i],
3565 server->querystats[i]);
3568 for (result = dns_zone_first(server->zonemgr, &zone);
3569 result == ISC_R_SUCCESS;
3570 next = NULL, result = dns_zone_next(zone, &next), zone = next)
3572 isc_uint64_t *zonestats = dns_zone_getstatscounters(zone);
3573 if (zonestats != NULL) {
3574 char zonename[DNS_NAME_FORMATSIZE];
3578 dns_name_format(dns_zone_getorigin(zone),
3579 zonename, sizeof(zonename));
3580 view = dns_zone_getview(zone);
3581 viewname = view->name;
3582 for (i = 0; i < ncounters; i++) {
3583 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT
3585 dns_statscounter_names[i],
3588 if (strcmp(viewname, "_default") != 0)
3589 fprintf(fp, " %s", viewname);
3594 if (result == ISC_R_NOMORE)
3595 result = ISC_R_SUCCESS;
3598 fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
3602 (void)isc_stdio_close(fp);
3607 add_zone_tolist(dns_zone_t *zone, void *uap) {
3608 struct dumpcontext *dctx = uap;
3609 struct zonelistentry *zle;
3611 zle = isc_mem_get(dctx->mctx, sizeof *zle);
3613 return (ISC_R_NOMEMORY);
3615 dns_zone_attach(zone, &zle->zone);
3616 ISC_LINK_INIT(zle, link);
3617 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
3618 return (ISC_R_SUCCESS);
3622 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
3623 struct viewlistentry *vle;
3624 isc_result_t result = ISC_R_SUCCESS;
3626 vle = isc_mem_get(dctx->mctx, sizeof *vle);
3628 return (ISC_R_NOMEMORY);
3630 dns_view_attach(view, &vle->view);
3631 ISC_LINK_INIT(vle, link);
3632 ISC_LIST_INIT(vle->zonelist);
3633 ISC_LIST_APPEND(dctx->viewlist, vle, link);
3634 if (dctx->dumpzones)
3635 result = dns_zt_apply(view->zonetable, ISC_TRUE,
3636 add_zone_tolist, dctx);
3641 dumpcontext_destroy(struct dumpcontext *dctx) {
3642 struct viewlistentry *vle;
3643 struct zonelistentry *zle;
3645 vle = ISC_LIST_HEAD(dctx->viewlist);
3646 while (vle != NULL) {
3647 ISC_LIST_UNLINK(dctx->viewlist, vle, link);
3648 zle = ISC_LIST_HEAD(vle->zonelist);
3649 while (zle != NULL) {
3650 ISC_LIST_UNLINK(vle->zonelist, zle, link);
3651 dns_zone_detach(&zle->zone);
3652 isc_mem_put(dctx->mctx, zle, sizeof *zle);
3653 zle = ISC_LIST_HEAD(vle->zonelist);
3655 dns_view_detach(&vle->view);
3656 isc_mem_put(dctx->mctx, vle, sizeof *vle);
3657 vle = ISC_LIST_HEAD(dctx->viewlist);
3659 if (dctx->version != NULL)
3660 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
3661 if (dctx->db != NULL)
3662 dns_db_detach(&dctx->db);
3663 if (dctx->cache != NULL)
3664 dns_db_detach(&dctx->cache);
3665 if (dctx->task != NULL)
3666 isc_task_detach(&dctx->task);
3667 if (dctx->fp != NULL)
3668 (void)isc_stdio_close(dctx->fp);
3669 if (dctx->mdctx != NULL)
3670 dns_dumpctx_detach(&dctx->mdctx);
3671 isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
3675 dumpdone(void *arg, isc_result_t result) {
3676 struct dumpcontext *dctx = arg;
3678 const dns_master_style_t *style;
3680 if (result != ISC_R_SUCCESS)
3682 if (dctx->mdctx != NULL)
3683 dns_dumpctx_detach(&dctx->mdctx);
3684 if (dctx->view == NULL) {
3685 dctx->view = ISC_LIST_HEAD(dctx->viewlist);
3686 if (dctx->view == NULL)
3688 INSIST(dctx->zone == NULL);
3691 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
3692 if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) {
3693 style = &dns_master_style_cache;
3694 /* start cache dump */
3695 if (dctx->view->view->cachedb != NULL)
3696 dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
3697 if (dctx->cache != NULL) {
3699 fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n",
3700 dctx->view->view->name);
3701 result = dns_master_dumptostreaminc(dctx->mctx,
3707 if (result == DNS_R_CONTINUE)
3709 if (result == ISC_R_NOTIMPLEMENTED)
3710 fprintf(dctx->fp, "; %s\n",
3711 dns_result_totext(result));
3712 else if (result != ISC_R_SUCCESS)
3716 if (dctx->cache != NULL) {
3717 dns_adb_dump(dctx->view->view->adb, dctx->fp);
3718 dns_db_detach(&dctx->cache);
3720 if (dctx->dumpzones) {
3721 style = &dns_master_style_full;
3723 if (dctx->version != NULL)
3724 dns_db_closeversion(dctx->db, &dctx->version,
3726 if (dctx->db != NULL)
3727 dns_db_detach(&dctx->db);
3728 if (dctx->zone == NULL)
3729 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
3731 dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
3732 if (dctx->zone != NULL) {
3733 /* start zone dump */
3734 dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
3735 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
3736 result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
3737 if (result != ISC_R_SUCCESS) {
3738 fprintf(dctx->fp, "; %s\n",
3739 dns_result_totext(result));
3742 dns_db_currentversion(dctx->db, &dctx->version);
3743 result = dns_master_dumptostreaminc(dctx->mctx,
3750 if (result == DNS_R_CONTINUE)
3752 if (result == ISC_R_NOTIMPLEMENTED)
3753 fprintf(dctx->fp, "; %s\n",
3754 dns_result_totext(result));
3755 if (result != ISC_R_SUCCESS)
3759 if (dctx->view != NULL)
3760 dctx->view = ISC_LIST_NEXT(dctx->view, link);
3761 if (dctx->view != NULL)
3764 fprintf(dctx->fp, "; Dump complete\n");
3765 result = isc_stdio_flush(dctx->fp);
3766 if (result == ISC_R_SUCCESS)
3767 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3768 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3771 if (result != ISC_R_SUCCESS)
3772 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3773 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3774 "dumpdb failed: %s", dns_result_totext(result));
3775 dumpcontext_destroy(dctx);
3780 ns_server_dumpdb(ns_server_t *server, char *args) {
3781 struct dumpcontext *dctx = NULL;
3783 isc_result_t result;
3787 dctx = isc_mem_get(server->mctx, sizeof(*dctx));
3789 return (ISC_R_NOMEMORY);
3791 dctx->mctx = server->mctx;
3792 dctx->dumpcache = ISC_TRUE;
3793 dctx->dumpzones = ISC_FALSE;
3795 ISC_LIST_INIT(dctx->viewlist);
3803 dctx->version = NULL;
3804 isc_task_attach(server->task, &dctx->task);
3806 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
3807 "could not open dump file", server->dumpfile);
3809 /* Skip the command name. */
3810 ptr = next_token(&args, " \t");
3812 return (ISC_R_UNEXPECTEDEND);
3814 sep = (args == NULL) ? "" : ": ";
3815 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3816 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3817 "dumpdb started%s%s", sep, (args != NULL) ? args : "");
3819 ptr = next_token(&args, " \t");
3820 if (ptr != NULL && strcmp(ptr, "-all") == 0) {
3821 dctx->dumpzones = ISC_TRUE;
3822 dctx->dumpcache = ISC_TRUE;
3823 ptr = next_token(&args, " \t");
3824 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
3825 dctx->dumpzones = ISC_FALSE;
3826 dctx->dumpcache = ISC_TRUE;
3827 ptr = next_token(&args, " \t");
3828 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
3829 dctx->dumpzones = ISC_TRUE;
3830 dctx->dumpcache = ISC_FALSE;
3831 ptr = next_token(&args, " \t");
3834 for (view = ISC_LIST_HEAD(server->viewlist);
3836 view = ISC_LIST_NEXT(view, link))
3838 if (ptr != NULL && strcmp(view->name, ptr) != 0)
3840 CHECK(add_view_tolist(dctx, view));
3842 dumpdone(dctx, ISC_R_SUCCESS);
3843 return (ISC_R_SUCCESS);
3847 dumpcontext_destroy(dctx);
3852 ns_server_dumprecursing(ns_server_t *server) {
3854 isc_result_t result;
3856 CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
3857 "could not open dump file", server->recfile);
3858 fprintf(fp,";\n; Recursing Queries\n;\n");
3859 ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
3860 fprintf(fp, "; Dump complete\n");
3864 result = isc_stdio_close(fp);
3869 ns_server_setdebuglevel(ns_server_t *server, char *args) {
3877 /* Skip the command name. */
3878 ptr = next_token(&args, " \t");
3880 return (ISC_R_UNEXPECTEDEND);
3882 /* Look for the new level name. */
3883 levelstr = next_token(&args, " \t");
3884 if (levelstr == NULL) {
3885 if (ns_g_debuglevel < 99)
3888 newlevel = strtol(levelstr, &endp, 10);
3889 if (*endp != '\0' || newlevel < 0 || newlevel > 99)
3890 return (ISC_R_RANGE);
3891 ns_g_debuglevel = (unsigned int)newlevel;
3893 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
3894 return (ISC_R_SUCCESS);
3898 ns_server_flushcache(ns_server_t *server, char *args) {
3899 char *ptr, *viewname;
3901 isc_boolean_t flushed = ISC_FALSE;
3902 isc_result_t result;
3904 /* Skip the command name. */
3905 ptr = next_token(&args, " \t");
3907 return (ISC_R_UNEXPECTEDEND);
3909 /* Look for the view name. */
3910 viewname = next_token(&args, " \t");
3912 result = isc_task_beginexclusive(server->task);
3913 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3914 for (view = ISC_LIST_HEAD(server->viewlist);
3916 view = ISC_LIST_NEXT(view, link))
3918 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
3920 result = dns_view_flushcache(view);
3921 if (result != ISC_R_SUCCESS)
3926 result = ISC_R_SUCCESS;
3928 result = ISC_R_FAILURE;
3930 isc_task_endexclusive(server->task);
3935 ns_server_flushname(ns_server_t *server, char *args) {
3936 char *ptr, *target, *viewname;
3938 isc_boolean_t flushed = ISC_FALSE;
3939 isc_result_t result;
3941 dns_fixedname_t fixed;
3944 /* Skip the command name. */
3945 ptr = next_token(&args, " \t");
3947 return (ISC_R_UNEXPECTEDEND);
3949 /* Find the domain name to flush. */
3950 target = next_token(&args, " \t");
3952 return (ISC_R_UNEXPECTEDEND);
3954 isc_buffer_init(&b, target, strlen(target));
3955 isc_buffer_add(&b, strlen(target));
3956 dns_fixedname_init(&fixed);
3957 name = dns_fixedname_name(&fixed);
3958 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
3959 if (result != ISC_R_SUCCESS)
3962 /* Look for the view name. */
3963 viewname = next_token(&args, " \t");
3965 result = isc_task_beginexclusive(server->task);
3966 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3968 for (view = ISC_LIST_HEAD(server->viewlist);
3970 view = ISC_LIST_NEXT(view, link))
3972 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
3974 result = dns_view_flushname(view, name);
3975 if (result != ISC_R_SUCCESS)
3976 flushed = ISC_FALSE;
3979 result = ISC_R_SUCCESS;
3981 result = ISC_R_FAILURE;
3982 isc_task_endexclusive(server->task);
3987 ns_server_status(ns_server_t *server, isc_buffer_t *text) {
3988 int zonecount, xferrunning, xferdeferred, soaqueries;
3991 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
3992 xferrunning = dns_zonemgr_getcount(server->zonemgr,
3993 DNS_ZONESTATE_XFERRUNNING);
3994 xferdeferred = dns_zonemgr_getcount(server->zonemgr,
3995 DNS_ZONESTATE_XFERDEFERRED);
3996 soaqueries = dns_zonemgr_getcount(server->zonemgr,
3997 DNS_ZONESTATE_SOAQUERY);
3998 n = snprintf((char *)isc_buffer_used(text),
3999 isc_buffer_availablelength(text),
4000 "number of zones: %u\n"
4002 "xfers running: %u\n"
4003 "xfers deferred: %u\n"
4004 "soa queries in progress: %u\n"
4005 "query logging is %s\n"
4006 "recursive clients: %d/%d\n"
4007 "tcp clients: %d/%d\n"
4008 "server is up and running",
4009 zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
4010 soaqueries, server->log_queries ? "ON" : "OFF",
4011 server->recursionquota.used, server->recursionquota.max,
4012 server->tcpquota.used, server->tcpquota.max);
4013 if (n >= isc_buffer_availablelength(text))
4014 return (ISC_R_NOSPACE);
4015 isc_buffer_add(text, n);
4016 return (ISC_R_SUCCESS);
4020 * Act on a "freeze" or "unfreeze" command from the command channel.
4023 ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) {
4024 isc_result_t result;
4025 dns_zone_t *zone = NULL;
4026 dns_zonetype_t type;
4027 char classstr[DNS_RDATACLASS_FORMATSIZE];
4028 char zonename[DNS_NAME_FORMATSIZE];
4031 const char *vname, *sep;
4032 isc_boolean_t frozen;
4034 result = zone_from_args(server, args, &zone);
4035 if (result != ISC_R_SUCCESS)
4038 return (ISC_R_UNEXPECTEDEND);
4039 type = dns_zone_gettype(zone);
4040 if (type != dns_zone_master) {
4041 dns_zone_detach(&zone);
4042 return (ISC_R_NOTFOUND);
4045 frozen = dns_zone_getupdatedisabled(zone);
4048 result = DNS_R_FROZEN;
4049 if (result == ISC_R_SUCCESS)
4050 result = dns_zone_flush(zone);
4051 if (result == ISC_R_SUCCESS) {
4052 journal = dns_zone_getjournal(zone);
4053 if (journal != NULL)
4054 (void)isc_file_remove(journal);
4058 result = dns_zone_load(zone);
4059 if (result == DNS_R_CONTINUE ||
4060 result == DNS_R_UPTODATE)
4061 result = ISC_R_SUCCESS;
4064 if (result == ISC_R_SUCCESS)
4065 dns_zone_setupdatedisabled(zone, freeze);
4067 view = dns_zone_getview(zone);
4068 if (strcmp(view->name, "_bind") == 0 ||
4069 strcmp(view->name, "_default") == 0)
4077 dns_rdataclass_format(dns_zone_getclass(zone), classstr,
4079 dns_name_format(dns_zone_getorigin(zone),
4080 zonename, sizeof(zonename));
4081 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4082 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4083 "%s zone '%s/%s'%s%s: %s",
4084 freeze ? "freezing" : "unfreezing",
4085 zonename, classstr, sep, vname,
4086 isc_result_totext(result));
4087 dns_zone_detach(&zone);