2 * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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.
28 #include <isc/base64.h>
30 #include <isc/entropy.h>
33 #include <isc/httpd.h>
35 #include <isc/parseint.h>
36 #include <isc/portset.h>
37 #include <isc/print.h>
38 #include <isc/resource.h>
39 #include <isc/socket.h>
40 #include <isc/stats.h>
41 #include <isc/stdio.h>
42 #include <isc/string.h>
44 #include <isc/timer.h>
48 #include <isccfg/namedconf.h>
50 #include <bind9/check.h>
52 #include <dns/acache.h>
54 #include <dns/cache.h>
56 #include <dns/dispatch.h>
60 #include <dns/forward.h>
61 #include <dns/journal.h>
62 #include <dns/keytable.h>
64 #include <dns/master.h>
65 #include <dns/masterdump.h>
66 #include <dns/order.h>
68 #include <dns/portlist.h>
70 #include <dns/rdataclass.h>
71 #include <dns/rdataset.h>
72 #include <dns/rdatastruct.h>
73 #include <dns/resolver.h>
74 #include <dns/rootns.h>
75 #include <dns/secalg.h>
76 #include <dns/stats.h>
84 #include <dst/result.h>
86 #include <named/client.h>
87 #include <named/config.h>
88 #include <named/control.h>
89 #include <named/interfacemgr.h>
90 #include <named/log.h>
91 #include <named/logconf.h>
92 #include <named/lwresd.h>
93 #include <named/main.h>
95 #include <named/server.h>
96 #include <named/statschannel.h>
97 #include <named/tkeyconf.h>
98 #include <named/tsigconf.h>
99 #include <named/zoneconf.h>
101 #include <named/ns_smf_globals.h>
106 * Check an operation for failure. Assumes that the function
107 * using it has a 'result' variable and a 'cleanup' label.
110 do { result = (op); \
111 if (result != ISC_R_SUCCESS) goto cleanup; \
114 #define CHECKM(op, msg) \
115 do { result = (op); \
116 if (result != ISC_R_SUCCESS) { \
117 isc_log_write(ns_g_lctx, \
118 NS_LOGCATEGORY_GENERAL, \
119 NS_LOGMODULE_SERVER, \
122 isc_result_totext(result)); \
127 #define CHECKMF(op, msg, file) \
128 do { result = (op); \
129 if (result != ISC_R_SUCCESS) { \
130 isc_log_write(ns_g_lctx, \
131 NS_LOGCATEGORY_GENERAL, \
132 NS_LOGMODULE_SERVER, \
134 "%s '%s': %s", msg, file, \
135 isc_result_totext(result)); \
140 #define CHECKFATAL(op, msg) \
141 do { result = (op); \
142 if (result != ISC_R_SUCCESS) \
143 fatal(msg, result); \
148 unsigned int dispatchgen;
149 dns_dispatch_t *dispatch;
150 ISC_LINK(struct ns_dispatch) link;
155 isc_boolean_t dumpcache;
156 isc_boolean_t dumpzones;
158 ISC_LIST(struct viewlistentry) viewlist;
159 struct viewlistentry *view;
160 struct zonelistentry *zone;
161 dns_dumpctx_t *mdctx;
165 dns_dbversion_t *version;
168 struct viewlistentry {
170 ISC_LINK(struct viewlistentry) link;
171 ISC_LIST(struct zonelistentry) zonelist;
174 struct zonelistentry {
176 ISC_LINK(struct zonelistentry) link;
180 * These zones should not leak onto the Internet.
182 static const struct {
184 isc_boolean_t rfc1918;
187 { "10.IN-ADDR.ARPA", ISC_TRUE },
188 { "16.172.IN-ADDR.ARPA", ISC_TRUE },
189 { "17.172.IN-ADDR.ARPA", ISC_TRUE },
190 { "18.172.IN-ADDR.ARPA", ISC_TRUE },
191 { "19.172.IN-ADDR.ARPA", ISC_TRUE },
192 { "20.172.IN-ADDR.ARPA", ISC_TRUE },
193 { "21.172.IN-ADDR.ARPA", ISC_TRUE },
194 { "22.172.IN-ADDR.ARPA", ISC_TRUE },
195 { "23.172.IN-ADDR.ARPA", ISC_TRUE },
196 { "24.172.IN-ADDR.ARPA", ISC_TRUE },
197 { "25.172.IN-ADDR.ARPA", ISC_TRUE },
198 { "26.172.IN-ADDR.ARPA", ISC_TRUE },
199 { "27.172.IN-ADDR.ARPA", ISC_TRUE },
200 { "28.172.IN-ADDR.ARPA", ISC_TRUE },
201 { "29.172.IN-ADDR.ARPA", ISC_TRUE },
202 { "30.172.IN-ADDR.ARPA", ISC_TRUE },
203 { "31.172.IN-ADDR.ARPA", ISC_TRUE },
204 { "168.192.IN-ADDR.ARPA", ISC_TRUE },
206 /* RFC 5735 and RFC 5737 */
207 { "0.IN-ADDR.ARPA", ISC_FALSE }, /* THIS NETWORK */
208 { "127.IN-ADDR.ARPA", ISC_FALSE }, /* LOOPBACK */
209 { "254.169.IN-ADDR.ARPA", ISC_FALSE }, /* LINK LOCAL */
210 { "2.0.192.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET */
211 { "100.51.198.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET 2 */
212 { "113.0.203.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET 3 */
213 { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE }, /* BROADCAST */
215 /* Local IPv6 Unicast Addresses */
216 { "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
217 { "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
218 /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */
219 { "D.F.IP6.ARPA", ISC_FALSE },
220 { "8.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
221 { "9.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
222 { "A.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
223 { "B.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
225 /* Example Prefix, RFC 3849. */
226 { "8.B.D.0.1.0.0.2.IP6.ARPA", ISC_FALSE },
231 ISC_PLATFORM_NORETURN_POST static void
232 fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST;
235 ns_server_reload(isc_task_t *task, isc_event_t *event);
238 ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
239 cfg_aclconfctx_t *actx,
240 isc_mem_t *mctx, ns_listenelt_t **target);
242 ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
243 cfg_aclconfctx_t *actx,
244 isc_mem_t *mctx, ns_listenlist_t **target);
247 configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
248 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype);
251 configure_alternates(const cfg_obj_t *config, dns_view_t *view,
252 const cfg_obj_t *alternates);
255 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
256 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
257 cfg_aclconfctx_t *aclconf);
260 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
263 * Configure a single view ACL at '*aclp'. Get its configuration from
264 * 'vconfig' (for per-view configuration) and maybe from 'config'
267 configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
268 const char *aclname, cfg_aclconfctx_t *actx,
269 isc_mem_t *mctx, dns_acl_t **aclp)
272 const cfg_obj_t *maps[3];
273 const cfg_obj_t *aclobj = NULL;
277 dns_acl_detach(aclp);
279 maps[i++] = cfg_tuple_get(vconfig, "options");
280 if (config != NULL) {
281 const cfg_obj_t *options = NULL;
282 (void)cfg_map_get(config, "options", &options);
288 (void)ns_config_get(maps, aclname, &aclobj);
291 * No value available. *aclp == NULL.
293 return (ISC_R_SUCCESS);
295 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
296 actx, mctx, 0, aclp);
303 * Configure a sortlist at '*aclp'. Essentially the same as
304 * configure_view_acl() except it calls cfg_acl_fromconfig with a
305 * nest_level value of 2.
308 configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
309 cfg_aclconfctx_t *actx, isc_mem_t *mctx,
313 const cfg_obj_t *maps[3];
314 const cfg_obj_t *aclobj = NULL;
318 dns_acl_detach(aclp);
320 maps[i++] = cfg_tuple_get(vconfig, "options");
321 if (config != NULL) {
322 const cfg_obj_t *options = NULL;
323 (void)cfg_map_get(config, "options", &options);
329 (void)ns_config_get(maps, "sortlist", &aclobj);
331 return (ISC_R_SUCCESS);
334 * Use a nest level of 3 for the "top level" of the sortlist;
335 * this means each entry in the top three levels will be stored
336 * as lists of separate, nested ACLs, rather than merged together
337 * into IP tables as is usually done with ACLs.
339 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
340 actx, mctx, 3, aclp);
346 configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
347 dns_keytable_t *keytable, isc_mem_t *mctx)
349 dns_rdataclass_t viewclass;
350 dns_rdata_dnskey_t keystruct;
351 isc_uint32_t flags, proto, alg;
352 const char *keystr, *keynamestr;
353 unsigned char keydata[4096];
354 isc_buffer_t keydatabuf;
355 unsigned char rrdata[4096];
356 isc_buffer_t rrdatabuf;
358 dns_fixedname_t fkeyname;
360 isc_buffer_t namebuf;
362 dst_key_t *dstkey = NULL;
364 flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
365 proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
366 alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
367 keyname = dns_fixedname_name(&fkeyname);
368 keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
371 viewclass = dns_rdataclass_in;
373 const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
374 CHECK(ns_config_getclass(classobj, dns_rdataclass_in,
377 keystruct.common.rdclass = viewclass;
378 keystruct.common.rdtype = dns_rdatatype_dnskey;
380 * The key data in keystruct is not dynamically allocated.
382 keystruct.mctx = NULL;
384 ISC_LINK_INIT(&keystruct.common, link);
387 CHECKM(ISC_R_RANGE, "key flags");
389 CHECKM(ISC_R_RANGE, "key protocol");
391 CHECKM(ISC_R_RANGE, "key algorithm");
392 keystruct.flags = (isc_uint16_t)flags;
393 keystruct.protocol = (isc_uint8_t)proto;
394 keystruct.algorithm = (isc_uint8_t)alg;
396 isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
397 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
399 keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
400 CHECK(isc_base64_decodestring(keystr, &keydatabuf));
401 isc_buffer_usedregion(&keydatabuf, &r);
402 keystruct.datalen = r.length;
403 keystruct.data = r.base;
405 if ((keystruct.algorithm == DST_ALG_RSASHA1 ||
406 keystruct.algorithm == DST_ALG_RSAMD5) &&
407 r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
408 cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
409 "trusted key '%s' has a weak exponent",
412 CHECK(dns_rdata_fromstruct(NULL,
413 keystruct.common.rdclass,
414 keystruct.common.rdtype,
415 &keystruct, &rrdatabuf));
416 dns_fixedname_init(&fkeyname);
417 isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr));
418 isc_buffer_add(&namebuf, strlen(keynamestr));
419 CHECK(dns_name_fromtext(keyname, &namebuf,
420 dns_rootname, ISC_FALSE,
422 CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
425 CHECK(dns_keytable_add(keytable, &dstkey));
426 INSIST(dstkey == NULL);
427 return (ISC_R_SUCCESS);
430 if (result == DST_R_NOCRYPTO) {
431 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
432 "ignoring trusted key for '%s': no crypto support",
434 result = ISC_R_SUCCESS;
436 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
437 "configuring trusted key for '%s': %s",
438 keynamestr, isc_result_totext(result));
439 result = ISC_R_FAILURE;
443 dst_key_free(&dstkey);
449 * Configure DNSSEC keys for a view. Currently used only for
450 * the security roots.
452 * The per-view configuration values and the server-global defaults are read
453 * from 'vconfig' and 'config'. The variable to be configured is '*target'.
456 configure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config,
457 isc_mem_t *mctx, dns_keytable_t **target)
460 const cfg_obj_t *keys = NULL;
461 const cfg_obj_t *voptions = NULL;
462 const cfg_listelt_t *element, *element2;
463 const cfg_obj_t *keylist;
464 const cfg_obj_t *key;
465 dns_keytable_t *keytable = NULL;
467 CHECK(dns_keytable_create(mctx, &keytable));
470 voptions = cfg_tuple_get(vconfig, "options");
473 if (voptions != NULL)
474 (void)cfg_map_get(voptions, "trusted-keys", &keys);
476 (void)cfg_map_get(config, "trusted-keys", &keys);
478 for (element = cfg_list_first(keys);
480 element = cfg_list_next(element))
482 keylist = cfg_listelt_value(element);
483 for (element2 = cfg_list_first(keylist);
485 element2 = cfg_list_next(element2))
487 key = cfg_listelt_value(element2);
488 CHECK(configure_view_dnsseckey(vconfig, key,
493 dns_keytable_detach(target);
494 *target = keytable; /* Transfer ownership. */
496 result = ISC_R_SUCCESS;
503 mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver)
505 const cfg_listelt_t *element;
506 const cfg_obj_t *obj;
508 dns_fixedname_t fixed;
514 dns_fixedname_init(&fixed);
515 name = dns_fixedname_name(&fixed);
516 for (element = cfg_list_first(mbs);
518 element = cfg_list_next(element))
520 obj = cfg_listelt_value(element);
521 str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
522 isc_buffer_init(&b, str, strlen(str));
523 isc_buffer_add(&b, strlen(str));
524 CHECK(dns_name_fromtext(name, &b, dns_rootname,
526 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
527 CHECK(dns_resolver_setmustbesecure(resolver, name, value));
530 result = ISC_R_SUCCESS;
537 * Get a dispatch appropriate for the resolver of a given view.
540 get_view_querysource_dispatch(const cfg_obj_t **maps,
541 int af, dns_dispatch_t **dispatchp,
542 isc_boolean_t is_firstview)
544 isc_result_t result = ISC_R_FAILURE;
545 dns_dispatch_t *disp;
547 unsigned int attrs, attrmask;
548 const cfg_obj_t *obj = NULL;
549 unsigned int maxdispatchbuffers;
553 result = ns_config_get(maps, "query-source", &obj);
554 INSIST(result == ISC_R_SUCCESS);
557 result = ns_config_get(maps, "query-source-v6", &obj);
558 INSIST(result == ISC_R_SUCCESS);
564 sa = *(cfg_obj_assockaddr(obj));
565 INSIST(isc_sockaddr_pf(&sa) == af);
568 * If we don't support this address family, we're done!
572 result = isc_net_probeipv4();
575 result = isc_net_probeipv6();
580 if (result != ISC_R_SUCCESS)
581 return (ISC_R_SUCCESS);
584 * Try to find a dispatcher that we can share.
587 attrs |= DNS_DISPATCHATTR_UDP;
590 attrs |= DNS_DISPATCHATTR_IPV4;
593 attrs |= DNS_DISPATCHATTR_IPV6;
596 if (isc_sockaddr_getport(&sa) == 0) {
597 attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
598 maxdispatchbuffers = 4096;
602 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
603 "using specific query-source port "
604 "suppresses port randomization and can be "
607 maxdispatchbuffers = 1000;
611 attrmask |= DNS_DISPATCHATTR_UDP;
612 attrmask |= DNS_DISPATCHATTR_TCP;
613 attrmask |= DNS_DISPATCHATTR_IPV4;
614 attrmask |= DNS_DISPATCHATTR_IPV6;
617 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
618 ns_g_taskmgr, &sa, 4096,
619 maxdispatchbuffers, 32768, 16411, 16433,
620 attrs, attrmask, &disp);
621 if (result != ISC_R_SUCCESS) {
623 char buf[ISC_SOCKADDR_FORMATSIZE];
627 isc_sockaddr_any(&any);
630 isc_sockaddr_any6(&any);
633 if (isc_sockaddr_equal(&sa, &any))
634 return (ISC_R_SUCCESS);
635 isc_sockaddr_format(&sa, buf, sizeof(buf));
636 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
637 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
638 "could not get query source dispatcher (%s)",
645 return (ISC_R_SUCCESS);
649 configure_order(dns_order_t *order, const cfg_obj_t *ent) {
650 dns_rdataclass_t rdclass;
651 dns_rdatatype_t rdtype;
652 const cfg_obj_t *obj;
653 dns_fixedname_t fixed;
654 unsigned int mode = 0;
658 isc_boolean_t addroot;
660 result = ns_config_getclass(cfg_tuple_get(ent, "class"),
661 dns_rdataclass_any, &rdclass);
662 if (result != ISC_R_SUCCESS)
665 result = ns_config_gettype(cfg_tuple_get(ent, "type"),
666 dns_rdatatype_any, &rdtype);
667 if (result != ISC_R_SUCCESS)
670 obj = cfg_tuple_get(ent, "name");
671 if (cfg_obj_isstring(obj))
672 str = cfg_obj_asstring(obj);
675 addroot = ISC_TF(strcmp(str, "*") == 0);
676 isc_buffer_init(&b, str, strlen(str));
677 isc_buffer_add(&b, strlen(str));
678 dns_fixedname_init(&fixed);
679 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
680 dns_rootname, ISC_FALSE, NULL);
681 if (result != ISC_R_SUCCESS)
684 obj = cfg_tuple_get(ent, "ordering");
685 INSIST(cfg_obj_isstring(obj));
686 str = cfg_obj_asstring(obj);
687 if (!strcasecmp(str, "fixed"))
688 mode = DNS_RDATASETATTR_FIXEDORDER;
689 else if (!strcasecmp(str, "random"))
690 mode = DNS_RDATASETATTR_RANDOMIZE;
691 else if (!strcasecmp(str, "cyclic"))
697 * "*" should match everything including the root (BIND 8 compat).
698 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a
699 * explicit entry for "." when the name is "*".
702 result = dns_order_add(order, dns_rootname,
703 rdtype, rdclass, mode);
704 if (result != ISC_R_SUCCESS)
708 return (dns_order_add(order, dns_fixedname_name(&fixed),
709 rdtype, rdclass, mode));
713 configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
716 const cfg_obj_t *obj;
719 unsigned int prefixlen;
721 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen);
724 result = dns_peer_newprefix(mctx, &na, prefixlen, &peer);
725 if (result != ISC_R_SUCCESS)
729 (void)cfg_map_get(cpeer, "bogus", &obj);
731 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
734 (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
736 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
739 (void)cfg_map_get(cpeer, "request-ixfr", &obj);
741 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
744 (void)cfg_map_get(cpeer, "request-nsid", &obj);
746 CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
749 (void)cfg_map_get(cpeer, "edns", &obj);
751 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
754 (void)cfg_map_get(cpeer, "edns-udp-size", &obj);
756 isc_uint32_t udpsize = cfg_obj_asuint32(obj);
761 CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize));
765 (void)cfg_map_get(cpeer, "max-udp-size", &obj);
767 isc_uint32_t udpsize = cfg_obj_asuint32(obj);
772 CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize));
776 (void)cfg_map_get(cpeer, "transfers", &obj);
778 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
781 (void)cfg_map_get(cpeer, "transfer-format", &obj);
783 str = cfg_obj_asstring(obj);
784 if (strcasecmp(str, "many-answers") == 0)
785 CHECK(dns_peer_settransferformat(peer,
787 else if (strcasecmp(str, "one-answer") == 0)
788 CHECK(dns_peer_settransferformat(peer,
795 (void)cfg_map_get(cpeer, "keys", &obj);
797 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
798 if (result != ISC_R_SUCCESS)
803 if (na.family == AF_INET)
804 (void)cfg_map_get(cpeer, "transfer-source", &obj);
806 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
808 result = dns_peer_settransfersource(peer,
809 cfg_obj_assockaddr(obj));
810 if (result != ISC_R_SUCCESS)
812 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
816 if (na.family == AF_INET)
817 (void)cfg_map_get(cpeer, "notify-source", &obj);
819 (void)cfg_map_get(cpeer, "notify-source-v6", &obj);
821 result = dns_peer_setnotifysource(peer,
822 cfg_obj_assockaddr(obj));
823 if (result != ISC_R_SUCCESS)
825 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
829 if (na.family == AF_INET)
830 (void)cfg_map_get(cpeer, "query-source", &obj);
832 (void)cfg_map_get(cpeer, "query-source-v6", &obj);
834 result = dns_peer_setquerysource(peer,
835 cfg_obj_assockaddr(obj));
836 if (result != ISC_R_SUCCESS)
838 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
842 return (ISC_R_SUCCESS);
845 dns_peer_detach(&peer);
850 disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
852 const cfg_obj_t *algorithms;
853 const cfg_listelt_t *element;
855 dns_fixedname_t fixed;
859 dns_fixedname_init(&fixed);
860 name = dns_fixedname_name(&fixed);
861 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
862 isc_buffer_init(&b, str, strlen(str));
863 isc_buffer_add(&b, strlen(str));
864 CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL));
866 algorithms = cfg_tuple_get(disabled, "algorithms");
867 for (element = cfg_list_first(algorithms);
869 element = cfg_list_next(element))
874 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
875 r.length = strlen(r.base);
877 result = dns_secalg_fromtext(&alg, &r);
878 if (result != ISC_R_SUCCESS) {
880 result = isc_parse_uint8(&ui, r.base, 10);
883 if (result != ISC_R_SUCCESS) {
884 cfg_obj_log(cfg_listelt_value(element),
885 ns_g_lctx, ISC_LOG_ERROR,
886 "invalid algorithm");
889 CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
896 on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) {
897 const cfg_listelt_t *element;
898 dns_fixedname_t fixed;
901 const cfg_obj_t *value;
905 dns_fixedname_init(&fixed);
906 name = dns_fixedname_name(&fixed);
908 for (element = cfg_list_first(disablelist);
910 element = cfg_list_next(element))
912 value = cfg_listelt_value(element);
913 str = cfg_obj_asstring(value);
914 isc_buffer_init(&b, str, strlen(str));
915 isc_buffer_add(&b, strlen(str));
916 result = dns_name_fromtext(name, &b, dns_rootname,
918 RUNTIME_CHECK(result == ISC_R_SUCCESS);
919 if (dns_name_equal(name, zonename))
926 check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv,
933 result = dns_zone_getdbtype(*zonep, &argv, mctx);
934 if (result != ISC_R_SUCCESS) {
935 dns_zone_detach(zonep);
940 * Check that all the arguments match.
942 for (i = 0; i < dbtypec; i++)
943 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) {
944 dns_zone_detach(zonep);
949 * Check that there are not extra arguments.
951 if (i == dbtypec && argv[i] != NULL)
952 dns_zone_detach(zonep);
953 isc_mem_free(mctx, argv);
957 setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) {
959 isc_stats_t *zoneqrystats;
963 result = isc_stats_create(mctx, &zoneqrystats,
964 dns_nsstatscounter_max);
965 if (result != ISC_R_SUCCESS)
968 dns_zone_setrequeststats(zone, zoneqrystats);
969 if (zoneqrystats != NULL)
970 isc_stats_detach(&zoneqrystats);
972 return (ISC_R_SUCCESS);
976 cache_reusable(dns_view_t *originview, dns_view_t *view,
977 isc_boolean_t new_zero_no_soattl)
979 if (originview->checknames != view->checknames ||
980 dns_resolver_getzeronosoattl(originview->resolver) !=
981 new_zero_no_soattl ||
982 originview->acceptexpired != view->acceptexpired ||
983 originview->enablevalidation != view->enablevalidation ||
984 originview->maxcachettl != view->maxcachettl ||
985 originview->maxncachettl != view->maxncachettl) {
993 * Configure 'view' according to 'vconfig', taking defaults from 'config'
994 * where values are missing in 'vconfig'.
996 * When configuring the default view, 'vconfig' will be NULL and the
997 * global defaults in 'config' used exclusively.
1000 configure_view(dns_view_t *view, const cfg_obj_t *config,
1001 const cfg_obj_t *vconfig, isc_mem_t *mctx,
1002 cfg_aclconfctx_t *actx, isc_boolean_t need_hints)
1004 const cfg_obj_t *maps[4];
1005 const cfg_obj_t *cfgmaps[3];
1006 const cfg_obj_t *options = NULL;
1007 const cfg_obj_t *voptions = NULL;
1008 const cfg_obj_t *forwardtype;
1009 const cfg_obj_t *forwarders;
1010 const cfg_obj_t *alternates;
1011 const cfg_obj_t *zonelist;
1013 const cfg_obj_t *dlz;
1014 unsigned int dlzargc;
1017 const cfg_obj_t *disabled;
1018 const cfg_obj_t *obj;
1019 const cfg_listelt_t *element;
1021 dns_cache_t *cache = NULL;
1022 isc_result_t result;
1023 isc_uint32_t max_adb_size;
1024 isc_uint32_t max_cache_size;
1025 isc_uint32_t max_acache_size;
1026 isc_uint32_t lame_ttl;
1027 dns_tsig_keyring_t *ring = NULL;
1028 dns_view_t *pview = NULL; /* Production view */
1029 isc_mem_t *cmctx = NULL, *hmctx = NULL;
1030 dns_dispatch_t *dispatch4 = NULL;
1031 dns_dispatch_t *dispatch6 = NULL;
1032 isc_boolean_t reused_cache = ISC_FALSE;
1035 dns_order_t *order = NULL;
1036 isc_uint32_t udpsize;
1037 unsigned int resopts = 0;
1038 dns_zone_t *zone = NULL;
1039 isc_uint32_t max_clients_per_query;
1040 const char *sep = ": view ";
1041 const char *viewname = view->name;
1042 const char *forview = " for view ";
1043 isc_boolean_t rfc1918;
1044 isc_boolean_t empty_zones_enable;
1045 const cfg_obj_t *disablelist = NULL;
1046 isc_stats_t *resstats = NULL;
1047 dns_stats_t *resquerystats = NULL;
1048 isc_boolean_t zero_no_soattl;
1050 REQUIRE(DNS_VIEW_VALID(view));
1053 (void)cfg_map_get(config, "options", &options);
1056 if (vconfig != NULL) {
1057 voptions = cfg_tuple_get(vconfig, "options");
1058 maps[i++] = voptions;
1060 if (options != NULL)
1061 maps[i++] = options;
1062 maps[i++] = ns_g_defaults;
1066 if (voptions != NULL)
1067 cfgmaps[i++] = voptions;
1069 cfgmaps[i++] = config;
1072 if (!strcmp(viewname, "_default")) {
1080 * Set the view's port number for outgoing queries.
1082 CHECKM(ns_config_getport(config, &port), "port");
1083 dns_view_setdstport(view, port);
1086 * Create additional cache for this view and zones under the view
1087 * if explicitly enabled.
1088 * XXX950 default to on.
1091 (void)ns_config_get(maps, "acache-enable", &obj);
1092 if (obj != NULL && cfg_obj_asboolean(obj)) {
1094 CHECK(isc_mem_create(0, 0, &cmctx));
1095 CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr,
1097 isc_mem_setname(cmctx, "acache", NULL);
1098 isc_mem_detach(&cmctx);
1100 if (view->acache != NULL) {
1102 result = ns_config_get(maps, "acache-cleaning-interval", &obj);
1103 INSIST(result == ISC_R_SUCCESS);
1104 dns_acache_setcleaninginterval(view->acache,
1105 cfg_obj_asuint32(obj) * 60);
1108 result = ns_config_get(maps, "max-acache-size", &obj);
1109 INSIST(result == ISC_R_SUCCESS);
1110 if (cfg_obj_isstring(obj)) {
1111 str = cfg_obj_asstring(obj);
1112 INSIST(strcasecmp(str, "unlimited") == 0);
1113 max_acache_size = ISC_UINT32_MAX;
1115 isc_resourcevalue_t value;
1117 value = cfg_obj_asuint64(obj);
1118 if (value > ISC_UINT32_MAX) {
1119 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
1121 "%" ISC_PRINT_QUADFORMAT
1124 result = ISC_R_RANGE;
1127 max_acache_size = (isc_uint32_t)value;
1129 dns_acache_setcachesize(view->acache, max_acache_size);
1132 CHECK(configure_view_acl(vconfig, config, "allow-query", actx,
1133 ns_g_mctx, &view->queryacl));
1135 if (view->queryacl == NULL) {
1136 CHECK(configure_view_acl(NULL, ns_g_config, "allow-query", actx,
1137 ns_g_mctx, &view->queryacl));
1141 * Configure the zones.
1144 if (voptions != NULL)
1145 (void)cfg_map_get(voptions, "zone", &zonelist);
1147 (void)cfg_map_get(config, "zone", &zonelist);
1150 * Load zone configuration
1152 for (element = cfg_list_first(zonelist);
1154 element = cfg_list_next(element))
1156 const cfg_obj_t *zconfig = cfg_listelt_value(element);
1157 CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
1163 * Create Dynamically Loadable Zone driver.
1166 if (voptions != NULL)
1167 (void)cfg_map_get(voptions, "dlz", &dlz);
1169 (void)cfg_map_get(config, "dlz", &dlz);
1173 (void)cfg_map_get(cfg_tuple_get(dlz, "options"),
1176 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
1178 result = ISC_R_NOMEMORY;
1182 result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv);
1183 if (result != ISC_R_SUCCESS) {
1184 isc_mem_free(mctx, s);
1188 obj = cfg_tuple_get(dlz, "name");
1189 result = dns_dlzcreate(mctx, cfg_obj_asstring(obj),
1190 dlzargv[0], dlzargc, dlzargv,
1191 &view->dlzdatabase);
1192 isc_mem_free(mctx, s);
1193 isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv));
1194 if (result != ISC_R_SUCCESS)
1201 * Obtain configuration parameters that affect the decision of whether
1202 * we can reuse/share an existing cache.
1206 result = ns_checknames_get(maps, "response", &obj);
1207 INSIST(result == ISC_R_SUCCESS);
1209 str = cfg_obj_asstring(obj);
1210 if (strcasecmp(str, "fail") == 0) {
1211 resopts |= DNS_RESOLVER_CHECKNAMES |
1212 DNS_RESOLVER_CHECKNAMESFAIL;
1213 view->checknames = ISC_TRUE;
1214 } else if (strcasecmp(str, "warn") == 0) {
1215 resopts |= DNS_RESOLVER_CHECKNAMES;
1216 view->checknames = ISC_FALSE;
1217 } else if (strcasecmp(str, "ignore") == 0) {
1218 view->checknames = ISC_FALSE;
1223 result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
1224 INSIST(result == ISC_R_SUCCESS);
1225 zero_no_soattl = cfg_obj_asboolean(obj);
1228 result = ns_config_get(maps, "dnssec-accept-expired", &obj);
1229 INSIST(result == ISC_R_SUCCESS);
1230 view->acceptexpired = cfg_obj_asboolean(obj);
1233 result = ns_config_get(maps, "dnssec-validation", &obj);
1234 INSIST(result == ISC_R_SUCCESS);
1235 view->enablevalidation = cfg_obj_asboolean(obj);
1238 result = ns_config_get(maps, "max-cache-ttl", &obj);
1239 INSIST(result == ISC_R_SUCCESS);
1240 view->maxcachettl = cfg_obj_asuint32(obj);
1243 result = ns_config_get(maps, "max-ncache-ttl", &obj);
1244 INSIST(result == ISC_R_SUCCESS);
1245 view->maxncachettl = cfg_obj_asuint32(obj);
1246 if (view->maxncachettl > 7 * 24 * 3600)
1247 view->maxncachettl = 7 * 24 * 3600;
1250 * Configure the view's cache. Try to reuse an existing
1251 * cache if possible, otherwise create a new cache.
1252 * Note that the ADB is not preserved in either case.
1253 * When a matching view is found, the associated statistics are
1254 * also retrieved and reused.
1256 * XXX Determining when it is safe to reuse a cache is tricky.
1257 * When the view's configuration changes, the cached data may become
1258 * invalid because it reflects our old view of the world. We check
1259 * some of the configuration parameters that could invalidate the cache,
1260 * but there are other configuration options that should be checked.
1261 * For example, if a view uses a forwarder, changes in the forwarder
1262 * configuration may invalidate the cache. At the moment, it's the
1263 * administrator's responsibility to ensure these configuration options
1264 * don't invalidate reusing.
1266 result = dns_viewlist_find(&ns_g_server->viewlist,
1267 view->name, view->rdclass,
1269 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
1271 if (pview != NULL) {
1272 if (cache_reusable(pview, view, zero_no_soattl)) {
1273 INSIST(pview->cache != NULL);
1274 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1275 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3),
1276 "reusing existing cache");
1277 reused_cache = ISC_TRUE;
1278 dns_cache_attach(pview->cache, &cache);
1280 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1281 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
1282 "cache cannot be reused for view %s "
1283 "due to configuration parameter mismatch",
1286 dns_view_getresstats(pview, &resstats);
1287 dns_view_getresquerystats(pview, &resquerystats);
1288 dns_view_detach(&pview);
1290 if (cache == NULL) {
1294 * We use two separate memory contexts for the
1295 * cache, for the main cache memory and the heap
1298 CHECK(isc_mem_create(0, 0, &cmctx));
1299 isc_mem_setname(cmctx, "cache", NULL);
1300 CHECK(isc_mem_create(0, 0, &hmctx));
1301 isc_mem_setname(hmctx, "cache_heap", NULL);
1302 CHECK(dns_cache_create3(cmctx, hmctx, ns_g_taskmgr,
1303 ns_g_timermgr, view->rdclass,
1304 NULL, "rbt", 0, NULL, &cache));
1305 isc_mem_detach(&cmctx);
1306 isc_mem_detach(&hmctx);
1308 dns_view_setcache(view, cache);
1311 * cache-file cannot be inherited if views are present, but this
1312 * should be caught by the configuration checking stage.
1315 result = ns_config_get(maps, "cache-file", &obj);
1316 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) {
1317 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj)));
1319 CHECK(dns_cache_load(cache));
1323 result = ns_config_get(maps, "cleaning-interval", &obj);
1324 INSIST(result == ISC_R_SUCCESS);
1325 dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60);
1328 result = ns_config_get(maps, "max-cache-size", &obj);
1329 INSIST(result == ISC_R_SUCCESS);
1330 if (cfg_obj_isstring(obj)) {
1331 str = cfg_obj_asstring(obj);
1332 INSIST(strcasecmp(str, "unlimited") == 0);
1333 max_cache_size = ISC_UINT32_MAX;
1335 isc_resourcevalue_t value;
1336 value = cfg_obj_asuint64(obj);
1337 if (value > ISC_UINT32_MAX) {
1338 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
1340 "%" ISC_PRINT_QUADFORMAT "d' is too large",
1342 result = ISC_R_RANGE;
1345 max_cache_size = (isc_uint32_t)value;
1347 dns_cache_setcachesize(cache, max_cache_size);
1349 dns_cache_detach(&cache);
1354 * XXXRTH Hardwired number of tasks.
1356 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4,
1357 ISC_TF(ISC_LIST_PREV(view, link)
1359 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6,
1360 ISC_TF(ISC_LIST_PREV(view, link)
1362 if (dispatch4 == NULL && dispatch6 == NULL) {
1363 UNEXPECTED_ERROR(__FILE__, __LINE__,
1364 "unable to obtain neither an IPv4 nor"
1365 " an IPv6 dispatch");
1366 result = ISC_R_UNEXPECTED;
1369 CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
1370 ns_g_socketmgr, ns_g_timermgr,
1371 resopts, ns_g_dispatchmgr,
1372 dispatch4, dispatch6));
1374 if (resstats == NULL) {
1375 CHECK(isc_stats_create(mctx, &resstats,
1376 dns_resstatscounter_max));
1378 dns_view_setresstats(view, resstats);
1379 if (resquerystats == NULL)
1380 CHECK(dns_rdatatypestats_create(mctx, &resquerystats));
1381 dns_view_setresquerystats(view, resquerystats);
1384 * Set the ADB cache size to 1/8th of the max-cache-size.
1387 if (max_cache_size != 0) {
1388 max_adb_size = max_cache_size / 8;
1389 if (max_adb_size == 0)
1390 max_adb_size = 1; /* Force minimum. */
1392 dns_adb_setadbsize(view->adb, max_adb_size);
1395 * Set resolver's lame-ttl.
1398 result = ns_config_get(maps, "lame-ttl", &obj);
1399 INSIST(result == ISC_R_SUCCESS);
1400 lame_ttl = cfg_obj_asuint32(obj);
1401 if (lame_ttl > 1800)
1403 dns_resolver_setlamettl(view->resolver, lame_ttl);
1406 * Set the resolver's EDNS UDP size.
1409 result = ns_config_get(maps, "edns-udp-size", &obj);
1410 INSIST(result == ISC_R_SUCCESS);
1411 udpsize = cfg_obj_asuint32(obj);
1416 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize);
1419 * Set the maximum UDP response size.
1422 result = ns_config_get(maps, "max-udp-size", &obj);
1423 INSIST(result == ISC_R_SUCCESS);
1424 udpsize = cfg_obj_asuint32(obj);
1429 view->maxudp = udpsize;
1432 * Set supported DNSSEC algorithms.
1434 dns_resolver_reset_algorithms(view->resolver);
1436 (void)ns_config_get(maps, "disable-algorithms", &disabled);
1437 if (disabled != NULL) {
1438 for (element = cfg_list_first(disabled);
1440 element = cfg_list_next(element))
1441 CHECK(disable_algorithms(cfg_listelt_value(element),
1446 * A global or view "forwarders" option, if present,
1447 * creates an entry for "." in the forwarding table.
1451 (void)ns_config_get(maps, "forward", &forwardtype);
1452 (void)ns_config_get(maps, "forwarders", &forwarders);
1453 if (forwarders != NULL)
1454 CHECK(configure_forward(config, view, dns_rootname,
1455 forwarders, forwardtype));
1458 * Dual Stack Servers.
1461 (void)ns_config_get(maps, "dual-stack-servers", &alternates);
1462 if (alternates != NULL)
1463 CHECK(configure_alternates(config, view, alternates));
1466 * We have default hints for class IN if we need them.
1468 if (view->rdclass == dns_rdataclass_in && view->hints == NULL)
1469 dns_view_sethints(view, ns_g_server->in_roothints);
1472 * If we still have no hints, this is a non-IN view with no
1473 * "hints zone" configured. Issue a warning, except if this
1474 * is a root server. Root servers never need to consult
1475 * their hints, so it's no point requiring users to configure
1478 if (view->hints == NULL) {
1479 dns_zone_t *rootzone = NULL;
1480 (void)dns_view_findzone(view, dns_rootname, &rootzone);
1481 if (rootzone != NULL) {
1482 dns_zone_detach(&rootzone);
1483 need_hints = ISC_FALSE;
1486 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1487 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1488 "no root hints for view '%s'",
1493 * Configure the view's TSIG keys.
1495 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
1496 dns_view_setkeyring(view, ring);
1497 ring = NULL; /* ownership transferred */
1500 * Configure the view's peer list.
1503 const cfg_obj_t *peers = NULL;
1504 const cfg_listelt_t *element;
1505 dns_peerlist_t *newpeers = NULL;
1507 (void)ns_config_get(cfgmaps, "server", &peers);
1508 CHECK(dns_peerlist_new(mctx, &newpeers));
1509 for (element = cfg_list_first(peers);
1511 element = cfg_list_next(element))
1513 const cfg_obj_t *cpeer = cfg_listelt_value(element);
1516 CHECK(configure_peer(cpeer, mctx, &peer));
1517 dns_peerlist_addpeer(newpeers, peer);
1518 dns_peer_detach(&peer);
1520 dns_peerlist_detach(&view->peers);
1521 view->peers = newpeers; /* Transfer ownership. */
1525 * Configure the views rrset-order.
1528 const cfg_obj_t *rrsetorder = NULL;
1529 const cfg_listelt_t *element;
1531 (void)ns_config_get(maps, "rrset-order", &rrsetorder);
1532 CHECK(dns_order_create(mctx, &order));
1533 for (element = cfg_list_first(rrsetorder);
1535 element = cfg_list_next(element))
1537 const cfg_obj_t *ent = cfg_listelt_value(element);
1539 CHECK(configure_order(order, ent));
1541 if (view->order != NULL)
1542 dns_order_detach(&view->order);
1543 dns_order_attach(order, &view->order);
1544 dns_order_detach(&order);
1547 * Copy the aclenv object.
1549 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv);
1552 * Configure the "match-clients" and "match-destinations" ACL.
1554 CHECK(configure_view_acl(vconfig, config, "match-clients", actx,
1555 ns_g_mctx, &view->matchclients));
1556 CHECK(configure_view_acl(vconfig, config, "match-destinations", actx,
1557 ns_g_mctx, &view->matchdestinations));
1560 * Configure the "match-recursive-only" option.
1563 (void)ns_config_get(maps, "match-recursive-only", &obj);
1564 if (obj != NULL && cfg_obj_asboolean(obj))
1565 view->matchrecursiveonly = ISC_TRUE;
1567 view->matchrecursiveonly = ISC_FALSE;
1570 * Configure other configurable data.
1573 result = ns_config_get(maps, "recursion", &obj);
1574 INSIST(result == ISC_R_SUCCESS);
1575 view->recursion = cfg_obj_asboolean(obj);
1578 result = ns_config_get(maps, "auth-nxdomain", &obj);
1579 INSIST(result == ISC_R_SUCCESS);
1580 view->auth_nxdomain = cfg_obj_asboolean(obj);
1583 result = ns_config_get(maps, "minimal-responses", &obj);
1584 INSIST(result == ISC_R_SUCCESS);
1585 view->minimalresponses = cfg_obj_asboolean(obj);
1588 result = ns_config_get(maps, "transfer-format", &obj);
1589 INSIST(result == ISC_R_SUCCESS);
1590 str = cfg_obj_asstring(obj);
1591 if (strcasecmp(str, "many-answers") == 0)
1592 view->transfer_format = dns_many_answers;
1593 else if (strcasecmp(str, "one-answer") == 0)
1594 view->transfer_format = dns_one_answer;
1599 * Set sources where additional data and CNAME/DNAME
1600 * targets for authoritative answers may be found.
1603 result = ns_config_get(maps, "additional-from-auth", &obj);
1604 INSIST(result == ISC_R_SUCCESS);
1605 view->additionalfromauth = cfg_obj_asboolean(obj);
1606 if (view->recursion && ! view->additionalfromauth) {
1607 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1608 "'additional-from-auth no' is only supported "
1609 "with 'recursion no'");
1610 view->additionalfromauth = ISC_TRUE;
1614 result = ns_config_get(maps, "additional-from-cache", &obj);
1615 INSIST(result == ISC_R_SUCCESS);
1616 view->additionalfromcache = cfg_obj_asboolean(obj);
1617 if (view->recursion && ! view->additionalfromcache) {
1618 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1619 "'additional-from-cache no' is only supported "
1620 "with 'recursion no'");
1621 view->additionalfromcache = ISC_TRUE;
1625 * Set "allow-query-cache", "allow-query-cache-on",
1626 * "allow-recursion", and "allow-recursion-on" acls if
1627 * configured in named.conf.
1629 CHECK(configure_view_acl(vconfig, config, "allow-query-cache",
1630 actx, ns_g_mctx, &view->cacheacl));
1631 CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on",
1632 actx, ns_g_mctx, &view->cacheonacl));
1633 if (view->cacheonacl == NULL)
1634 CHECK(configure_view_acl(NULL, ns_g_config,
1635 "allow-query-cache-on", actx,
1636 ns_g_mctx, &view->cacheonacl));
1637 if (strcmp(view->name, "_bind") != 0) {
1638 CHECK(configure_view_acl(vconfig, config, "allow-recursion",
1640 &view->recursionacl));
1641 CHECK(configure_view_acl(vconfig, config, "allow-recursion-on",
1643 &view->recursiononacl));
1647 * "allow-query-cache" inherits from "allow-recursion" if set,
1648 * otherwise from "allow-query" if set.
1649 * "allow-recursion" inherits from "allow-query-cache" if set,
1650 * otherwise from "allow-query" if set.
1652 if (view->cacheacl == NULL && view->recursionacl != NULL)
1653 dns_acl_attach(view->recursionacl, &view->cacheacl);
1654 if (view->cacheacl == NULL && view->recursion)
1655 CHECK(configure_view_acl(vconfig, config, "allow-query",
1656 actx, ns_g_mctx, &view->cacheacl));
1657 if (view->recursion &&
1658 view->recursionacl == NULL && view->cacheacl != NULL)
1659 dns_acl_attach(view->cacheacl, &view->recursionacl);
1662 * Set default "allow-recursion", "allow-recursion-on" and
1663 * "allow-query-cache" acls.
1665 if (view->recursionacl == NULL && view->recursion)
1666 CHECK(configure_view_acl(NULL, ns_g_config,
1669 &view->recursionacl));
1670 if (view->recursiononacl == NULL && view->recursion)
1671 CHECK(configure_view_acl(NULL, ns_g_config,
1672 "allow-recursion-on",
1674 &view->recursiononacl));
1675 if (view->cacheacl == NULL) {
1676 if (view->recursion)
1677 CHECK(configure_view_acl(NULL, ns_g_config,
1678 "allow-query-cache", actx,
1679 ns_g_mctx, &view->cacheacl));
1681 CHECK(dns_acl_none(ns_g_mctx, &view->cacheacl));
1685 * Configure sortlist, if set
1687 CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx,
1691 * Configure default allow-transfer, allow-notify, allow-update
1692 * and allow-update-forwarding ACLs, if set, so they can be
1693 * inherited by zones.
1695 if (view->notifyacl == NULL)
1696 CHECK(configure_view_acl(NULL, ns_g_config,
1697 "allow-notify", actx,
1698 ns_g_mctx, &view->notifyacl));
1699 if (view->transferacl == NULL)
1700 CHECK(configure_view_acl(NULL, ns_g_config,
1701 "allow-transfer", actx,
1702 ns_g_mctx, &view->transferacl));
1703 if (view->updateacl == NULL)
1704 CHECK(configure_view_acl(NULL, ns_g_config,
1705 "allow-update", actx,
1706 ns_g_mctx, &view->updateacl));
1707 if (view->upfwdacl == NULL)
1708 CHECK(configure_view_acl(NULL, ns_g_config,
1709 "allow-update-forwarding", actx,
1710 ns_g_mctx, &view->upfwdacl));
1713 result = ns_config_get(maps, "request-ixfr", &obj);
1714 INSIST(result == ISC_R_SUCCESS);
1715 view->requestixfr = cfg_obj_asboolean(obj);
1718 result = ns_config_get(maps, "provide-ixfr", &obj);
1719 INSIST(result == ISC_R_SUCCESS);
1720 view->provideixfr = cfg_obj_asboolean(obj);
1723 result = ns_config_get(maps, "request-nsid", &obj);
1724 INSIST(result == ISC_R_SUCCESS);
1725 view->requestnsid = cfg_obj_asboolean(obj);
1728 result = ns_config_get(maps, "max-clients-per-query", &obj);
1729 INSIST(result == ISC_R_SUCCESS);
1730 max_clients_per_query = cfg_obj_asuint32(obj);
1733 result = ns_config_get(maps, "clients-per-query", &obj);
1734 INSIST(result == ISC_R_SUCCESS);
1735 dns_resolver_setclientsperquery(view->resolver,
1736 cfg_obj_asuint32(obj),
1737 max_clients_per_query);
1740 result = ns_config_get(maps, "dnssec-enable", &obj);
1741 INSIST(result == ISC_R_SUCCESS);
1742 view->enablednssec = cfg_obj_asboolean(obj);
1745 result = ns_config_get(maps, "dnssec-lookaside", &obj);
1746 if (result == ISC_R_SUCCESS) {
1747 for (element = cfg_list_first(obj);
1749 element = cfg_list_next(element))
1755 obj = cfg_listelt_value(element);
1757 dns_fixedname_t fixed;
1761 * When we support multiple dnssec-lookaside
1762 * entries this is how to find the domain to be
1765 dns_fixedname_init(&fixed);
1766 name = dns_fixedname_name(&fixed);
1767 str = cfg_obj_asstring(cfg_tuple_get(obj,
1769 isc_buffer_init(&b, str, strlen(str));
1770 isc_buffer_add(&b, strlen(str));
1771 CHECK(dns_name_fromtext(name, &b, dns_rootname,
1774 str = cfg_obj_asstring(cfg_tuple_get(obj,
1776 isc_buffer_init(&b, str, strlen(str));
1777 isc_buffer_add(&b, strlen(str));
1778 dlv = dns_fixedname_name(&view->dlv_fixed);
1779 CHECK(dns_name_fromtext(dlv, &b, dns_rootname,
1781 view->dlv = dns_fixedname_name(&view->dlv_fixed);
1787 * For now, there is only one kind of trusted keys, the
1790 CHECK(configure_view_dnsseckeys(vconfig, config, mctx,
1792 dns_resolver_resetmustbesecure(view->resolver);
1794 result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
1795 if (result == ISC_R_SUCCESS)
1796 CHECK(mustbesecure(obj, view->resolver));
1799 result = ns_config_get(maps, "preferred-glue", &obj);
1800 if (result == ISC_R_SUCCESS) {
1801 str = cfg_obj_asstring(obj);
1802 if (strcasecmp(str, "a") == 0)
1803 view->preferred_glue = dns_rdatatype_a;
1804 else if (strcasecmp(str, "aaaa") == 0)
1805 view->preferred_glue = dns_rdatatype_aaaa;
1807 view->preferred_glue = 0;
1809 view->preferred_glue = 0;
1812 result = ns_config_get(maps, "root-delegation-only", &obj);
1813 if (result == ISC_R_SUCCESS) {
1814 dns_view_setrootdelonly(view, ISC_TRUE);
1815 if (!cfg_obj_isvoid(obj)) {
1816 dns_fixedname_t fixed;
1820 const cfg_obj_t *exclude;
1822 dns_fixedname_init(&fixed);
1823 name = dns_fixedname_name(&fixed);
1824 for (element = cfg_list_first(obj);
1826 element = cfg_list_next(element)) {
1827 exclude = cfg_listelt_value(element);
1828 str = cfg_obj_asstring(exclude);
1829 isc_buffer_init(&b, str, strlen(str));
1830 isc_buffer_add(&b, strlen(str));
1831 CHECK(dns_name_fromtext(name, &b, dns_rootname,
1833 CHECK(dns_view_excludedelegationonly(view,
1838 dns_view_setrootdelonly(view, ISC_FALSE);
1841 * Setup automatic empty zones. If recursion is off then
1842 * they are disabled by default.
1845 (void)ns_config_get(maps, "empty-zones-enable", &obj);
1846 (void)ns_config_get(maps, "disable-empty-zone", &disablelist);
1847 if (obj == NULL && disablelist == NULL &&
1848 view->rdclass == dns_rdataclass_in) {
1849 rfc1918 = ISC_FALSE;
1850 empty_zones_enable = view->recursion;
1851 } else if (view->rdclass == dns_rdataclass_in) {
1854 empty_zones_enable = cfg_obj_asboolean(obj);
1856 empty_zones_enable = view->recursion;
1858 rfc1918 = ISC_FALSE;
1859 empty_zones_enable = ISC_FALSE;
1861 if (empty_zones_enable && !lwresd_g_useresolvconf) {
1864 dns_fixedname_t fixed;
1866 isc_buffer_t buffer;
1868 char server[DNS_NAME_FORMATSIZE + 1];
1869 char contact[DNS_NAME_FORMATSIZE + 1];
1870 isc_boolean_t logit;
1871 const char *empty_dbtype[4] =
1872 { "_builtin", "empty", NULL, NULL };
1873 int empty_dbtypec = 4;
1874 isc_boolean_t zonestats_on;
1876 dns_fixedname_init(&fixed);
1877 name = dns_fixedname_name(&fixed);
1880 result = ns_config_get(maps, "empty-server", &obj);
1881 if (result == ISC_R_SUCCESS) {
1882 str = cfg_obj_asstring(obj);
1883 isc_buffer_init(&buffer, str, strlen(str));
1884 isc_buffer_add(&buffer, strlen(str));
1885 CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
1887 isc_buffer_init(&buffer, server, sizeof(server) - 1);
1888 CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
1889 server[isc_buffer_usedlength(&buffer)] = 0;
1890 empty_dbtype[2] = server;
1892 empty_dbtype[2] = "@";
1895 result = ns_config_get(maps, "empty-contact", &obj);
1896 if (result == ISC_R_SUCCESS) {
1897 str = cfg_obj_asstring(obj);
1898 isc_buffer_init(&buffer, str, strlen(str));
1899 isc_buffer_add(&buffer, strlen(str));
1900 CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
1902 isc_buffer_init(&buffer, contact, sizeof(contact) - 1);
1903 CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
1904 contact[isc_buffer_usedlength(&buffer)] = 0;
1905 empty_dbtype[3] = contact;
1907 empty_dbtype[3] = ".";
1910 result = ns_config_get(maps, "zone-statistics", &obj);
1911 INSIST(result == ISC_R_SUCCESS);
1912 zonestats_on = cfg_obj_asboolean(obj);
1915 for (empty = empty_zones[empty_zone].zone;
1917 empty = empty_zones[++empty_zone].zone)
1919 dns_forwarders_t *forwarders = NULL;
1920 dns_view_t *pview = NULL;
1922 isc_buffer_init(&buffer, empty, strlen(empty));
1923 isc_buffer_add(&buffer, strlen(empty));
1925 * Look for zone on drop list.
1927 CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
1929 if (disablelist != NULL &&
1930 on_disable_list(disablelist, name))
1934 * This zone already exists.
1936 (void)dns_view_findzone(view, name, &zone);
1938 CHECK(setquerystats(zone, mctx, zonestats_on));
1939 dns_zone_detach(&zone);
1944 * If we would forward this name don't add a
1945 * empty zone for it.
1947 result = dns_fwdtable_find(view->fwdtable, name,
1949 if (result == ISC_R_SUCCESS &&
1950 forwarders->fwdpolicy == dns_fwdpolicy_only)
1953 if (!rfc1918 && empty_zones[empty_zone].rfc1918) {
1955 isc_log_write(ns_g_lctx,
1956 NS_LOGCATEGORY_GENERAL,
1957 NS_LOGMODULE_SERVER,
1960 "'empty-zones-enable/"
1961 "disable-empty-zone' "
1962 "not set: disabling "
1963 "RFC 1918 empty zones",
1971 * See if we can re-use a existing zone.
1973 result = dns_viewlist_find(&ns_g_server->viewlist,
1974 view->name, view->rdclass,
1976 if (result != ISC_R_NOTFOUND &&
1977 result != ISC_R_SUCCESS)
1980 if (pview != NULL) {
1981 (void)dns_view_findzone(pview, name, &zone);
1982 dns_view_detach(&pview);
1984 check_dbtype(&zone, empty_dbtypec,
1985 empty_dbtype, mctx);
1987 dns_zone_setview(zone, view);
1988 CHECK(dns_view_addzone(view, zone));
1989 CHECK(setquerystats(zone, mctx,
1991 dns_zone_detach(&zone);
1996 CHECK(dns_zone_create(&zone, mctx));
1997 CHECK(dns_zone_setorigin(zone, name));
1998 dns_zone_setview(zone, view);
1999 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
2000 dns_zone_setclass(zone, view->rdclass);
2001 dns_zone_settype(zone, dns_zone_master);
2002 dns_zone_setstats(zone, ns_g_server->zonestats);
2003 CHECK(dns_zone_setdbtype(zone, empty_dbtypec,
2005 if (view->queryacl != NULL)
2006 dns_zone_setqueryacl(zone, view->queryacl);
2007 if (view->queryonacl != NULL)
2008 dns_zone_setqueryonacl(zone, view->queryonacl);
2009 dns_zone_setdialup(zone, dns_dialuptype_no);
2010 dns_zone_setnotifytype(zone, dns_notifytype_no);
2011 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS,
2013 CHECK(setquerystats(zone, mctx, zonestats_on));
2014 CHECK(dns_view_addzone(view, zone));
2015 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2016 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
2017 "automatic empty zone%s%s: %s",
2018 sep, viewname, empty);
2019 dns_zone_detach(&zone);
2023 result = ISC_R_SUCCESS;
2027 dns_tsigkeyring_destroy(&ring);
2029 dns_zone_detach(&zone);
2030 if (dispatch4 != NULL)
2031 dns_dispatch_detach(&dispatch4);
2032 if (dispatch6 != NULL)
2033 dns_dispatch_detach(&dispatch6);
2034 if (resstats != NULL)
2035 isc_stats_detach(&resstats);
2036 if (resquerystats != NULL)
2037 dns_stats_detach(&resquerystats);
2039 dns_order_detach(&order);
2041 isc_mem_detach(&cmctx);
2043 isc_mem_detach(&hmctx);
2046 dns_cache_detach(&cache);
2052 configure_hints(dns_view_t *view, const char *filename) {
2053 isc_result_t result;
2057 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db);
2058 if (result == ISC_R_SUCCESS) {
2059 dns_view_sethints(view, db);
2067 configure_alternates(const cfg_obj_t *config, dns_view_t *view,
2068 const cfg_obj_t *alternates)
2070 const cfg_obj_t *portobj;
2071 const cfg_obj_t *addresses;
2072 const cfg_listelt_t *element;
2073 isc_result_t result = ISC_R_SUCCESS;
2077 * Determine which port to send requests to.
2079 if (ns_g_lwresdonly && ns_g_port != 0)
2082 CHECKM(ns_config_getport(config, &port), "port");
2084 if (alternates != NULL) {
2085 portobj = cfg_tuple_get(alternates, "port");
2086 if (cfg_obj_isuint32(portobj)) {
2087 isc_uint32_t val = cfg_obj_asuint32(portobj);
2088 if (val > ISC_UINT16_MAX) {
2089 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
2090 "port '%u' out of range", val);
2091 return (ISC_R_RANGE);
2093 port = (in_port_t) val;
2098 if (alternates != NULL)
2099 addresses = cfg_tuple_get(alternates, "addresses");
2101 for (element = cfg_list_first(addresses);
2103 element = cfg_list_next(element))
2105 const cfg_obj_t *alternate = cfg_listelt_value(element);
2108 if (!cfg_obj_issockaddr(alternate)) {
2109 dns_fixedname_t fixed;
2111 const char *str = cfg_obj_asstring(cfg_tuple_get(
2112 alternate, "name"));
2113 isc_buffer_t buffer;
2114 in_port_t myport = port;
2116 isc_buffer_init(&buffer, str, strlen(str));
2117 isc_buffer_add(&buffer, strlen(str));
2118 dns_fixedname_init(&fixed);
2119 name = dns_fixedname_name(&fixed);
2120 CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
2123 portobj = cfg_tuple_get(alternate, "port");
2124 if (cfg_obj_isuint32(portobj)) {
2125 isc_uint32_t val = cfg_obj_asuint32(portobj);
2126 if (val > ISC_UINT16_MAX) {
2127 cfg_obj_log(portobj, ns_g_lctx,
2129 "port '%u' out of range",
2131 return (ISC_R_RANGE);
2133 myport = (in_port_t) val;
2135 CHECK(dns_resolver_addalternate(view->resolver, NULL,
2140 sa = *cfg_obj_assockaddr(alternate);
2141 if (isc_sockaddr_getport(&sa) == 0)
2142 isc_sockaddr_setport(&sa, port);
2143 CHECK(dns_resolver_addalternate(view->resolver, &sa,
2152 configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
2153 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype)
2155 const cfg_obj_t *portobj;
2156 const cfg_obj_t *faddresses;
2157 const cfg_listelt_t *element;
2158 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
2159 isc_sockaddrlist_t addresses;
2161 isc_result_t result;
2164 ISC_LIST_INIT(addresses);
2167 * Determine which port to send forwarded requests to.
2169 if (ns_g_lwresdonly && ns_g_port != 0)
2172 CHECKM(ns_config_getport(config, &port), "port");
2174 if (forwarders != NULL) {
2175 portobj = cfg_tuple_get(forwarders, "port");
2176 if (cfg_obj_isuint32(portobj)) {
2177 isc_uint32_t val = cfg_obj_asuint32(portobj);
2178 if (val > ISC_UINT16_MAX) {
2179 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
2180 "port '%u' out of range", val);
2181 return (ISC_R_RANGE);
2183 port = (in_port_t) val;
2188 if (forwarders != NULL)
2189 faddresses = cfg_tuple_get(forwarders, "addresses");
2191 for (element = cfg_list_first(faddresses);
2193 element = cfg_list_next(element))
2195 const cfg_obj_t *forwarder = cfg_listelt_value(element);
2196 sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t));
2198 result = ISC_R_NOMEMORY;
2201 *sa = *cfg_obj_assockaddr(forwarder);
2202 if (isc_sockaddr_getport(sa) == 0)
2203 isc_sockaddr_setport(sa, port);
2204 ISC_LINK_INIT(sa, link);
2205 ISC_LIST_APPEND(addresses, sa, link);
2208 if (ISC_LIST_EMPTY(addresses)) {
2209 if (forwardtype != NULL)
2210 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
2211 "no forwarders seen; disabling "
2213 fwdpolicy = dns_fwdpolicy_none;
2215 if (forwardtype == NULL)
2216 fwdpolicy = dns_fwdpolicy_first;
2218 const char *forwardstr = cfg_obj_asstring(forwardtype);
2219 if (strcasecmp(forwardstr, "first") == 0)
2220 fwdpolicy = dns_fwdpolicy_first;
2221 else if (strcasecmp(forwardstr, "only") == 0)
2222 fwdpolicy = dns_fwdpolicy_only;
2228 result = dns_fwdtable_add(view->fwdtable, origin, &addresses,
2230 if (result != ISC_R_SUCCESS) {
2231 char namebuf[DNS_NAME_FORMATSIZE];
2232 dns_name_format(origin, namebuf, sizeof(namebuf));
2233 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
2234 "could not set up forwarding for domain '%s': %s",
2235 namebuf, isc_result_totext(result));
2239 result = ISC_R_SUCCESS;
2243 while (!ISC_LIST_EMPTY(addresses)) {
2244 sa = ISC_LIST_HEAD(addresses);
2245 ISC_LIST_UNLINK(addresses, sa, link);
2246 isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t));
2253 get_viewinfo(const cfg_obj_t *vconfig, const char **namep,
2254 dns_rdataclass_t *classp)
2256 isc_result_t result = ISC_R_SUCCESS;
2257 const char *viewname;
2258 dns_rdataclass_t viewclass;
2260 REQUIRE(namep != NULL && *namep == NULL);
2261 REQUIRE(classp != NULL);
2263 if (vconfig != NULL) {
2264 const cfg_obj_t *classobj = NULL;
2266 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
2267 classobj = cfg_tuple_get(vconfig, "class");
2268 result = ns_config_getclass(classobj, dns_rdataclass_in,
2271 viewname = "_default";
2272 viewclass = dns_rdataclass_in;
2276 *classp = viewclass;
2282 * Find a view based on its configuration info and attach to it.
2284 * If 'vconfig' is NULL, attach to the default view.
2287 find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
2290 isc_result_t result;
2291 const char *viewname = NULL;
2292 dns_rdataclass_t viewclass;
2293 dns_view_t *view = NULL;
2295 result = get_viewinfo(vconfig, &viewname, &viewclass);
2296 if (result != ISC_R_SUCCESS)
2299 result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
2300 if (result != ISC_R_SUCCESS)
2304 return (ISC_R_SUCCESS);
2308 * Create a new view and add it to the list.
2310 * If 'vconfig' is NULL, create the default view.
2312 * The view created is attached to '*viewp'.
2315 create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
2318 isc_result_t result;
2319 const char *viewname = NULL;
2320 dns_rdataclass_t viewclass;
2321 dns_view_t *view = NULL;
2323 result = get_viewinfo(vconfig, &viewname, &viewclass);
2324 if (result != ISC_R_SUCCESS)
2327 result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
2328 if (result == ISC_R_SUCCESS)
2329 return (ISC_R_EXISTS);
2330 if (result != ISC_R_NOTFOUND)
2332 INSIST(view == NULL);
2334 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view);
2335 if (result != ISC_R_SUCCESS)
2338 ISC_LIST_APPEND(*viewlist, view, link);
2339 dns_view_attach(view, viewp);
2340 return (ISC_R_SUCCESS);
2344 * Configure or reconfigure a zone.
2347 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
2348 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
2349 cfg_aclconfctx_t *aclconf)
2351 dns_view_t *pview = NULL; /* Production view */
2352 dns_zone_t *zone = NULL; /* New or reused zone */
2353 dns_zone_t *dupzone = NULL;
2354 const cfg_obj_t *options = NULL;
2355 const cfg_obj_t *zoptions = NULL;
2356 const cfg_obj_t *typeobj = NULL;
2357 const cfg_obj_t *forwarders = NULL;
2358 const cfg_obj_t *forwardtype = NULL;
2359 const cfg_obj_t *only = NULL;
2360 isc_result_t result;
2361 isc_result_t tresult;
2362 isc_buffer_t buffer;
2363 dns_fixedname_t fixorigin;
2366 dns_rdataclass_t zclass;
2367 const char *ztypestr;
2370 (void)cfg_map_get(config, "options", &options);
2372 zoptions = cfg_tuple_get(zconfig, "options");
2375 * Get the zone origin as a dns_name_t.
2377 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
2378 isc_buffer_init(&buffer, zname, strlen(zname));
2379 isc_buffer_add(&buffer, strlen(zname));
2380 dns_fixedname_init(&fixorigin);
2381 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin),
2382 &buffer, dns_rootname, ISC_FALSE, NULL));
2383 origin = dns_fixedname_name(&fixorigin);
2385 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
2386 view->rdclass, &zclass));
2387 if (zclass != view->rdclass) {
2388 const char *vname = NULL;
2389 if (vconfig != NULL)
2390 vname = cfg_obj_asstring(cfg_tuple_get(vconfig,
2393 vname = "<default view>";
2395 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2396 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
2397 "zone '%s': wrong class for view '%s'",
2399 result = ISC_R_FAILURE;
2403 (void)cfg_map_get(zoptions, "type", &typeobj);
2404 if (typeobj == NULL) {
2405 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
2406 "zone '%s' 'type' not specified", zname);
2407 return (ISC_R_FAILURE);
2409 ztypestr = cfg_obj_asstring(typeobj);
2412 * "hints zones" aren't zones. If we've got one,
2413 * configure it and return.
2415 if (strcasecmp(ztypestr, "hint") == 0) {
2416 const cfg_obj_t *fileobj = NULL;
2417 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
2418 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2419 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
2420 "zone '%s': 'file' not specified",
2422 result = ISC_R_FAILURE;
2425 if (dns_name_equal(origin, dns_rootname)) {
2426 const char *hintsfile = cfg_obj_asstring(fileobj);
2428 result = configure_hints(view, hintsfile);
2429 if (result != ISC_R_SUCCESS) {
2430 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2431 NS_LOGMODULE_SERVER,
2433 "could not configure root hints "
2434 "from '%s': %s", hintsfile,
2435 isc_result_totext(result));
2439 * Hint zones may also refer to delegation only points.
2442 tresult = cfg_map_get(zoptions, "delegation-only",
2444 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
2445 CHECK(dns_view_adddelegationonly(view, origin));
2447 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2448 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
2449 "ignoring non-root hint zone '%s'",
2451 result = ISC_R_SUCCESS;
2453 /* Skip ordinary zone processing. */
2458 * "forward zones" aren't zones either. Translate this syntax into
2459 * the appropriate selective forwarding configuration and return.
2461 if (strcasecmp(ztypestr, "forward") == 0) {
2465 (void)cfg_map_get(zoptions, "forward", &forwardtype);
2466 (void)cfg_map_get(zoptions, "forwarders", &forwarders);
2467 result = configure_forward(config, view, origin, forwarders,
2473 * "delegation-only zones" aren't zones either.
2475 if (strcasecmp(ztypestr, "delegation-only") == 0) {
2476 result = dns_view_adddelegationonly(view, origin);
2481 * Check for duplicates in the new zone table.
2483 result = dns_view_findzone(view, origin, &dupzone);
2484 if (result == ISC_R_SUCCESS) {
2486 * We already have this zone!
2488 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
2489 "zone '%s' already exists", zname);
2490 dns_zone_detach(&dupzone);
2491 result = ISC_R_EXISTS;
2494 INSIST(dupzone == NULL);
2497 * See if we can reuse an existing zone. This is
2498 * only possible if all of these are true:
2499 * - The zone's view exists
2500 * - A zone with the right name exists in the view
2501 * - The zone is compatible with the config
2502 * options (e.g., an existing master zone cannot
2503 * be reused if the options specify a slave zone)
2505 result = dns_viewlist_find(&ns_g_server->viewlist,
2506 view->name, view->rdclass,
2508 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
2511 result = dns_view_findzone(pview, origin, &zone);
2512 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
2514 if (zone != NULL && !ns_zone_reusable(zone, zconfig))
2515 dns_zone_detach(&zone);
2519 * We found a reusable zone. Make it use the
2522 dns_zone_setview(zone, view);
2523 if (view->acache != NULL)
2524 dns_zone_setacache(zone, view->acache);
2527 * We cannot reuse an existing zone, we have
2528 * to create a new one.
2530 CHECK(dns_zone_create(&zone, mctx));
2531 CHECK(dns_zone_setorigin(zone, origin));
2532 dns_zone_setview(zone, view);
2533 if (view->acache != NULL)
2534 dns_zone_setacache(zone, view->acache);
2535 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
2536 dns_zone_setstats(zone, ns_g_server->zonestats);
2540 * If the zone contains a 'forwarders' statement, configure
2541 * selective forwarding.
2544 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS)
2547 (void)cfg_map_get(zoptions, "forward", &forwardtype);
2548 CHECK(configure_forward(config, view, origin, forwarders,
2553 * Stub and forward zones may also refer to delegation only points.
2556 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS)
2558 if (cfg_obj_asboolean(only))
2559 CHECK(dns_view_adddelegationonly(view, origin));
2563 * Configure the zone.
2565 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone));
2568 * Add the zone to its view in the new view list.
2570 CHECK(dns_view_addzone(view, zone));
2574 dns_zone_detach(&zone);
2576 dns_view_detach(&pview);
2582 * Configure a single server quota.
2585 configure_server_quota(const cfg_obj_t **maps, const char *name,
2588 const cfg_obj_t *obj = NULL;
2589 isc_result_t result;
2591 result = ns_config_get(maps, name, &obj);
2592 INSIST(result == ISC_R_SUCCESS);
2593 isc_quota_max(quota, cfg_obj_asuint32(obj));
2597 * This function is called as soon as the 'directory' statement has been
2598 * parsed. This can be extended to support other options if necessary.
2601 directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
2602 isc_result_t result;
2603 const char *directory;
2605 REQUIRE(strcasecmp("directory", clausename) == 0);
2613 directory = cfg_obj_asstring(obj);
2615 if (! isc_file_ischdiridempotent(directory))
2616 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
2617 "option 'directory' contains relative path '%s'",
2620 result = isc_dir_chdir(directory);
2621 if (result != ISC_R_SUCCESS) {
2622 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
2623 "change directory to '%s' failed: %s",
2624 directory, isc_result_totext(result));
2628 return (ISC_R_SUCCESS);
2632 scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
2633 isc_boolean_t match_mapped = server->aclenv.match_mapped;
2635 ns_interfacemgr_scan(server->interfacemgr, verbose);
2637 * Update the "localhost" and "localnets" ACLs to match the
2638 * current set of network interfaces.
2640 dns_aclenv_copy(&server->aclenv,
2641 ns_interfacemgr_getaclenv(server->interfacemgr));
2643 server->aclenv.match_mapped = match_mapped;
2647 add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
2648 isc_boolean_t wcardport_ok)
2650 ns_listenelt_t *lelt = NULL;
2651 dns_acl_t *src_acl = NULL;
2652 isc_result_t result;
2653 isc_sockaddr_t any_sa6;
2654 isc_netaddr_t netaddr;
2656 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
2658 isc_sockaddr_any6(&any_sa6);
2659 if (!isc_sockaddr_equal(&any_sa6, addr) &&
2660 (wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
2661 isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr);
2663 result = dns_acl_create(mctx, 0, &src_acl);
2664 if (result != ISC_R_SUCCESS)
2667 result = dns_iptable_addprefix(src_acl->iptable,
2668 &netaddr, 128, ISC_TRUE);
2669 if (result != ISC_R_SUCCESS)
2672 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
2674 if (result != ISC_R_SUCCESS)
2676 ISC_LIST_APPEND(list->elts, lelt, link);
2679 return (ISC_R_SUCCESS);
2682 INSIST(lelt == NULL);
2683 dns_acl_detach(&src_acl);
2689 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust()
2690 * to update the listening interfaces accordingly.
2691 * We currently only consider IPv6, because this only affects IPv6 wildcard
2695 adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
2696 isc_result_t result;
2697 ns_listenlist_t *list = NULL;
2699 dns_zone_t *zone, *next;
2700 isc_sockaddr_t addr, *addrp;
2702 result = ns_listenlist_create(mctx, &list);
2703 if (result != ISC_R_SUCCESS)
2706 for (view = ISC_LIST_HEAD(server->viewlist);
2708 view = ISC_LIST_NEXT(view, link)) {
2709 dns_dispatch_t *dispatch6;
2711 dispatch6 = dns_resolver_dispatchv6(view->resolver);
2712 if (dispatch6 == NULL)
2714 result = dns_dispatch_getlocaladdress(dispatch6, &addr);
2715 if (result != ISC_R_SUCCESS)
2719 * We always add non-wildcard address regardless of whether
2720 * the port is 'any' (the fourth arg is TRUE): if the port is
2721 * specific, we need to add it since it may conflict with a
2722 * listening interface; if it's zero, we'll dynamically open
2723 * query ports, and some of them may override an existing
2724 * wildcard IPv6 port.
2726 result = add_listenelt(mctx, list, &addr, ISC_TRUE);
2727 if (result != ISC_R_SUCCESS)
2732 for (result = dns_zone_first(server->zonemgr, &zone);
2733 result == ISC_R_SUCCESS;
2734 next = NULL, result = dns_zone_next(zone, &next), zone = next) {
2735 dns_view_t *zoneview;
2738 * At this point the zone list may contain a stale zone
2739 * just removed from the configuration. To see the validity,
2740 * check if the corresponding view is in our current view list.
2741 * There may also be old zones that are still in the process
2742 * of shutting down and have detached from their old view
2743 * (zoneview == NULL).
2745 zoneview = dns_zone_getview(zone);
2746 if (zoneview == NULL)
2748 for (view = ISC_LIST_HEAD(server->viewlist);
2749 view != NULL && view != zoneview;
2750 view = ISC_LIST_NEXT(view, link))
2755 addrp = dns_zone_getnotifysrc6(zone);
2756 result = add_listenelt(mctx, list, addrp, ISC_FALSE);
2757 if (result != ISC_R_SUCCESS)
2760 addrp = dns_zone_getxfrsource6(zone);
2761 result = add_listenelt(mctx, list, addrp, ISC_FALSE);
2762 if (result != ISC_R_SUCCESS)
2766 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE);
2769 ns_listenlist_detach(&list);
2774 * Even when we failed the procedure, most of other interfaces
2775 * should work correctly. We therefore just warn it.
2777 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2778 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
2779 "could not adjust the listen-on list; "
2780 "some interfaces may not work");
2785 * This event callback is invoked to do periodic network
2786 * interface scanning.
2789 interface_timer_tick(isc_task_t *task, isc_event_t *event) {
2790 isc_result_t result;
2791 ns_server_t *server = (ns_server_t *) event->ev_arg;
2792 INSIST(task == server->task);
2794 isc_event_free(&event);
2796 * XXX should scan interfaces unlocked and get exclusive access
2797 * only to replace ACLs.
2799 result = isc_task_beginexclusive(server->task);
2800 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2801 scan_interfaces(server, ISC_FALSE);
2802 isc_task_endexclusive(server->task);
2806 heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
2807 ns_server_t *server = (ns_server_t *) event->ev_arg;
2811 isc_event_free(&event);
2812 view = ISC_LIST_HEAD(server->viewlist);
2813 while (view != NULL) {
2814 dns_view_dialup(view);
2815 view = ISC_LIST_NEXT(view, link);
2820 pps_timer_tick(isc_task_t *task, isc_event_t *event) {
2821 static unsigned int oldrequests = 0;
2822 unsigned int requests = ns_client_requests;
2825 isc_event_free(&event);
2828 * Don't worry about wrapping as the overflow result will be right.
2830 dns_pps = (requests - oldrequests) / 1200;
2831 oldrequests = requests;
2835 * Replace the current value of '*field', a dynamically allocated
2836 * string or NULL, with a dynamically allocated copy of the
2837 * null-terminated string pointed to by 'value', or NULL.
2840 setstring(ns_server_t *server, char **field, const char *value) {
2843 if (value != NULL) {
2844 copy = isc_mem_strdup(server->mctx, value);
2846 return (ISC_R_NOMEMORY);
2852 isc_mem_free(server->mctx, *field);
2855 return (ISC_R_SUCCESS);
2859 * Replace the current value of '*field', a dynamically allocated
2860 * string or NULL, with another dynamically allocated string
2861 * or NULL if whether 'obj' is a string or void value, respectively.
2864 setoptstring(ns_server_t *server, char **field, const cfg_obj_t *obj) {
2865 if (cfg_obj_isvoid(obj))
2866 return (setstring(server, field, NULL));
2868 return (setstring(server, field, cfg_obj_asstring(obj)));
2872 set_limit(const cfg_obj_t **maps, const char *configname,
2873 const char *description, isc_resource_t resourceid,
2874 isc_resourcevalue_t defaultvalue)
2876 const cfg_obj_t *obj = NULL;
2877 const char *resource;
2878 isc_resourcevalue_t value;
2879 isc_result_t result;
2881 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS)
2884 if (cfg_obj_isstring(obj)) {
2885 resource = cfg_obj_asstring(obj);
2886 if (strcasecmp(resource, "unlimited") == 0)
2887 value = ISC_RESOURCE_UNLIMITED;
2889 INSIST(strcasecmp(resource, "default") == 0);
2890 value = defaultvalue;
2893 value = cfg_obj_asuint64(obj);
2895 result = isc_resource_setlimit(resourceid, value);
2896 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
2897 result == ISC_R_SUCCESS ?
2898 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
2899 "set maximum %s to %" ISC_PRINT_QUADFORMAT "u: %s",
2900 description, value, isc_result_totext(result));
2903 #define SETLIMIT(cfgvar, resource, description) \
2904 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \
2905 ns_g_init ## resource)
2908 set_limits(const cfg_obj_t **maps) {
2909 SETLIMIT("stacksize", stacksize, "stack size");
2910 SETLIMIT("datasize", datasize, "data size");
2911 SETLIMIT("coresize", coresize, "core size");
2912 SETLIMIT("files", openfiles, "open files");
2916 portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports,
2917 isc_boolean_t positive)
2919 const cfg_listelt_t *element;
2921 for (element = cfg_list_first(ports);
2923 element = cfg_list_next(element)) {
2924 const cfg_obj_t *obj = cfg_listelt_value(element);
2926 if (cfg_obj_isuint32(obj)) {
2927 in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
2930 isc_portset_add(portset, port);
2932 isc_portset_remove(portset, port);
2934 const cfg_obj_t *obj_loport, *obj_hiport;
2935 in_port_t loport, hiport;
2937 obj_loport = cfg_tuple_get(obj, "loport");
2938 loport = (in_port_t)cfg_obj_asuint32(obj_loport);
2939 obj_hiport = cfg_tuple_get(obj, "hiport");
2940 hiport = (in_port_t)cfg_obj_asuint32(obj_hiport);
2943 isc_portset_addrange(portset, loport, hiport);
2945 isc_portset_removerange(portset, loport,
2953 removed(dns_zone_t *zone, void *uap) {
2956 if (dns_zone_getview(zone) != uap)
2957 return (ISC_R_SUCCESS);
2959 switch (dns_zone_gettype(zone)) {
2960 case dns_zone_master:
2963 case dns_zone_slave:
2973 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type);
2974 return (ISC_R_SUCCESS);
2978 count_zones(const cfg_obj_t *conf) {
2979 const cfg_obj_t *zonelist = NULL;
2980 const cfg_listelt_t *element;
2983 REQUIRE(conf != NULL);
2985 cfg_map_get(conf, "zone", &zonelist);
2986 for (element = cfg_list_first(zonelist);
2988 element = cfg_list_next(element))
2995 load_configuration(const char *filename, ns_server_t *server,
2996 isc_boolean_t first_time)
2998 cfg_aclconfctx_t aclconfctx;
3000 cfg_parser_t *parser = NULL;
3001 const cfg_listelt_t *element;
3002 const cfg_obj_t *builtin_views;
3003 const cfg_obj_t *maps[3];
3004 const cfg_obj_t *obj;
3005 const cfg_obj_t *options;
3006 const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports;
3007 const cfg_obj_t *views;
3008 dns_view_t *view = NULL;
3009 dns_view_t *view_next;
3010 dns_viewlist_t tmpviewlist;
3011 dns_viewlist_t viewlist;
3012 in_port_t listen_port, udpport_low, udpport_high;
3014 isc_interval_t interval;
3015 isc_portset_t *v4portset = NULL;
3016 isc_portset_t *v6portset = NULL;
3017 isc_resourcevalue_t nfiles;
3018 isc_result_t result;
3019 isc_uint32_t heartbeat_interval;
3020 isc_uint32_t interface_interval;
3021 isc_uint32_t reserved;
3022 isc_uint32_t udpsize;
3023 unsigned int maxsocks;
3025 isc_boolean_t exclusive = ISC_FALSE;
3027 cfg_aclconfctx_init(&aclconfctx);
3028 ISC_LIST_INIT(viewlist);
3031 * Parse the global default pseudo-config file.
3034 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config));
3035 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options",
3041 * Parse the configuration file using the new config code.
3043 result = ISC_R_FAILURE;
3047 * Unless this is lwresd with the -C option, parse the config file.
3049 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) {
3050 isc_log_write(ns_g_lctx,
3051 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3052 ISC_LOG_INFO, "loading configuration from '%s'",
3054 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
3055 cfg_parser_setcallback(parser, directory_callback, NULL);
3056 result = cfg_parse_file(parser, filename, &cfg_type_namedconf,
3061 * If this is lwresd with the -C option, or lwresd with no -C or -c
3062 * option where the above parsing failed, parse resolv.conf.
3064 if (ns_g_lwresdonly &&
3065 (lwresd_g_useresolvconf ||
3066 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND)))
3068 isc_log_write(ns_g_lctx,
3069 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3070 ISC_LOG_INFO, "loading configuration from '%s'",
3071 lwresd_g_resolvconffile);
3073 cfg_parser_destroy(&parser);
3074 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
3075 result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser,
3081 * Check the validity of the configuration.
3083 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx));
3086 * Fill in the maps array, used for resolving defaults.
3090 result = cfg_map_get(config, "options", &options);
3091 if (result == ISC_R_SUCCESS)
3092 maps[i++] = options;
3093 maps[i++] = ns_g_defaults;
3096 /* Ensure exclusive access to configuration data. */
3098 result = isc_task_beginexclusive(server->task);
3099 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3100 exclusive = ISC_TRUE;
3104 * Set process limits, which (usually) needs to be done as root.
3109 * Check if max number of open sockets that the system allows is
3110 * sufficiently large. Failing this condition is not necessarily fatal,
3111 * but may cause subsequent runtime failures for a busy recursive
3114 result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks);
3115 if (result != ISC_R_SUCCESS)
3117 result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles);
3118 if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) {
3119 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3120 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
3121 "max open files (%" ISC_PRINT_QUADFORMAT "u)"
3122 " is smaller than max sockets (%u)",
3127 * Set the number of socket reserved for TCP, stdio etc.
3130 result = ns_config_get(maps, "reserved-sockets", &obj);
3131 INSIST(result == ISC_R_SUCCESS);
3132 reserved = cfg_obj_asuint32(obj);
3133 if (maxsocks != 0) {
3134 if (maxsocks < 128U) /* Prevent underflow. */
3136 else if (reserved > maxsocks - 128U) /* Minimum UDP space. */
3137 reserved = maxsocks - 128;
3139 /* Minimum TCP/stdio space. */
3140 if (reserved < 128U)
3142 if (reserved + 128U > maxsocks && maxsocks != 0) {
3143 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3144 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
3145 "less than 128 UDP sockets available after "
3146 "applying 'reserved-sockets' and 'maxsockets'");
3148 isc__socketmgr_setreserved(ns_g_socketmgr, reserved);
3151 * Configure various server options.
3153 configure_server_quota(maps, "transfers-out", &server->xfroutquota);
3154 configure_server_quota(maps, "tcp-clients", &server->tcpquota);
3155 configure_server_quota(maps, "recursive-clients",
3156 &server->recursionquota);
3157 if (server->recursionquota.max > 1000)
3158 isc_quota_soft(&server->recursionquota,
3159 server->recursionquota.max - 100);
3161 isc_quota_soft(&server->recursionquota, 0);
3163 CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
3164 ns_g_mctx, &server->blackholeacl));
3165 if (server->blackholeacl != NULL)
3166 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
3167 server->blackholeacl);
3170 result = ns_config_get(maps, "match-mapped-addresses", &obj);
3171 INSIST(result == ISC_R_SUCCESS);
3172 server->aclenv.match_mapped = cfg_obj_asboolean(obj);
3174 CHECKM(ns_statschannels_configure(ns_g_server, config, &aclconfctx),
3175 "configuring statistics server(s)");
3178 * Configure sets of UDP query source ports.
3180 CHECKM(isc_portset_create(ns_g_mctx, &v4portset),
3181 "creating UDP port set");
3182 CHECKM(isc_portset_create(ns_g_mctx, &v6portset),
3183 "creating UDP port set");
3187 avoidv4ports = NULL;
3188 avoidv6ports = NULL;
3190 (void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports);
3191 if (usev4ports != NULL)
3192 portset_fromconf(v4portset, usev4ports, ISC_TRUE);
3194 CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
3196 "get the default UDP/IPv4 port range");
3197 if (udpport_low == udpport_high)
3198 isc_portset_add(v4portset, udpport_low);
3200 isc_portset_addrange(v4portset, udpport_low,
3203 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3204 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3205 "using default UDP/IPv4 port range: [%d, %d]",
3206 udpport_low, udpport_high);
3208 (void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
3209 if (avoidv4ports != NULL)
3210 portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);
3212 (void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports);
3213 if (usev6ports != NULL)
3214 portset_fromconf(v6portset, usev6ports, ISC_TRUE);
3216 CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
3218 "get the default UDP/IPv6 port range");
3219 if (udpport_low == udpport_high)
3220 isc_portset_add(v6portset, udpport_low);
3222 isc_portset_addrange(v6portset, udpport_low,
3225 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3226 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3227 "using default UDP/IPv6 port range: [%d, %d]",
3228 udpport_low, udpport_high);
3230 (void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
3231 if (avoidv6ports != NULL)
3232 portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);
3234 dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);
3237 * Set the EDNS UDP size when we don't match a view.
3240 result = ns_config_get(maps, "edns-udp-size", &obj);
3241 INSIST(result == ISC_R_SUCCESS);
3242 udpsize = cfg_obj_asuint32(obj);
3247 ns_g_udpsize = (isc_uint16_t)udpsize;
3250 * Configure the zone manager.
3253 result = ns_config_get(maps, "transfers-in", &obj);
3254 INSIST(result == ISC_R_SUCCESS);
3255 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
3258 result = ns_config_get(maps, "transfers-per-ns", &obj);
3259 INSIST(result == ISC_R_SUCCESS);
3260 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
3263 result = ns_config_get(maps, "serial-query-rate", &obj);
3264 INSIST(result == ISC_R_SUCCESS);
3265 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj));
3268 * Determine which port to use for listening for incoming connections.
3271 listen_port = ns_g_port;
3273 CHECKM(ns_config_getport(config, &listen_port), "port");
3276 * Find the listen queue depth.
3279 result = ns_config_get(maps, "tcp-listen-queue", &obj);
3280 INSIST(result == ISC_R_SUCCESS);
3281 ns_g_listen = cfg_obj_asuint32(obj);
3282 if (ns_g_listen < 3)
3286 * Configure the interface manager according to the "listen-on"
3290 const cfg_obj_t *clistenon = NULL;
3291 ns_listenlist_t *listenon = NULL;
3295 * Even though listen-on is present in the default
3296 * configuration, we can't use it here, since it isn't
3297 * used if we're in lwresd mode. This way is easier.
3299 if (options != NULL)
3300 (void)cfg_map_get(options, "listen-on", &clistenon);
3301 if (clistenon != NULL) {
3302 /* check return code? */
3303 (void)ns_listenlist_fromconfig(clistenon, config,
3304 &aclconfctx, ns_g_mctx,
3306 } else if (!ns_g_lwresdonly) {
3308 * Not specified, use default.
3310 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
3311 ISC_TRUE, &listenon));
3313 if (listenon != NULL) {
3314 ns_interfacemgr_setlistenon4(server->interfacemgr,
3316 ns_listenlist_detach(&listenon);
3323 const cfg_obj_t *clistenon = NULL;
3324 ns_listenlist_t *listenon = NULL;
3326 if (options != NULL)
3327 (void)cfg_map_get(options, "listen-on-v6", &clistenon);
3328 if (clistenon != NULL) {
3329 /* check return code? */
3330 (void)ns_listenlist_fromconfig(clistenon, config,
3331 &aclconfctx, ns_g_mctx,
3333 } else if (!ns_g_lwresdonly) {
3334 isc_boolean_t enable;
3336 * Not specified, use default.
3338 enable = ISC_TF(isc_net_probeipv4() != ISC_R_SUCCESS);
3339 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
3340 enable, &listenon));
3342 if (listenon != NULL) {
3343 ns_interfacemgr_setlistenon6(server->interfacemgr,
3345 ns_listenlist_detach(&listenon);
3350 * Rescan the interface list to pick up changes in the
3351 * listen-on option. It's important that we do this before we try
3352 * to configure the query source, since the dispatcher we use might
3353 * be shared with an interface.
3355 scan_interfaces(server, ISC_TRUE);
3358 * Arrange for further interface scanning to occur periodically
3359 * as specified by the "interface-interval" option.
3362 result = ns_config_get(maps, "interface-interval", &obj);
3363 INSIST(result == ISC_R_SUCCESS);
3364 interface_interval = cfg_obj_asuint32(obj) * 60;
3365 if (interface_interval == 0) {
3366 CHECK(isc_timer_reset(server->interface_timer,
3367 isc_timertype_inactive,
3368 NULL, NULL, ISC_TRUE));
3369 } else if (server->interface_interval != interface_interval) {
3370 isc_interval_set(&interval, interface_interval, 0);
3371 CHECK(isc_timer_reset(server->interface_timer,
3372 isc_timertype_ticker,
3373 NULL, &interval, ISC_FALSE));
3375 server->interface_interval = interface_interval;
3378 * Configure the dialup heartbeat timer.
3381 result = ns_config_get(maps, "heartbeat-interval", &obj);
3382 INSIST(result == ISC_R_SUCCESS);
3383 heartbeat_interval = cfg_obj_asuint32(obj) * 60;
3384 if (heartbeat_interval == 0) {
3385 CHECK(isc_timer_reset(server->heartbeat_timer,
3386 isc_timertype_inactive,
3387 NULL, NULL, ISC_TRUE));
3388 } else if (server->heartbeat_interval != heartbeat_interval) {
3389 isc_interval_set(&interval, heartbeat_interval, 0);
3390 CHECK(isc_timer_reset(server->heartbeat_timer,
3391 isc_timertype_ticker,
3392 NULL, &interval, ISC_FALSE));
3394 server->heartbeat_interval = heartbeat_interval;
3396 isc_interval_set(&interval, 1200, 0);
3397 CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL,
3398 &interval, ISC_FALSE));
3401 (void)cfg_map_get(config, "view", &views);
3404 * Create the views and count all the configured zones in
3405 * order to correctly size the zone manager's task table.
3406 * (We only count zones for configured views; the built-in
3407 * "bind" view can be ignored as it only adds a negligible
3410 * If we're allowing new zones, we need to be able to find the
3411 * new zone file and count those as well. So we setup the new
3412 * zone configuration context, but otherwise view configuration
3413 * waits until after the zone manager's task list has been sized.
3415 for (element = cfg_list_first(views);
3417 element = cfg_list_next(element))
3419 const cfg_obj_t *vconfig = cfg_listelt_value(element);
3420 const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options");
3423 CHECK(create_view(vconfig, &viewlist, &view));
3424 INSIST(view != NULL);
3426 num_zones += count_zones(voptions);
3427 dns_view_detach(&view);
3431 * If there were no explicit views then we do the default
3434 if (views == NULL) {
3435 CHECK(create_view(NULL, &viewlist, &view));
3436 INSIST(view != NULL);
3438 num_zones = count_zones(config);
3439 dns_view_detach(&view);
3443 * Zones have been counted; set the zone manager task pool size.
3445 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3446 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3447 "sizing zone task pool based on %d zones", num_zones);
3448 CHECK(dns_zonemgr_setsize(ns_g_server->zonemgr, num_zones));
3451 * Configure and freeze all explicit views. Explicit
3452 * views that have zones were already created at parsing
3453 * time, but views with no zones must be created here.
3455 for (element = cfg_list_first(views);
3457 element = cfg_list_next(element))
3459 const cfg_obj_t *vconfig = cfg_listelt_value(element);
3462 CHECK(find_view(vconfig, &viewlist, &view));
3463 CHECK(configure_view(view, config, vconfig,
3464 ns_g_mctx, &aclconfctx, ISC_TRUE));
3466 dns_view_freeze(view);
3467 dns_view_detach(&view);
3471 * Make sure we have a default view if and only if there
3472 * were no explicit views.
3474 if (views == NULL) {
3476 * No explicit views; there ought to be a default view.
3477 * There may already be one created as a side effect
3478 * of zone statements, or we may have to create one.
3479 * In either case, we need to configure and freeze it.
3481 CHECK(find_view(NULL, &viewlist, &view));
3482 CHECK(configure_view(view, config, NULL, ns_g_mctx,
3483 &aclconfctx, ISC_TRUE));
3484 dns_view_freeze(view);
3485 dns_view_detach(&view);
3489 * Create (or recreate) the built-in views. Currently
3490 * there is only one, the _bind view.
3492 builtin_views = NULL;
3493 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
3494 &builtin_views) == ISC_R_SUCCESS);
3495 for (element = cfg_list_first(builtin_views);
3497 element = cfg_list_next(element))
3499 const cfg_obj_t *vconfig = cfg_listelt_value(element);
3500 CHECK(create_view(vconfig, &viewlist, &view));
3501 CHECK(configure_view(view, config, vconfig, ns_g_mctx,
3502 &aclconfctx, ISC_FALSE));
3503 dns_view_freeze(view);
3504 dns_view_detach(&view);
3509 * Swap our new view list with the production one.
3511 tmpviewlist = server->viewlist;
3512 server->viewlist = viewlist;
3513 viewlist = tmpviewlist;
3516 * Load the TKEY information from the configuration.
3518 if (options != NULL) {
3519 dns_tkeyctx_t *t = NULL;
3520 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
3522 "configuring TKEY");
3523 if (server->tkeyctx != NULL)
3524 dns_tkeyctx_destroy(&server->tkeyctx);
3525 server->tkeyctx = t;
3529 * Bind the control port(s).
3531 CHECKM(ns_controls_configure(ns_g_server->controls, config,
3533 "binding control channel(s)");
3536 * Bind the lwresd port(s).
3538 CHECKM(ns_lwresd_configure(ns_g_mctx, config),
3539 "binding lightweight resolver ports");
3542 * Open the source of entropy.
3546 result = ns_config_get(maps, "random-device", &obj);
3547 if (result != ISC_R_SUCCESS) {
3548 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3549 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3550 "no source of entropy found");
3552 const char *randomdev = cfg_obj_asstring(obj);
3553 result = isc_entropy_createfilesource(ns_g_entropy,
3555 if (result != ISC_R_SUCCESS)
3556 isc_log_write(ns_g_lctx,
3557 NS_LOGCATEGORY_GENERAL,
3558 NS_LOGMODULE_SERVER,
3560 "could not open entropy source "
3563 isc_result_totext(result));
3564 #ifdef PATH_RANDOMDEV
3565 if (ns_g_fallbackentropy != NULL) {
3566 if (result != ISC_R_SUCCESS) {
3567 isc_log_write(ns_g_lctx,
3568 NS_LOGCATEGORY_GENERAL,
3569 NS_LOGMODULE_SERVER,
3571 "using pre-chroot entropy source "
3574 isc_entropy_detach(&ns_g_entropy);
3575 isc_entropy_attach(ns_g_fallbackentropy,
3578 isc_entropy_detach(&ns_g_fallbackentropy);
3585 * Relinquish root privileges.
3591 * Check that the working directory is writable.
3593 if (access(".", W_OK) != 0) {
3594 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3595 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3596 "the working directory is not writable");
3600 * Configure the logging system.
3602 * Do this after changing UID to make sure that any log
3603 * files specified in named.conf get created by the
3604 * unprivileged user, not root.
3606 if (ns_g_logstderr) {
3607 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3608 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3609 "ignoring config file logging "
3610 "statement due to -g option");
3612 const cfg_obj_t *logobj = NULL;
3613 isc_logconfig_t *logc = NULL;
3615 CHECKM(isc_logconfig_create(ns_g_lctx, &logc),
3616 "creating new logging configuration");
3619 (void)cfg_map_get(config, "logging", &logobj);
3620 if (logobj != NULL) {
3621 CHECKM(ns_log_configure(logc, logobj),
3622 "configuring logging");
3624 CHECKM(ns_log_setdefaultchannels(logc),
3625 "setting up default logging channels");
3626 CHECKM(ns_log_setunmatchedcategory(logc),
3627 "setting up default 'category unmatched'");
3628 CHECKM(ns_log_setdefaultcategory(logc),
3629 "setting up default 'category default'");
3632 result = isc_logconfig_use(ns_g_lctx, logc);
3633 if (result != ISC_R_SUCCESS) {
3634 isc_logconfig_destroy(&logc);
3635 CHECKM(result, "installing logging configuration");
3638 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3639 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
3640 "now using logging configuration from "
3645 * Set the default value of the query logging flag depending
3646 * whether a "queries" category has been defined. This is
3647 * a disgusting hack, but we need to do this for BIND 8
3651 const cfg_obj_t *logobj = NULL;
3652 const cfg_obj_t *categories = NULL;
3655 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
3656 server->log_queries = cfg_obj_asboolean(obj);
3659 (void)cfg_map_get(config, "logging", &logobj);
3661 (void)cfg_map_get(logobj, "category",
3663 if (categories != NULL) {
3664 const cfg_listelt_t *element;
3665 for (element = cfg_list_first(categories);
3667 element = cfg_list_next(element))
3669 const cfg_obj_t *catobj;
3672 obj = cfg_listelt_value(element);
3673 catobj = cfg_tuple_get(obj, "name");
3674 str = cfg_obj_asstring(catobj);
3675 if (strcasecmp(str, "queries") == 0)
3676 server->log_queries = ISC_TRUE;
3683 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)
3684 if (cfg_obj_isvoid(obj))
3685 ns_os_writepidfile(NULL, first_time);
3687 ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
3688 else if (ns_g_lwresdonly)
3689 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
3691 ns_os_writepidfile(ns_g_defaultpidfile, first_time);
3694 if (options != NULL &&
3695 cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS)
3696 ns_g_memstatistics = cfg_obj_asboolean(obj);
3698 ns_g_memstatistics =
3699 ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0);
3702 if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS)
3703 ns_main_setmemstats(cfg_obj_asstring(obj));
3704 else if (ns_g_memstatistics)
3705 ns_main_setmemstats("named.memstats");
3707 ns_main_setmemstats(NULL);
3710 result = ns_config_get(maps, "statistics-file", &obj);
3711 INSIST(result == ISC_R_SUCCESS);
3712 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
3716 result = ns_config_get(maps, "dump-file", &obj);
3717 INSIST(result == ISC_R_SUCCESS);
3718 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),
3722 result = ns_config_get(maps, "recursing-file", &obj);
3723 INSIST(result == ISC_R_SUCCESS);
3724 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
3728 result = ns_config_get(maps, "version", &obj);
3729 if (result == ISC_R_SUCCESS) {
3730 CHECKM(setoptstring(server, &server->version, obj), "strdup");
3731 server->version_set = ISC_TRUE;
3733 server->version_set = ISC_FALSE;
3737 result = ns_config_get(maps, "hostname", &obj);
3738 if (result == ISC_R_SUCCESS) {
3739 CHECKM(setoptstring(server, &server->hostname, obj), "strdup");
3740 server->hostname_set = ISC_TRUE;
3742 server->hostname_set = ISC_FALSE;
3746 result = ns_config_get(maps, "server-id", &obj);
3747 server->server_usehostname = ISC_FALSE;
3748 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
3749 /* The parser translates "hostname" to ISC_TRUE */
3750 server->server_usehostname = cfg_obj_asboolean(obj);
3751 result = setstring(server, &server->server_id, NULL);
3752 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3753 } else if (result == ISC_R_SUCCESS) {
3754 /* Found a quoted string */
3755 CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
3757 result = setstring(server, &server->server_id, NULL);
3758 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3762 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj);
3763 if (result == ISC_R_SUCCESS) {
3764 server->flushonshutdown = cfg_obj_asboolean(obj);
3766 server->flushonshutdown = ISC_FALSE;
3769 result = ISC_R_SUCCESS;
3772 if (v4portset != NULL)
3773 isc_portset_destroy(ns_g_mctx, &v4portset);
3775 if (v6portset != NULL)
3776 isc_portset_destroy(ns_g_mctx, &v6portset);
3778 cfg_aclconfctx_destroy(&aclconfctx);
3780 if (parser != NULL) {
3782 cfg_obj_destroy(parser, &config);
3783 cfg_parser_destroy(&parser);
3787 dns_view_detach(&view);
3790 * This cleans up either the old production view list
3791 * or our temporary list depending on whether they
3792 * were swapped above or not.
3794 for (view = ISC_LIST_HEAD(viewlist);
3797 view_next = ISC_LIST_NEXT(view, link);
3798 ISC_LIST_UNLINK(viewlist, view, link);
3799 if (result == ISC_R_SUCCESS &&
3800 strcmp(view->name, "_bind") != 0)
3801 (void)dns_zt_apply(view->zonetable, ISC_FALSE,
3803 dns_view_detach(&view);
3807 * Adjust the listening interfaces in accordance with the source
3808 * addresses specified in views and zones.
3810 if (isc_net_probeipv6() == ISC_R_SUCCESS)
3811 adjust_interfaces(server, ns_g_mctx);
3813 /* Relinquish exclusive access to configuration data. */
3815 isc_task_endexclusive(server->task);
3817 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3818 ISC_LOG_DEBUG(1), "load_configuration: %s",
3819 isc_result_totext(result));
3825 load_zones(ns_server_t *server, isc_boolean_t stop) {
3826 isc_result_t result;
3829 result = isc_task_beginexclusive(server->task);
3830 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3833 * Load zone data from disk.
3835 for (view = ISC_LIST_HEAD(server->viewlist);
3837 view = ISC_LIST_NEXT(view, link))
3839 CHECK(dns_view_load(view, stop));
3843 * Force zone maintenance. Do this after loading
3844 * so that we know when we need to force AXFR of
3845 * slave zones whose master files are missing.
3847 CHECK(dns_zonemgr_forcemaint(server->zonemgr));
3849 isc_task_endexclusive(server->task);
3854 load_new_zones(ns_server_t *server, isc_boolean_t stop) {
3855 isc_result_t result;
3858 result = isc_task_beginexclusive(server->task);
3859 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3862 * Load zone data from disk.
3864 for (view = ISC_LIST_HEAD(server->viewlist);
3866 view = ISC_LIST_NEXT(view, link))
3868 CHECK(dns_view_loadnew(view, stop));
3871 * Force zone maintenance. Do this after loading
3872 * so that we know when we need to force AXFR of
3873 * slave zones whose master files are missing.
3875 dns_zonemgr_resumexfrs(server->zonemgr);
3877 isc_task_endexclusive(server->task);
3882 run_server(isc_task_t *task, isc_event_t *event) {
3883 isc_result_t result;
3884 ns_server_t *server = (ns_server_t *)event->ev_arg;
3886 INSIST(task == server->task);
3888 isc_event_free(&event);
3890 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy,
3892 "creating dispatch manager");
3894 dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats);
3896 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
3897 ns_g_socketmgr, ns_g_dispatchmgr,
3898 &server->interfacemgr),
3899 "creating interface manager");
3901 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
3902 NULL, NULL, server->task,
3903 interface_timer_tick,
3904 server, &server->interface_timer),
3905 "creating interface timer");
3907 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
3908 NULL, NULL, server->task,
3909 heartbeat_timer_tick,
3910 server, &server->heartbeat_timer),
3911 "creating heartbeat timer");
3913 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
3914 NULL, NULL, server->task, pps_timer_tick,
3915 server, &server->pps_timer),
3916 "creating pps timer");
3918 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser),
3919 "creating default configuration parser");
3921 if (ns_g_lwresdonly)
3922 CHECKFATAL(load_configuration(lwresd_g_conffile, server,
3924 "loading configuration");
3926 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE),
3927 "loading configuration");
3931 CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones");
3934 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3935 ISC_LOG_NOTICE, "running");
3939 ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) {
3941 REQUIRE(NS_SERVER_VALID(server));
3943 server->flushonshutdown = flush;
3947 shutdown_server(isc_task_t *task, isc_event_t *event) {
3948 isc_result_t result;
3949 dns_view_t *view, *view_next;
3950 ns_server_t *server = (ns_server_t *)event->ev_arg;
3951 isc_boolean_t flush = server->flushonshutdown;
3954 INSIST(task == server->task);
3956 result = isc_task_beginexclusive(server->task);
3957 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3959 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3960 ISC_LOG_INFO, "shutting down%s",
3961 flush ? ": flushing changes" : "");
3963 ns_statschannels_shutdown(server);
3964 ns_controls_shutdown(server->controls);
3965 end_reserved_dispatches(server, ISC_TRUE);
3967 cfg_obj_destroy(ns_g_parser, &ns_g_config);
3968 cfg_parser_destroy(&ns_g_parser);
3970 for (view = ISC_LIST_HEAD(server->viewlist);
3973 view_next = ISC_LIST_NEXT(view, link);
3974 ISC_LIST_UNLINK(server->viewlist, view, link);
3976 dns_view_flushanddetach(&view);
3978 dns_view_detach(&view);
3981 isc_timer_detach(&server->interface_timer);
3982 isc_timer_detach(&server->heartbeat_timer);
3983 isc_timer_detach(&server->pps_timer);
3985 ns_interfacemgr_shutdown(server->interfacemgr);
3986 ns_interfacemgr_detach(&server->interfacemgr);
3988 dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
3990 dns_zonemgr_shutdown(server->zonemgr);
3992 if (server->blackholeacl != NULL)
3993 dns_acl_detach(&server->blackholeacl);
3995 dns_db_detach(&server->in_roothints);
3997 isc_task_endexclusive(server->task);
3999 isc_task_detach(&server->task);
4001 isc_event_free(&event);
4005 ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
4006 isc_result_t result;
4007 ns_server_t *server = isc_mem_get(mctx, sizeof(*server));
4010 fatal("allocating server object", ISC_R_NOMEMORY);
4012 server->mctx = mctx;
4013 server->task = NULL;
4015 /* Initialize configuration data with default values. */
4017 result = isc_quota_init(&server->xfroutquota, 10);
4018 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4019 result = isc_quota_init(&server->tcpquota, 10);
4020 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4021 result = isc_quota_init(&server->recursionquota, 100);
4022 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4024 result = dns_aclenv_init(mctx, &server->aclenv);
4025 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4027 /* Initialize server data structures. */
4028 server->zonemgr = NULL;
4029 server->interfacemgr = NULL;
4030 ISC_LIST_INIT(server->viewlist);
4031 server->in_roothints = NULL;
4032 server->blackholeacl = NULL;
4034 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
4035 &server->in_roothints),
4036 "setting up root hints");
4038 CHECKFATAL(isc_mutex_init(&server->reload_event_lock),
4039 "initializing reload event lock");
4040 server->reload_event =
4041 isc_event_allocate(ns_g_mctx, server,
4045 sizeof(isc_event_t));
4046 CHECKFATAL(server->reload_event == NULL ?
4047 ISC_R_NOMEMORY : ISC_R_SUCCESS,
4048 "allocating reload event");
4050 CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY),
4051 "initializing DST");
4053 server->tkeyctx = NULL;
4054 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
4056 "creating TKEY context");
4059 * Setup the server task, which is responsible for coordinating
4060 * startup and shutdown of the server.
4062 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),
4063 "creating server task");
4064 isc_task_setname(server->task, "server", server);
4065 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
4066 "isc_task_onshutdown");
4067 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
4070 server->interface_timer = NULL;
4071 server->heartbeat_timer = NULL;
4072 server->pps_timer = NULL;
4074 server->interface_interval = 0;
4075 server->heartbeat_interval = 0;
4077 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
4078 ns_g_socketmgr, &server->zonemgr),
4079 "dns_zonemgr_create");
4080 CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000),
4081 "dns_zonemgr_setsize");
4083 server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
4084 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
4086 server->nsstats = NULL;
4087 server->rcvquerystats = NULL;
4088 server->opcodestats = NULL;
4089 server->zonestats = NULL;
4090 server->resolverstats = NULL;
4091 server->sockstats = NULL;
4092 CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats,
4093 isc_sockstatscounter_max),
4094 "isc_stats_create");
4095 isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats);
4097 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
4098 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
4101 server->recfile = isc_mem_strdup(server->mctx, "named.recursing");
4102 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
4105 server->hostname_set = ISC_FALSE;
4106 server->hostname = NULL;
4107 server->version_set = ISC_FALSE;
4108 server->version = NULL;
4109 server->server_usehostname = ISC_FALSE;
4110 server->server_id = NULL;
4112 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->nsstats,
4113 dns_nsstatscounter_max),
4114 "dns_stats_create (server)");
4116 CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx,
4117 &server->rcvquerystats),
4118 "dns_stats_create (rcvquery)");
4120 CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats),
4121 "dns_stats_create (opcode)");
4123 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->zonestats,
4124 dns_zonestatscounter_max),
4125 "dns_stats_create (zone)");
4127 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->resolverstats,
4128 dns_resstatscounter_max),
4129 "dns_stats_create (resolver)");
4131 server->flushonshutdown = ISC_FALSE;
4132 server->log_queries = ISC_FALSE;
4134 server->controls = NULL;
4135 CHECKFATAL(ns_controls_create(server, &server->controls),
4136 "ns_controls_create");
4137 server->dispatchgen = 0;
4138 ISC_LIST_INIT(server->dispatches);
4140 ISC_LIST_INIT(server->statschannels);
4142 server->magic = NS_SERVER_MAGIC;
4147 ns_server_destroy(ns_server_t **serverp) {
4148 ns_server_t *server = *serverp;
4149 REQUIRE(NS_SERVER_VALID(server));
4151 ns_controls_destroy(&server->controls);
4153 isc_stats_detach(&server->nsstats);
4154 dns_stats_detach(&server->rcvquerystats);
4155 dns_stats_detach(&server->opcodestats);
4156 isc_stats_detach(&server->zonestats);
4157 isc_stats_detach(&server->resolverstats);
4158 isc_stats_detach(&server->sockstats);
4160 isc_mem_free(server->mctx, server->statsfile);
4161 isc_mem_free(server->mctx, server->dumpfile);
4162 isc_mem_free(server->mctx, server->recfile);
4164 if (server->version != NULL)
4165 isc_mem_free(server->mctx, server->version);
4166 if (server->hostname != NULL)
4167 isc_mem_free(server->mctx, server->hostname);
4168 if (server->server_id != NULL)
4169 isc_mem_free(server->mctx, server->server_id);
4171 if (server->zonemgr != NULL)
4172 dns_zonemgr_detach(&server->zonemgr);
4174 if (server->tkeyctx != NULL)
4175 dns_tkeyctx_destroy(&server->tkeyctx);
4179 isc_event_free(&server->reload_event);
4181 INSIST(ISC_LIST_EMPTY(server->viewlist));
4183 dns_aclenv_destroy(&server->aclenv);
4185 isc_quota_destroy(&server->recursionquota);
4186 isc_quota_destroy(&server->tcpquota);
4187 isc_quota_destroy(&server->xfroutquota);
4190 isc_mem_put(server->mctx, server, sizeof(*server));
4195 fatal(const char *msg, isc_result_t result) {
4196 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
4197 ISC_LOG_CRITICAL, "%s: %s", msg,
4198 isc_result_totext(result));
4199 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
4200 ISC_LOG_CRITICAL, "exiting (due to fatal error)");
4205 start_reserved_dispatches(ns_server_t *server) {
4207 REQUIRE(NS_SERVER_VALID(server));
4209 server->dispatchgen++;
4213 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) {
4214 ns_dispatch_t *dispatch, *nextdispatch;
4216 REQUIRE(NS_SERVER_VALID(server));
4218 for (dispatch = ISC_LIST_HEAD(server->dispatches);
4220 dispatch = nextdispatch) {
4221 nextdispatch = ISC_LIST_NEXT(dispatch, link);
4222 if (!all && server->dispatchgen == dispatch-> dispatchgen)
4224 ISC_LIST_UNLINK(server->dispatches, dispatch, link);
4225 dns_dispatch_detach(&dispatch->dispatch);
4226 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
4231 ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) {
4232 ns_dispatch_t *dispatch;
4234 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
4235 isc_result_t result;
4236 unsigned int attrs, attrmask;
4238 REQUIRE(NS_SERVER_VALID(server));
4240 port = isc_sockaddr_getport(addr);
4241 if (port == 0 || port >= 1024)
4244 for (dispatch = ISC_LIST_HEAD(server->dispatches);
4246 dispatch = ISC_LIST_NEXT(dispatch, link)) {
4247 if (isc_sockaddr_equal(&dispatch->addr, addr))
4250 if (dispatch != NULL) {
4251 dispatch->dispatchgen = server->dispatchgen;
4255 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch));
4256 if (dispatch == NULL) {
4257 result = ISC_R_NOMEMORY;
4261 dispatch->addr = *addr;
4262 dispatch->dispatchgen = server->dispatchgen;
4263 dispatch->dispatch = NULL;
4266 attrs |= DNS_DISPATCHATTR_UDP;
4267 switch (isc_sockaddr_pf(addr)) {
4269 attrs |= DNS_DISPATCHATTR_IPV4;
4272 attrs |= DNS_DISPATCHATTR_IPV6;
4275 result = ISC_R_NOTIMPLEMENTED;
4279 attrmask |= DNS_DISPATCHATTR_UDP;
4280 attrmask |= DNS_DISPATCHATTR_TCP;
4281 attrmask |= DNS_DISPATCHATTR_IPV4;
4282 attrmask |= DNS_DISPATCHATTR_IPV6;
4284 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
4285 ns_g_taskmgr, &dispatch->addr, 4096,
4286 1000, 32768, 16411, 16433,
4287 attrs, attrmask, &dispatch->dispatch);
4288 if (result != ISC_R_SUCCESS)
4291 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
4296 if (dispatch != NULL)
4297 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
4298 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
4299 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4300 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
4301 "unable to create dispatch for reserved port %s: %s",
4302 addrbuf, isc_result_totext(result));
4307 loadconfig(ns_server_t *server) {
4308 isc_result_t result;
4309 start_reserved_dispatches(server);
4310 result = load_configuration(ns_g_lwresdonly ?
4311 lwresd_g_conffile : ns_g_conffile,
4313 if (result == ISC_R_SUCCESS) {
4314 end_reserved_dispatches(server, ISC_FALSE);
4315 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4316 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4317 "reloading configuration succeeded");
4319 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4320 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
4321 "reloading configuration failed: %s",
4322 isc_result_totext(result));
4328 reload(ns_server_t *server) {
4329 isc_result_t result;
4330 CHECK(loadconfig(server));
4332 result = load_zones(server, ISC_FALSE);
4333 if (result == ISC_R_SUCCESS)
4334 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4335 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4336 "reloading zones succeeded");
4338 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4339 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
4340 "reloading zones failed: %s",
4341 isc_result_totext(result));
4348 reconfig(ns_server_t *server) {
4349 isc_result_t result;
4350 CHECK(loadconfig(server));
4352 result = load_new_zones(server, ISC_FALSE);
4353 if (result == ISC_R_SUCCESS)
4354 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4355 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4356 "any newly configured zones are now loaded");
4358 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4359 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
4360 "loading new zones failed: %s",
4361 isc_result_totext(result));
4367 * Handle a reload event (from SIGHUP).
4370 ns_server_reload(isc_task_t *task, isc_event_t *event) {
4371 ns_server_t *server = (ns_server_t *)event->ev_arg;
4373 INSIST(task = server->task);
4376 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4377 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4378 "received SIGHUP signal to reload zones");
4379 (void)reload(server);
4381 LOCK(&server->reload_event_lock);
4382 INSIST(server->reload_event == NULL);
4383 server->reload_event = event;
4384 UNLOCK(&server->reload_event_lock);
4388 ns_server_reloadwanted(ns_server_t *server) {
4389 LOCK(&server->reload_event_lock);
4390 if (server->reload_event != NULL)
4391 isc_task_send(server->task, &server->reload_event);
4392 UNLOCK(&server->reload_event_lock);
4396 next_token(char **stringp, const char *delim) {
4400 res = strsep(stringp, delim);
4403 } while (*res == '\0');
4408 * Find the zone specified in the control channel command 'args',
4409 * if any. If a zone is specified, point '*zonep' at it, otherwise
4410 * set '*zonep' to NULL.
4413 zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
4415 const char *zonetxt;
4417 const char *viewtxt = NULL;
4418 dns_fixedname_t name;
4419 isc_result_t result;
4421 dns_view_t *view = NULL;
4422 dns_rdataclass_t rdclass;
4424 REQUIRE(zonep != NULL && *zonep == NULL);
4428 /* Skip the command name. */
4429 ptr = next_token(&input, " \t");
4431 return (ISC_R_UNEXPECTEDEND);
4433 /* Look for the zone name. */
4434 zonetxt = next_token(&input, " \t");
4435 if (zonetxt == NULL)
4436 return (ISC_R_SUCCESS);
4438 /* Look for the optional class name. */
4439 classtxt = next_token(&input, " \t");
4440 if (classtxt != NULL) {
4441 /* Look for the optional view name. */
4442 viewtxt = next_token(&input, " \t");
4445 isc_buffer_init(&buf, zonetxt, strlen(zonetxt));
4446 isc_buffer_add(&buf, strlen(zonetxt));
4447 dns_fixedname_init(&name);
4448 result = dns_name_fromtext(dns_fixedname_name(&name),
4449 &buf, dns_rootname, ISC_FALSE, NULL);
4450 if (result != ISC_R_SUCCESS)
4453 if (classtxt != NULL) {
4456 r.length = strlen(classtxt);
4457 result = dns_rdataclass_fromtext(&rdclass, &r);
4458 if (result != ISC_R_SUCCESS)
4461 rdclass = dns_rdataclass_in;
4463 if (viewtxt == NULL) {
4464 result = dns_viewlist_findzone(&server->viewlist,
4465 dns_fixedname_name(&name),
4466 ISC_TF(classtxt == NULL),
4469 result = dns_viewlist_find(&server->viewlist, viewtxt,
4471 if (result != ISC_R_SUCCESS)
4474 result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
4476 dns_view_detach(&view);
4479 /* Partial match? */
4480 if (result != ISC_R_SUCCESS && *zonep != NULL)
4481 dns_zone_detach(zonep);
4482 if (result == DNS_R_PARTIALMATCH)
4483 result = ISC_R_NOTFOUND;
4489 * Act on a "retransfer" command from the command channel.
4492 ns_server_retransfercommand(ns_server_t *server, char *args) {
4493 isc_result_t result;
4494 dns_zone_t *zone = NULL;
4495 dns_zonetype_t type;
4497 result = zone_from_args(server, args, &zone);
4498 if (result != ISC_R_SUCCESS)
4501 return (ISC_R_UNEXPECTEDEND);
4502 type = dns_zone_gettype(zone);
4503 if (type == dns_zone_slave || type == dns_zone_stub)
4504 dns_zone_forcereload(zone);
4506 result = ISC_R_NOTFOUND;
4507 dns_zone_detach(&zone);
4512 * Act on a "reload" command from the command channel.
4515 ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
4516 isc_result_t result;
4517 dns_zone_t *zone = NULL;
4518 dns_zonetype_t type;
4519 const char *msg = NULL;
4521 result = zone_from_args(server, args, &zone);
4522 if (result != ISC_R_SUCCESS)
4525 result = reload(server);
4526 if (result == ISC_R_SUCCESS)
4527 msg = "server reload successful";
4529 type = dns_zone_gettype(zone);
4530 if (type == dns_zone_slave || type == dns_zone_stub) {
4531 dns_zone_refresh(zone);
4532 dns_zone_detach(&zone);
4533 msg = "zone refresh queued";
4535 result = dns_zone_load(zone);
4536 dns_zone_detach(&zone);
4539 msg = "zone reload successful";
4541 case DNS_R_CONTINUE:
4542 msg = "zone reload queued";
4543 result = ISC_R_SUCCESS;
4545 case DNS_R_UPTODATE:
4546 msg = "zone reload up-to-date";
4547 result = ISC_R_SUCCESS;
4550 /* failure message will be generated by rndc */
4555 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
4556 isc_buffer_putmem(text, (const unsigned char *)msg,
4562 * Act on a "reconfig" command from the command channel.
4565 ns_server_reconfigcommand(ns_server_t *server, char *args) {
4569 return (ISC_R_SUCCESS);
4573 * Act on a "notify" command from the command channel.
4576 ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) {
4577 isc_result_t result;
4578 dns_zone_t *zone = NULL;
4579 const unsigned char msg[] = "zone notify queued";
4581 result = zone_from_args(server, args, &zone);
4582 if (result != ISC_R_SUCCESS)
4585 return (ISC_R_UNEXPECTEDEND);
4587 dns_zone_notify(zone);
4588 dns_zone_detach(&zone);
4589 if (sizeof(msg) <= isc_buffer_availablelength(text))
4590 isc_buffer_putmem(text, msg, sizeof(msg));
4592 return (ISC_R_SUCCESS);
4596 * Act on a "refresh" command from the command channel.
4599 ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
4600 isc_result_t result;
4601 dns_zone_t *zone = NULL;
4602 const unsigned char msg1[] = "zone refresh queued";
4603 const unsigned char msg2[] = "not a slave or stub zone";
4604 dns_zonetype_t type;
4606 result = zone_from_args(server, args, &zone);
4607 if (result != ISC_R_SUCCESS)
4610 return (ISC_R_UNEXPECTEDEND);
4612 type = dns_zone_gettype(zone);
4613 if (type == dns_zone_slave || type == dns_zone_stub) {
4614 dns_zone_refresh(zone);
4615 dns_zone_detach(&zone);
4616 if (sizeof(msg1) <= isc_buffer_availablelength(text))
4617 isc_buffer_putmem(text, msg1, sizeof(msg1));
4618 return (ISC_R_SUCCESS);
4621 dns_zone_detach(&zone);
4622 if (sizeof(msg2) <= isc_buffer_availablelength(text))
4623 isc_buffer_putmem(text, msg2, sizeof(msg2));
4624 return (ISC_R_FAILURE);
4628 ns_server_togglequerylog(ns_server_t *server) {
4629 server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE;
4631 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4632 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4633 "query logging is now %s",
4634 server->log_queries ? "on" : "off");
4635 return (ISC_R_SUCCESS);
4639 ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
4640 cfg_aclconfctx_t *actx,
4641 isc_mem_t *mctx, ns_listenlist_t **target)
4643 isc_result_t result;
4644 const cfg_listelt_t *element;
4645 ns_listenlist_t *dlist = NULL;
4647 REQUIRE(target != NULL && *target == NULL);
4649 result = ns_listenlist_create(mctx, &dlist);
4650 if (result != ISC_R_SUCCESS)
4653 for (element = cfg_list_first(listenlist);
4655 element = cfg_list_next(element))
4657 ns_listenelt_t *delt = NULL;
4658 const cfg_obj_t *listener = cfg_listelt_value(element);
4659 result = ns_listenelt_fromconfig(listener, config, actx,
4661 if (result != ISC_R_SUCCESS)
4663 ISC_LIST_APPEND(dlist->elts, delt, link);
4666 return (ISC_R_SUCCESS);
4669 ns_listenlist_detach(&dlist);
4674 * Create a listen list from the corresponding configuration
4678 ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
4679 cfg_aclconfctx_t *actx,
4680 isc_mem_t *mctx, ns_listenelt_t **target)
4682 isc_result_t result;
4683 const cfg_obj_t *portobj;
4685 ns_listenelt_t *delt = NULL;
4686 REQUIRE(target != NULL && *target == NULL);
4688 portobj = cfg_tuple_get(listener, "port");
4689 if (!cfg_obj_isuint32(portobj)) {
4690 if (ns_g_port != 0) {
4693 result = ns_config_getport(config, &port);
4694 if (result != ISC_R_SUCCESS)
4698 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
4699 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
4700 "port value '%u' is out of range",
4701 cfg_obj_asuint32(portobj));
4702 return (ISC_R_RANGE);
4704 port = (in_port_t)cfg_obj_asuint32(portobj);
4707 result = ns_listenelt_create(mctx, port, NULL, &delt);
4708 if (result != ISC_R_SUCCESS)
4711 result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"),
4712 config, ns_g_lctx, actx, mctx, 0,
4714 if (result != ISC_R_SUCCESS) {
4715 ns_listenelt_destroy(delt);
4719 return (ISC_R_SUCCESS);
4723 ns_server_dumpstats(ns_server_t *server) {
4724 isc_result_t result;
4727 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
4728 "could not open statistics dump file", server->statsfile);
4730 result = ns_stats_dump(server, fp);
4734 (void)isc_stdio_close(fp);
4735 if (result == ISC_R_SUCCESS)
4736 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4737 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4738 "dumpstats complete");
4740 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4741 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
4742 "dumpstats failed: %s",
4743 dns_result_totext(result));
4748 add_zone_tolist(dns_zone_t *zone, void *uap) {
4749 struct dumpcontext *dctx = uap;
4750 struct zonelistentry *zle;
4752 zle = isc_mem_get(dctx->mctx, sizeof *zle);
4754 return (ISC_R_NOMEMORY);
4756 dns_zone_attach(zone, &zle->zone);
4757 ISC_LINK_INIT(zle, link);
4758 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
4759 return (ISC_R_SUCCESS);
4763 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
4764 struct viewlistentry *vle;
4765 isc_result_t result = ISC_R_SUCCESS;
4768 * Prevent duplicate views.
4770 for (vle = ISC_LIST_HEAD(dctx->viewlist);
4772 vle = ISC_LIST_NEXT(vle, link))
4773 if (vle->view == view)
4774 return (ISC_R_SUCCESS);
4776 vle = isc_mem_get(dctx->mctx, sizeof *vle);
4778 return (ISC_R_NOMEMORY);
4780 dns_view_attach(view, &vle->view);
4781 ISC_LINK_INIT(vle, link);
4782 ISC_LIST_INIT(vle->zonelist);
4783 ISC_LIST_APPEND(dctx->viewlist, vle, link);
4784 if (dctx->dumpzones)
4785 result = dns_zt_apply(view->zonetable, ISC_TRUE,
4786 add_zone_tolist, dctx);
4791 dumpcontext_destroy(struct dumpcontext *dctx) {
4792 struct viewlistentry *vle;
4793 struct zonelistentry *zle;
4795 vle = ISC_LIST_HEAD(dctx->viewlist);
4796 while (vle != NULL) {
4797 ISC_LIST_UNLINK(dctx->viewlist, vle, link);
4798 zle = ISC_LIST_HEAD(vle->zonelist);
4799 while (zle != NULL) {
4800 ISC_LIST_UNLINK(vle->zonelist, zle, link);
4801 dns_zone_detach(&zle->zone);
4802 isc_mem_put(dctx->mctx, zle, sizeof *zle);
4803 zle = ISC_LIST_HEAD(vle->zonelist);
4805 dns_view_detach(&vle->view);
4806 isc_mem_put(dctx->mctx, vle, sizeof *vle);
4807 vle = ISC_LIST_HEAD(dctx->viewlist);
4809 if (dctx->version != NULL)
4810 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
4811 if (dctx->db != NULL)
4812 dns_db_detach(&dctx->db);
4813 if (dctx->cache != NULL)
4814 dns_db_detach(&dctx->cache);
4815 if (dctx->task != NULL)
4816 isc_task_detach(&dctx->task);
4817 if (dctx->fp != NULL)
4818 (void)isc_stdio_close(dctx->fp);
4819 if (dctx->mdctx != NULL)
4820 dns_dumpctx_detach(&dctx->mdctx);
4821 isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
4825 dumpdone(void *arg, isc_result_t result) {
4826 struct dumpcontext *dctx = arg;
4828 const dns_master_style_t *style;
4830 if (result != ISC_R_SUCCESS)
4832 if (dctx->mdctx != NULL)
4833 dns_dumpctx_detach(&dctx->mdctx);
4834 if (dctx->view == NULL) {
4835 dctx->view = ISC_LIST_HEAD(dctx->viewlist);
4836 if (dctx->view == NULL)
4838 INSIST(dctx->zone == NULL);
4842 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
4844 if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) {
4845 style = &dns_master_style_cache;
4846 /* start cache dump */
4847 if (dctx->view->view->cachedb != NULL)
4848 dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
4849 if (dctx->cache != NULL) {
4851 fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n",
4852 dctx->view->view->name);
4853 result = dns_master_dumptostreaminc(dctx->mctx,
4859 if (result == DNS_R_CONTINUE)
4861 if (result == ISC_R_NOTIMPLEMENTED)
4862 fprintf(dctx->fp, "; %s\n",
4863 dns_result_totext(result));
4864 else if (result != ISC_R_SUCCESS)
4868 if (dctx->cache != NULL) {
4869 dns_adb_dump(dctx->view->view->adb, dctx->fp);
4870 dns_resolver_printbadcache(dctx->view->view->resolver,
4872 dns_db_detach(&dctx->cache);
4874 if (dctx->dumpzones) {
4875 style = &dns_master_style_full;
4877 if (dctx->version != NULL)
4878 dns_db_closeversion(dctx->db, &dctx->version,
4880 if (dctx->db != NULL)
4881 dns_db_detach(&dctx->db);
4882 if (dctx->zone == NULL)
4883 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
4885 dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
4886 if (dctx->zone != NULL) {
4887 /* start zone dump */
4888 dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
4889 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
4890 result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
4891 if (result != ISC_R_SUCCESS) {
4892 fprintf(dctx->fp, "; %s\n",
4893 dns_result_totext(result));
4896 dns_db_currentversion(dctx->db, &dctx->version);
4897 result = dns_master_dumptostreaminc(dctx->mctx,
4904 if (result == DNS_R_CONTINUE)
4906 if (result == ISC_R_NOTIMPLEMENTED) {
4907 fprintf(dctx->fp, "; %s\n",
4908 dns_result_totext(result));
4909 result = ISC_R_SUCCESS;
4913 if (result != ISC_R_SUCCESS)
4917 if (dctx->view != NULL)
4918 dctx->view = ISC_LIST_NEXT(dctx->view, link);
4919 if (dctx->view != NULL)
4922 fprintf(dctx->fp, "; Dump complete\n");
4923 result = isc_stdio_flush(dctx->fp);
4924 if (result == ISC_R_SUCCESS)
4925 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4926 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4929 if (result != ISC_R_SUCCESS)
4930 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4931 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
4932 "dumpdb failed: %s", dns_result_totext(result));
4933 dumpcontext_destroy(dctx);
4937 ns_server_dumpdb(ns_server_t *server, char *args) {
4938 struct dumpcontext *dctx = NULL;
4940 isc_result_t result;
4944 /* Skip the command name. */
4945 ptr = next_token(&args, " \t");
4947 return (ISC_R_UNEXPECTEDEND);
4949 dctx = isc_mem_get(server->mctx, sizeof(*dctx));
4951 return (ISC_R_NOMEMORY);
4953 dctx->mctx = server->mctx;
4954 dctx->dumpcache = ISC_TRUE;
4955 dctx->dumpzones = ISC_FALSE;
4957 ISC_LIST_INIT(dctx->viewlist);
4965 dctx->version = NULL;
4966 isc_task_attach(server->task, &dctx->task);
4968 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
4969 "could not open dump file", server->dumpfile);
4971 sep = (args == NULL) ? "" : ": ";
4972 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4973 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4974 "dumpdb started%s%s", sep, (args != NULL) ? args : "");
4976 ptr = next_token(&args, " \t");
4977 if (ptr != NULL && strcmp(ptr, "-all") == 0) {
4978 dctx->dumpzones = ISC_TRUE;
4979 dctx->dumpcache = ISC_TRUE;
4980 ptr = next_token(&args, " \t");
4981 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
4982 dctx->dumpzones = ISC_FALSE;
4983 dctx->dumpcache = ISC_TRUE;
4984 ptr = next_token(&args, " \t");
4985 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
4986 dctx->dumpzones = ISC_TRUE;
4987 dctx->dumpcache = ISC_FALSE;
4988 ptr = next_token(&args, " \t");
4992 for (view = ISC_LIST_HEAD(server->viewlist);
4994 view = ISC_LIST_NEXT(view, link))
4996 if (ptr != NULL && strcmp(view->name, ptr) != 0)
4998 CHECK(add_view_tolist(dctx, view));
5001 ptr = next_token(&args, " \t");
5005 dumpdone(dctx, ISC_R_SUCCESS);
5006 return (ISC_R_SUCCESS);
5010 dumpcontext_destroy(dctx);
5015 ns_server_dumprecursing(ns_server_t *server) {
5017 isc_result_t result;
5019 CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
5020 "could not open dump file", server->recfile);
5021 fprintf(fp,";\n; Recursing Queries\n;\n");
5022 ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
5023 fprintf(fp, "; Dump complete\n");
5027 result = isc_stdio_close(fp);
5028 if (result == ISC_R_SUCCESS)
5029 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5030 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5031 "dumprecursing complete");
5033 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5034 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5035 "dumprecursing failed: %s",
5036 dns_result_totext(result));
5041 ns_server_setdebuglevel(ns_server_t *server, char *args) {
5049 /* Skip the command name. */
5050 ptr = next_token(&args, " \t");
5052 return (ISC_R_UNEXPECTEDEND);
5054 /* Look for the new level name. */
5055 levelstr = next_token(&args, " \t");
5056 if (levelstr == NULL) {
5057 if (ns_g_debuglevel < 99)
5060 newlevel = strtol(levelstr, &endp, 10);
5061 if (*endp != '\0' || newlevel < 0 || newlevel > 99)
5062 return (ISC_R_RANGE);
5063 ns_g_debuglevel = (unsigned int)newlevel;
5065 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
5066 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5067 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5068 "debug level is now %d", ns_g_debuglevel);
5069 return (ISC_R_SUCCESS);
5073 ns_server_validation(ns_server_t *server, char *args) {
5074 char *ptr, *viewname;
5076 isc_boolean_t changed = ISC_FALSE;
5077 isc_result_t result;
5078 isc_boolean_t enable;
5080 /* Skip the command name. */
5081 ptr = next_token(&args, " \t");
5083 return (ISC_R_UNEXPECTEDEND);
5085 /* Find out what we are to do. */
5086 ptr = next_token(&args, " \t");
5088 return (ISC_R_UNEXPECTEDEND);
5090 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") ||
5091 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true"))
5093 else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") ||
5094 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false"))
5097 return (DNS_R_SYNTAX);
5099 /* Look for the view name. */
5100 viewname = next_token(&args, " \t");
5102 result = isc_task_beginexclusive(server->task);
5103 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5104 for (view = ISC_LIST_HEAD(server->viewlist);
5106 view = ISC_LIST_NEXT(view, link))
5108 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
5110 result = dns_view_flushcache(view);
5111 if (result != ISC_R_SUCCESS)
5113 view->enablevalidation = enable;
5117 result = ISC_R_SUCCESS;
5119 result = ISC_R_FAILURE;
5121 isc_task_endexclusive(server->task);
5126 ns_server_flushcache(ns_server_t *server, char *args) {
5127 char *ptr, *viewname;
5129 isc_boolean_t flushed;
5130 isc_boolean_t found;
5131 isc_result_t result;
5133 /* Skip the command name. */
5134 ptr = next_token(&args, " \t");
5136 return (ISC_R_UNEXPECTEDEND);
5138 /* Look for the view name. */
5139 viewname = next_token(&args, " \t");
5141 result = isc_task_beginexclusive(server->task);
5142 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5145 for (view = ISC_LIST_HEAD(server->viewlist);
5147 view = ISC_LIST_NEXT(view, link))
5149 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
5152 result = dns_view_flushcache(view);
5153 if (result != ISC_R_SUCCESS) {
5154 flushed = ISC_FALSE;
5155 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5156 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5157 "flushing cache in view '%s' failed: %s",
5158 view->name, isc_result_totext(result));
5161 if (flushed && found) {
5162 if (viewname != NULL)
5163 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5164 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5165 "flushing cache in view '%s' succeeded",
5168 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5169 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5170 "flushing caches in all views succeeded");
5171 result = ISC_R_SUCCESS;
5174 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5175 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5176 "flushing cache in view '%s' failed: "
5177 "view not found", viewname);
5178 result = ISC_R_NOTFOUND;
5180 result = ISC_R_FAILURE;
5182 isc_task_endexclusive(server->task);
5187 ns_server_flushname(ns_server_t *server, char *args) {
5188 char *ptr, *target, *viewname;
5190 isc_boolean_t flushed;
5191 isc_boolean_t found;
5192 isc_result_t result;
5194 dns_fixedname_t fixed;
5197 /* Skip the command name. */
5198 ptr = next_token(&args, " \t");
5200 return (ISC_R_UNEXPECTEDEND);
5202 /* Find the domain name to flush. */
5203 target = next_token(&args, " \t");
5205 return (ISC_R_UNEXPECTEDEND);
5207 isc_buffer_init(&b, target, strlen(target));
5208 isc_buffer_add(&b, strlen(target));
5209 dns_fixedname_init(&fixed);
5210 name = dns_fixedname_name(&fixed);
5211 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
5212 if (result != ISC_R_SUCCESS)
5215 /* Look for the view name. */
5216 viewname = next_token(&args, " \t");
5218 result = isc_task_beginexclusive(server->task);
5219 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5222 for (view = ISC_LIST_HEAD(server->viewlist);
5224 view = ISC_LIST_NEXT(view, link))
5226 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
5229 result = dns_view_flushname(view, name);
5230 if (result != ISC_R_SUCCESS) {
5231 flushed = ISC_FALSE;
5232 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5233 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5234 "flushing name '%s' in cache view '%s' "
5235 "failed: %s", target, view->name,
5236 isc_result_totext(result));
5239 if (flushed && found) {
5240 if (viewname != NULL)
5241 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5242 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5243 "flushing name '%s' in cache view '%s' "
5244 "succeeded", target, viewname);
5246 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5247 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5248 "flushing name '%s' in all cache views "
5249 "succeeded", target);
5250 result = ISC_R_SUCCESS;
5253 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5254 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5255 "flushing name '%s' in cache view '%s' "
5256 "failed: view not found", target,
5258 result = ISC_R_FAILURE;
5260 isc_task_endexclusive(server->task);
5265 ns_server_status(ns_server_t *server, isc_buffer_t *text) {
5266 int zonecount, xferrunning, xferdeferred, soaqueries;
5268 const char *ob = "", *cb = "", *alt = "";
5270 if (ns_g_server->version_set) {
5273 if (ns_g_server->version == NULL)
5274 alt = "version.bind/txt/ch disabled";
5276 alt = ns_g_server->version;
5278 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
5279 xferrunning = dns_zonemgr_getcount(server->zonemgr,
5280 DNS_ZONESTATE_XFERRUNNING);
5281 xferdeferred = dns_zonemgr_getcount(server->zonemgr,
5282 DNS_ZONESTATE_XFERDEFERRED);
5283 soaqueries = dns_zonemgr_getcount(server->zonemgr,
5284 DNS_ZONESTATE_SOAQUERY);
5286 n = snprintf((char *)isc_buffer_used(text),
5287 isc_buffer_availablelength(text),
5288 "version: %s%s%s%s\n"
5289 #ifdef ISC_PLATFORM_USETHREADS
5291 "worker threads: %u\n"
5293 "number of zones: %u\n"
5295 "xfers running: %u\n"
5296 "xfers deferred: %u\n"
5297 "soa queries in progress: %u\n"
5298 "query logging is %s\n"
5299 "recursive clients: %d/%d/%d\n"
5300 "tcp clients: %d/%d\n"
5301 "server is up and running",
5302 ns_g_version, ob, alt, cb,
5303 #ifdef ISC_PLATFORM_USETHREADS
5304 ns_g_cpus_detected, ns_g_cpus,
5306 zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
5307 soaqueries, server->log_queries ? "ON" : "OFF",
5308 server->recursionquota.used, server->recursionquota.soft,
5309 server->recursionquota.max,
5310 server->tcpquota.used, server->tcpquota.max);
5311 if (n >= isc_buffer_availablelength(text))
5312 return (ISC_R_NOSPACE);
5313 isc_buffer_add(text, n);
5314 return (ISC_R_SUCCESS);
5318 delete_keynames(dns_tsig_keyring_t *ring, char *target,
5319 unsigned int *foundkeys)
5321 char namestr[DNS_NAME_FORMATSIZE];
5322 isc_result_t result;
5323 dns_rbtnodechain_t chain;
5324 dns_name_t foundname;
5325 dns_fixedname_t fixedorigin;
5327 dns_rbtnode_t *node;
5328 dns_tsigkey_t *tkey;
5330 dns_name_init(&foundname, NULL);
5331 dns_fixedname_init(&fixedorigin);
5332 origin = dns_fixedname_name(&fixedorigin);
5335 dns_rbtnodechain_init(&chain, ring->mctx);
5336 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
5338 if (result == ISC_R_NOTFOUND) {
5339 dns_rbtnodechain_invalidate(&chain);
5340 return (ISC_R_SUCCESS);
5342 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
5343 dns_rbtnodechain_invalidate(&chain);
5349 dns_rbtnodechain_current(&chain, &foundname, origin, &node);
5353 if (!tkey->generated)
5356 dns_name_format(&tkey->name, namestr, sizeof(namestr));
5357 if (strcmp(namestr, target) == 0) {
5359 dns_rbtnodechain_invalidate(&chain);
5360 (void)dns_rbt_deletename(ring->keys,
5368 result = dns_rbtnodechain_next(&chain, &foundname, origin);
5369 if (result == ISC_R_NOMORE)
5371 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
5372 dns_rbtnodechain_invalidate(&chain);
5377 return (ISC_R_SUCCESS);
5381 ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) {
5382 isc_result_t result;
5385 unsigned int foundkeys = 0;
5389 (void)next_token(&command, " \t"); /* skip command name */
5390 target = next_token(&command, " \t");
5392 return (ISC_R_UNEXPECTEDEND);
5393 viewname = next_token(&command, " \t");
5395 result = isc_task_beginexclusive(server->task);
5396 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5397 for (view = ISC_LIST_HEAD(server->viewlist);
5399 view = ISC_LIST_NEXT(view, link)) {
5400 if (viewname == NULL || strcmp(view->name, viewname) == 0) {
5401 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write);
5402 result = delete_keynames(view->dynamickeys, target,
5404 RWUNLOCK(&view->dynamickeys->lock,
5405 isc_rwlocktype_write);
5406 if (result != ISC_R_SUCCESS) {
5407 isc_task_endexclusive(server->task);
5412 isc_task_endexclusive(server->task);
5414 n = snprintf((char *)isc_buffer_used(text),
5415 isc_buffer_availablelength(text),
5416 "%d tsig keys deleted.\n", foundkeys);
5417 if (n >= isc_buffer_availablelength(text))
5418 return (ISC_R_NOSPACE);
5419 isc_buffer_add(text, n);
5421 return (ISC_R_SUCCESS);
5425 list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text,
5426 unsigned int *foundkeys)
5428 char namestr[DNS_NAME_FORMATSIZE];
5429 char creatorstr[DNS_NAME_FORMATSIZE];
5430 isc_result_t result;
5431 dns_rbtnodechain_t chain;
5432 dns_name_t foundname;
5433 dns_fixedname_t fixedorigin;
5435 dns_rbtnode_t *node;
5436 dns_tsigkey_t *tkey;
5438 const char *viewname;
5441 viewname = view->name;
5443 viewname = "(global)";
5445 dns_name_init(&foundname, NULL);
5446 dns_fixedname_init(&fixedorigin);
5447 origin = dns_fixedname_name(&fixedorigin);
5448 dns_rbtnodechain_init(&chain, ring->mctx);
5449 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
5451 if (result == ISC_R_NOTFOUND) {
5452 dns_rbtnodechain_invalidate(&chain);
5453 return (ISC_R_SUCCESS);
5455 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
5456 dns_rbtnodechain_invalidate(&chain);
5462 dns_rbtnodechain_current(&chain, &foundname, origin, &node);
5467 dns_name_format(&tkey->name, namestr, sizeof(namestr));
5468 if (tkey->generated) {
5469 dns_name_format(tkey->creator, creatorstr,
5470 sizeof(creatorstr));
5471 n = snprintf((char *)isc_buffer_used(text),
5472 isc_buffer_availablelength(text),
5473 "view \"%s\"; type \"dynamic\"; key \"%s\"; creator \"%s\";\n",
5474 viewname, namestr, creatorstr);
5476 n = snprintf((char *)isc_buffer_used(text),
5477 isc_buffer_availablelength(text),
5478 "view \"%s\"; type \"static\"; key \"%s\";\n",
5481 if (n >= isc_buffer_availablelength(text)) {
5482 dns_rbtnodechain_invalidate(&chain);
5483 return (ISC_R_NOSPACE);
5485 isc_buffer_add(text, n);
5487 result = dns_rbtnodechain_next(&chain, &foundname, origin);
5488 if (result == ISC_R_NOMORE)
5490 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
5491 dns_rbtnodechain_invalidate(&chain);
5496 return (ISC_R_SUCCESS);
5500 ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
5501 isc_result_t result;
5504 unsigned int foundkeys = 0;
5506 result = isc_task_beginexclusive(server->task);
5507 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5508 for (view = ISC_LIST_HEAD(server->viewlist);
5510 view = ISC_LIST_NEXT(view, link)) {
5511 RWLOCK(&view->statickeys->lock, isc_rwlocktype_read);
5512 result = list_keynames(view, view->statickeys, text,
5514 RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read);
5515 if (result != ISC_R_SUCCESS) {
5516 isc_task_endexclusive(server->task);
5519 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
5520 result = list_keynames(view, view->dynamickeys, text,
5522 RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
5523 if (result != ISC_R_SUCCESS) {
5524 isc_task_endexclusive(server->task);
5528 isc_task_endexclusive(server->task);
5530 if (foundkeys == 0) {
5531 n = snprintf((char *)isc_buffer_used(text),
5532 isc_buffer_availablelength(text),
5533 "no tsig keys found.\n");
5534 if (n >= isc_buffer_availablelength(text))
5535 return (ISC_R_NOSPACE);
5536 isc_buffer_add(text, n);
5539 return (ISC_R_SUCCESS);
5543 * Act on a "freeze" or "thaw" command from the command channel.
5546 ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
5549 isc_result_t result, tresult;
5550 dns_zone_t *zone = NULL;
5551 dns_zonetype_t type;
5552 char classstr[DNS_RDATACLASS_FORMATSIZE];
5553 char zonename[DNS_NAME_FORMATSIZE];
5556 const char *vname, *sep;
5557 isc_boolean_t frozen;
5558 const char *msg = NULL;
5560 result = zone_from_args(server, args, &zone);
5561 if (result != ISC_R_SUCCESS)
5564 result = isc_task_beginexclusive(server->task);
5565 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5566 tresult = ISC_R_SUCCESS;
5567 for (view = ISC_LIST_HEAD(server->viewlist);
5569 view = ISC_LIST_NEXT(view, link)) {
5570 result = dns_view_freezezones(view, freeze);
5571 if (result != ISC_R_SUCCESS &&
5572 tresult == ISC_R_SUCCESS)
5575 isc_task_endexclusive(server->task);
5576 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5577 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5579 freeze ? "freezing" : "thawing",
5580 isc_result_totext(tresult));
5583 type = dns_zone_gettype(zone);
5584 if (type != dns_zone_master) {
5585 dns_zone_detach(&zone);
5586 return (ISC_R_NOTFOUND);
5589 result = isc_task_beginexclusive(server->task);
5590 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5591 frozen = dns_zone_getupdatedisabled(zone);
5594 msg = "WARNING: The zone was already frozen.\n"
5595 "Someone else may be editing it or "
5596 "it may still be re-loading.";
5597 result = DNS_R_FROZEN;
5599 if (result == ISC_R_SUCCESS) {
5600 result = dns_zone_flush(zone);
5601 if (result != ISC_R_SUCCESS)
5602 msg = "Flushing the zone updates to "
5605 if (result == ISC_R_SUCCESS) {
5606 journal = dns_zone_getjournal(zone);
5607 if (journal != NULL)
5608 (void)isc_file_remove(journal);
5610 if (result == ISC_R_SUCCESS)
5611 dns_zone_setupdatedisabled(zone, freeze);
5614 result = dns_zone_loadandthaw(zone);
5617 case DNS_R_UPTODATE:
5618 msg = "The zone reload and thaw was "
5620 result = ISC_R_SUCCESS;
5622 case DNS_R_CONTINUE:
5623 msg = "A zone reload and thaw was started.\n"
5624 "Check the logs to see the result.";
5625 result = ISC_R_SUCCESS;
5630 isc_task_endexclusive(server->task);
5632 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
5633 isc_buffer_putmem(text, (const unsigned char *)msg,
5636 view = dns_zone_getview(zone);
5637 if (strcmp(view->name, "_bind") == 0 ||
5638 strcmp(view->name, "_default") == 0)
5646 dns_rdataclass_format(dns_zone_getclass(zone), classstr,
5648 dns_name_format(dns_zone_getorigin(zone),
5649 zonename, sizeof(zonename));
5650 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5651 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5652 "%s zone '%s/%s'%s%s: %s",
5653 freeze ? "freezing" : "thawing",
5654 zonename, classstr, sep, vname,
5655 isc_result_totext(result));
5656 dns_zone_detach(&zone);
5662 * This function adds a message for rndc to echo if named
5663 * is managed by smf and is also running chroot.
5666 ns_smf_add_message(isc_buffer_t *text) {
5669 n = snprintf((char *)isc_buffer_used(text),
5670 isc_buffer_availablelength(text),
5671 "use svcadm(1M) to manage named");
5672 if (n >= isc_buffer_availablelength(text))
5673 return (ISC_R_NOSPACE);
5674 isc_buffer_add(text, n);
5675 return (ISC_R_SUCCESS);
5677 #endif /* HAVE_LIBSCF */