2 * Copyright (C) 2004, 2005 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.65 2005/07/27 02:53:15 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>
85 #include <named/ns_smf_globals.h>
90 * Check an operation for failure. Assumes that the function
91 * using it has a 'result' variable and a 'cleanup' label.
95 if (result != ISC_R_SUCCESS) goto cleanup; \
98 #define CHECKM(op, msg) \
100 if (result != ISC_R_SUCCESS) { \
101 isc_log_write(ns_g_lctx, \
102 NS_LOGCATEGORY_GENERAL, \
103 NS_LOGMODULE_SERVER, \
106 isc_result_totext(result)); \
111 #define CHECKMF(op, msg, file) \
112 do { result = (op); \
113 if (result != ISC_R_SUCCESS) { \
114 isc_log_write(ns_g_lctx, \
115 NS_LOGCATEGORY_GENERAL, \
116 NS_LOGMODULE_SERVER, \
118 "%s '%s': %s", msg, file, \
119 isc_result_totext(result)); \
124 #define CHECKFATAL(op, msg) \
125 do { result = (op); \
126 if (result != ISC_R_SUCCESS) \
127 fatal(msg, result); \
132 unsigned int dispatchgen;
133 dns_dispatch_t *dispatch;
134 ISC_LINK(struct ns_dispatch) link;
139 isc_boolean_t dumpcache;
140 isc_boolean_t dumpzones;
142 ISC_LIST(struct viewlistentry) viewlist;
143 struct viewlistentry *view;
144 struct zonelistentry *zone;
145 dns_dumpctx_t *mdctx;
149 dns_dbversion_t *version;
152 struct viewlistentry {
154 ISC_LINK(struct viewlistentry) link;
155 ISC_LIST(struct zonelistentry) zonelist;
158 struct zonelistentry {
160 ISC_LINK(struct zonelistentry) link;
164 fatal(const char *msg, isc_result_t result);
167 ns_server_reload(isc_task_t *task, isc_event_t *event);
170 ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config,
171 ns_aclconfctx_t *actx,
172 isc_mem_t *mctx, ns_listenelt_t **target);
174 ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config,
175 ns_aclconfctx_t *actx,
176 isc_mem_t *mctx, ns_listenlist_t **target);
179 configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
180 cfg_obj_t *forwarders, cfg_obj_t *forwardtype);
183 configure_alternates(cfg_obj_t *config, dns_view_t *view,
184 cfg_obj_t *alternates);
187 configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
188 isc_mem_t *mctx, dns_view_t *view,
189 ns_aclconfctx_t *aclconf);
192 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
195 * Configure a single view ACL at '*aclp'. Get its configuration by
196 * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl'
197 * (for a global default).
200 configure_view_acl(cfg_obj_t *vconfig, cfg_obj_t *config,
201 const char *aclname, ns_aclconfctx_t *actx,
202 isc_mem_t *mctx, dns_acl_t **aclp)
206 cfg_obj_t *aclobj = NULL;
210 dns_acl_detach(aclp);
212 maps[i++] = cfg_tuple_get(vconfig, "options");
213 if (config != NULL) {
214 cfg_obj_t *options = NULL;
215 (void)cfg_map_get(config, "options", &options);
221 result = ns_config_get(maps, aclname, &aclobj);
224 * No value available. *aclp == NULL.
226 return (ISC_R_SUCCESS);
228 result = ns_acl_fromconfig(aclobj, config, actx, mctx, aclp);
234 configure_view_dnsseckey(cfg_obj_t *vconfig, cfg_obj_t *key,
235 dns_keytable_t *keytable, isc_mem_t *mctx)
237 dns_rdataclass_t viewclass;
238 dns_rdata_dnskey_t keystruct;
239 isc_uint32_t flags, proto, alg;
240 char *keystr, *keynamestr;
241 unsigned char keydata[4096];
242 isc_buffer_t keydatabuf;
243 unsigned char rrdata[4096];
244 isc_buffer_t rrdatabuf;
246 dns_fixedname_t fkeyname;
248 isc_buffer_t namebuf;
250 dst_key_t *dstkey = NULL;
252 flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
253 proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
254 alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
255 keyname = dns_fixedname_name(&fkeyname);
256 keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
259 viewclass = dns_rdataclass_in;
261 cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
262 CHECK(ns_config_getclass(classobj, dns_rdataclass_in,
265 keystruct.common.rdclass = viewclass;
266 keystruct.common.rdtype = dns_rdatatype_dnskey;
268 * The key data in keystruct is not dynamically allocated.
270 keystruct.mctx = NULL;
272 ISC_LINK_INIT(&keystruct.common, link);
275 CHECKM(ISC_R_RANGE, "key flags");
277 CHECKM(ISC_R_RANGE, "key protocol");
279 CHECKM(ISC_R_RANGE, "key algorithm");
280 keystruct.flags = (isc_uint16_t)flags;
281 keystruct.protocol = (isc_uint8_t)proto;
282 keystruct.algorithm = (isc_uint8_t)alg;
284 isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
285 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
287 keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
288 CHECK(isc_base64_decodestring(keystr, &keydatabuf));
289 isc_buffer_usedregion(&keydatabuf, &r);
290 keystruct.datalen = r.length;
291 keystruct.data = r.base;
293 CHECK(dns_rdata_fromstruct(NULL,
294 keystruct.common.rdclass,
295 keystruct.common.rdtype,
296 &keystruct, &rrdatabuf));
297 dns_fixedname_init(&fkeyname);
298 isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr));
299 isc_buffer_add(&namebuf, strlen(keynamestr));
300 CHECK(dns_name_fromtext(keyname, &namebuf,
301 dns_rootname, ISC_FALSE,
303 CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
306 CHECK(dns_keytable_add(keytable, &dstkey));
307 INSIST(dstkey == NULL);
308 return (ISC_R_SUCCESS);
311 if (result == DST_R_NOCRYPTO) {
312 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
313 "ignoring trusted key for '%s': no crypto support",
315 result = ISC_R_SUCCESS;
317 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
318 "configuring trusted key for '%s': %s",
319 keynamestr, isc_result_totext(result));
320 result = ISC_R_FAILURE;
324 dst_key_free(&dstkey);
330 * Configure DNSSEC keys for a view. Currently used only for
331 * the security roots.
333 * The per-view configuration values and the server-global defaults are read
334 * from 'vconfig' and 'config'. The variable to be configured is '*target'.
337 configure_view_dnsseckeys(cfg_obj_t *vconfig, cfg_obj_t *config,
338 isc_mem_t *mctx, dns_keytable_t **target)
341 cfg_obj_t *keys = NULL;
342 cfg_obj_t *voptions = NULL;
343 cfg_listelt_t *element, *element2;
346 dns_keytable_t *keytable = NULL;
348 CHECK(dns_keytable_create(mctx, &keytable));
351 voptions = cfg_tuple_get(vconfig, "options");
354 if (voptions != NULL)
355 (void)cfg_map_get(voptions, "trusted-keys", &keys);
357 (void)cfg_map_get(config, "trusted-keys", &keys);
359 for (element = cfg_list_first(keys);
361 element = cfg_list_next(element))
363 keylist = cfg_listelt_value(element);
364 for (element2 = cfg_list_first(keylist);
366 element2 = cfg_list_next(element2))
368 key = cfg_listelt_value(element2);
369 CHECK(configure_view_dnsseckey(vconfig, key,
374 dns_keytable_detach(target);
375 *target = keytable; /* Transfer ownership. */
377 result = ISC_R_SUCCESS;
384 mustbesecure(cfg_obj_t *mbs, dns_resolver_t *resolver)
386 cfg_listelt_t *element;
389 dns_fixedname_t fixed;
395 dns_fixedname_init(&fixed);
396 name = dns_fixedname_name(&fixed);
397 for (element = cfg_list_first(mbs);
399 element = cfg_list_next(element))
401 obj = cfg_listelt_value(element);
402 str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
403 isc_buffer_init(&b, str, strlen(str));
404 isc_buffer_add(&b, strlen(str));
405 CHECK(dns_name_fromtext(name, &b, dns_rootname,
407 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
408 CHECK(dns_resolver_setmustbesecure(resolver, name, value));
411 result = ISC_R_SUCCESS;
418 * Get a dispatch appropriate for the resolver of a given view.
421 get_view_querysource_dispatch(cfg_obj_t **maps,
422 int af, dns_dispatch_t **dispatchp)
425 dns_dispatch_t *disp;
427 unsigned int attrs, attrmask;
428 cfg_obj_t *obj = NULL;
431 * Make compiler happy.
433 result = ISC_R_FAILURE;
437 result = ns_config_get(maps, "query-source", &obj);
438 INSIST(result == ISC_R_SUCCESS);
442 result = ns_config_get(maps, "query-source-v6", &obj);
443 INSIST(result == ISC_R_SUCCESS);
449 sa = *(cfg_obj_assockaddr(obj));
450 INSIST(isc_sockaddr_pf(&sa) == af);
453 * If we don't support this address family, we're done!
457 result = isc_net_probeipv4();
460 result = isc_net_probeipv6();
465 if (result != ISC_R_SUCCESS)
466 return (ISC_R_SUCCESS);
469 * Try to find a dispatcher that we can share.
472 attrs |= DNS_DISPATCHATTR_UDP;
475 attrs |= DNS_DISPATCHATTR_IPV4;
478 attrs |= DNS_DISPATCHATTR_IPV6;
482 attrmask |= DNS_DISPATCHATTR_UDP;
483 attrmask |= DNS_DISPATCHATTR_TCP;
484 attrmask |= DNS_DISPATCHATTR_IPV4;
485 attrmask |= DNS_DISPATCHATTR_IPV6;
488 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
489 ns_g_taskmgr, &sa, 4096,
490 1000, 32768, 16411, 16433,
491 attrs, attrmask, &disp);
492 if (result != ISC_R_SUCCESS) {
494 char buf[ISC_SOCKADDR_FORMATSIZE];
498 isc_sockaddr_any(&any);
501 isc_sockaddr_any6(&any);
504 if (isc_sockaddr_equal(&sa, &any))
505 return (ISC_R_SUCCESS);
506 isc_sockaddr_format(&sa, buf, sizeof(buf));
507 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
508 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
509 "could not get query source dispatcher (%s)",
516 return (ISC_R_SUCCESS);
520 configure_order(dns_order_t *order, cfg_obj_t *ent) {
521 dns_rdataclass_t rdclass;
522 dns_rdatatype_t rdtype;
524 dns_fixedname_t fixed;
525 unsigned int mode = 0;
529 isc_boolean_t addroot;
531 result = ns_config_getclass(cfg_tuple_get(ent, "class"),
532 dns_rdataclass_any, &rdclass);
533 if (result != ISC_R_SUCCESS)
536 result = ns_config_gettype(cfg_tuple_get(ent, "type"),
537 dns_rdatatype_any, &rdtype);
538 if (result != ISC_R_SUCCESS)
541 obj = cfg_tuple_get(ent, "name");
542 if (cfg_obj_isstring(obj))
543 str = cfg_obj_asstring(obj);
546 addroot = ISC_TF(strcmp(str, "*") == 0);
547 isc_buffer_init(&b, str, strlen(str));
548 isc_buffer_add(&b, strlen(str));
549 dns_fixedname_init(&fixed);
550 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
551 dns_rootname, ISC_FALSE, NULL);
552 if (result != ISC_R_SUCCESS)
555 obj = cfg_tuple_get(ent, "ordering");
556 INSIST(cfg_obj_isstring(obj));
557 str = cfg_obj_asstring(obj);
558 if (!strcasecmp(str, "fixed"))
559 mode = DNS_RDATASETATTR_FIXEDORDER;
560 else if (!strcasecmp(str, "random"))
561 mode = DNS_RDATASETATTR_RANDOMIZE;
562 else if (!strcasecmp(str, "cyclic"))
568 * "*" should match everything including the root (BIND 8 compat).
569 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a
570 * explict entry for "." when the name is "*".
573 result = dns_order_add(order, dns_rootname,
574 rdtype, rdclass, mode);
575 if (result != ISC_R_SUCCESS)
579 return (dns_order_add(order, dns_fixedname_name(&fixed),
580 rdtype, rdclass, mode));
584 configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
592 sa = cfg_obj_assockaddr(cfg_map_getname(cpeer));
593 isc_netaddr_fromsockaddr(&na, sa);
596 result = dns_peer_new(mctx, &na, &peer);
597 if (result != ISC_R_SUCCESS)
601 (void)cfg_map_get(cpeer, "bogus", &obj);
603 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
606 (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
608 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
611 (void)cfg_map_get(cpeer, "request-ixfr", &obj);
613 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
616 (void)cfg_map_get(cpeer, "edns", &obj);
618 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
621 (void)cfg_map_get(cpeer, "transfers", &obj);
623 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
626 (void)cfg_map_get(cpeer, "transfer-format", &obj);
628 str = cfg_obj_asstring(obj);
629 if (strcasecmp(str, "many-answers") == 0)
630 CHECK(dns_peer_settransferformat(peer,
632 else if (strcasecmp(str, "one-answer") == 0)
633 CHECK(dns_peer_settransferformat(peer,
640 (void)cfg_map_get(cpeer, "keys", &obj);
642 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
643 if (result != ISC_R_SUCCESS)
648 if (isc_sockaddr_pf(sa) == AF_INET)
649 (void)cfg_map_get(cpeer, "transfer-source", &obj);
651 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
653 result = dns_peer_settransfersource(peer,
654 cfg_obj_assockaddr(obj));
655 if (result != ISC_R_SUCCESS)
659 return (ISC_R_SUCCESS);
662 dns_peer_detach(&peer);
667 disable_algorithms(cfg_obj_t *disabled, dns_resolver_t *resolver) {
669 cfg_obj_t *algorithms;
670 cfg_listelt_t *element;
672 dns_fixedname_t fixed;
676 dns_fixedname_init(&fixed);
677 name = dns_fixedname_name(&fixed);
678 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
679 isc_buffer_init(&b, str, strlen(str));
680 isc_buffer_add(&b, strlen(str));
681 CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL));
683 algorithms = cfg_tuple_get(disabled, "algorithms");
684 for (element = cfg_list_first(algorithms);
686 element = cfg_list_next(element))
691 r.base = cfg_obj_asstring(cfg_listelt_value(element));
692 r.length = strlen(r.base);
694 result = dns_secalg_fromtext(&alg, &r);
695 if (result != ISC_R_SUCCESS) {
697 result = isc_parse_uint8(&ui, r.base, 10);
700 if (result != ISC_R_SUCCESS) {
701 cfg_obj_log(cfg_listelt_value(element),
702 ns_g_lctx, ISC_LOG_ERROR,
703 "invalid algorithm");
706 CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
713 * Configure 'view' according to 'vconfig', taking defaults from 'config'
714 * where values are missing in 'vconfig'.
716 * When configuring the default view, 'vconfig' will be NULL and the
717 * global defaults in 'config' used exclusively.
720 configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
721 isc_mem_t *mctx, ns_aclconfctx_t *actx,
722 isc_boolean_t need_hints)
725 cfg_obj_t *cfgmaps[3];
726 cfg_obj_t *options = NULL;
727 cfg_obj_t *voptions = NULL;
728 cfg_obj_t *forwardtype;
729 cfg_obj_t *forwarders;
730 cfg_obj_t *alternates;
734 cfg_listelt_t *element;
736 dns_cache_t *cache = NULL;
738 isc_uint32_t max_adb_size;
739 isc_uint32_t max_cache_size;
740 isc_uint32_t lame_ttl;
741 dns_tsig_keyring_t *ring;
742 dns_view_t *pview = NULL; /* Production view */
744 dns_dispatch_t *dispatch4 = NULL;
745 dns_dispatch_t *dispatch6 = NULL;
746 isc_boolean_t reused_cache = ISC_FALSE;
749 dns_order_t *order = NULL;
750 isc_uint32_t udpsize;
751 unsigned int check = 0;
753 REQUIRE(DNS_VIEW_VALID(view));
758 (void)cfg_map_get(config, "options", &options);
761 if (vconfig != NULL) {
762 voptions = cfg_tuple_get(vconfig, "options");
763 maps[i++] = voptions;
767 maps[i++] = ns_g_defaults;
771 if (voptions != NULL)
772 cfgmaps[i++] = voptions;
774 cfgmaps[i++] = config;
778 * Set the view's port number for outgoing queries.
780 CHECKM(ns_config_getport(config, &port), "port");
781 dns_view_setdstport(view, port);
784 * Configure the zones.
787 if (voptions != NULL)
788 (void)cfg_map_get(voptions, "zone", &zonelist);
790 (void)cfg_map_get(config, "zone", &zonelist);
791 for (element = cfg_list_first(zonelist);
793 element = cfg_list_next(element))
795 cfg_obj_t *zconfig = cfg_listelt_value(element);
796 CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
801 * Configure the view's cache. Try to reuse an existing
802 * cache if possible, otherwise create a new cache.
803 * Note that the ADB is not preserved in either case.
805 * XXX Determining when it is safe to reuse a cache is
806 * tricky. When the view's configuration changes, the cached
807 * data may become invalid because it reflects our old
808 * view of the world. As more view attributes become
809 * configurable, we will have to add code here to check
810 * whether they have changed in ways that could
811 * invalidate the cache.
813 result = dns_viewlist_find(&ns_g_server->viewlist,
814 view->name, view->rdclass,
816 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
819 INSIST(pview->cache != NULL);
820 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
821 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3),
822 "reusing existing cache");
823 reused_cache = ISC_TRUE;
824 dns_cache_attach(pview->cache, &cache);
825 dns_view_detach(&pview);
827 CHECK(isc_mem_create(0, 0, &cmctx));
828 CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr,
829 view->rdclass, "rbt", 0, NULL, &cache));
831 dns_view_setcache(view, cache);
834 * cache-file cannot be inherited if views are present, but this
835 * should be caught by the configuration checking stage.
838 result = ns_config_get(maps, "cache-file", &obj);
839 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) {
840 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj)));
842 CHECK(dns_cache_load(cache));
846 result = ns_config_get(maps, "cleaning-interval", &obj);
847 INSIST(result == ISC_R_SUCCESS);
848 dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60);
851 result = ns_config_get(maps, "max-cache-size", &obj);
852 INSIST(result == ISC_R_SUCCESS);
853 if (cfg_obj_isstring(obj)) {
854 str = cfg_obj_asstring(obj);
855 INSIST(strcasecmp(str, "unlimited") == 0);
856 max_cache_size = ISC_UINT32_MAX;
858 isc_resourcevalue_t value;
859 value = cfg_obj_asuint64(obj);
860 if (value > ISC_UINT32_MAX) {
861 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
863 "%" ISC_PRINT_QUADFORMAT "d' is too large",
865 result = ISC_R_RANGE;
868 max_cache_size = (isc_uint32_t)value;
870 dns_cache_setcachesize(cache, max_cache_size);
872 dns_cache_detach(&cache);
878 result = ns_checknames_get(maps, "response", &obj);
879 INSIST(result == ISC_R_SUCCESS);
881 str = cfg_obj_asstring(obj);
882 if (strcasecmp(str, "fail") == 0) {
883 check = DNS_RESOLVER_CHECKNAMES |
884 DNS_RESOLVER_CHECKNAMESFAIL;
885 view->checknames = ISC_TRUE;
886 } else if (strcasecmp(str, "warn") == 0) {
887 check = DNS_RESOLVER_CHECKNAMES;
888 view->checknames = ISC_FALSE;
889 } else if (strcasecmp(str, "ignore") == 0) {
891 view->checknames = ISC_FALSE;
898 * XXXRTH Hardwired number of tasks.
900 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4));
901 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6));
902 if (dispatch4 == NULL && dispatch6 == NULL) {
903 UNEXPECTED_ERROR(__FILE__, __LINE__,
904 "unable to obtain neither an IPv4 nor"
905 " an IPv6 dispatch");
906 result = ISC_R_UNEXPECTED;
909 CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
910 ns_g_socketmgr, ns_g_timermgr,
911 check, ns_g_dispatchmgr,
912 dispatch4, dispatch6));
915 * Set the ADB cache size to 1/8th of the max-cache-size.
918 if (max_cache_size != 0) {
919 max_adb_size = max_cache_size / 8;
920 if (max_adb_size == 0)
921 max_adb_size = 1; /* Force minimum. */
923 dns_adb_setadbsize(view->adb, max_adb_size);
926 * Set resolver's lame-ttl.
929 result = ns_config_get(maps, "lame-ttl", &obj);
930 INSIST(result == ISC_R_SUCCESS);
931 lame_ttl = cfg_obj_asuint32(obj);
934 dns_resolver_setlamettl(view->resolver, lame_ttl);
937 * Set the resolver's EDNS UDP size.
940 result = ns_config_get(maps, "edns-udp-size", &obj);
941 INSIST(result == ISC_R_SUCCESS);
942 udpsize = cfg_obj_asuint32(obj);
947 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize);
950 * Set supported DNSSEC algorithms.
952 dns_resolver_reset_algorithms(view->resolver);
954 (void)ns_config_get(maps, "disable-algorithms", &disabled);
955 if (disabled != NULL) {
956 for (element = cfg_list_first(disabled);
958 element = cfg_list_next(element))
959 CHECK(disable_algorithms(cfg_listelt_value(element),
964 * A global or view "forwarders" option, if present,
965 * creates an entry for "." in the forwarding table.
969 (void)ns_config_get(maps, "forward", &forwardtype);
970 (void)ns_config_get(maps, "forwarders", &forwarders);
971 if (forwarders != NULL)
972 CHECK(configure_forward(config, view, dns_rootname,
973 forwarders, forwardtype));
976 * Dual Stack Servers.
979 (void)ns_config_get(maps, "dual-stack-servers", &alternates);
980 if (alternates != NULL)
981 CHECK(configure_alternates(config, view, alternates));
984 * We have default hints for class IN if we need them.
986 if (view->rdclass == dns_rdataclass_in && view->hints == NULL)
987 dns_view_sethints(view, ns_g_server->in_roothints);
990 * If we still have no hints, this is a non-IN view with no
991 * "hints zone" configured. Issue a warning, except if this
992 * is a root server. Root servers never need to consult
993 * their hints, so it's no point requiring users to configure
996 if (view->hints == NULL) {
997 dns_zone_t *rootzone = NULL;
998 (void)dns_view_findzone(view, dns_rootname, &rootzone);
999 if (rootzone != NULL) {
1000 dns_zone_detach(&rootzone);
1001 need_hints = ISC_FALSE;
1004 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1005 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1006 "no root hints for view '%s'",
1011 * Configure the view's TSIG keys.
1014 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
1015 dns_view_setkeyring(view, ring);
1018 * Configure the view's peer list.
1021 cfg_obj_t *peers = NULL;
1022 cfg_listelt_t *element;
1023 dns_peerlist_t *newpeers = NULL;
1025 (void)ns_config_get(cfgmaps, "server", &peers);
1026 CHECK(dns_peerlist_new(mctx, &newpeers));
1027 for (element = cfg_list_first(peers);
1029 element = cfg_list_next(element))
1031 cfg_obj_t *cpeer = cfg_listelt_value(element);
1034 CHECK(configure_peer(cpeer, mctx, &peer));
1035 dns_peerlist_addpeer(newpeers, peer);
1036 dns_peer_detach(&peer);
1038 dns_peerlist_detach(&view->peers);
1039 view->peers = newpeers; /* Transfer ownership. */
1043 * Configure the views rrset-order.
1046 cfg_obj_t *rrsetorder = NULL;
1047 cfg_listelt_t *element;
1049 (void)ns_config_get(maps, "rrset-order", &rrsetorder);
1050 CHECK(dns_order_create(mctx, &order));
1051 for (element = cfg_list_first(rrsetorder);
1053 element = cfg_list_next(element))
1055 cfg_obj_t *ent = cfg_listelt_value(element);
1057 CHECK(configure_order(order, ent));
1059 if (view->order != NULL)
1060 dns_order_detach(&view->order);
1061 dns_order_attach(order, &view->order);
1062 dns_order_detach(&order);
1065 * Copy the aclenv object.
1067 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv);
1070 * Configure the "match-clients" and "match-destinations" ACL.
1072 CHECK(configure_view_acl(vconfig, config, "match-clients", actx,
1073 ns_g_mctx, &view->matchclients));
1074 CHECK(configure_view_acl(vconfig, config, "match-destinations", actx,
1075 ns_g_mctx, &view->matchdestinations));
1078 * Configure the "match-recursive-only" option.
1081 (void) ns_config_get(maps, "match-recursive-only", &obj);
1082 if (obj != NULL && cfg_obj_asboolean(obj))
1083 view->matchrecursiveonly = ISC_TRUE;
1085 view->matchrecursiveonly = ISC_FALSE;
1088 * Configure other configurable data.
1091 result = ns_config_get(maps, "recursion", &obj);
1092 INSIST(result == ISC_R_SUCCESS);
1093 view->recursion = cfg_obj_asboolean(obj);
1096 result = ns_config_get(maps, "auth-nxdomain", &obj);
1097 INSIST(result == ISC_R_SUCCESS);
1098 view->auth_nxdomain = cfg_obj_asboolean(obj);
1101 result = ns_config_get(maps, "minimal-responses", &obj);
1102 INSIST(result == ISC_R_SUCCESS);
1103 view->minimalresponses = cfg_obj_asboolean(obj);
1106 result = ns_config_get(maps, "transfer-format", &obj);
1107 INSIST(result == ISC_R_SUCCESS);
1108 str = cfg_obj_asstring(obj);
1109 if (strcasecmp(str, "many-answers") == 0)
1110 view->transfer_format = dns_many_answers;
1111 else if (strcasecmp(str, "one-answer") == 0)
1112 view->transfer_format = dns_one_answer;
1117 * Set sources where additional data and CNAME/DNAME
1118 * targets for authoritative answers may be found.
1121 result = ns_config_get(maps, "additional-from-auth", &obj);
1122 INSIST(result == ISC_R_SUCCESS);
1123 view->additionalfromauth = cfg_obj_asboolean(obj);
1124 if (view->recursion && ! view->additionalfromauth) {
1125 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1126 "'additional-from-auth no' is only supported "
1127 "with 'recursion no'");
1128 view->additionalfromauth = ISC_TRUE;
1132 result = ns_config_get(maps, "additional-from-cache", &obj);
1133 INSIST(result == ISC_R_SUCCESS);
1134 view->additionalfromcache = cfg_obj_asboolean(obj);
1135 if (view->recursion && ! view->additionalfromcache) {
1136 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1137 "'additional-from-cache no' is only supported "
1138 "with 'recursion no'");
1139 view->additionalfromcache = ISC_TRUE;
1142 CHECK(configure_view_acl(vconfig, config, "allow-query",
1143 actx, ns_g_mctx, &view->queryacl));
1145 if (strcmp(view->name, "_bind") != 0)
1146 CHECK(configure_view_acl(vconfig, config, "allow-recursion",
1147 actx, ns_g_mctx, &view->recursionacl));
1150 * Warning if both "recursion no;" and allow-recursion are active
1151 * except for "allow-recursion { none; };".
1153 if (!view->recursion && view->recursionacl != NULL &&
1154 (view->recursionacl->length != 1 ||
1155 view->recursionacl->elements[0].type != dns_aclelementtype_any ||
1156 view->recursionacl->elements[0].negative != ISC_TRUE)) {
1157 const char *forview = " for view ";
1158 const char *viewname = view->name;
1160 if (!strcmp(view->name, "_bind") ||
1161 !strcmp(view->name, "_default")) {
1165 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1166 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1167 "both \"recursion no;\" and \"allow-recursion\" "
1168 "active%s%s", forview, viewname);
1171 CHECK(configure_view_acl(vconfig, config, "sortlist",
1172 actx, ns_g_mctx, &view->sortlist));
1175 result = ns_config_get(maps, "request-ixfr", &obj);
1176 INSIST(result == ISC_R_SUCCESS);
1177 view->requestixfr = cfg_obj_asboolean(obj);
1180 result = ns_config_get(maps, "provide-ixfr", &obj);
1181 INSIST(result == ISC_R_SUCCESS);
1182 view->provideixfr = cfg_obj_asboolean(obj);
1185 result = ns_config_get(maps, "dnssec-enable", &obj);
1186 INSIST(result == ISC_R_SUCCESS);
1187 view->enablednssec = cfg_obj_asboolean(obj);
1190 result = ns_config_get(maps, "dnssec-lookaside", &obj);
1191 if (result == ISC_R_SUCCESS) {
1192 for (element = cfg_list_first(obj);
1194 element = cfg_list_next(element))
1200 obj = cfg_listelt_value(element);
1202 dns_fixedname_t fixed;
1206 * When we support multiple dnssec-lookaside
1207 * entries this is how to find the domain to be
1210 dns_fixedname_init(&fixed);
1211 name = dns_fixedname_name(&fixed);
1212 str = cfg_obj_asstring(cfg_tuple_get(obj,
1214 isc_buffer_init(&b, str, strlen(str));
1215 isc_buffer_add(&b, strlen(str));
1216 CHECK(dns_name_fromtext(name, &b, dns_rootname,
1219 str = cfg_obj_asstring(cfg_tuple_get(obj,
1221 isc_buffer_init(&b, str, strlen(str));
1222 isc_buffer_add(&b, strlen(str));
1223 dlv = dns_fixedname_name(&view->dlv_fixed);
1224 CHECK(dns_name_fromtext(dlv, &b, dns_rootname,
1226 view->dlv = dns_fixedname_name(&view->dlv_fixed);
1232 * For now, there is only one kind of trusted keys, the
1235 if (view->enablednssec) {
1236 CHECK(configure_view_dnsseckeys(vconfig, config, mctx,
1238 dns_resolver_resetmustbesecure(view->resolver);
1240 result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
1241 if (result == ISC_R_SUCCESS)
1242 CHECK(mustbesecure(obj, view->resolver));
1246 result = ns_config_get(maps, "max-cache-ttl", &obj);
1247 INSIST(result == ISC_R_SUCCESS);
1248 view->maxcachettl = cfg_obj_asuint32(obj);
1251 result = ns_config_get(maps, "max-ncache-ttl", &obj);
1252 INSIST(result == ISC_R_SUCCESS);
1253 view->maxncachettl = cfg_obj_asuint32(obj);
1254 if (view->maxncachettl > 7 * 24 * 3600)
1255 view->maxncachettl = 7 * 24 * 3600;
1258 result = ns_config_get(maps, "preferred-glue", &obj);
1259 if (result == ISC_R_SUCCESS) {
1260 str = cfg_obj_asstring(obj);
1261 if (strcasecmp(str, "a") == 0)
1262 view->preferred_glue = dns_rdatatype_a;
1263 else if (strcasecmp(str, "aaaa") == 0)
1264 view->preferred_glue = dns_rdatatype_aaaa;
1266 view->preferred_glue = 0;
1268 view->preferred_glue = 0;
1271 result = ns_config_get(maps, "root-delegation-only", &obj);
1272 if (result == ISC_R_SUCCESS) {
1273 dns_view_setrootdelonly(view, ISC_TRUE);
1274 if (!cfg_obj_isvoid(obj)) {
1275 dns_fixedname_t fixed;
1281 dns_fixedname_init(&fixed);
1282 name = dns_fixedname_name(&fixed);
1283 for (element = cfg_list_first(obj);
1285 element = cfg_list_next(element)) {
1286 exclude = cfg_listelt_value(element);
1287 str = cfg_obj_asstring(exclude);
1288 isc_buffer_init(&b, str, strlen(str));
1289 isc_buffer_add(&b, strlen(str));
1290 CHECK(dns_name_fromtext(name, &b, dns_rootname,
1292 CHECK(dns_view_excludedelegationonly(view,
1297 dns_view_setrootdelonly(view, ISC_FALSE);
1299 result = ISC_R_SUCCESS;
1302 if (dispatch4 != NULL)
1303 dns_dispatch_detach(&dispatch4);
1304 if (dispatch6 != NULL)
1305 dns_dispatch_detach(&dispatch6);
1307 dns_order_detach(&order);
1309 isc_mem_detach(&cmctx);
1312 dns_cache_detach(&cache);
1318 configure_hints(dns_view_t *view, const char *filename) {
1319 isc_result_t result;
1323 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db);
1324 if (result == ISC_R_SUCCESS) {
1325 dns_view_sethints(view, db);
1333 configure_alternates(cfg_obj_t *config, dns_view_t *view,
1334 cfg_obj_t *alternates)
1337 cfg_obj_t *addresses;
1338 cfg_listelt_t *element;
1339 isc_result_t result = ISC_R_SUCCESS;
1343 * Determine which port to send requests to.
1345 if (ns_g_lwresdonly && ns_g_port != 0)
1348 CHECKM(ns_config_getport(config, &port), "port");
1350 if (alternates != NULL) {
1351 portobj = cfg_tuple_get(alternates, "port");
1352 if (cfg_obj_isuint32(portobj)) {
1353 isc_uint32_t val = cfg_obj_asuint32(portobj);
1354 if (val > ISC_UINT16_MAX) {
1355 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
1356 "port '%u' out of range", val);
1357 return (ISC_R_RANGE);
1359 port = (in_port_t) val;
1364 if (alternates != NULL)
1365 addresses = cfg_tuple_get(alternates, "addresses");
1367 for (element = cfg_list_first(addresses);
1369 element = cfg_list_next(element))
1371 cfg_obj_t *alternate = cfg_listelt_value(element);
1374 if (!cfg_obj_issockaddr(alternate)) {
1375 dns_fixedname_t fixed;
1377 char *str = cfg_obj_asstring(cfg_tuple_get(alternate,
1379 isc_buffer_t buffer;
1380 in_port_t myport = port;
1382 isc_buffer_init(&buffer, str, strlen(str));
1383 isc_buffer_add(&buffer, strlen(str));
1384 dns_fixedname_init(&fixed);
1385 name = dns_fixedname_name(&fixed);
1386 CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
1389 portobj = cfg_tuple_get(alternate, "port");
1390 if (cfg_obj_isuint32(portobj)) {
1391 isc_uint32_t val = cfg_obj_asuint32(portobj);
1392 if (val > ISC_UINT16_MAX) {
1393 cfg_obj_log(portobj, ns_g_lctx,
1395 "port '%u' out of range",
1397 return (ISC_R_RANGE);
1399 myport = (in_port_t) val;
1401 CHECK(dns_resolver_addalternate(view->resolver, NULL,
1406 sa = *cfg_obj_assockaddr(alternate);
1407 if (isc_sockaddr_getport(&sa) == 0)
1408 isc_sockaddr_setport(&sa, port);
1409 CHECK(dns_resolver_addalternate(view->resolver, &sa,
1418 configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
1419 cfg_obj_t *forwarders, cfg_obj_t *forwardtype)
1422 cfg_obj_t *faddresses;
1423 cfg_listelt_t *element;
1424 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
1425 isc_sockaddrlist_t addresses;
1427 isc_result_t result;
1431 * Determine which port to send forwarded requests to.
1433 if (ns_g_lwresdonly && ns_g_port != 0)
1436 CHECKM(ns_config_getport(config, &port), "port");
1438 if (forwarders != NULL) {
1439 portobj = cfg_tuple_get(forwarders, "port");
1440 if (cfg_obj_isuint32(portobj)) {
1441 isc_uint32_t val = cfg_obj_asuint32(portobj);
1442 if (val > ISC_UINT16_MAX) {
1443 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
1444 "port '%u' out of range", val);
1445 return (ISC_R_RANGE);
1447 port = (in_port_t) val;
1452 if (forwarders != NULL)
1453 faddresses = cfg_tuple_get(forwarders, "addresses");
1455 ISC_LIST_INIT(addresses);
1457 for (element = cfg_list_first(faddresses);
1459 element = cfg_list_next(element))
1461 cfg_obj_t *forwarder = cfg_listelt_value(element);
1462 sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t));
1464 result = ISC_R_NOMEMORY;
1467 *sa = *cfg_obj_assockaddr(forwarder);
1468 if (isc_sockaddr_getport(sa) == 0)
1469 isc_sockaddr_setport(sa, port);
1470 ISC_LINK_INIT(sa, link);
1471 ISC_LIST_APPEND(addresses, sa, link);
1474 if (ISC_LIST_EMPTY(addresses)) {
1475 if (forwardtype != NULL)
1476 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
1477 "no forwarders seen; disabling "
1479 fwdpolicy = dns_fwdpolicy_none;
1481 if (forwardtype == NULL)
1482 fwdpolicy = dns_fwdpolicy_first;
1484 char *forwardstr = cfg_obj_asstring(forwardtype);
1485 if (strcasecmp(forwardstr, "first") == 0)
1486 fwdpolicy = dns_fwdpolicy_first;
1487 else if (strcasecmp(forwardstr, "only") == 0)
1488 fwdpolicy = dns_fwdpolicy_only;
1494 result = dns_fwdtable_add(view->fwdtable, origin, &addresses,
1496 if (result != ISC_R_SUCCESS) {
1497 char namebuf[DNS_NAME_FORMATSIZE];
1498 dns_name_format(origin, namebuf, sizeof(namebuf));
1499 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
1500 "could not set up forwarding for domain '%s': %s",
1501 namebuf, isc_result_totext(result));
1505 result = ISC_R_SUCCESS;
1509 while (!ISC_LIST_EMPTY(addresses)) {
1510 sa = ISC_LIST_HEAD(addresses);
1511 ISC_LIST_UNLINK(addresses, sa, link);
1512 isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t));
1519 * Create a new view and add it to the list.
1521 * If 'vconfig' is NULL, create the default view.
1523 * The view created is attached to '*viewp'.
1526 create_view(cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) {
1527 isc_result_t result;
1528 const char *viewname;
1529 dns_rdataclass_t viewclass;
1530 dns_view_t *view = NULL;
1532 if (vconfig != NULL) {
1533 cfg_obj_t *classobj = NULL;
1535 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
1536 classobj = cfg_tuple_get(vconfig, "class");
1537 result = ns_config_getclass(classobj, dns_rdataclass_in,
1540 viewname = "_default";
1541 viewclass = dns_rdataclass_in;
1543 result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
1544 if (result == ISC_R_SUCCESS)
1545 return (ISC_R_EXISTS);
1546 if (result != ISC_R_NOTFOUND)
1548 INSIST(view == NULL);
1550 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view);
1551 if (result != ISC_R_SUCCESS)
1554 ISC_LIST_APPEND(*viewlist, view, link);
1555 dns_view_attach(view, viewp);
1556 return (ISC_R_SUCCESS);
1560 * Configure or reconfigure a zone.
1563 configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
1564 isc_mem_t *mctx, dns_view_t *view,
1565 ns_aclconfctx_t *aclconf)
1567 dns_view_t *pview = NULL; /* Production view */
1568 dns_zone_t *zone = NULL; /* New or reused zone */
1569 dns_zone_t *dupzone = NULL;
1570 cfg_obj_t *options = NULL;
1571 cfg_obj_t *zoptions = NULL;
1572 cfg_obj_t *typeobj = NULL;
1573 cfg_obj_t *forwarders = NULL;
1574 cfg_obj_t *forwardtype = NULL;
1575 cfg_obj_t *only = NULL;
1576 isc_result_t result;
1577 isc_result_t tresult;
1578 isc_buffer_t buffer;
1579 dns_fixedname_t fixorigin;
1582 dns_rdataclass_t zclass;
1583 const char *ztypestr;
1586 (void)cfg_map_get(config, "options", &options);
1588 zoptions = cfg_tuple_get(zconfig, "options");
1591 * Get the zone origin as a dns_name_t.
1593 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
1594 isc_buffer_init(&buffer, zname, strlen(zname));
1595 isc_buffer_add(&buffer, strlen(zname));
1596 dns_fixedname_init(&fixorigin);
1597 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin),
1598 &buffer, dns_rootname, ISC_FALSE, NULL));
1599 origin = dns_fixedname_name(&fixorigin);
1601 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
1602 view->rdclass, &zclass));
1603 if (zclass != view->rdclass) {
1604 const char *vname = NULL;
1605 if (vconfig != NULL)
1606 vname = cfg_obj_asstring(cfg_tuple_get(vconfig,
1609 vname = "<default view>";
1611 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1612 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
1613 "zone '%s': wrong class for view '%s'",
1615 result = ISC_R_FAILURE;
1619 (void)cfg_map_get(zoptions, "type", &typeobj);
1620 if (typeobj == NULL) {
1621 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
1622 "zone '%s' 'type' not specified", zname);
1623 return (ISC_R_FAILURE);
1625 ztypestr = cfg_obj_asstring(typeobj);
1628 * "hints zones" aren't zones. If we've got one,
1629 * configure it and return.
1631 if (strcasecmp(ztypestr, "hint") == 0) {
1632 cfg_obj_t *fileobj = NULL;
1633 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
1634 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1635 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
1636 "zone '%s': 'file' not specified",
1638 result = ISC_R_FAILURE;
1641 if (dns_name_equal(origin, dns_rootname)) {
1642 char *hintsfile = cfg_obj_asstring(fileobj);
1644 result = configure_hints(view, hintsfile);
1645 if (result != ISC_R_SUCCESS) {
1646 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1647 NS_LOGMODULE_SERVER,
1649 "could not configure root hints "
1650 "from '%s': %s", hintsfile,
1651 isc_result_totext(result));
1655 * Hint zones may also refer to delegation only points.
1658 tresult = cfg_map_get(zoptions, "delegation-only",
1660 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
1661 CHECK(dns_view_adddelegationonly(view, origin));
1663 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1664 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1665 "ignoring non-root hint zone '%s'",
1667 result = ISC_R_SUCCESS;
1669 /* Skip ordinary zone processing. */
1674 * "forward zones" aren't zones either. Translate this syntax into
1675 * the appropriate selective forwarding configuration and return.
1677 if (strcasecmp(ztypestr, "forward") == 0) {
1681 (void)cfg_map_get(zoptions, "forward", &forwardtype);
1682 (void)cfg_map_get(zoptions, "forwarders", &forwarders);
1683 result = configure_forward(config, view, origin, forwarders,
1689 * "delegation-only zones" aren't zones either.
1691 if (strcasecmp(ztypestr, "delegation-only") == 0) {
1692 result = dns_view_adddelegationonly(view, origin);
1697 * Check for duplicates in the new zone table.
1699 result = dns_view_findzone(view, origin, &dupzone);
1700 if (result == ISC_R_SUCCESS) {
1702 * We already have this zone!
1704 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
1705 "zone '%s' already exists", zname);
1706 dns_zone_detach(&dupzone);
1707 result = ISC_R_EXISTS;
1710 INSIST(dupzone == NULL);
1713 * See if we can reuse an existing zone. This is
1714 * only possible if all of these are true:
1715 * - The zone's view exists
1716 * - A zone with the right name exists in the view
1717 * - The zone is compatible with the config
1718 * options (e.g., an existing master zone cannot
1719 * be reused if the options specify a slave zone)
1721 result = dns_viewlist_find(&ns_g_server->viewlist,
1722 view->name, view->rdclass,
1724 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
1727 result = dns_view_findzone(pview, origin, &zone);
1728 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
1731 if (! ns_zone_reusable(zone, zconfig))
1732 dns_zone_detach(&zone);
1737 * We found a reusable zone. Make it use the
1740 dns_zone_setview(zone, view);
1743 * We cannot reuse an existing zone, we have
1744 * to create a new one.
1746 CHECK(dns_zone_create(&zone, mctx));
1747 CHECK(dns_zone_setorigin(zone, origin));
1748 dns_zone_setview(zone, view);
1749 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
1753 * If the zone contains a 'forwarders' statement, configure
1754 * selective forwarding.
1757 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS)
1760 (void)cfg_map_get(zoptions, "forward", &forwardtype);
1761 CHECK(configure_forward(config, view, origin, forwarders,
1766 * Stub and forward zones may also refer to delegation only points.
1769 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS)
1771 if (cfg_obj_asboolean(only))
1772 CHECK(dns_view_adddelegationonly(view, origin));
1776 * Configure the zone.
1778 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone));
1781 * Add the zone to its view in the new view list.
1783 CHECK(dns_view_addzone(view, zone));
1787 dns_zone_detach(&zone);
1789 dns_view_detach(&pview);
1795 * Configure a single server quota.
1798 configure_server_quota(cfg_obj_t **maps, const char *name, isc_quota_t *quota)
1800 cfg_obj_t *obj = NULL;
1801 isc_result_t result;
1803 result = ns_config_get(maps, name, &obj);
1804 INSIST(result == ISC_R_SUCCESS);
1805 isc_quota_max(quota, cfg_obj_asuint32(obj));
1809 * This function is called as soon as the 'directory' statement has been
1810 * parsed. This can be extended to support other options if necessary.
1813 directory_callback(const char *clausename, cfg_obj_t *obj, void *arg) {
1814 isc_result_t result;
1817 REQUIRE(strcasecmp("directory", clausename) == 0);
1825 directory = cfg_obj_asstring(obj);
1827 if (! isc_file_ischdiridempotent(directory))
1828 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1829 "option 'directory' contains relative path '%s'",
1832 result = isc_dir_chdir(directory);
1833 if (result != ISC_R_SUCCESS) {
1834 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
1835 "change directory to '%s' failed: %s",
1836 directory, isc_result_totext(result));
1840 return (ISC_R_SUCCESS);
1844 scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
1845 isc_boolean_t match_mapped = server->aclenv.match_mapped;
1847 ns_interfacemgr_scan(server->interfacemgr, verbose);
1849 * Update the "localhost" and "localnets" ACLs to match the
1850 * current set of network interfaces.
1852 dns_aclenv_copy(&server->aclenv,
1853 ns_interfacemgr_getaclenv(server->interfacemgr));
1855 server->aclenv.match_mapped = match_mapped;
1859 add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr) {
1860 ns_listenelt_t *lelt = NULL;
1861 dns_acl_t *src_acl = NULL;
1862 dns_aclelement_t aelt;
1863 isc_result_t result;
1864 isc_sockaddr_t any_sa6;
1866 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
1868 isc_sockaddr_any6(&any_sa6);
1869 if (!isc_sockaddr_equal(&any_sa6, addr)) {
1870 aelt.type = dns_aclelementtype_ipprefix;
1871 aelt.negative = ISC_FALSE;
1872 aelt.u.ip_prefix.prefixlen = 128;
1873 isc_netaddr_fromin6(&aelt.u.ip_prefix.address,
1874 &addr->type.sin6.sin6_addr);
1876 result = dns_acl_create(mctx, 1, &src_acl);
1877 if (result != ISC_R_SUCCESS)
1879 result = dns_acl_appendelement(src_acl, &aelt);
1880 if (result != ISC_R_SUCCESS)
1883 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
1885 if (result != ISC_R_SUCCESS)
1887 ISC_LIST_APPEND(list->elts, lelt, link);
1890 return (ISC_R_SUCCESS);
1893 INSIST(lelt == NULL);
1894 if (src_acl != NULL)
1895 dns_acl_detach(&src_acl);
1901 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust()
1902 * to update the listening interfaces accordingly.
1903 * We currently only consider IPv6, because this only affects IPv6 wildcard
1907 adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
1908 isc_result_t result;
1909 ns_listenlist_t *list = NULL;
1911 dns_zone_t *zone, *next;
1912 isc_sockaddr_t addr, *addrp;
1914 result = ns_listenlist_create(mctx, &list);
1915 if (result != ISC_R_SUCCESS)
1918 for (view = ISC_LIST_HEAD(server->viewlist);
1920 view = ISC_LIST_NEXT(view, link)) {
1921 dns_dispatch_t *dispatch6;
1923 dispatch6 = dns_resolver_dispatchv6(view->resolver);
1924 if (dispatch6 == NULL)
1926 result = dns_dispatch_getlocaladdress(dispatch6, &addr);
1927 if (result != ISC_R_SUCCESS)
1929 result = add_listenelt(mctx, list, &addr);
1930 if (result != ISC_R_SUCCESS)
1935 for (result = dns_zone_first(server->zonemgr, &zone);
1936 result == ISC_R_SUCCESS;
1937 next = NULL, result = dns_zone_next(zone, &next), zone = next) {
1938 dns_view_t *zoneview;
1941 * At this point the zone list may contain a stale zone
1942 * just removed from the configuration. To see the validity,
1943 * check if the corresponding view is in our current view list.
1944 * There may also be old zones that are still in the process
1945 * of shutting down and have detached from their old view
1946 * (zoneview == NULL).
1948 zoneview = dns_zone_getview(zone);
1949 if (zoneview == NULL)
1951 for (view = ISC_LIST_HEAD(server->viewlist);
1952 view != NULL && view != zoneview;
1953 view = ISC_LIST_NEXT(view, link))
1958 addrp = dns_zone_getnotifysrc6(zone);
1959 result = add_listenelt(mctx, list, addrp);
1960 if (result != ISC_R_SUCCESS)
1963 addrp = dns_zone_getxfrsource6(zone);
1964 result = add_listenelt(mctx, list, addrp);
1965 if (result != ISC_R_SUCCESS)
1969 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE);
1972 ns_listenlist_detach(&list);
1977 * Even when we failed the procedure, most of other interfaces
1978 * should work correctly. We therefore just warn it.
1980 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1981 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1982 "could not adjust the listen-on list; "
1983 "some interfaces may not work");
1988 * This event callback is invoked to do periodic network
1989 * interface scanning.
1992 interface_timer_tick(isc_task_t *task, isc_event_t *event) {
1993 isc_result_t result;
1994 ns_server_t *server = (ns_server_t *) event->ev_arg;
1995 INSIST(task == server->task);
1997 isc_event_free(&event);
1999 * XXX should scan interfaces unlocked and get exclusive access
2000 * only to replace ACLs.
2002 result = isc_task_beginexclusive(server->task);
2003 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2004 scan_interfaces(server, ISC_FALSE);
2005 isc_task_endexclusive(server->task);
2009 heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
2010 ns_server_t *server = (ns_server_t *) event->ev_arg;
2014 isc_event_free(&event);
2015 view = ISC_LIST_HEAD(server->viewlist);
2016 while (view != NULL) {
2017 dns_view_dialup(view);
2018 view = ISC_LIST_NEXT(view, link);
2023 * Replace the current value of '*field', a dynamically allocated
2024 * string or NULL, with a dynamically allocated copy of the
2025 * null-terminated string pointed to by 'value', or NULL.
2028 setstring(ns_server_t *server, char **field, const char *value) {
2031 if (value != NULL) {
2032 copy = isc_mem_strdup(server->mctx, value);
2034 return (ISC_R_NOMEMORY);
2040 isc_mem_free(server->mctx, *field);
2043 return (ISC_R_SUCCESS);
2047 * Replace the current value of '*field', a dynamically allocated
2048 * string or NULL, with another dynamically allocated string
2049 * or NULL if whether 'obj' is a string or void value, respectively.
2052 setoptstring(ns_server_t *server, char **field, cfg_obj_t *obj) {
2053 if (cfg_obj_isvoid(obj))
2054 return (setstring(server, field, NULL));
2056 return (setstring(server, field, cfg_obj_asstring(obj)));
2060 set_limit(cfg_obj_t **maps, const char *configname, const char *description,
2061 isc_resource_t resourceid, isc_resourcevalue_t defaultvalue)
2063 cfg_obj_t *obj = NULL;
2065 isc_resourcevalue_t value;
2066 isc_result_t result;
2068 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS)
2071 if (cfg_obj_isstring(obj)) {
2072 resource = cfg_obj_asstring(obj);
2073 if (strcasecmp(resource, "unlimited") == 0)
2074 value = ISC_RESOURCE_UNLIMITED;
2076 INSIST(strcasecmp(resource, "default") == 0);
2077 value = defaultvalue;
2080 value = cfg_obj_asuint64(obj);
2082 result = isc_resource_setlimit(resourceid, value);
2083 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2084 result == ISC_R_SUCCESS ?
2085 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
2086 "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s",
2087 description, value, isc_result_totext(result));
2090 #define SETLIMIT(cfgvar, resource, description) \
2091 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \
2092 ns_g_init ## resource)
2095 set_limits(cfg_obj_t **maps) {
2096 SETLIMIT("stacksize", stacksize, "stack size");
2097 SETLIMIT("datasize", datasize, "data size");
2098 SETLIMIT("coresize", coresize, "core size");
2099 SETLIMIT("files", openfiles, "open files");
2103 portlist_fromconf(dns_portlist_t *portlist, unsigned int family,
2106 cfg_listelt_t *element;
2107 isc_result_t result = ISC_R_SUCCESS;
2109 for (element = cfg_list_first(ports);
2111 element = cfg_list_next(element)) {
2112 cfg_obj_t *obj = cfg_listelt_value(element);
2113 in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
2115 result = dns_portlist_add(portlist, family, port);
2116 if (result != ISC_R_SUCCESS)
2123 load_configuration(const char *filename, ns_server_t *server,
2124 isc_boolean_t first_time)
2126 isc_result_t result;
2127 cfg_parser_t *parser = NULL;
2132 cfg_obj_t *v4ports, *v6ports;
2134 cfg_obj_t *builtin_views;
2135 cfg_listelt_t *element;
2136 dns_view_t *view = NULL;
2137 dns_view_t *view_next;
2138 dns_viewlist_t viewlist;
2139 dns_viewlist_t tmpviewlist;
2140 ns_aclconfctx_t aclconfctx;
2141 isc_uint32_t interface_interval;
2142 isc_uint32_t heartbeat_interval;
2143 isc_uint32_t udpsize;
2144 in_port_t listen_port;
2147 ns_aclconfctx_init(&aclconfctx);
2148 ISC_LIST_INIT(viewlist);
2150 /* Ensure exclusive access to configuration data. */
2151 result = isc_task_beginexclusive(server->task);
2152 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2155 * Parse the global default pseudo-config file.
2158 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config));
2159 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options",
2165 * Parse the configuration file using the new config code.
2167 result = ISC_R_FAILURE;
2171 * Unless this is lwresd with the -C option, parse the config file.
2173 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) {
2174 isc_log_write(ns_g_lctx,
2175 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2176 ISC_LOG_INFO, "loading configuration from '%s'",
2178 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
2179 cfg_parser_setcallback(parser, directory_callback, NULL);
2180 result = cfg_parse_file(parser, filename, &cfg_type_namedconf,
2185 * If this is lwresd with the -C option, or lwresd with no -C or -c
2186 * option where the above parsing failed, parse resolv.conf.
2188 if (ns_g_lwresdonly &&
2189 (lwresd_g_useresolvconf ||
2190 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND)))
2192 isc_log_write(ns_g_lctx,
2193 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2194 ISC_LOG_INFO, "loading configuration from '%s'",
2195 lwresd_g_resolvconffile);
2197 cfg_parser_destroy(&parser);
2198 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
2199 result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser,
2205 * Check the validity of the configuration.
2207 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx));
2210 * Fill in the maps array, used for resolving defaults.
2214 result = cfg_map_get(config, "options", &options);
2215 if (result == ISC_R_SUCCESS)
2216 maps[i++] = options;
2217 maps[i++] = ns_g_defaults;
2221 * Set process limits, which (usually) needs to be done as root.
2226 * Configure various server options.
2228 configure_server_quota(maps, "transfers-out", &server->xfroutquota);
2229 configure_server_quota(maps, "tcp-clients", &server->tcpquota);
2230 configure_server_quota(maps, "recursive-clients",
2231 &server->recursionquota);
2232 if (server->recursionquota.max > 1000)
2233 isc_quota_soft(&server->recursionquota,
2234 server->recursionquota.max - 100);
2236 isc_quota_soft(&server->recursionquota, 0);
2238 CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
2239 ns_g_mctx, &server->blackholeacl));
2240 if (server->blackholeacl != NULL)
2241 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
2242 server->blackholeacl);
2245 result = ns_config_get(maps, "match-mapped-addresses", &obj);
2246 INSIST(result == ISC_R_SUCCESS);
2247 server->aclenv.match_mapped = cfg_obj_asboolean(obj);
2251 (void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports);
2252 (void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports);
2253 if (v4ports != NULL || v6ports != NULL) {
2254 dns_portlist_t *portlist = NULL;
2255 result = dns_portlist_create(ns_g_mctx, &portlist);
2256 if (result == ISC_R_SUCCESS && v4ports != NULL)
2257 result = portlist_fromconf(portlist, AF_INET, v4ports);
2258 if (result == ISC_R_SUCCESS && v6ports != NULL)
2259 portlist_fromconf(portlist, AF_INET6, v6ports);
2260 if (result == ISC_R_SUCCESS)
2261 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist);
2262 if (portlist != NULL)
2263 dns_portlist_detach(&portlist);
2266 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL);
2269 * Set the EDNS UDP size when we don't match a view.
2272 result = ns_config_get(maps, "edns-udp-size", &obj);
2273 INSIST(result == ISC_R_SUCCESS);
2274 udpsize = cfg_obj_asuint32(obj);
2279 ns_g_udpsize = (isc_uint16_t)udpsize;
2282 * Configure the zone manager.
2285 result = ns_config_get(maps, "transfers-in", &obj);
2286 INSIST(result == ISC_R_SUCCESS);
2287 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
2290 result = ns_config_get(maps, "transfers-per-ns", &obj);
2291 INSIST(result == ISC_R_SUCCESS);
2292 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
2295 result = ns_config_get(maps, "serial-query-rate", &obj);
2296 INSIST(result == ISC_R_SUCCESS);
2297 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj));
2300 * Determine which port to use for listening for incoming connections.
2303 listen_port = ns_g_port;
2305 CHECKM(ns_config_getport(config, &listen_port), "port");
2308 * Find the listen queue depth.
2311 result = ns_config_get(maps, "tcp-listen-queue", &obj);
2312 INSIST(result == ISC_R_SUCCESS);
2313 ns_g_listen = cfg_obj_asuint32(obj);
2314 if (ns_g_listen < 3)
2318 * Configure the interface manager according to the "listen-on"
2322 cfg_obj_t *clistenon = NULL;
2323 ns_listenlist_t *listenon = NULL;
2327 * Even though listen-on is present in the default
2328 * configuration, we can't use it here, since it isn't
2329 * used if we're in lwresd mode. This way is easier.
2331 if (options != NULL)
2332 (void)cfg_map_get(options, "listen-on", &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_TRUE, &listenon));
2346 if (listenon != NULL) {
2347 ns_interfacemgr_setlistenon4(server->interfacemgr,
2349 ns_listenlist_detach(&listenon);
2356 cfg_obj_t *clistenon = NULL;
2357 ns_listenlist_t *listenon = NULL;
2359 if (options != NULL)
2360 (void)cfg_map_get(options, "listen-on-v6", &clistenon);
2361 if (clistenon != NULL) {
2362 result = ns_listenlist_fromconfig(clistenon,
2367 } else if (!ns_g_lwresdonly) {
2369 * Not specified, use default.
2371 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
2372 ISC_FALSE, &listenon));
2374 if (listenon != NULL) {
2375 ns_interfacemgr_setlistenon6(server->interfacemgr,
2377 ns_listenlist_detach(&listenon);
2382 * Rescan the interface list to pick up changes in the
2383 * listen-on option. It's important that we do this before we try
2384 * to configure the query source, since the dispatcher we use might
2385 * be shared with an interface.
2387 scan_interfaces(server, ISC_TRUE);
2390 * Arrange for further interface scanning to occur periodically
2391 * as specified by the "interface-interval" option.
2394 result = ns_config_get(maps, "interface-interval", &obj);
2395 INSIST(result == ISC_R_SUCCESS);
2396 interface_interval = cfg_obj_asuint32(obj) * 60;
2397 if (interface_interval == 0) {
2398 CHECK(isc_timer_reset(server->interface_timer,
2399 isc_timertype_inactive,
2400 NULL, NULL, ISC_TRUE));
2401 } else if (server->interface_interval != interface_interval) {
2402 isc_interval_t interval;
2403 isc_interval_set(&interval, interface_interval, 0);
2404 CHECK(isc_timer_reset(server->interface_timer,
2405 isc_timertype_ticker,
2406 NULL, &interval, ISC_FALSE));
2408 server->interface_interval = interface_interval;
2411 * Configure the dialup heartbeat timer.
2414 result = ns_config_get(maps, "heartbeat-interval", &obj);
2415 INSIST(result == ISC_R_SUCCESS);
2416 heartbeat_interval = cfg_obj_asuint32(obj) * 60;
2417 if (heartbeat_interval == 0) {
2418 CHECK(isc_timer_reset(server->heartbeat_timer,
2419 isc_timertype_inactive,
2420 NULL, NULL, ISC_TRUE));
2421 } else if (server->heartbeat_interval != heartbeat_interval) {
2422 isc_interval_t interval;
2423 isc_interval_set(&interval, heartbeat_interval, 0);
2424 CHECK(isc_timer_reset(server->heartbeat_timer,
2425 isc_timertype_ticker,
2426 NULL, &interval, ISC_FALSE));
2428 server->heartbeat_interval = heartbeat_interval;
2431 * Configure and freeze all explicit views. Explicit
2432 * views that have zones were already created at parsing
2433 * time, but views with no zones must be created here.
2436 (void)cfg_map_get(config, "view", &views);
2437 for (element = cfg_list_first(views);
2439 element = cfg_list_next(element))
2441 cfg_obj_t *vconfig = cfg_listelt_value(element);
2444 CHECK(create_view(vconfig, &viewlist, &view));
2445 INSIST(view != NULL);
2446 CHECK(configure_view(view, config, vconfig,
2447 ns_g_mctx, &aclconfctx, ISC_TRUE));
2448 dns_view_freeze(view);
2449 dns_view_detach(&view);
2453 * Make sure we have a default view if and only if there
2454 * were no explicit views.
2456 if (views == NULL) {
2458 * No explicit views; there ought to be a default view.
2459 * There may already be one created as a side effect
2460 * of zone statements, or we may have to create one.
2461 * In either case, we need to configure and freeze it.
2463 CHECK(create_view(NULL, &viewlist, &view));
2464 CHECK(configure_view(view, config, NULL, ns_g_mctx,
2465 &aclconfctx, ISC_TRUE));
2466 dns_view_freeze(view);
2467 dns_view_detach(&view);
2471 * Create (or recreate) the built-in views. Currently
2472 * there is only one, the _bind view.
2474 builtin_views = NULL;
2475 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
2476 &builtin_views) == ISC_R_SUCCESS);
2477 for (element = cfg_list_first(builtin_views);
2479 element = cfg_list_next(element))
2481 cfg_obj_t *vconfig = cfg_listelt_value(element);
2482 CHECK(create_view(vconfig, &viewlist, &view));
2483 CHECK(configure_view(view, config, vconfig, ns_g_mctx,
2484 &aclconfctx, ISC_FALSE));
2485 dns_view_freeze(view);
2486 dns_view_detach(&view);
2491 * Swap our new view list with the production one.
2493 tmpviewlist = server->viewlist;
2494 server->viewlist = viewlist;
2495 viewlist = tmpviewlist;
2498 * Load the TKEY information from the configuration.
2500 if (options != NULL) {
2501 dns_tkeyctx_t *t = NULL;
2502 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
2504 "configuring TKEY");
2505 if (server->tkeyctx != NULL)
2506 dns_tkeyctx_destroy(&server->tkeyctx);
2507 server->tkeyctx = t;
2511 * Bind the control port(s).
2513 CHECKM(ns_controls_configure(ns_g_server->controls, config,
2515 "binding control channel(s)");
2518 * Bind the lwresd port(s).
2520 CHECKM(ns_lwresd_configure(ns_g_mctx, config),
2521 "binding lightweight resolver ports");
2524 * Open the source of entropy.
2528 result = ns_config_get(maps, "random-device", &obj);
2529 if (result != ISC_R_SUCCESS) {
2530 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2531 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
2532 "no source of entropy found");
2534 const char *randomdev = cfg_obj_asstring(obj);
2535 result = isc_entropy_createfilesource(ns_g_entropy,
2537 if (result != ISC_R_SUCCESS)
2538 isc_log_write(ns_g_lctx,
2539 NS_LOGCATEGORY_GENERAL,
2540 NS_LOGMODULE_SERVER,
2542 "could not open entropy source "
2545 isc_result_totext(result));
2546 #ifdef PATH_RANDOMDEV
2547 if (ns_g_fallbackentropy != NULL) {
2548 if (result != ISC_R_SUCCESS) {
2549 isc_log_write(ns_g_lctx,
2550 NS_LOGCATEGORY_GENERAL,
2551 NS_LOGMODULE_SERVER,
2553 "using pre-chroot entropy source "
2556 isc_entropy_detach(&ns_g_entropy);
2557 isc_entropy_attach(ns_g_fallbackentropy,
2560 isc_entropy_detach(&ns_g_fallbackentropy);
2567 * Relinquish root privileges.
2573 * Configure the logging system.
2575 * Do this after changing UID to make sure that any log
2576 * files specified in named.conf get created by the
2577 * unprivileged user, not root.
2579 if (ns_g_logstderr) {
2580 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2581 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
2582 "ignoring config file logging "
2583 "statement due to -g option");
2585 cfg_obj_t *logobj = NULL;
2586 isc_logconfig_t *logc = NULL;
2588 CHECKM(isc_logconfig_create(ns_g_lctx, &logc),
2589 "creating new logging configuration");
2592 (void)cfg_map_get(config, "logging", &logobj);
2593 if (logobj != NULL) {
2594 CHECKM(ns_log_configure(logc, logobj),
2595 "configuring logging");
2597 CHECKM(ns_log_setdefaultchannels(logc),
2598 "setting up default logging channels");
2599 CHECKM(ns_log_setunmatchedcategory(logc),
2600 "setting up default 'category unmatched'");
2601 CHECKM(ns_log_setdefaultcategory(logc),
2602 "setting up default 'category default'");
2605 result = isc_logconfig_use(ns_g_lctx, logc);
2606 if (result != ISC_R_SUCCESS) {
2607 isc_logconfig_destroy(&logc);
2608 CHECKM(result, "installing logging configuration");
2611 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2612 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
2613 "now using logging configuration from "
2618 * Set the default value of the query logging flag depending
2619 * whether a "queries" category has been defined. This is
2620 * a disgusting hack, but we need to do this for BIND 8
2624 cfg_obj_t *logobj = NULL;
2625 cfg_obj_t *categories = NULL;
2628 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
2629 server->log_queries = cfg_obj_asboolean(obj);
2632 (void)cfg_map_get(config, "logging", &logobj);
2634 (void)cfg_map_get(logobj, "category",
2636 if (categories != NULL) {
2637 cfg_listelt_t *element;
2638 for (element = cfg_list_first(categories);
2640 element = cfg_list_next(element))
2645 obj = cfg_listelt_value(element);
2646 catobj = cfg_tuple_get(obj, "name");
2647 str = cfg_obj_asstring(catobj);
2648 if (strcasecmp(str, "queries") == 0)
2649 server->log_queries = ISC_TRUE;
2656 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)
2657 if (cfg_obj_isvoid(obj))
2658 ns_os_writepidfile(NULL, first_time);
2660 ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
2661 else if (ns_g_lwresdonly)
2662 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
2664 ns_os_writepidfile(ns_g_defaultpidfile, first_time);
2667 if (options != NULL &&
2668 cfg_map_get(options, "memstatistics-file", &obj) == ISC_R_SUCCESS)
2669 ns_main_setmemstats(cfg_obj_asstring(obj));
2671 ns_main_setmemstats(NULL);
2674 result = ns_config_get(maps, "statistics-file", &obj);
2675 INSIST(result == ISC_R_SUCCESS);
2676 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
2680 result = ns_config_get(maps, "dump-file", &obj);
2681 INSIST(result == ISC_R_SUCCESS);
2682 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),
2686 result = ns_config_get(maps, "recursing-file", &obj);
2687 INSIST(result == ISC_R_SUCCESS);
2688 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
2692 result = ns_config_get(maps, "version", &obj);
2693 if (result == ISC_R_SUCCESS) {
2694 CHECKM(setoptstring(server, &server->version, obj), "strdup");
2695 server->version_set = ISC_TRUE;
2697 server->version_set = ISC_FALSE;
2701 result = ns_config_get(maps, "hostname", &obj);
2702 if (result == ISC_R_SUCCESS) {
2703 CHECKM(setoptstring(server, &server->hostname, obj), "strdup");
2704 server->hostname_set = ISC_TRUE;
2706 server->hostname_set = ISC_FALSE;
2710 result = ns_config_get(maps, "server-id", &obj);
2711 server->server_usehostname = ISC_FALSE;
2712 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
2713 server->server_usehostname = ISC_TRUE;
2714 } else if (result == ISC_R_SUCCESS) {
2715 CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
2717 result = setoptstring(server, &server->server_id, NULL);
2718 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2722 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj);
2723 if (result == ISC_R_SUCCESS) {
2724 server->flushonshutdown = cfg_obj_asboolean(obj);
2726 server->flushonshutdown = ISC_FALSE;
2729 result = ISC_R_SUCCESS;
2732 ns_aclconfctx_destroy(&aclconfctx);
2734 if (parser != NULL) {
2736 cfg_obj_destroy(parser, &config);
2737 cfg_parser_destroy(&parser);
2741 dns_view_detach(&view);
2744 * This cleans up either the old production view list
2745 * or our temporary list depending on whether they
2746 * were swapped above or not.
2748 for (view = ISC_LIST_HEAD(viewlist);
2751 view_next = ISC_LIST_NEXT(view, link);
2752 ISC_LIST_UNLINK(viewlist, view, link);
2753 dns_view_detach(&view);
2758 * Adjust the listening interfaces in accordance with the source
2759 * addresses specified in views and zones.
2761 if (isc_net_probeipv6() == ISC_R_SUCCESS)
2762 adjust_interfaces(server, ns_g_mctx);
2764 /* Relinquish exclusive access to configuration data. */
2765 isc_task_endexclusive(server->task);
2767 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2768 ISC_LOG_DEBUG(1), "load_configuration: %s",
2769 isc_result_totext(result));
2775 load_zones(ns_server_t *server, isc_boolean_t stop) {
2776 isc_result_t result;
2779 result = isc_task_beginexclusive(server->task);
2780 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2783 * Load zone data from disk.
2785 for (view = ISC_LIST_HEAD(server->viewlist);
2787 view = ISC_LIST_NEXT(view, link))
2789 CHECK(dns_view_load(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 CHECK(dns_zonemgr_forcemaint(server->zonemgr));
2799 isc_task_endexclusive(server->task);
2804 load_new_zones(ns_server_t *server, isc_boolean_t stop) {
2805 isc_result_t result;
2808 result = isc_task_beginexclusive(server->task);
2809 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2812 * Load zone data from disk.
2814 for (view = ISC_LIST_HEAD(server->viewlist);
2816 view = ISC_LIST_NEXT(view, link))
2818 CHECK(dns_view_loadnew(view, stop));
2821 * Force zone maintenance. Do this after loading
2822 * so that we know when we need to force AXFR of
2823 * slave zones whose master files are missing.
2825 dns_zonemgr_resumexfrs(server->zonemgr);
2827 isc_task_endexclusive(server->task);
2832 run_server(isc_task_t *task, isc_event_t *event) {
2833 isc_result_t result;
2834 ns_server_t *server = (ns_server_t *)event->ev_arg;
2836 INSIST(task == server->task);
2838 isc_event_free(&event);
2840 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy,
2842 "creating dispatch manager");
2844 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
2845 ns_g_socketmgr, ns_g_dispatchmgr,
2846 &server->interfacemgr),
2847 "creating interface manager");
2849 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
2850 NULL, NULL, server->task,
2851 interface_timer_tick,
2852 server, &server->interface_timer),
2853 "creating interface timer");
2855 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
2856 NULL, NULL, server->task,
2857 heartbeat_timer_tick,
2858 server, &server->heartbeat_timer),
2859 "creating heartbeat timer");
2861 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser),
2862 "creating default configuration parser");
2864 if (ns_g_lwresdonly)
2865 CHECKFATAL(load_configuration(lwresd_g_conffile, server,
2867 "loading configuration");
2869 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE),
2870 "loading configuration");
2874 CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones");
2877 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2878 ISC_LOG_NOTICE, "running");
2882 ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) {
2884 REQUIRE(NS_SERVER_VALID(server));
2886 server->flushonshutdown = flush;
2890 shutdown_server(isc_task_t *task, isc_event_t *event) {
2891 isc_result_t result;
2892 dns_view_t *view, *view_next;
2893 ns_server_t *server = (ns_server_t *)event->ev_arg;
2894 isc_boolean_t flush = server->flushonshutdown;
2897 INSIST(task == server->task);
2899 result = isc_task_beginexclusive(server->task);
2900 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2902 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2903 ISC_LOG_INFO, "shutting down%s",
2904 flush ? ": flushing changes" : "");
2906 ns_controls_shutdown(server->controls);
2907 end_reserved_dispatches(server, ISC_TRUE);
2909 cfg_obj_destroy(ns_g_parser, &ns_g_config);
2910 cfg_parser_destroy(&ns_g_parser);
2912 for (view = ISC_LIST_HEAD(server->viewlist);
2915 view_next = ISC_LIST_NEXT(view, link);
2916 ISC_LIST_UNLINK(server->viewlist, view, link);
2918 dns_view_flushanddetach(&view);
2920 dns_view_detach(&view);
2923 isc_timer_detach(&server->interface_timer);
2924 isc_timer_detach(&server->heartbeat_timer);
2926 ns_interfacemgr_shutdown(server->interfacemgr);
2927 ns_interfacemgr_detach(&server->interfacemgr);
2929 dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
2931 dns_zonemgr_shutdown(server->zonemgr);
2933 if (server->blackholeacl != NULL)
2934 dns_acl_detach(&server->blackholeacl);
2936 dns_db_detach(&server->in_roothints);
2938 isc_task_endexclusive(server->task);
2940 isc_task_detach(&server->task);
2942 isc_event_free(&event);
2946 ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
2947 isc_result_t result;
2949 ns_server_t *server = isc_mem_get(mctx, sizeof(*server));
2951 fatal("allocating server object", ISC_R_NOMEMORY);
2953 server->mctx = mctx;
2954 server->task = NULL;
2956 /* Initialize configuration data with default values. */
2958 result = isc_quota_init(&server->xfroutquota, 10);
2959 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2960 result = isc_quota_init(&server->tcpquota, 10);
2961 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2962 result = isc_quota_init(&server->recursionquota, 100);
2963 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2965 result = dns_aclenv_init(mctx, &server->aclenv);
2966 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2968 /* Initialize server data structures. */
2969 server->zonemgr = NULL;
2970 server->interfacemgr = NULL;
2971 ISC_LIST_INIT(server->viewlist);
2972 server->in_roothints = NULL;
2973 server->blackholeacl = NULL;
2975 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
2976 &server->in_roothints),
2977 "setting up root hints");
2979 CHECKFATAL(isc_mutex_init(&server->reload_event_lock),
2980 "initializing reload event lock");
2981 server->reload_event =
2982 isc_event_allocate(ns_g_mctx, server,
2986 sizeof(isc_event_t));
2987 CHECKFATAL(server->reload_event == NULL ?
2988 ISC_R_NOMEMORY : ISC_R_SUCCESS,
2989 "allocating reload event");
2991 CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY),
2992 "initializing DST");
2994 server->tkeyctx = NULL;
2995 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
2997 "creating TKEY context");
3000 * Setup the server task, which is responsible for coordinating
3001 * startup and shutdown of the server.
3003 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),
3004 "creating server task");
3005 isc_task_setname(server->task, "server", server);
3006 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
3007 "isc_task_onshutdown");
3008 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
3011 server->interface_timer = NULL;
3012 server->heartbeat_timer = NULL;
3014 server->interface_interval = 0;
3015 server->heartbeat_interval = 0;
3017 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
3018 ns_g_socketmgr, &server->zonemgr),
3019 "dns_zonemgr_create");
3021 server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
3022 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
3024 server->querystats = NULL;
3026 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
3027 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
3030 server->recfile = isc_mem_strdup(server->mctx, "named.recursing");
3031 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
3034 server->hostname_set = ISC_FALSE;
3035 server->hostname = NULL;
3036 server->version_set = ISC_FALSE;
3037 server->version = NULL;
3038 server->server_usehostname = ISC_FALSE;
3039 server->server_id = NULL;
3041 CHECKFATAL(dns_stats_alloccounters(ns_g_mctx, &server->querystats),
3042 "dns_stats_alloccounters");
3044 server->flushonshutdown = ISC_FALSE;
3045 server->log_queries = ISC_FALSE;
3047 server->controls = NULL;
3048 CHECKFATAL(ns_controls_create(server, &server->controls),
3049 "ns_controls_create");
3050 server->dispatchgen = 0;
3051 ISC_LIST_INIT(server->dispatches);
3053 server->magic = NS_SERVER_MAGIC;
3058 ns_server_destroy(ns_server_t **serverp) {
3059 ns_server_t *server = *serverp;
3060 REQUIRE(NS_SERVER_VALID(server));
3062 ns_controls_destroy(&server->controls);
3064 dns_stats_freecounters(server->mctx, &server->querystats);
3066 isc_mem_free(server->mctx, server->statsfile);
3067 isc_mem_free(server->mctx, server->dumpfile);
3068 isc_mem_free(server->mctx, server->recfile);
3070 if (server->version != NULL)
3071 isc_mem_free(server->mctx, server->version);
3072 if (server->hostname != NULL)
3073 isc_mem_free(server->mctx, server->hostname);
3074 if (server->server_id != NULL)
3075 isc_mem_free(server->mctx, server->server_id);
3077 dns_zonemgr_detach(&server->zonemgr);
3079 if (server->tkeyctx != NULL)
3080 dns_tkeyctx_destroy(&server->tkeyctx);
3084 isc_event_free(&server->reload_event);
3086 INSIST(ISC_LIST_EMPTY(server->viewlist));
3088 dns_aclenv_destroy(&server->aclenv);
3090 isc_quota_destroy(&server->recursionquota);
3091 isc_quota_destroy(&server->tcpquota);
3092 isc_quota_destroy(&server->xfroutquota);
3095 isc_mem_put(server->mctx, server, sizeof(*server));
3100 fatal(const char *msg, isc_result_t result) {
3101 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3102 ISC_LOG_CRITICAL, "%s: %s", msg,
3103 isc_result_totext(result));
3104 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3105 ISC_LOG_CRITICAL, "exiting (due to fatal error)");
3110 start_reserved_dispatches(ns_server_t *server) {
3112 REQUIRE(NS_SERVER_VALID(server));
3114 server->dispatchgen++;
3118 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) {
3119 ns_dispatch_t *dispatch, *nextdispatch;
3121 REQUIRE(NS_SERVER_VALID(server));
3123 for (dispatch = ISC_LIST_HEAD(server->dispatches);
3125 dispatch = nextdispatch) {
3126 nextdispatch = ISC_LIST_NEXT(dispatch, link);
3127 if (!all && server->dispatchgen == dispatch-> dispatchgen)
3129 ISC_LIST_UNLINK(server->dispatches, dispatch, link);
3130 dns_dispatch_detach(&dispatch->dispatch);
3131 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
3136 ns_add_reserved_dispatch(ns_server_t *server, isc_sockaddr_t *addr) {
3137 ns_dispatch_t *dispatch;
3139 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3140 isc_result_t result;
3141 unsigned int attrs, attrmask;
3143 REQUIRE(NS_SERVER_VALID(server));
3145 port = isc_sockaddr_getport(addr);
3146 if (port == 0 || port >= 1024)
3149 for (dispatch = ISC_LIST_HEAD(server->dispatches);
3151 dispatch = ISC_LIST_NEXT(dispatch, link)) {
3152 if (isc_sockaddr_equal(&dispatch->addr, addr))
3155 if (dispatch != NULL) {
3156 dispatch->dispatchgen = server->dispatchgen;
3160 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch));
3161 if (dispatch == NULL) {
3162 result = ISC_R_NOMEMORY;
3166 dispatch->addr = *addr;
3167 dispatch->dispatchgen = server->dispatchgen;
3168 dispatch->dispatch = NULL;
3171 attrs |= DNS_DISPATCHATTR_UDP;
3172 switch (isc_sockaddr_pf(addr)) {
3174 attrs |= DNS_DISPATCHATTR_IPV4;
3177 attrs |= DNS_DISPATCHATTR_IPV6;
3180 result = ISC_R_NOTIMPLEMENTED;
3184 attrmask |= DNS_DISPATCHATTR_UDP;
3185 attrmask |= DNS_DISPATCHATTR_TCP;
3186 attrmask |= DNS_DISPATCHATTR_IPV4;
3187 attrmask |= DNS_DISPATCHATTR_IPV6;
3189 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
3190 ns_g_taskmgr, &dispatch->addr, 4096,
3191 1000, 32768, 16411, 16433,
3192 attrs, attrmask, &dispatch->dispatch);
3193 if (result != ISC_R_SUCCESS)
3196 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
3201 if (dispatch != NULL)
3202 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
3203 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
3204 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3205 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
3206 "unable to create dispatch for reserved port %s: %s",
3207 addrbuf, isc_result_totext(result));
3212 loadconfig(ns_server_t *server) {
3213 isc_result_t result;
3214 start_reserved_dispatches(server);
3215 result = load_configuration(ns_g_lwresdonly ?
3216 lwresd_g_conffile : ns_g_conffile,
3218 if (result == ISC_R_SUCCESS)
3219 end_reserved_dispatches(server, ISC_FALSE);
3221 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3222 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3223 "reloading configuration failed: %s",
3224 isc_result_totext(result));
3229 reload(ns_server_t *server) {
3230 isc_result_t result;
3231 CHECK(loadconfig(server));
3233 result = load_zones(server, ISC_FALSE);
3234 if (result != ISC_R_SUCCESS) {
3235 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3236 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3237 "reloading zones failed: %s",
3238 isc_result_totext(result));
3245 reconfig(ns_server_t *server) {
3246 isc_result_t result;
3247 CHECK(loadconfig(server));
3249 result = load_new_zones(server, ISC_FALSE);
3250 if (result != ISC_R_SUCCESS) {
3251 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3252 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3253 "loading new zones failed: %s",
3254 isc_result_totext(result));
3260 * Handle a reload event (from SIGHUP).
3263 ns_server_reload(isc_task_t *task, isc_event_t *event) {
3264 ns_server_t *server = (ns_server_t *)event->ev_arg;
3266 INSIST(task = server->task);
3269 (void)reload(server);
3271 LOCK(&server->reload_event_lock);
3272 INSIST(server->reload_event == NULL);
3273 server->reload_event = event;
3274 UNLOCK(&server->reload_event_lock);
3278 ns_server_reloadwanted(ns_server_t *server) {
3279 LOCK(&server->reload_event_lock);
3280 if (server->reload_event != NULL)
3281 isc_task_send(server->task, &server->reload_event);
3282 UNLOCK(&server->reload_event_lock);
3286 next_token(char **stringp, const char *delim) {
3290 res = strsep(stringp, delim);
3293 } while (*res == '\0');
3298 * Find the zone specified in the control channel command 'args',
3299 * if any. If a zone is specified, point '*zonep' at it, otherwise
3300 * set '*zonep' to NULL.
3303 zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
3305 const char *zonetxt;
3307 const char *viewtxt = NULL;
3308 dns_fixedname_t name;
3309 isc_result_t result;
3311 dns_view_t *view = NULL;
3312 dns_rdataclass_t rdclass;
3314 REQUIRE(zonep != NULL && *zonep == NULL);
3318 /* Skip the command name. */
3319 ptr = next_token(&input, " \t");
3321 return (ISC_R_UNEXPECTEDEND);
3323 /* Look for the zone name. */
3324 zonetxt = next_token(&input, " \t");
3325 if (zonetxt == NULL)
3326 return (ISC_R_SUCCESS);
3328 /* Look for the optional class name. */
3329 classtxt = next_token(&input, " \t");
3330 if (classtxt != NULL) {
3331 /* Look for the optional view name. */
3332 viewtxt = next_token(&input, " \t");
3335 isc_buffer_init(&buf, zonetxt, strlen(zonetxt));
3336 isc_buffer_add(&buf, strlen(zonetxt));
3337 dns_fixedname_init(&name);
3338 result = dns_name_fromtext(dns_fixedname_name(&name),
3339 &buf, dns_rootname, ISC_FALSE, NULL);
3340 if (result != ISC_R_SUCCESS)
3343 if (classtxt != NULL) {
3346 r.length = strlen(classtxt);
3347 result = dns_rdataclass_fromtext(&rdclass, &r);
3348 if (result != ISC_R_SUCCESS)
3351 rdclass = dns_rdataclass_in;
3354 if (viewtxt == NULL)
3355 viewtxt = "_default";
3356 result = dns_viewlist_find(&server->viewlist, viewtxt,
3358 if (result != ISC_R_SUCCESS)
3361 result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
3363 /* Partial match? */
3364 if (result != ISC_R_SUCCESS && *zonep != NULL)
3365 dns_zone_detach(zonep);
3366 dns_view_detach(&view);
3372 * Act on a "retransfer" command from the command channel.
3375 ns_server_retransfercommand(ns_server_t *server, char *args) {
3376 isc_result_t result;
3377 dns_zone_t *zone = NULL;
3378 dns_zonetype_t type;
3380 result = zone_from_args(server, args, &zone);
3381 if (result != ISC_R_SUCCESS)
3384 return (ISC_R_UNEXPECTEDEND);
3385 type = dns_zone_gettype(zone);
3386 if (type == dns_zone_slave || type == dns_zone_stub)
3387 dns_zone_forcereload(zone);
3389 result = ISC_R_NOTFOUND;
3390 dns_zone_detach(&zone);
3395 * Act on a "reload" command from the command channel.
3398 ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
3399 isc_result_t result;
3400 dns_zone_t *zone = NULL;
3401 dns_zonetype_t type;
3402 const char *msg = NULL;
3404 result = zone_from_args(server, args, &zone);
3405 if (result != ISC_R_SUCCESS)
3408 result = reload(server);
3409 if (result == ISC_R_SUCCESS)
3410 msg = "server reload successful";
3412 type = dns_zone_gettype(zone);
3413 if (type == dns_zone_slave || type == dns_zone_stub) {
3414 dns_zone_refresh(zone);
3415 msg = "zone refresh queued";
3417 result = dns_zone_load(zone);
3418 dns_zone_detach(&zone);
3421 msg = "zone reload successful";
3423 case DNS_R_CONTINUE:
3424 msg = "zone reload queued";
3425 result = ISC_R_SUCCESS;
3427 case DNS_R_UPTODATE:
3428 msg = "zone reload up-to-date";
3429 result = ISC_R_SUCCESS;
3432 /* failure message will be generated by rndc */
3437 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
3438 isc_buffer_putmem(text, (const unsigned char *)msg,
3444 * Act on a "reconfig" command from the command channel.
3447 ns_server_reconfigcommand(ns_server_t *server, char *args) {
3451 return (ISC_R_SUCCESS);
3455 * Act on a "refresh" command from the command channel.
3458 ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
3459 isc_result_t result;
3460 dns_zone_t *zone = NULL;
3461 const unsigned char msg[] = "zone refresh queued";
3463 result = zone_from_args(server, args, &zone);
3464 if (result != ISC_R_SUCCESS)
3467 return (ISC_R_UNEXPECTEDEND);
3469 dns_zone_refresh(zone);
3470 dns_zone_detach(&zone);
3471 if (sizeof(msg) <= isc_buffer_availablelength(text))
3472 isc_buffer_putmem(text, msg, sizeof(msg));
3474 return (ISC_R_SUCCESS);
3478 ns_server_togglequerylog(ns_server_t *server) {
3479 server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE;
3481 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3482 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3483 "query logging is now %s",
3484 server->log_queries ? "on" : "off");
3485 return (ISC_R_SUCCESS);
3489 ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config,
3490 ns_aclconfctx_t *actx,
3491 isc_mem_t *mctx, ns_listenlist_t **target)
3493 isc_result_t result;
3494 cfg_listelt_t *element;
3495 ns_listenlist_t *dlist = NULL;
3497 REQUIRE(target != NULL && *target == NULL);
3499 result = ns_listenlist_create(mctx, &dlist);
3500 if (result != ISC_R_SUCCESS)
3503 for (element = cfg_list_first(listenlist);
3505 element = cfg_list_next(element))
3507 ns_listenelt_t *delt = NULL;
3508 cfg_obj_t *listener = cfg_listelt_value(element);
3509 result = ns_listenelt_fromconfig(listener, config, actx,
3511 if (result != ISC_R_SUCCESS)
3513 ISC_LIST_APPEND(dlist->elts, delt, link);
3516 return (ISC_R_SUCCESS);
3519 ns_listenlist_detach(&dlist);
3524 * Create a listen list from the corresponding configuration
3528 ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config,
3529 ns_aclconfctx_t *actx,
3530 isc_mem_t *mctx, ns_listenelt_t **target)
3532 isc_result_t result;
3535 ns_listenelt_t *delt = NULL;
3536 REQUIRE(target != NULL && *target == NULL);
3538 portobj = cfg_tuple_get(listener, "port");
3539 if (!cfg_obj_isuint32(portobj)) {
3540 if (ns_g_port != 0) {
3543 result = ns_config_getport(config, &port);
3544 if (result != ISC_R_SUCCESS)
3548 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
3549 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
3550 "port value '%u' is out of range",
3551 cfg_obj_asuint32(portobj));
3552 return (ISC_R_RANGE);
3554 port = (in_port_t)cfg_obj_asuint32(portobj);
3557 result = ns_listenelt_create(mctx, port, NULL, &delt);
3558 if (result != ISC_R_SUCCESS)
3561 result = ns_acl_fromconfig(cfg_tuple_get(listener, "acl"),
3562 config, actx, mctx, &delt->acl);
3563 if (result != ISC_R_SUCCESS) {
3564 ns_listenelt_destroy(delt);
3568 return (ISC_R_SUCCESS);
3572 ns_server_dumpstats(ns_server_t *server) {
3573 isc_result_t result;
3574 dns_zone_t *zone, *next;
3580 isc_stdtime_get(&now);
3582 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
3583 "could not open statistics dump file", server->statsfile);
3585 ncounters = DNS_STATS_NCOUNTERS;
3586 fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
3588 for (i = 0; i < ncounters; i++)
3589 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT "u\n",
3590 dns_statscounter_names[i],
3591 server->querystats[i]);
3594 for (result = dns_zone_first(server->zonemgr, &zone);
3595 result == ISC_R_SUCCESS;
3596 next = NULL, result = dns_zone_next(zone, &next), zone = next)
3598 isc_uint64_t *zonestats = dns_zone_getstatscounters(zone);
3599 if (zonestats != NULL) {
3600 char zonename[DNS_NAME_FORMATSIZE];
3604 dns_name_format(dns_zone_getorigin(zone),
3605 zonename, sizeof(zonename));
3606 view = dns_zone_getview(zone);
3607 viewname = view->name;
3608 for (i = 0; i < ncounters; i++) {
3609 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT
3611 dns_statscounter_names[i],
3614 if (strcmp(viewname, "_default") != 0)
3615 fprintf(fp, " %s", viewname);
3620 if (result == ISC_R_NOMORE)
3621 result = ISC_R_SUCCESS;
3624 fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
3628 (void)isc_stdio_close(fp);
3633 add_zone_tolist(dns_zone_t *zone, void *uap) {
3634 struct dumpcontext *dctx = uap;
3635 struct zonelistentry *zle;
3637 zle = isc_mem_get(dctx->mctx, sizeof *zle);
3639 return (ISC_R_NOMEMORY);
3641 dns_zone_attach(zone, &zle->zone);
3642 ISC_LINK_INIT(zle, link);
3643 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
3644 return (ISC_R_SUCCESS);
3648 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
3649 struct viewlistentry *vle;
3650 isc_result_t result = ISC_R_SUCCESS;
3653 * Prevent duplicate views.
3655 for (vle = ISC_LIST_HEAD(dctx->viewlist);
3657 vle = ISC_LIST_NEXT(vle, link))
3658 if (vle->view == view)
3659 return (ISC_R_SUCCESS);
3661 vle = isc_mem_get(dctx->mctx, sizeof *vle);
3663 return (ISC_R_NOMEMORY);
3665 dns_view_attach(view, &vle->view);
3666 ISC_LINK_INIT(vle, link);
3667 ISC_LIST_INIT(vle->zonelist);
3668 ISC_LIST_APPEND(dctx->viewlist, vle, link);
3669 if (dctx->dumpzones)
3670 result = dns_zt_apply(view->zonetable, ISC_TRUE,
3671 add_zone_tolist, dctx);
3676 dumpcontext_destroy(struct dumpcontext *dctx) {
3677 struct viewlistentry *vle;
3678 struct zonelistentry *zle;
3680 vle = ISC_LIST_HEAD(dctx->viewlist);
3681 while (vle != NULL) {
3682 ISC_LIST_UNLINK(dctx->viewlist, vle, link);
3683 zle = ISC_LIST_HEAD(vle->zonelist);
3684 while (zle != NULL) {
3685 ISC_LIST_UNLINK(vle->zonelist, zle, link);
3686 dns_zone_detach(&zle->zone);
3687 isc_mem_put(dctx->mctx, zle, sizeof *zle);
3688 zle = ISC_LIST_HEAD(vle->zonelist);
3690 dns_view_detach(&vle->view);
3691 isc_mem_put(dctx->mctx, vle, sizeof *vle);
3692 vle = ISC_LIST_HEAD(dctx->viewlist);
3694 if (dctx->version != NULL)
3695 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
3696 if (dctx->db != NULL)
3697 dns_db_detach(&dctx->db);
3698 if (dctx->cache != NULL)
3699 dns_db_detach(&dctx->cache);
3700 if (dctx->task != NULL)
3701 isc_task_detach(&dctx->task);
3702 if (dctx->fp != NULL)
3703 (void)isc_stdio_close(dctx->fp);
3704 if (dctx->mdctx != NULL)
3705 dns_dumpctx_detach(&dctx->mdctx);
3706 isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
3710 dumpdone(void *arg, isc_result_t result) {
3711 struct dumpcontext *dctx = arg;
3713 const dns_master_style_t *style;
3715 if (result != ISC_R_SUCCESS)
3717 if (dctx->mdctx != NULL)
3718 dns_dumpctx_detach(&dctx->mdctx);
3719 if (dctx->view == NULL) {
3720 dctx->view = ISC_LIST_HEAD(dctx->viewlist);
3721 if (dctx->view == NULL)
3723 INSIST(dctx->zone == NULL);
3727 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
3729 if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) {
3730 style = &dns_master_style_cache;
3731 /* start cache dump */
3732 if (dctx->view->view->cachedb != NULL)
3733 dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
3734 if (dctx->cache != NULL) {
3736 fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n",
3737 dctx->view->view->name);
3738 result = dns_master_dumptostreaminc(dctx->mctx,
3744 if (result == DNS_R_CONTINUE)
3746 if (result == ISC_R_NOTIMPLEMENTED)
3747 fprintf(dctx->fp, "; %s\n",
3748 dns_result_totext(result));
3749 else if (result != ISC_R_SUCCESS)
3753 if (dctx->cache != NULL) {
3754 dns_adb_dump(dctx->view->view->adb, dctx->fp);
3755 dns_db_detach(&dctx->cache);
3757 if (dctx->dumpzones) {
3758 style = &dns_master_style_full;
3760 if (dctx->version != NULL)
3761 dns_db_closeversion(dctx->db, &dctx->version,
3763 if (dctx->db != NULL)
3764 dns_db_detach(&dctx->db);
3765 if (dctx->zone == NULL)
3766 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
3768 dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
3769 if (dctx->zone != NULL) {
3770 /* start zone dump */
3771 dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
3772 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
3773 result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
3774 if (result != ISC_R_SUCCESS) {
3775 fprintf(dctx->fp, "; %s\n",
3776 dns_result_totext(result));
3779 dns_db_currentversion(dctx->db, &dctx->version);
3780 result = dns_master_dumptostreaminc(dctx->mctx,
3787 if (result == DNS_R_CONTINUE)
3789 if (result == ISC_R_NOTIMPLEMENTED) {
3790 fprintf(dctx->fp, "; %s\n",
3791 dns_result_totext(result));
3792 result = ISC_R_SUCCESS;
3795 if (result != ISC_R_SUCCESS)
3799 if (dctx->view != NULL)
3800 dctx->view = ISC_LIST_NEXT(dctx->view, link);
3801 if (dctx->view != NULL)
3804 fprintf(dctx->fp, "; Dump complete\n");
3805 result = isc_stdio_flush(dctx->fp);
3806 if (result == ISC_R_SUCCESS)
3807 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3808 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3811 if (result != ISC_R_SUCCESS)
3812 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3813 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3814 "dumpdb failed: %s", dns_result_totext(result));
3815 dumpcontext_destroy(dctx);
3819 ns_server_dumpdb(ns_server_t *server, char *args) {
3820 struct dumpcontext *dctx = NULL;
3822 isc_result_t result;
3826 dctx = isc_mem_get(server->mctx, sizeof(*dctx));
3828 return (ISC_R_NOMEMORY);
3830 dctx->mctx = server->mctx;
3831 dctx->dumpcache = ISC_TRUE;
3832 dctx->dumpzones = ISC_FALSE;
3834 ISC_LIST_INIT(dctx->viewlist);
3842 dctx->version = NULL;
3843 isc_task_attach(server->task, &dctx->task);
3845 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
3846 "could not open dump file", server->dumpfile);
3848 /* Skip the command name. */
3849 ptr = next_token(&args, " \t");
3851 return (ISC_R_UNEXPECTEDEND);
3853 sep = (args == NULL) ? "" : ": ";
3854 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3855 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3856 "dumpdb started%s%s", sep, (args != NULL) ? args : "");
3858 ptr = next_token(&args, " \t");
3859 if (ptr != NULL && strcmp(ptr, "-all") == 0) {
3860 dctx->dumpzones = ISC_TRUE;
3861 dctx->dumpcache = ISC_TRUE;
3862 ptr = next_token(&args, " \t");
3863 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
3864 dctx->dumpzones = ISC_FALSE;
3865 dctx->dumpcache = ISC_TRUE;
3866 ptr = next_token(&args, " \t");
3867 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
3868 dctx->dumpzones = ISC_TRUE;
3869 dctx->dumpcache = ISC_FALSE;
3870 ptr = next_token(&args, " \t");
3874 for (view = ISC_LIST_HEAD(server->viewlist);
3876 view = ISC_LIST_NEXT(view, link))
3878 if (ptr != NULL && strcmp(view->name, ptr) != 0)
3880 CHECK(add_view_tolist(dctx, view));
3883 ptr = next_token(&args, " \t");
3887 dumpdone(dctx, ISC_R_SUCCESS);
3888 return (ISC_R_SUCCESS);
3892 dumpcontext_destroy(dctx);
3897 ns_server_dumprecursing(ns_server_t *server) {
3899 isc_result_t result;
3901 CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
3902 "could not open dump file", server->recfile);
3903 fprintf(fp,";\n; Recursing Queries\n;\n");
3904 ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
3905 fprintf(fp, "; Dump complete\n");
3909 result = isc_stdio_close(fp);
3914 ns_server_setdebuglevel(ns_server_t *server, char *args) {
3922 /* Skip the command name. */
3923 ptr = next_token(&args, " \t");
3925 return (ISC_R_UNEXPECTEDEND);
3927 /* Look for the new level name. */
3928 levelstr = next_token(&args, " \t");
3929 if (levelstr == NULL) {
3930 if (ns_g_debuglevel < 99)
3933 newlevel = strtol(levelstr, &endp, 10);
3934 if (*endp != '\0' || newlevel < 0 || newlevel > 99)
3935 return (ISC_R_RANGE);
3936 ns_g_debuglevel = (unsigned int)newlevel;
3938 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
3939 return (ISC_R_SUCCESS);
3943 ns_server_flushcache(ns_server_t *server, char *args) {
3944 char *ptr, *viewname;
3946 isc_boolean_t flushed = ISC_FALSE;
3947 isc_result_t result;
3949 /* Skip the command name. */
3950 ptr = next_token(&args, " \t");
3952 return (ISC_R_UNEXPECTEDEND);
3954 /* Look for the view name. */
3955 viewname = next_token(&args, " \t");
3957 result = isc_task_beginexclusive(server->task);
3958 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3959 for (view = ISC_LIST_HEAD(server->viewlist);
3961 view = ISC_LIST_NEXT(view, link))
3963 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
3965 result = dns_view_flushcache(view);
3966 if (result != ISC_R_SUCCESS)
3971 result = ISC_R_SUCCESS;
3973 result = ISC_R_FAILURE;
3975 isc_task_endexclusive(server->task);
3980 ns_server_flushname(ns_server_t *server, char *args) {
3981 char *ptr, *target, *viewname;
3983 isc_boolean_t flushed = ISC_FALSE;
3984 isc_result_t result;
3986 dns_fixedname_t fixed;
3989 /* Skip the command name. */
3990 ptr = next_token(&args, " \t");
3992 return (ISC_R_UNEXPECTEDEND);
3994 /* Find the domain name to flush. */
3995 target = next_token(&args, " \t");
3997 return (ISC_R_UNEXPECTEDEND);
3999 isc_buffer_init(&b, target, strlen(target));
4000 isc_buffer_add(&b, strlen(target));
4001 dns_fixedname_init(&fixed);
4002 name = dns_fixedname_name(&fixed);
4003 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
4004 if (result != ISC_R_SUCCESS)
4007 /* Look for the view name. */
4008 viewname = next_token(&args, " \t");
4010 result = isc_task_beginexclusive(server->task);
4011 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4013 for (view = ISC_LIST_HEAD(server->viewlist);
4015 view = ISC_LIST_NEXT(view, link))
4017 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
4019 result = dns_view_flushname(view, name);
4020 if (result != ISC_R_SUCCESS)
4021 flushed = ISC_FALSE;
4024 result = ISC_R_SUCCESS;
4026 result = ISC_R_FAILURE;
4027 isc_task_endexclusive(server->task);
4032 ns_server_status(ns_server_t *server, isc_buffer_t *text) {
4033 int zonecount, xferrunning, xferdeferred, soaqueries;
4036 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
4037 xferrunning = dns_zonemgr_getcount(server->zonemgr,
4038 DNS_ZONESTATE_XFERRUNNING);
4039 xferdeferred = dns_zonemgr_getcount(server->zonemgr,
4040 DNS_ZONESTATE_XFERDEFERRED);
4041 soaqueries = dns_zonemgr_getcount(server->zonemgr,
4042 DNS_ZONESTATE_SOAQUERY);
4043 n = snprintf((char *)isc_buffer_used(text),
4044 isc_buffer_availablelength(text),
4045 "number of zones: %u\n"
4047 "xfers running: %u\n"
4048 "xfers deferred: %u\n"
4049 "soa queries in progress: %u\n"
4050 "query logging is %s\n"
4051 "recursive clients: %d/%d\n"
4052 "tcp clients: %d/%d\n"
4053 "server is up and running",
4054 zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
4055 soaqueries, server->log_queries ? "ON" : "OFF",
4056 server->recursionquota.used, server->recursionquota.max,
4057 server->tcpquota.used, server->tcpquota.max);
4058 if (n >= isc_buffer_availablelength(text))
4059 return (ISC_R_NOSPACE);
4060 isc_buffer_add(text, n);
4061 return (ISC_R_SUCCESS);
4065 * Act on a "freeze" or "unfreeze" command from the command channel.
4068 ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) {
4069 isc_result_t result;
4070 dns_zone_t *zone = NULL;
4071 dns_zonetype_t type;
4072 char classstr[DNS_RDATACLASS_FORMATSIZE];
4073 char zonename[DNS_NAME_FORMATSIZE];
4076 const char *vname, *sep;
4077 isc_boolean_t frozen;
4079 result = zone_from_args(server, args, &zone);
4080 if (result != ISC_R_SUCCESS)
4083 return (ISC_R_UNEXPECTEDEND);
4084 type = dns_zone_gettype(zone);
4085 if (type != dns_zone_master) {
4086 dns_zone_detach(&zone);
4087 return (ISC_R_NOTFOUND);
4090 frozen = dns_zone_getupdatedisabled(zone);
4093 result = DNS_R_FROZEN;
4094 if (result == ISC_R_SUCCESS)
4095 result = dns_zone_flush(zone);
4096 if (result == ISC_R_SUCCESS) {
4097 journal = dns_zone_getjournal(zone);
4098 if (journal != NULL)
4099 (void)isc_file_remove(journal);
4103 result = dns_zone_load(zone);
4104 if (result == DNS_R_CONTINUE ||
4105 result == DNS_R_UPTODATE)
4106 result = ISC_R_SUCCESS;
4109 if (result == ISC_R_SUCCESS)
4110 dns_zone_setupdatedisabled(zone, freeze);
4112 view = dns_zone_getview(zone);
4113 if (strcmp(view->name, "_bind") == 0 ||
4114 strcmp(view->name, "_default") == 0)
4122 dns_rdataclass_format(dns_zone_getclass(zone), classstr,
4124 dns_name_format(dns_zone_getorigin(zone),
4125 zonename, sizeof(zonename));
4126 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4127 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4128 "%s zone '%s/%s'%s%s: %s",
4129 freeze ? "freezing" : "unfreezing",
4130 zonename, classstr, sep, vname,
4131 isc_result_totext(result));
4132 dns_zone_detach(&zone);
4138 * This function adds a message for rndc to echo if named
4139 * is managed by smf and is also running chroot.
4142 ns_smf_add_message(isc_buffer_t *text) {
4145 n = snprintf((char *)isc_buffer_used(text),
4146 isc_buffer_availablelength(text),
4147 "use svcadm(1M) to manage named");
4148 if (n >= isc_buffer_availablelength(text))
4149 return (ISC_R_NOSPACE);
4150 isc_buffer_add(text, n);
4151 return (ISC_R_SUCCESS);
4153 #endif /* HAVE_LIBSCF */