2 * Copyright (C) 2004-2008 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.
18 /* $Id: server.c,v 1.419.18.57.10.3 2008/07/23 12:04:32 marka Exp $ */
27 #include <isc/base64.h>
29 #include <isc/entropy.h>
33 #include <isc/parseint.h>
34 #include <isc/print.h>
35 #include <isc/resource.h>
36 #include <isc/stdio.h>
37 #include <isc/string.h>
39 #include <isc/timer.h>
42 #include <isccfg/namedconf.h>
44 #include <bind9/check.h>
46 #include <dns/acache.h>
48 #include <dns/cache.h>
50 #include <dns/dispatch.h>
54 #include <dns/forward.h>
55 #include <dns/journal.h>
56 #include <dns/keytable.h>
58 #include <dns/master.h>
59 #include <dns/masterdump.h>
60 #include <dns/order.h>
62 #include <dns/portlist.h>
63 #include <dns/rdataclass.h>
64 #include <dns/rdataset.h>
65 #include <dns/rdatastruct.h>
66 #include <dns/resolver.h>
67 #include <dns/rootns.h>
68 #include <dns/secalg.h>
69 #include <dns/stats.h>
76 #include <dst/result.h>
78 #include <named/client.h>
79 #include <named/config.h>
80 #include <named/control.h>
81 #include <named/interfacemgr.h>
82 #include <named/log.h>
83 #include <named/logconf.h>
84 #include <named/lwresd.h>
85 #include <named/main.h>
87 #include <named/server.h>
88 #include <named/tkeyconf.h>
89 #include <named/tsigconf.h>
90 #include <named/zoneconf.h>
92 #include <named/ns_smf_globals.h>
97 * Check an operation for failure. Assumes that the function
98 * using it has a 'result' variable and a 'cleanup' label.
101 do { result = (op); \
102 if (result != ISC_R_SUCCESS) goto cleanup; \
105 #define CHECKM(op, msg) \
106 do { result = (op); \
107 if (result != ISC_R_SUCCESS) { \
108 isc_log_write(ns_g_lctx, \
109 NS_LOGCATEGORY_GENERAL, \
110 NS_LOGMODULE_SERVER, \
113 isc_result_totext(result)); \
118 #define CHECKMF(op, msg, file) \
119 do { result = (op); \
120 if (result != ISC_R_SUCCESS) { \
121 isc_log_write(ns_g_lctx, \
122 NS_LOGCATEGORY_GENERAL, \
123 NS_LOGMODULE_SERVER, \
125 "%s '%s': %s", msg, file, \
126 isc_result_totext(result)); \
131 #define CHECKFATAL(op, msg) \
132 do { result = (op); \
133 if (result != ISC_R_SUCCESS) \
134 fatal(msg, result); \
139 unsigned int dispatchgen
;
140 dns_dispatch_t
*dispatch
;
141 ISC_LINK(struct ns_dispatch
) link
;
146 isc_boolean_t dumpcache
;
147 isc_boolean_t dumpzones
;
149 ISC_LIST(struct viewlistentry
) viewlist
;
150 struct viewlistentry
*view
;
151 struct zonelistentry
*zone
;
152 dns_dumpctx_t
*mdctx
;
156 dns_dbversion_t
*version
;
159 struct viewlistentry
{
161 ISC_LINK(struct viewlistentry
) link
;
162 ISC_LIST(struct zonelistentry
) zonelist
;
165 struct zonelistentry
{
167 ISC_LINK(struct zonelistentry
) link
;
171 * These zones should not leak onto the Internet.
173 static const struct {
175 isc_boolean_t rfc1918
;
179 { "10.IN-ADDR.ARPA", ISC_TRUE
},
180 { "16.172.IN-ADDR.ARPA", ISC_TRUE
},
181 { "17.172.IN-ADDR.ARPA", ISC_TRUE
},
182 { "18.172.IN-ADDR.ARPA", ISC_TRUE
},
183 { "19.172.IN-ADDR.ARPA", ISC_TRUE
},
184 { "20.172.IN-ADDR.ARPA", ISC_TRUE
},
185 { "21.172.IN-ADDR.ARPA", ISC_TRUE
},
186 { "22.172.IN-ADDR.ARPA", ISC_TRUE
},
187 { "23.172.IN-ADDR.ARPA", ISC_TRUE
},
188 { "24.172.IN-ADDR.ARPA", ISC_TRUE
},
189 { "25.172.IN-ADDR.ARPA", ISC_TRUE
},
190 { "26.172.IN-ADDR.ARPA", ISC_TRUE
},
191 { "27.172.IN-ADDR.ARPA", ISC_TRUE
},
192 { "28.172.IN-ADDR.ARPA", ISC_TRUE
},
193 { "29.172.IN-ADDR.ARPA", ISC_TRUE
},
194 { "30.172.IN-ADDR.ARPA", ISC_TRUE
},
195 { "31.172.IN-ADDR.ARPA", ISC_TRUE
},
196 { "168.192.IN-ADDR.ARPA", ISC_TRUE
},
200 { "127.IN-ADDR.ARPA", ISC_FALSE
}, /* LOOPBACK */
201 { "254.169.IN-ADDR.ARPA", ISC_FALSE
}, /* LINK LOCAL */
202 { "2.0.192.IN-ADDR.ARPA", ISC_FALSE
}, /* TEST NET */
203 { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE
}, /* BROADCAST */
205 /* Local IPv6 Unicast Addresses */
206 { "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
},
207 { "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
},
208 /* LOCALLY ASSIGNED LOCAL ADDRES S SCOPE */
209 { "D.F.IP6.ARPA", ISC_FALSE
},
210 { "8.E.F.IP6.ARPA", ISC_FALSE
}, /* LINK LOCAL */
211 { "9.E.F.IP6.ARPA", ISC_FALSE
}, /* LINK LOCAL */
212 { "A.E.F.IP6.ARPA", ISC_FALSE
}, /* LINK LOCAL */
213 { "B.E.F.IP6.ARPA", ISC_FALSE
}, /* LINK LOCAL */
219 fatal(const char *msg
, isc_result_t result
);
222 ns_server_reload(isc_task_t
*task
, isc_event_t
*event
);
225 ns_listenelt_fromconfig(const cfg_obj_t
*listener
, const cfg_obj_t
*config
,
226 cfg_aclconfctx_t
*actx
,
227 isc_mem_t
*mctx
, ns_listenelt_t
**target
);
229 ns_listenlist_fromconfig(const cfg_obj_t
*listenlist
, const cfg_obj_t
*config
,
230 cfg_aclconfctx_t
*actx
,
231 isc_mem_t
*mctx
, ns_listenlist_t
**target
);
234 configure_forward(const cfg_obj_t
*config
, dns_view_t
*view
, dns_name_t
*origin
,
235 const cfg_obj_t
*forwarders
, const cfg_obj_t
*forwardtype
);
238 configure_alternates(const cfg_obj_t
*config
, dns_view_t
*view
,
239 const cfg_obj_t
*alternates
);
242 configure_zone(const cfg_obj_t
*config
, const cfg_obj_t
*zconfig
,
243 const cfg_obj_t
*vconfig
, isc_mem_t
*mctx
, dns_view_t
*view
,
244 cfg_aclconfctx_t
*aclconf
);
247 end_reserved_dispatches(ns_server_t
*server
, isc_boolean_t all
);
250 * Configure a single view ACL at '*aclp'. Get its configuration by
251 * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl'
252 * (for a global default).
255 configure_view_acl(const cfg_obj_t
*vconfig
, const cfg_obj_t
*config
,
256 const char *aclname
, cfg_aclconfctx_t
*actx
,
257 isc_mem_t
*mctx
, dns_acl_t
**aclp
)
260 const cfg_obj_t
*maps
[3];
261 const cfg_obj_t
*aclobj
= NULL
;
265 dns_acl_detach(aclp
);
267 maps
[i
++] = cfg_tuple_get(vconfig
, "options");
268 if (config
!= NULL
) {
269 const cfg_obj_t
*options
= NULL
;
270 (void)cfg_map_get(config
, "options", &options
);
276 (void)ns_config_get(maps
, aclname
, &aclobj
);
279 * No value available. *aclp == NULL.
281 return (ISC_R_SUCCESS
);
283 result
= cfg_acl_fromconfig(aclobj
, config
, ns_g_lctx
,
290 configure_view_dnsseckey(const cfg_obj_t
*vconfig
, const cfg_obj_t
*key
,
291 dns_keytable_t
*keytable
, isc_mem_t
*mctx
)
293 dns_rdataclass_t viewclass
;
294 dns_rdata_dnskey_t keystruct
;
295 isc_uint32_t flags
, proto
, alg
;
296 const char *keystr
, *keynamestr
;
297 unsigned char keydata
[4096];
298 isc_buffer_t keydatabuf
;
299 unsigned char rrdata
[4096];
300 isc_buffer_t rrdatabuf
;
302 dns_fixedname_t fkeyname
;
304 isc_buffer_t namebuf
;
306 dst_key_t
*dstkey
= NULL
;
308 flags
= cfg_obj_asuint32(cfg_tuple_get(key
, "flags"));
309 proto
= cfg_obj_asuint32(cfg_tuple_get(key
, "protocol"));
310 alg
= cfg_obj_asuint32(cfg_tuple_get(key
, "algorithm"));
311 keyname
= dns_fixedname_name(&fkeyname
);
312 keynamestr
= cfg_obj_asstring(cfg_tuple_get(key
, "name"));
315 viewclass
= dns_rdataclass_in
;
317 const cfg_obj_t
*classobj
= cfg_tuple_get(vconfig
, "class");
318 CHECK(ns_config_getclass(classobj
, dns_rdataclass_in
,
321 keystruct
.common
.rdclass
= viewclass
;
322 keystruct
.common
.rdtype
= dns_rdatatype_dnskey
;
324 * The key data in keystruct is not dynamically allocated.
326 keystruct
.mctx
= NULL
;
328 ISC_LINK_INIT(&keystruct
.common
, link
);
331 CHECKM(ISC_R_RANGE
, "key flags");
333 CHECKM(ISC_R_RANGE
, "key protocol");
335 CHECKM(ISC_R_RANGE
, "key algorithm");
336 keystruct
.flags
= (isc_uint16_t
)flags
;
337 keystruct
.protocol
= (isc_uint8_t
)proto
;
338 keystruct
.algorithm
= (isc_uint8_t
)alg
;
340 isc_buffer_init(&keydatabuf
, keydata
, sizeof(keydata
));
341 isc_buffer_init(&rrdatabuf
, rrdata
, sizeof(rrdata
));
343 keystr
= cfg_obj_asstring(cfg_tuple_get(key
, "key"));
344 CHECK(isc_base64_decodestring(keystr
, &keydatabuf
));
345 isc_buffer_usedregion(&keydatabuf
, &r
);
346 keystruct
.datalen
= r
.length
;
347 keystruct
.data
= r
.base
;
349 if ((keystruct
.algorithm
== DST_ALG_RSASHA1
||
350 keystruct
.algorithm
== DST_ALG_RSAMD5
) &&
351 r
.length
> 1 && r
.base
[0] == 1 && r
.base
[1] == 3)
352 cfg_obj_log(key
, ns_g_lctx
, ISC_LOG_WARNING
,
353 "trusted key '%s' has a weak exponent",
356 CHECK(dns_rdata_fromstruct(NULL
,
357 keystruct
.common
.rdclass
,
358 keystruct
.common
.rdtype
,
359 &keystruct
, &rrdatabuf
));
360 dns_fixedname_init(&fkeyname
);
361 isc_buffer_init(&namebuf
, keynamestr
, strlen(keynamestr
));
362 isc_buffer_add(&namebuf
, strlen(keynamestr
));
363 CHECK(dns_name_fromtext(keyname
, &namebuf
,
364 dns_rootname
, ISC_FALSE
,
366 CHECK(dst_key_fromdns(keyname
, viewclass
, &rrdatabuf
,
369 CHECK(dns_keytable_add(keytable
, &dstkey
));
370 INSIST(dstkey
== NULL
);
371 return (ISC_R_SUCCESS
);
374 if (result
== DST_R_NOCRYPTO
) {
375 cfg_obj_log(key
, ns_g_lctx
, ISC_LOG_ERROR
,
376 "ignoring trusted key for '%s': no crypto support",
378 result
= ISC_R_SUCCESS
;
380 cfg_obj_log(key
, ns_g_lctx
, ISC_LOG_ERROR
,
381 "configuring trusted key for '%s': %s",
382 keynamestr
, isc_result_totext(result
));
383 result
= ISC_R_FAILURE
;
387 dst_key_free(&dstkey
);
393 * Configure DNSSEC keys for a view. Currently used only for
394 * the security roots.
396 * The per-view configuration values and the server-global defaults are read
397 * from 'vconfig' and 'config'. The variable to be configured is '*target'.
400 configure_view_dnsseckeys(const cfg_obj_t
*vconfig
, const cfg_obj_t
*config
,
401 isc_mem_t
*mctx
, dns_keytable_t
**target
)
404 const cfg_obj_t
*keys
= NULL
;
405 const cfg_obj_t
*voptions
= NULL
;
406 const cfg_listelt_t
*element
, *element2
;
407 const cfg_obj_t
*keylist
;
408 const cfg_obj_t
*key
;
409 dns_keytable_t
*keytable
= NULL
;
411 CHECK(dns_keytable_create(mctx
, &keytable
));
414 voptions
= cfg_tuple_get(vconfig
, "options");
417 if (voptions
!= NULL
)
418 (void)cfg_map_get(voptions
, "trusted-keys", &keys
);
420 (void)cfg_map_get(config
, "trusted-keys", &keys
);
422 for (element
= cfg_list_first(keys
);
424 element
= cfg_list_next(element
))
426 keylist
= cfg_listelt_value(element
);
427 for (element2
= cfg_list_first(keylist
);
429 element2
= cfg_list_next(element2
))
431 key
= cfg_listelt_value(element2
);
432 CHECK(configure_view_dnsseckey(vconfig
, key
,
437 dns_keytable_detach(target
);
438 *target
= keytable
; /* Transfer ownership. */
440 result
= ISC_R_SUCCESS
;
447 mustbesecure(const cfg_obj_t
*mbs
, dns_resolver_t
*resolver
)
449 const cfg_listelt_t
*element
;
450 const cfg_obj_t
*obj
;
452 dns_fixedname_t fixed
;
458 dns_fixedname_init(&fixed
);
459 name
= dns_fixedname_name(&fixed
);
460 for (element
= cfg_list_first(mbs
);
462 element
= cfg_list_next(element
))
464 obj
= cfg_listelt_value(element
);
465 str
= cfg_obj_asstring(cfg_tuple_get(obj
, "name"));
466 isc_buffer_init(&b
, str
, strlen(str
));
467 isc_buffer_add(&b
, strlen(str
));
468 CHECK(dns_name_fromtext(name
, &b
, dns_rootname
,
470 value
= cfg_obj_asboolean(cfg_tuple_get(obj
, "value"));
471 CHECK(dns_resolver_setmustbesecure(resolver
, name
, value
));
474 result
= ISC_R_SUCCESS
;
481 * Get a dispatch appropriate for the resolver of a given view.
484 get_view_querysource_dispatch(const cfg_obj_t
**maps
,
485 int af
, dns_dispatch_t
**dispatchp
)
488 dns_dispatch_t
*disp
;
490 unsigned int attrs
, attrmask
;
491 const cfg_obj_t
*obj
= NULL
;
494 * Make compiler happy.
496 result
= ISC_R_FAILURE
;
500 result
= ns_config_get(maps
, "query-source", &obj
);
501 INSIST(result
== ISC_R_SUCCESS
);
504 result
= ns_config_get(maps
, "query-source-v6", &obj
);
505 INSIST(result
== ISC_R_SUCCESS
);
511 sa
= *(cfg_obj_assockaddr(obj
));
512 INSIST(isc_sockaddr_pf(&sa
) == af
);
515 * If we don't support this address family, we're done!
519 result
= isc_net_probeipv4();
522 result
= isc_net_probeipv6();
527 if (result
!= ISC_R_SUCCESS
)
528 return (ISC_R_SUCCESS
);
531 * Try to find a dispatcher that we can share.
534 attrs
|= DNS_DISPATCHATTR_UDP
;
537 attrs
|= DNS_DISPATCHATTR_IPV4
;
540 attrs
|= DNS_DISPATCHATTR_IPV6
;
544 if (isc_sockaddr_getport(&sa
) != 0) {
546 cfg_obj_log(obj
, ns_g_lctx
, ISC_LOG_INFO
,
547 "using specific query-source port suppresses port "
548 "randomization and can be insecure.");
552 attrmask
|= DNS_DISPATCHATTR_UDP
;
553 attrmask
|= DNS_DISPATCHATTR_TCP
;
554 attrmask
|= DNS_DISPATCHATTR_IPV4
;
555 attrmask
|= DNS_DISPATCHATTR_IPV6
;
558 result
= dns_dispatch_getudp(ns_g_dispatchmgr
, ns_g_socketmgr
,
559 ns_g_taskmgr
, &sa
, 4096,
560 1024, 32768, 16411, 16433,
561 attrs
, attrmask
, &disp
);
562 if (result
!= ISC_R_SUCCESS
) {
564 char buf
[ISC_SOCKADDR_FORMATSIZE
];
568 isc_sockaddr_any(&any
);
571 isc_sockaddr_any6(&any
);
574 if (isc_sockaddr_equal(&sa
, &any
))
575 return (ISC_R_SUCCESS
);
576 isc_sockaddr_format(&sa
, buf
, sizeof(buf
));
577 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
578 NS_LOGMODULE_SERVER
, ISC_LOG_ERROR
,
579 "could not get query source dispatcher (%s)",
586 return (ISC_R_SUCCESS
);
590 configure_order(dns_order_t
*order
, const cfg_obj_t
*ent
) {
591 dns_rdataclass_t rdclass
;
592 dns_rdatatype_t rdtype
;
593 const cfg_obj_t
*obj
;
594 dns_fixedname_t fixed
;
595 unsigned int mode
= 0;
599 isc_boolean_t addroot
;
601 result
= ns_config_getclass(cfg_tuple_get(ent
, "class"),
602 dns_rdataclass_any
, &rdclass
);
603 if (result
!= ISC_R_SUCCESS
)
606 result
= ns_config_gettype(cfg_tuple_get(ent
, "type"),
607 dns_rdatatype_any
, &rdtype
);
608 if (result
!= ISC_R_SUCCESS
)
611 obj
= cfg_tuple_get(ent
, "name");
612 if (cfg_obj_isstring(obj
))
613 str
= cfg_obj_asstring(obj
);
616 addroot
= ISC_TF(strcmp(str
, "*") == 0);
617 isc_buffer_init(&b
, str
, strlen(str
));
618 isc_buffer_add(&b
, strlen(str
));
619 dns_fixedname_init(&fixed
);
620 result
= dns_name_fromtext(dns_fixedname_name(&fixed
), &b
,
621 dns_rootname
, ISC_FALSE
, NULL
);
622 if (result
!= ISC_R_SUCCESS
)
625 obj
= cfg_tuple_get(ent
, "ordering");
626 INSIST(cfg_obj_isstring(obj
));
627 str
= cfg_obj_asstring(obj
);
628 if (!strcasecmp(str
, "fixed"))
629 mode
= DNS_RDATASETATTR_FIXEDORDER
;
630 else if (!strcasecmp(str
, "random"))
631 mode
= DNS_RDATASETATTR_RANDOMIZE
;
632 else if (!strcasecmp(str
, "cyclic"))
638 * "*" should match everything including the root (BIND 8 compat).
639 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a
640 * explicit entry for "." when the name is "*".
643 result
= dns_order_add(order
, dns_rootname
,
644 rdtype
, rdclass
, mode
);
645 if (result
!= ISC_R_SUCCESS
)
649 return (dns_order_add(order
, dns_fixedname_name(&fixed
),
650 rdtype
, rdclass
, mode
));
654 configure_peer(const cfg_obj_t
*cpeer
, isc_mem_t
*mctx
, dns_peer_t
**peerp
) {
657 const cfg_obj_t
*obj
;
660 unsigned int prefixlen
;
662 cfg_obj_asnetprefix(cfg_map_getname(cpeer
), &na
, &prefixlen
);
665 result
= dns_peer_new(mctx
, &na
, &peer
);
666 if (result
!= ISC_R_SUCCESS
)
670 (void)cfg_map_get(cpeer
, "bogus", &obj
);
672 CHECK(dns_peer_setbogus(peer
, cfg_obj_asboolean(obj
)));
675 (void)cfg_map_get(cpeer
, "provide-ixfr", &obj
);
677 CHECK(dns_peer_setprovideixfr(peer
, cfg_obj_asboolean(obj
)));
680 (void)cfg_map_get(cpeer
, "request-ixfr", &obj
);
682 CHECK(dns_peer_setrequestixfr(peer
, cfg_obj_asboolean(obj
)));
685 (void)cfg_map_get(cpeer
, "edns", &obj
);
687 CHECK(dns_peer_setsupportedns(peer
, cfg_obj_asboolean(obj
)));
690 (void)cfg_map_get(cpeer
, "edns-udp-size", &obj
);
692 isc_uint32_t udpsize
= cfg_obj_asuint32(obj
);
697 CHECK(dns_peer_setudpsize(peer
, (isc_uint16_t
)udpsize
));
701 (void)cfg_map_get(cpeer
, "max-udp-size", &obj
);
703 isc_uint32_t udpsize
= cfg_obj_asuint32(obj
);
708 CHECK(dns_peer_setmaxudp(peer
, (isc_uint16_t
)udpsize
));
712 (void)cfg_map_get(cpeer
, "transfers", &obj
);
714 CHECK(dns_peer_settransfers(peer
, cfg_obj_asuint32(obj
)));
717 (void)cfg_map_get(cpeer
, "transfer-format", &obj
);
719 str
= cfg_obj_asstring(obj
);
720 if (strcasecmp(str
, "many-answers") == 0)
721 CHECK(dns_peer_settransferformat(peer
,
723 else if (strcasecmp(str
, "one-answer") == 0)
724 CHECK(dns_peer_settransferformat(peer
,
731 (void)cfg_map_get(cpeer
, "keys", &obj
);
733 result
= dns_peer_setkeybycharp(peer
, cfg_obj_asstring(obj
));
734 if (result
!= ISC_R_SUCCESS
)
739 if (na
.family
== AF_INET
)
740 (void)cfg_map_get(cpeer
, "transfer-source", &obj
);
742 (void)cfg_map_get(cpeer
, "transfer-source-v6", &obj
);
744 result
= dns_peer_settransfersource(peer
,
745 cfg_obj_assockaddr(obj
));
746 if (result
!= ISC_R_SUCCESS
)
748 ns_add_reserved_dispatch(ns_g_server
, cfg_obj_assockaddr(obj
));
752 if (na
.family
== AF_INET
)
753 (void)cfg_map_get(cpeer
, "notify-source", &obj
);
755 (void)cfg_map_get(cpeer
, "notify-source-v6", &obj
);
757 result
= dns_peer_setnotifysource(peer
,
758 cfg_obj_assockaddr(obj
));
759 if (result
!= ISC_R_SUCCESS
)
761 ns_add_reserved_dispatch(ns_g_server
, cfg_obj_assockaddr(obj
));
765 if (na
.family
== AF_INET
)
766 (void)cfg_map_get(cpeer
, "query-source", &obj
);
768 (void)cfg_map_get(cpeer
, "query-source-v6", &obj
);
770 result
= dns_peer_setquerysource(peer
,
771 cfg_obj_assockaddr(obj
));
772 if (result
!= ISC_R_SUCCESS
)
774 ns_add_reserved_dispatch(ns_g_server
, cfg_obj_assockaddr(obj
));
778 return (ISC_R_SUCCESS
);
781 dns_peer_detach(&peer
);
786 disable_algorithms(const cfg_obj_t
*disabled
, dns_resolver_t
*resolver
) {
788 const cfg_obj_t
*algorithms
;
789 const cfg_listelt_t
*element
;
791 dns_fixedname_t fixed
;
795 dns_fixedname_init(&fixed
);
796 name
= dns_fixedname_name(&fixed
);
797 str
= cfg_obj_asstring(cfg_tuple_get(disabled
, "name"));
798 isc_buffer_init(&b
, str
, strlen(str
));
799 isc_buffer_add(&b
, strlen(str
));
800 CHECK(dns_name_fromtext(name
, &b
, dns_rootname
, ISC_FALSE
, NULL
));
802 algorithms
= cfg_tuple_get(disabled
, "algorithms");
803 for (element
= cfg_list_first(algorithms
);
805 element
= cfg_list_next(element
))
810 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element
)), r
.base
);
811 r
.length
= strlen(r
.base
);
813 result
= dns_secalg_fromtext(&alg
, &r
);
814 if (result
!= ISC_R_SUCCESS
) {
816 result
= isc_parse_uint8(&ui
, r
.base
, 10);
819 if (result
!= ISC_R_SUCCESS
) {
820 cfg_obj_log(cfg_listelt_value(element
),
821 ns_g_lctx
, ISC_LOG_ERROR
,
822 "invalid algorithm");
825 CHECK(dns_resolver_disable_algorithm(resolver
, name
, alg
));
832 on_disable_list(const cfg_obj_t
*disablelist
, dns_name_t
*zonename
) {
833 const cfg_listelt_t
*element
;
834 dns_fixedname_t fixed
;
837 const cfg_obj_t
*value
;
841 dns_fixedname_init(&fixed
);
842 name
= dns_fixedname_name(&fixed
);
844 for (element
= cfg_list_first(disablelist
);
846 element
= cfg_list_next(element
))
848 value
= cfg_listelt_value(element
);
849 str
= cfg_obj_asstring(value
);
850 isc_buffer_init(&b
, str
, strlen(str
));
851 isc_buffer_add(&b
, strlen(str
));
852 result
= dns_name_fromtext(name
, &b
, dns_rootname
,
854 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
855 if (dns_name_equal(name
, zonename
))
862 check_dbtype(dns_zone_t
**zonep
, unsigned int dbtypec
, const char **dbargv
,
869 result
= dns_zone_getdbtype(*zonep
, &argv
, mctx
);
870 if (result
!= ISC_R_SUCCESS
) {
871 dns_zone_detach(zonep
);
876 * Check that all the arguments match.
878 for (i
= 0; i
< dbtypec
; i
++)
879 if (argv
[i
] == NULL
|| strcmp(argv
[i
], dbargv
[i
]) != 0) {
880 dns_zone_detach(zonep
);
885 * Check that there are not extra arguments.
887 if (i
== dbtypec
&& argv
[i
] != NULL
)
888 dns_zone_detach(zonep
);
889 isc_mem_free(mctx
, argv
);
894 * Configure 'view' according to 'vconfig', taking defaults from 'config'
895 * where values are missing in 'vconfig'.
897 * When configuring the default view, 'vconfig' will be NULL and the
898 * global defaults in 'config' used exclusively.
901 configure_view(dns_view_t
*view
, const cfg_obj_t
*config
,
902 const cfg_obj_t
*vconfig
, isc_mem_t
*mctx
,
903 cfg_aclconfctx_t
*actx
, isc_boolean_t need_hints
)
905 const cfg_obj_t
*maps
[4];
906 const cfg_obj_t
*cfgmaps
[3];
907 const cfg_obj_t
*options
= NULL
;
908 const cfg_obj_t
*voptions
= NULL
;
909 const cfg_obj_t
*forwardtype
;
910 const cfg_obj_t
*forwarders
;
911 const cfg_obj_t
*alternates
;
912 const cfg_obj_t
*zonelist
;
914 const cfg_obj_t
*dlz
;
915 unsigned int dlzargc
;
918 const cfg_obj_t
*disabled
;
919 const cfg_obj_t
*obj
;
920 const cfg_listelt_t
*element
;
922 dns_cache_t
*cache
= NULL
;
924 isc_uint32_t max_adb_size
;
925 isc_uint32_t max_cache_size
;
926 isc_uint32_t max_acache_size
;
927 isc_uint32_t lame_ttl
;
928 dns_tsig_keyring_t
*ring
;
929 dns_view_t
*pview
= NULL
; /* Production view */
931 dns_dispatch_t
*dispatch4
= NULL
;
932 dns_dispatch_t
*dispatch6
= NULL
;
933 isc_boolean_t reused_cache
= ISC_FALSE
;
936 dns_order_t
*order
= NULL
;
937 isc_uint32_t udpsize
;
938 unsigned int check
= 0;
939 dns_zone_t
*zone
= NULL
;
940 isc_uint32_t max_clients_per_query
;
941 const char *sep
= ": view ";
942 const char *viewname
= view
->name
;
943 const char *forview
= " for view ";
944 isc_boolean_t rfc1918
;
945 isc_boolean_t empty_zones_enable
;
946 const cfg_obj_t
*disablelist
= NULL
;
948 REQUIRE(DNS_VIEW_VALID(view
));
953 (void)cfg_map_get(config
, "options", &options
);
956 if (vconfig
!= NULL
) {
957 voptions
= cfg_tuple_get(vconfig
, "options");
958 maps
[i
++] = voptions
;
962 maps
[i
++] = ns_g_defaults
;
966 if (voptions
!= NULL
)
967 cfgmaps
[i
++] = voptions
;
969 cfgmaps
[i
++] = config
;
972 if (!strcmp(viewname
, "_default")) {
979 * Set the view's port number for outgoing queries.
981 CHECKM(ns_config_getport(config
, &port
), "port");
982 dns_view_setdstport(view
, port
);
985 * Create additional cache for this view and zones under the view
986 * if explicitly enabled.
987 * XXX950 default to on.
990 (void)ns_config_get(maps
, "acache-enable", &obj
);
991 if (obj
!= NULL
&& cfg_obj_asboolean(obj
)) {
993 CHECK(isc_mem_create(0, 0, &cmctx
));
994 CHECK(dns_acache_create(&view
->acache
, cmctx
, ns_g_taskmgr
,
996 isc_mem_detach(&cmctx
);
998 if (view
->acache
!= NULL
) {
1000 result
= ns_config_get(maps
, "acache-cleaning-interval", &obj
);
1001 INSIST(result
== ISC_R_SUCCESS
);
1002 dns_acache_setcleaninginterval(view
->acache
,
1003 cfg_obj_asuint32(obj
) * 60);
1006 result
= ns_config_get(maps
, "max-acache-size", &obj
);
1007 INSIST(result
== ISC_R_SUCCESS
);
1008 if (cfg_obj_isstring(obj
)) {
1009 str
= cfg_obj_asstring(obj
);
1010 INSIST(strcasecmp(str
, "unlimited") == 0);
1011 max_acache_size
= ISC_UINT32_MAX
;
1013 isc_resourcevalue_t value
;
1015 value
= cfg_obj_asuint64(obj
);
1016 if (value
> ISC_UINT32_MAX
) {
1017 cfg_obj_log(obj
, ns_g_lctx
, ISC_LOG_ERROR
,
1019 "%" ISC_PRINT_QUADFORMAT
1022 result
= ISC_R_RANGE
;
1025 max_acache_size
= (isc_uint32_t
)value
;
1027 dns_acache_setcachesize(view
->acache
, max_acache_size
);
1031 * Configure the zones.
1034 if (voptions
!= NULL
)
1035 (void)cfg_map_get(voptions
, "zone", &zonelist
);
1037 (void)cfg_map_get(config
, "zone", &zonelist
);
1038 for (element
= cfg_list_first(zonelist
);
1040 element
= cfg_list_next(element
))
1042 const cfg_obj_t
*zconfig
= cfg_listelt_value(element
);
1043 CHECK(configure_zone(config
, zconfig
, vconfig
, mctx
, view
,
1049 * Create Dynamically Loadable Zone driver.
1052 if (voptions
!= NULL
)
1053 (void)cfg_map_get(voptions
, "dlz", &dlz
);
1055 (void)cfg_map_get(config
, "dlz", &dlz
);
1059 (void)cfg_map_get(cfg_tuple_get(dlz
, "options"),
1062 char *s
= isc_mem_strdup(mctx
, cfg_obj_asstring(obj
));
1064 result
= ISC_R_NOMEMORY
;
1068 result
= dns_dlzstrtoargv(mctx
, s
, &dlzargc
, &dlzargv
);
1069 if (result
!= ISC_R_SUCCESS
) {
1070 isc_mem_free(mctx
, s
);
1074 obj
= cfg_tuple_get(dlz
, "name");
1075 result
= dns_dlzcreate(mctx
, cfg_obj_asstring(obj
),
1076 dlzargv
[0], dlzargc
, dlzargv
,
1077 &view
->dlzdatabase
);
1078 isc_mem_free(mctx
, s
);
1079 isc_mem_put(mctx
, dlzargv
, dlzargc
* sizeof(*dlzargv
));
1080 if (result
!= ISC_R_SUCCESS
)
1087 * Configure the view's cache. Try to reuse an existing
1088 * cache if possible, otherwise create a new cache.
1089 * Note that the ADB is not preserved in either case.
1091 * XXX Determining when it is safe to reuse a cache is
1092 * tricky. When the view's configuration changes, the cached
1093 * data may become invalid because it reflects our old
1094 * view of the world. As more view attributes become
1095 * configurable, we will have to add code here to check
1096 * whether they have changed in ways that could
1097 * invalidate the cache.
1099 result
= dns_viewlist_find(&ns_g_server
->viewlist
,
1100 view
->name
, view
->rdclass
,
1102 if (result
!= ISC_R_NOTFOUND
&& result
!= ISC_R_SUCCESS
)
1104 if (pview
!= NULL
) {
1105 INSIST(pview
->cache
!= NULL
);
1106 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1107 NS_LOGMODULE_SERVER
, ISC_LOG_DEBUG(3),
1108 "reusing existing cache");
1109 reused_cache
= ISC_TRUE
;
1110 dns_cache_attach(pview
->cache
, &cache
);
1111 dns_view_detach(&pview
);
1113 CHECK(isc_mem_create(0, 0, &cmctx
));
1114 CHECK(dns_cache_create(cmctx
, ns_g_taskmgr
, ns_g_timermgr
,
1115 view
->rdclass
, "rbt", 0, NULL
, &cache
));
1117 dns_view_setcache(view
, cache
);
1120 * cache-file cannot be inherited if views are present, but this
1121 * should be caught by the configuration checking stage.
1124 result
= ns_config_get(maps
, "cache-file", &obj
);
1125 if (result
== ISC_R_SUCCESS
&& strcmp(view
->name
, "_bind") != 0) {
1126 CHECK(dns_cache_setfilename(cache
, cfg_obj_asstring(obj
)));
1128 CHECK(dns_cache_load(cache
));
1132 result
= ns_config_get(maps
, "cleaning-interval", &obj
);
1133 INSIST(result
== ISC_R_SUCCESS
);
1134 dns_cache_setcleaninginterval(cache
, cfg_obj_asuint32(obj
) * 60);
1137 result
= ns_config_get(maps
, "max-cache-size", &obj
);
1138 INSIST(result
== ISC_R_SUCCESS
);
1139 if (cfg_obj_isstring(obj
)) {
1140 str
= cfg_obj_asstring(obj
);
1141 INSIST(strcasecmp(str
, "unlimited") == 0);
1142 max_cache_size
= ISC_UINT32_MAX
;
1144 isc_resourcevalue_t value
;
1145 value
= cfg_obj_asuint64(obj
);
1146 if (value
> ISC_UINT32_MAX
) {
1147 cfg_obj_log(obj
, ns_g_lctx
, ISC_LOG_ERROR
,
1149 "%" ISC_PRINT_QUADFORMAT
"d' is too large",
1151 result
= ISC_R_RANGE
;
1154 max_cache_size
= (isc_uint32_t
)value
;
1156 dns_cache_setcachesize(cache
, max_cache_size
);
1158 dns_cache_detach(&cache
);
1164 result
= ns_checknames_get(maps
, "response", &obj
);
1165 INSIST(result
== ISC_R_SUCCESS
);
1167 str
= cfg_obj_asstring(obj
);
1168 if (strcasecmp(str
, "fail") == 0) {
1169 check
= DNS_RESOLVER_CHECKNAMES
|
1170 DNS_RESOLVER_CHECKNAMESFAIL
;
1171 view
->checknames
= ISC_TRUE
;
1172 } else if (strcasecmp(str
, "warn") == 0) {
1173 check
= DNS_RESOLVER_CHECKNAMES
;
1174 view
->checknames
= ISC_FALSE
;
1175 } else if (strcasecmp(str
, "ignore") == 0) {
1177 view
->checknames
= ISC_FALSE
;
1184 * XXXRTH Hardwired number of tasks.
1186 CHECK(get_view_querysource_dispatch(maps
, AF_INET
, &dispatch4
));
1187 CHECK(get_view_querysource_dispatch(maps
, AF_INET6
, &dispatch6
));
1188 if (dispatch4
== NULL
&& dispatch6
== NULL
) {
1189 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1190 "unable to obtain neither an IPv4 nor"
1191 " an IPv6 dispatch");
1192 result
= ISC_R_UNEXPECTED
;
1195 CHECK(dns_view_createresolver(view
, ns_g_taskmgr
, 31,
1196 ns_g_socketmgr
, ns_g_timermgr
,
1197 check
, ns_g_dispatchmgr
,
1198 dispatch4
, dispatch6
));
1201 * Set the ADB cache size to 1/8th of the max-cache-size.
1204 if (max_cache_size
!= 0) {
1205 max_adb_size
= max_cache_size
/ 8;
1206 if (max_adb_size
== 0)
1207 max_adb_size
= 1; /* Force minimum. */
1209 dns_adb_setadbsize(view
->adb
, max_adb_size
);
1212 * Set resolver's lame-ttl.
1215 result
= ns_config_get(maps
, "lame-ttl", &obj
);
1216 INSIST(result
== ISC_R_SUCCESS
);
1217 lame_ttl
= cfg_obj_asuint32(obj
);
1218 if (lame_ttl
> 1800)
1220 dns_resolver_setlamettl(view
->resolver
, lame_ttl
);
1223 result
= ns_config_get(maps
, "zero-no-soa-ttl-cache", &obj
);
1224 INSIST(result
== ISC_R_SUCCESS
);
1225 dns_resolver_setzeronosoattl(view
->resolver
, cfg_obj_asboolean(obj
));
1228 * Set the resolver's EDNS UDP size.
1231 result
= ns_config_get(maps
, "edns-udp-size", &obj
);
1232 INSIST(result
== ISC_R_SUCCESS
);
1233 udpsize
= cfg_obj_asuint32(obj
);
1238 dns_resolver_setudpsize(view
->resolver
, (isc_uint16_t
)udpsize
);
1241 * Set the maximum UDP response size.
1244 result
= ns_config_get(maps
, "max-udp-size", &obj
);
1245 INSIST(result
== ISC_R_SUCCESS
);
1246 udpsize
= cfg_obj_asuint32(obj
);
1251 view
->maxudp
= udpsize
;
1254 * Set supported DNSSEC algorithms.
1256 dns_resolver_reset_algorithms(view
->resolver
);
1258 (void)ns_config_get(maps
, "disable-algorithms", &disabled
);
1259 if (disabled
!= NULL
) {
1260 for (element
= cfg_list_first(disabled
);
1262 element
= cfg_list_next(element
))
1263 CHECK(disable_algorithms(cfg_listelt_value(element
),
1268 * A global or view "forwarders" option, if present,
1269 * creates an entry for "." in the forwarding table.
1273 (void)ns_config_get(maps
, "forward", &forwardtype
);
1274 (void)ns_config_get(maps
, "forwarders", &forwarders
);
1275 if (forwarders
!= NULL
)
1276 CHECK(configure_forward(config
, view
, dns_rootname
,
1277 forwarders
, forwardtype
));
1280 * Dual Stack Servers.
1283 (void)ns_config_get(maps
, "dual-stack-servers", &alternates
);
1284 if (alternates
!= NULL
)
1285 CHECK(configure_alternates(config
, view
, alternates
));
1288 * We have default hints for class IN if we need them.
1290 if (view
->rdclass
== dns_rdataclass_in
&& view
->hints
== NULL
)
1291 dns_view_sethints(view
, ns_g_server
->in_roothints
);
1294 * If we still have no hints, this is a non-IN view with no
1295 * "hints zone" configured. Issue a warning, except if this
1296 * is a root server. Root servers never need to consult
1297 * their hints, so it's no point requiring users to configure
1300 if (view
->hints
== NULL
) {
1301 dns_zone_t
*rootzone
= NULL
;
1302 (void)dns_view_findzone(view
, dns_rootname
, &rootzone
);
1303 if (rootzone
!= NULL
) {
1304 dns_zone_detach(&rootzone
);
1305 need_hints
= ISC_FALSE
;
1308 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1309 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
1310 "no root hints for view '%s'",
1315 * Configure the view's TSIG keys.
1318 CHECK(ns_tsigkeyring_fromconfig(config
, vconfig
, view
->mctx
, &ring
));
1319 dns_view_setkeyring(view
, ring
);
1322 * Configure the view's peer list.
1325 const cfg_obj_t
*peers
= NULL
;
1326 const cfg_listelt_t
*element
;
1327 dns_peerlist_t
*newpeers
= NULL
;
1329 (void)ns_config_get(cfgmaps
, "server", &peers
);
1330 CHECK(dns_peerlist_new(mctx
, &newpeers
));
1331 for (element
= cfg_list_first(peers
);
1333 element
= cfg_list_next(element
))
1335 const cfg_obj_t
*cpeer
= cfg_listelt_value(element
);
1338 CHECK(configure_peer(cpeer
, mctx
, &peer
));
1339 dns_peerlist_addpeer(newpeers
, peer
);
1340 dns_peer_detach(&peer
);
1342 dns_peerlist_detach(&view
->peers
);
1343 view
->peers
= newpeers
; /* Transfer ownership. */
1347 * Configure the views rrset-order.
1350 const cfg_obj_t
*rrsetorder
= NULL
;
1351 const cfg_listelt_t
*element
;
1353 (void)ns_config_get(maps
, "rrset-order", &rrsetorder
);
1354 CHECK(dns_order_create(mctx
, &order
));
1355 for (element
= cfg_list_first(rrsetorder
);
1357 element
= cfg_list_next(element
))
1359 const cfg_obj_t
*ent
= cfg_listelt_value(element
);
1361 CHECK(configure_order(order
, ent
));
1363 if (view
->order
!= NULL
)
1364 dns_order_detach(&view
->order
);
1365 dns_order_attach(order
, &view
->order
);
1366 dns_order_detach(&order
);
1369 * Copy the aclenv object.
1371 dns_aclenv_copy(&view
->aclenv
, &ns_g_server
->aclenv
);
1374 * Configure the "match-clients" and "match-destinations" ACL.
1376 CHECK(configure_view_acl(vconfig
, config
, "match-clients", actx
,
1377 ns_g_mctx
, &view
->matchclients
));
1378 CHECK(configure_view_acl(vconfig
, config
, "match-destinations", actx
,
1379 ns_g_mctx
, &view
->matchdestinations
));
1382 * Configure the "match-recursive-only" option.
1385 (void)ns_config_get(maps
, "match-recursive-only", &obj
);
1386 if (obj
!= NULL
&& cfg_obj_asboolean(obj
))
1387 view
->matchrecursiveonly
= ISC_TRUE
;
1389 view
->matchrecursiveonly
= ISC_FALSE
;
1392 * Configure other configurable data.
1395 result
= ns_config_get(maps
, "recursion", &obj
);
1396 INSIST(result
== ISC_R_SUCCESS
);
1397 view
->recursion
= cfg_obj_asboolean(obj
);
1400 result
= ns_config_get(maps
, "auth-nxdomain", &obj
);
1401 INSIST(result
== ISC_R_SUCCESS
);
1402 view
->auth_nxdomain
= cfg_obj_asboolean(obj
);
1405 result
= ns_config_get(maps
, "minimal-responses", &obj
);
1406 INSIST(result
== ISC_R_SUCCESS
);
1407 view
->minimalresponses
= cfg_obj_asboolean(obj
);
1410 result
= ns_config_get(maps
, "transfer-format", &obj
);
1411 INSIST(result
== ISC_R_SUCCESS
);
1412 str
= cfg_obj_asstring(obj
);
1413 if (strcasecmp(str
, "many-answers") == 0)
1414 view
->transfer_format
= dns_many_answers
;
1415 else if (strcasecmp(str
, "one-answer") == 0)
1416 view
->transfer_format
= dns_one_answer
;
1421 * Set sources where additional data and CNAME/DNAME
1422 * targets for authoritative answers may be found.
1425 result
= ns_config_get(maps
, "additional-from-auth", &obj
);
1426 INSIST(result
== ISC_R_SUCCESS
);
1427 view
->additionalfromauth
= cfg_obj_asboolean(obj
);
1428 if (view
->recursion
&& ! view
->additionalfromauth
) {
1429 cfg_obj_log(obj
, ns_g_lctx
, ISC_LOG_WARNING
,
1430 "'additional-from-auth no' is only supported "
1431 "with 'recursion no'");
1432 view
->additionalfromauth
= ISC_TRUE
;
1436 result
= ns_config_get(maps
, "additional-from-cache", &obj
);
1437 INSIST(result
== ISC_R_SUCCESS
);
1438 view
->additionalfromcache
= cfg_obj_asboolean(obj
);
1439 if (view
->recursion
&& ! view
->additionalfromcache
) {
1440 cfg_obj_log(obj
, ns_g_lctx
, ISC_LOG_WARNING
,
1441 "'additional-from-cache no' is only supported "
1442 "with 'recursion no'");
1443 view
->additionalfromcache
= ISC_TRUE
;
1447 * Set "allow-query-cache" and "allow-recursion" acls if
1448 * configured in named.conf.
1450 CHECK(configure_view_acl(vconfig
, config
, "allow-query-cache",
1451 actx
, ns_g_mctx
, &view
->queryacl
));
1453 if (strcmp(view
->name
, "_bind") != 0)
1454 CHECK(configure_view_acl(vconfig
, config
, "allow-recursion",
1455 actx
, ns_g_mctx
, &view
->recursionacl
));
1458 * Warning if both "recursion no;" and allow-recursion are active
1459 * except for "allow-recursion { none; };".
1461 if (!view
->recursion
&& view
->recursionacl
!= NULL
&&
1462 (view
->recursionacl
->length
!= 1 ||
1463 view
->recursionacl
->elements
[0].type
!= dns_aclelementtype_any
||
1464 view
->recursionacl
->elements
[0].negative
!= ISC_TRUE
))
1465 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1466 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
1467 "both \"recursion no;\" and \"allow-recursion\" "
1468 "active%s%s", forview
, viewname
);
1471 * "allow-query-cache" inherits from "allow-recursion" if set,
1472 * otherwise from "allow-query" if set.
1473 * "allow-recursion" inherits from "allow-query-cache" if set,
1474 * otherwise from "allow-query" if set.
1476 if (view
->queryacl
== NULL
&& view
->recursionacl
!= NULL
)
1477 dns_acl_attach(view
->recursionacl
, &view
->queryacl
);
1478 if (view
->queryacl
== NULL
)
1479 CHECK(configure_view_acl(vconfig
, config
, "allow-query",
1480 actx
, ns_g_mctx
, &view
->queryacl
));
1481 if (view
->recursionacl
== NULL
&& view
->queryacl
!= NULL
)
1482 dns_acl_attach(view
->queryacl
, &view
->recursionacl
);
1485 * Set default "allow-recursion" and "allow-query-cache" acls.
1487 if (view
->recursionacl
== NULL
&& view
->recursion
)
1488 CHECK(configure_view_acl(NULL
, ns_g_config
, "allow-recursion",
1489 actx
, ns_g_mctx
, &view
->recursionacl
));
1490 if (view
->queryacl
== NULL
)
1491 CHECK(configure_view_acl(NULL
, ns_g_config
,
1492 "allow-query-cache", actx
,
1493 ns_g_mctx
, &view
->queryacl
));
1495 CHECK(configure_view_acl(vconfig
, config
, "sortlist",
1496 actx
, ns_g_mctx
, &view
->sortlist
));
1499 result
= ns_config_get(maps
, "request-ixfr", &obj
);
1500 INSIST(result
== ISC_R_SUCCESS
);
1501 view
->requestixfr
= cfg_obj_asboolean(obj
);
1504 result
= ns_config_get(maps
, "provide-ixfr", &obj
);
1505 INSIST(result
== ISC_R_SUCCESS
);
1506 view
->provideixfr
= cfg_obj_asboolean(obj
);
1509 result
= ns_config_get(maps
, "max-clients-per-query", &obj
);
1510 INSIST(result
== ISC_R_SUCCESS
);
1511 max_clients_per_query
= cfg_obj_asuint32(obj
);
1514 result
= ns_config_get(maps
, "clients-per-query", &obj
);
1515 INSIST(result
== ISC_R_SUCCESS
);
1516 dns_resolver_setclientsperquery(view
->resolver
,
1517 cfg_obj_asuint32(obj
),
1518 max_clients_per_query
);
1521 result
= ns_config_get(maps
, "dnssec-enable", &obj
);
1522 INSIST(result
== ISC_R_SUCCESS
);
1523 view
->enablednssec
= cfg_obj_asboolean(obj
);
1526 result
= ns_config_get(maps
, "dnssec-accept-expired", &obj
);
1527 INSIST(result
== ISC_R_SUCCESS
);
1528 view
->acceptexpired
= cfg_obj_asboolean(obj
);
1531 result
= ns_config_get(maps
, "dnssec-validation", &obj
);
1532 INSIST(result
== ISC_R_SUCCESS
);
1533 view
->enablevalidation
= cfg_obj_asboolean(obj
);
1536 result
= ns_config_get(maps
, "dnssec-lookaside", &obj
);
1537 if (result
== ISC_R_SUCCESS
) {
1538 for (element
= cfg_list_first(obj
);
1540 element
= cfg_list_next(element
))
1546 obj
= cfg_listelt_value(element
);
1548 dns_fixedname_t fixed
;
1552 * When we support multiple dnssec-lookaside
1553 * entries this is how to find the domain to be
1556 dns_fixedname_init(&fixed
);
1557 name
= dns_fixedname_name(&fixed
);
1558 str
= cfg_obj_asstring(cfg_tuple_get(obj
,
1560 isc_buffer_init(&b
, str
, strlen(str
));
1561 isc_buffer_add(&b
, strlen(str
));
1562 CHECK(dns_name_fromtext(name
, &b
, dns_rootname
,
1565 str
= cfg_obj_asstring(cfg_tuple_get(obj
,
1567 isc_buffer_init(&b
, str
, strlen(str
));
1568 isc_buffer_add(&b
, strlen(str
));
1569 dlv
= dns_fixedname_name(&view
->dlv_fixed
);
1570 CHECK(dns_name_fromtext(dlv
, &b
, dns_rootname
,
1572 view
->dlv
= dns_fixedname_name(&view
->dlv_fixed
);
1578 * For now, there is only one kind of trusted keys, the
1581 CHECK(configure_view_dnsseckeys(vconfig
, config
, mctx
,
1583 dns_resolver_resetmustbesecure(view
->resolver
);
1585 result
= ns_config_get(maps
, "dnssec-must-be-secure", &obj
);
1586 if (result
== ISC_R_SUCCESS
)
1587 CHECK(mustbesecure(obj
, view
->resolver
));
1590 result
= ns_config_get(maps
, "max-cache-ttl", &obj
);
1591 INSIST(result
== ISC_R_SUCCESS
);
1592 view
->maxcachettl
= cfg_obj_asuint32(obj
);
1595 result
= ns_config_get(maps
, "max-ncache-ttl", &obj
);
1596 INSIST(result
== ISC_R_SUCCESS
);
1597 view
->maxncachettl
= cfg_obj_asuint32(obj
);
1598 if (view
->maxncachettl
> 7 * 24 * 3600)
1599 view
->maxncachettl
= 7 * 24 * 3600;
1602 result
= ns_config_get(maps
, "preferred-glue", &obj
);
1603 if (result
== ISC_R_SUCCESS
) {
1604 str
= cfg_obj_asstring(obj
);
1605 if (strcasecmp(str
, "a") == 0)
1606 view
->preferred_glue
= dns_rdatatype_a
;
1607 else if (strcasecmp(str
, "aaaa") == 0)
1608 view
->preferred_glue
= dns_rdatatype_aaaa
;
1610 view
->preferred_glue
= 0;
1612 view
->preferred_glue
= 0;
1615 result
= ns_config_get(maps
, "root-delegation-only", &obj
);
1616 if (result
== ISC_R_SUCCESS
) {
1617 dns_view_setrootdelonly(view
, ISC_TRUE
);
1618 if (!cfg_obj_isvoid(obj
)) {
1619 dns_fixedname_t fixed
;
1623 const cfg_obj_t
*exclude
;
1625 dns_fixedname_init(&fixed
);
1626 name
= dns_fixedname_name(&fixed
);
1627 for (element
= cfg_list_first(obj
);
1629 element
= cfg_list_next(element
)) {
1630 exclude
= cfg_listelt_value(element
);
1631 str
= cfg_obj_asstring(exclude
);
1632 isc_buffer_init(&b
, str
, strlen(str
));
1633 isc_buffer_add(&b
, strlen(str
));
1634 CHECK(dns_name_fromtext(name
, &b
, dns_rootname
,
1636 CHECK(dns_view_excludedelegationonly(view
,
1641 dns_view_setrootdelonly(view
, ISC_FALSE
);
1644 * Setup automatic empty zones. If recursion is off then
1645 * they are disabled by default.
1648 (void)ns_config_get(maps
, "empty-zones-enable", &obj
);
1649 (void)ns_config_get(maps
, "disable-empty-zone", &disablelist
);
1650 if (obj
== NULL
&& disablelist
== NULL
&&
1651 view
->rdclass
== dns_rdataclass_in
) {
1652 rfc1918
= ISC_FALSE
;
1653 empty_zones_enable
= view
->recursion
;
1654 } else if (view
->rdclass
== dns_rdataclass_in
) {
1657 empty_zones_enable
= cfg_obj_asboolean(obj
);
1659 empty_zones_enable
= view
->recursion
;
1661 rfc1918
= ISC_FALSE
;
1662 empty_zones_enable
= ISC_FALSE
;
1664 if (empty_zones_enable
) {
1667 dns_fixedname_t fixed
;
1669 isc_buffer_t buffer
;
1671 char server
[DNS_NAME_FORMATSIZE
+ 1];
1672 char contact
[DNS_NAME_FORMATSIZE
+ 1];
1673 isc_boolean_t logit
;
1674 const char *empty_dbtype
[4] =
1675 { "_builtin", "empty", NULL
, NULL
};
1676 int empty_dbtypec
= 4;
1678 dns_fixedname_init(&fixed
);
1679 name
= dns_fixedname_name(&fixed
);
1682 result
= ns_config_get(maps
, "empty-server", &obj
);
1683 if (result
== ISC_R_SUCCESS
) {
1684 str
= cfg_obj_asstring(obj
);
1685 isc_buffer_init(&buffer
, str
, strlen(str
));
1686 isc_buffer_add(&buffer
, strlen(str
));
1687 CHECK(dns_name_fromtext(name
, &buffer
, dns_rootname
,
1689 isc_buffer_init(&buffer
, server
, sizeof(server
) - 1);
1690 CHECK(dns_name_totext(name
, ISC_FALSE
, &buffer
));
1691 server
[isc_buffer_usedlength(&buffer
)] = 0;
1692 empty_dbtype
[2] = server
;
1694 empty_dbtype
[2] = "@";
1697 result
= ns_config_get(maps
, "empty-contact", &obj
);
1698 if (result
== ISC_R_SUCCESS
) {
1699 str
= cfg_obj_asstring(obj
);
1700 isc_buffer_init(&buffer
, str
, strlen(str
));
1701 isc_buffer_add(&buffer
, strlen(str
));
1702 CHECK(dns_name_fromtext(name
, &buffer
, dns_rootname
,
1704 isc_buffer_init(&buffer
, contact
, sizeof(contact
) - 1);
1705 CHECK(dns_name_totext(name
, ISC_FALSE
, &buffer
));
1706 contact
[isc_buffer_usedlength(&buffer
)] = 0;
1707 empty_dbtype
[3] = contact
;
1709 empty_dbtype
[3] = ".";
1712 for (empty
= empty_zones
[empty_zone
].zone
;
1714 empty
= empty_zones
[++empty_zone
].zone
)
1716 dns_forwarders_t
*forwarders
= NULL
;
1717 dns_view_t
*pview
= NULL
;
1719 isc_buffer_init(&buffer
, empty
, strlen(empty
));
1720 isc_buffer_add(&buffer
, strlen(empty
));
1722 * Look for zone on drop list.
1724 CHECK(dns_name_fromtext(name
, &buffer
, dns_rootname
,
1726 if (disablelist
!= NULL
&&
1727 on_disable_list(disablelist
, name
))
1731 * This zone already exists.
1733 (void)dns_view_findzone(view
, name
, &zone
);
1735 dns_zone_detach(&zone
);
1740 * If we would forward this name don't add a
1741 * empty zone for it.
1743 result
= dns_fwdtable_find(view
->fwdtable
, name
,
1745 if (result
== ISC_R_SUCCESS
&&
1746 forwarders
->fwdpolicy
== dns_fwdpolicy_only
)
1749 if (!rfc1918
&& empty_zones
[empty_zone
].rfc1918
) {
1751 isc_log_write(ns_g_lctx
,
1752 NS_LOGCATEGORY_GENERAL
,
1753 NS_LOGMODULE_SERVER
,
1756 "'empty-zones-enable/"
1757 "disable-empty-zone' "
1758 "not set: disabling "
1759 "RFC 1918 empty zones",
1767 * See if we can re-use a existing zone.
1769 result
= dns_viewlist_find(&ns_g_server
->viewlist
,
1770 view
->name
, view
->rdclass
,
1772 if (result
!= ISC_R_NOTFOUND
&&
1773 result
!= ISC_R_SUCCESS
)
1776 if (pview
!= NULL
) {
1777 (void)dns_view_findzone(pview
, name
, &zone
);
1778 dns_view_detach(&pview
);
1780 check_dbtype(&zone
, empty_dbtypec
,
1781 empty_dbtype
, mctx
);
1783 dns_zone_setview(zone
, view
);
1784 CHECK(dns_view_addzone(view
, zone
));
1785 dns_zone_detach(&zone
);
1790 CHECK(dns_zone_create(&zone
, mctx
));
1791 CHECK(dns_zone_setorigin(zone
, name
));
1792 dns_zone_setview(zone
, view
);
1793 CHECK(dns_zonemgr_managezone(ns_g_server
->zonemgr
, zone
));
1794 dns_zone_setclass(zone
, view
->rdclass
);
1795 dns_zone_settype(zone
, dns_zone_master
);
1796 CHECK(dns_zone_setdbtype(zone
, empty_dbtypec
,
1798 if (view
->queryacl
!= NULL
)
1799 dns_zone_setqueryacl(zone
, view
->queryacl
);
1800 dns_zone_setdialup(zone
, dns_dialuptype_no
);
1801 dns_zone_setnotifytype(zone
, dns_notifytype_no
);
1802 dns_zone_setoption(zone
, DNS_ZONEOPT_NOCHECKNS
,
1804 CHECK(dns_view_addzone(view
, zone
));
1805 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
1806 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
1807 "automatic empty zone%s%s: %s",
1808 sep
, viewname
, empty
);
1809 dns_zone_detach(&zone
);
1813 result
= ISC_R_SUCCESS
;
1817 dns_zone_detach(&zone
);
1818 if (dispatch4
!= NULL
)
1819 dns_dispatch_detach(&dispatch4
);
1820 if (dispatch6
!= NULL
)
1821 dns_dispatch_detach(&dispatch6
);
1823 dns_order_detach(&order
);
1825 isc_mem_detach(&cmctx
);
1828 dns_cache_detach(&cache
);
1834 configure_hints(dns_view_t
*view
, const char *filename
) {
1835 isc_result_t result
;
1839 result
= dns_rootns_create(view
->mctx
, view
->rdclass
, filename
, &db
);
1840 if (result
== ISC_R_SUCCESS
) {
1841 dns_view_sethints(view
, db
);
1849 configure_alternates(const cfg_obj_t
*config
, dns_view_t
*view
,
1850 const cfg_obj_t
*alternates
)
1852 const cfg_obj_t
*portobj
;
1853 const cfg_obj_t
*addresses
;
1854 const cfg_listelt_t
*element
;
1855 isc_result_t result
= ISC_R_SUCCESS
;
1859 * Determine which port to send requests to.
1861 if (ns_g_lwresdonly
&& ns_g_port
!= 0)
1864 CHECKM(ns_config_getport(config
, &port
), "port");
1866 if (alternates
!= NULL
) {
1867 portobj
= cfg_tuple_get(alternates
, "port");
1868 if (cfg_obj_isuint32(portobj
)) {
1869 isc_uint32_t val
= cfg_obj_asuint32(portobj
);
1870 if (val
> ISC_UINT16_MAX
) {
1871 cfg_obj_log(portobj
, ns_g_lctx
, ISC_LOG_ERROR
,
1872 "port '%u' out of range", val
);
1873 return (ISC_R_RANGE
);
1875 port
= (in_port_t
) val
;
1880 if (alternates
!= NULL
)
1881 addresses
= cfg_tuple_get(alternates
, "addresses");
1883 for (element
= cfg_list_first(addresses
);
1885 element
= cfg_list_next(element
))
1887 const cfg_obj_t
*alternate
= cfg_listelt_value(element
);
1890 if (!cfg_obj_issockaddr(alternate
)) {
1891 dns_fixedname_t fixed
;
1893 const char *str
= cfg_obj_asstring(cfg_tuple_get(
1894 alternate
, "name"));
1895 isc_buffer_t buffer
;
1896 in_port_t myport
= port
;
1898 isc_buffer_init(&buffer
, str
, strlen(str
));
1899 isc_buffer_add(&buffer
, strlen(str
));
1900 dns_fixedname_init(&fixed
);
1901 name
= dns_fixedname_name(&fixed
);
1902 CHECK(dns_name_fromtext(name
, &buffer
, dns_rootname
,
1905 portobj
= cfg_tuple_get(alternate
, "port");
1906 if (cfg_obj_isuint32(portobj
)) {
1907 isc_uint32_t val
= cfg_obj_asuint32(portobj
);
1908 if (val
> ISC_UINT16_MAX
) {
1909 cfg_obj_log(portobj
, ns_g_lctx
,
1911 "port '%u' out of range",
1913 return (ISC_R_RANGE
);
1915 myport
= (in_port_t
) val
;
1917 CHECK(dns_resolver_addalternate(view
->resolver
, NULL
,
1922 sa
= *cfg_obj_assockaddr(alternate
);
1923 if (isc_sockaddr_getport(&sa
) == 0)
1924 isc_sockaddr_setport(&sa
, port
);
1925 CHECK(dns_resolver_addalternate(view
->resolver
, &sa
,
1934 configure_forward(const cfg_obj_t
*config
, dns_view_t
*view
, dns_name_t
*origin
,
1935 const cfg_obj_t
*forwarders
, const cfg_obj_t
*forwardtype
)
1937 const cfg_obj_t
*portobj
;
1938 const cfg_obj_t
*faddresses
;
1939 const cfg_listelt_t
*element
;
1940 dns_fwdpolicy_t fwdpolicy
= dns_fwdpolicy_none
;
1941 isc_sockaddrlist_t addresses
;
1943 isc_result_t result
;
1947 * Determine which port to send forwarded requests to.
1949 if (ns_g_lwresdonly
&& ns_g_port
!= 0)
1952 CHECKM(ns_config_getport(config
, &port
), "port");
1954 if (forwarders
!= NULL
) {
1955 portobj
= cfg_tuple_get(forwarders
, "port");
1956 if (cfg_obj_isuint32(portobj
)) {
1957 isc_uint32_t val
= cfg_obj_asuint32(portobj
);
1958 if (val
> ISC_UINT16_MAX
) {
1959 cfg_obj_log(portobj
, ns_g_lctx
, ISC_LOG_ERROR
,
1960 "port '%u' out of range", val
);
1961 return (ISC_R_RANGE
);
1963 port
= (in_port_t
) val
;
1968 if (forwarders
!= NULL
)
1969 faddresses
= cfg_tuple_get(forwarders
, "addresses");
1971 ISC_LIST_INIT(addresses
);
1973 for (element
= cfg_list_first(faddresses
);
1975 element
= cfg_list_next(element
))
1977 const cfg_obj_t
*forwarder
= cfg_listelt_value(element
);
1978 sa
= isc_mem_get(view
->mctx
, sizeof(isc_sockaddr_t
));
1980 result
= ISC_R_NOMEMORY
;
1983 *sa
= *cfg_obj_assockaddr(forwarder
);
1984 if (isc_sockaddr_getport(sa
) == 0)
1985 isc_sockaddr_setport(sa
, port
);
1986 ISC_LINK_INIT(sa
, link
);
1987 ISC_LIST_APPEND(addresses
, sa
, link
);
1990 if (ISC_LIST_EMPTY(addresses
)) {
1991 if (forwardtype
!= NULL
)
1992 cfg_obj_log(forwarders
, ns_g_lctx
, ISC_LOG_WARNING
,
1993 "no forwarders seen; disabling "
1995 fwdpolicy
= dns_fwdpolicy_none
;
1997 if (forwardtype
== NULL
)
1998 fwdpolicy
= dns_fwdpolicy_first
;
2000 const char *forwardstr
= cfg_obj_asstring(forwardtype
);
2001 if (strcasecmp(forwardstr
, "first") == 0)
2002 fwdpolicy
= dns_fwdpolicy_first
;
2003 else if (strcasecmp(forwardstr
, "only") == 0)
2004 fwdpolicy
= dns_fwdpolicy_only
;
2010 result
= dns_fwdtable_add(view
->fwdtable
, origin
, &addresses
,
2012 if (result
!= ISC_R_SUCCESS
) {
2013 char namebuf
[DNS_NAME_FORMATSIZE
];
2014 dns_name_format(origin
, namebuf
, sizeof(namebuf
));
2015 cfg_obj_log(forwarders
, ns_g_lctx
, ISC_LOG_WARNING
,
2016 "could not set up forwarding for domain '%s': %s",
2017 namebuf
, isc_result_totext(result
));
2021 result
= ISC_R_SUCCESS
;
2025 while (!ISC_LIST_EMPTY(addresses
)) {
2026 sa
= ISC_LIST_HEAD(addresses
);
2027 ISC_LIST_UNLINK(addresses
, sa
, link
);
2028 isc_mem_put(view
->mctx
, sa
, sizeof(isc_sockaddr_t
));
2035 * Create a new view and add it to the list.
2037 * If 'vconfig' is NULL, create the default view.
2039 * The view created is attached to '*viewp'.
2042 create_view(const cfg_obj_t
*vconfig
, dns_viewlist_t
*viewlist
,
2045 isc_result_t result
;
2046 const char *viewname
;
2047 dns_rdataclass_t viewclass
;
2048 dns_view_t
*view
= NULL
;
2050 if (vconfig
!= NULL
) {
2051 const cfg_obj_t
*classobj
= NULL
;
2053 viewname
= cfg_obj_asstring(cfg_tuple_get(vconfig
, "name"));
2054 classobj
= cfg_tuple_get(vconfig
, "class");
2055 result
= ns_config_getclass(classobj
, dns_rdataclass_in
,
2058 viewname
= "_default";
2059 viewclass
= dns_rdataclass_in
;
2061 result
= dns_viewlist_find(viewlist
, viewname
, viewclass
, &view
);
2062 if (result
== ISC_R_SUCCESS
)
2063 return (ISC_R_EXISTS
);
2064 if (result
!= ISC_R_NOTFOUND
)
2066 INSIST(view
== NULL
);
2068 result
= dns_view_create(ns_g_mctx
, viewclass
, viewname
, &view
);
2069 if (result
!= ISC_R_SUCCESS
)
2072 ISC_LIST_APPEND(*viewlist
, view
, link
);
2073 dns_view_attach(view
, viewp
);
2074 return (ISC_R_SUCCESS
);
2078 * Configure or reconfigure a zone.
2081 configure_zone(const cfg_obj_t
*config
, const cfg_obj_t
*zconfig
,
2082 const cfg_obj_t
*vconfig
, isc_mem_t
*mctx
, dns_view_t
*view
,
2083 cfg_aclconfctx_t
*aclconf
)
2085 dns_view_t
*pview
= NULL
; /* Production view */
2086 dns_zone_t
*zone
= NULL
; /* New or reused zone */
2087 dns_zone_t
*dupzone
= NULL
;
2088 const cfg_obj_t
*options
= NULL
;
2089 const cfg_obj_t
*zoptions
= NULL
;
2090 const cfg_obj_t
*typeobj
= NULL
;
2091 const cfg_obj_t
*forwarders
= NULL
;
2092 const cfg_obj_t
*forwardtype
= NULL
;
2093 const cfg_obj_t
*only
= NULL
;
2094 isc_result_t result
;
2095 isc_result_t tresult
;
2096 isc_buffer_t buffer
;
2097 dns_fixedname_t fixorigin
;
2100 dns_rdataclass_t zclass
;
2101 const char *ztypestr
;
2104 (void)cfg_map_get(config
, "options", &options
);
2106 zoptions
= cfg_tuple_get(zconfig
, "options");
2109 * Get the zone origin as a dns_name_t.
2111 zname
= cfg_obj_asstring(cfg_tuple_get(zconfig
, "name"));
2112 isc_buffer_init(&buffer
, zname
, strlen(zname
));
2113 isc_buffer_add(&buffer
, strlen(zname
));
2114 dns_fixedname_init(&fixorigin
);
2115 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin
),
2116 &buffer
, dns_rootname
, ISC_FALSE
, NULL
));
2117 origin
= dns_fixedname_name(&fixorigin
);
2119 CHECK(ns_config_getclass(cfg_tuple_get(zconfig
, "class"),
2120 view
->rdclass
, &zclass
));
2121 if (zclass
!= view
->rdclass
) {
2122 const char *vname
= NULL
;
2123 if (vconfig
!= NULL
)
2124 vname
= cfg_obj_asstring(cfg_tuple_get(vconfig
,
2127 vname
= "<default view>";
2129 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2130 NS_LOGMODULE_SERVER
, ISC_LOG_ERROR
,
2131 "zone '%s': wrong class for view '%s'",
2133 result
= ISC_R_FAILURE
;
2137 (void)cfg_map_get(zoptions
, "type", &typeobj
);
2138 if (typeobj
== NULL
) {
2139 cfg_obj_log(zconfig
, ns_g_lctx
, ISC_LOG_ERROR
,
2140 "zone '%s' 'type' not specified", zname
);
2141 return (ISC_R_FAILURE
);
2143 ztypestr
= cfg_obj_asstring(typeobj
);
2146 * "hints zones" aren't zones. If we've got one,
2147 * configure it and return.
2149 if (strcasecmp(ztypestr
, "hint") == 0) {
2150 const cfg_obj_t
*fileobj
= NULL
;
2151 if (cfg_map_get(zoptions
, "file", &fileobj
) != ISC_R_SUCCESS
) {
2152 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2153 NS_LOGMODULE_SERVER
, ISC_LOG_ERROR
,
2154 "zone '%s': 'file' not specified",
2156 result
= ISC_R_FAILURE
;
2159 if (dns_name_equal(origin
, dns_rootname
)) {
2160 const char *hintsfile
= cfg_obj_asstring(fileobj
);
2162 result
= configure_hints(view
, hintsfile
);
2163 if (result
!= ISC_R_SUCCESS
) {
2164 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2165 NS_LOGMODULE_SERVER
,
2167 "could not configure root hints "
2168 "from '%s': %s", hintsfile
,
2169 isc_result_totext(result
));
2173 * Hint zones may also refer to delegation only points.
2176 tresult
= cfg_map_get(zoptions
, "delegation-only",
2178 if (tresult
== ISC_R_SUCCESS
&& cfg_obj_asboolean(only
))
2179 CHECK(dns_view_adddelegationonly(view
, origin
));
2181 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2182 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
2183 "ignoring non-root hint zone '%s'",
2185 result
= ISC_R_SUCCESS
;
2187 /* Skip ordinary zone processing. */
2192 * "forward zones" aren't zones either. Translate this syntax into
2193 * the appropriate selective forwarding configuration and return.
2195 if (strcasecmp(ztypestr
, "forward") == 0) {
2199 (void)cfg_map_get(zoptions
, "forward", &forwardtype
);
2200 (void)cfg_map_get(zoptions
, "forwarders", &forwarders
);
2201 result
= configure_forward(config
, view
, origin
, forwarders
,
2207 * "delegation-only zones" aren't zones either.
2209 if (strcasecmp(ztypestr
, "delegation-only") == 0) {
2210 result
= dns_view_adddelegationonly(view
, origin
);
2215 * Check for duplicates in the new zone table.
2217 result
= dns_view_findzone(view
, origin
, &dupzone
);
2218 if (result
== ISC_R_SUCCESS
) {
2220 * We already have this zone!
2222 cfg_obj_log(zconfig
, ns_g_lctx
, ISC_LOG_ERROR
,
2223 "zone '%s' already exists", zname
);
2224 dns_zone_detach(&dupzone
);
2225 result
= ISC_R_EXISTS
;
2228 INSIST(dupzone
== NULL
);
2231 * See if we can reuse an existing zone. This is
2232 * only possible if all of these are true:
2233 * - The zone's view exists
2234 * - A zone with the right name exists in the view
2235 * - The zone is compatible with the config
2236 * options (e.g., an existing master zone cannot
2237 * be reused if the options specify a slave zone)
2239 result
= dns_viewlist_find(&ns_g_server
->viewlist
,
2240 view
->name
, view
->rdclass
,
2242 if (result
!= ISC_R_NOTFOUND
&& result
!= ISC_R_SUCCESS
)
2245 result
= dns_view_findzone(pview
, origin
, &zone
);
2246 if (result
!= ISC_R_NOTFOUND
&& result
!= ISC_R_SUCCESS
)
2248 if (zone
!= NULL
&& !ns_zone_reusable(zone
, zconfig
))
2249 dns_zone_detach(&zone
);
2253 * We found a reusable zone. Make it use the
2256 dns_zone_setview(zone
, view
);
2257 if (view
->acache
!= NULL
)
2258 dns_zone_setacache(zone
, view
->acache
);
2261 * We cannot reuse an existing zone, we have
2262 * to create a new one.
2264 CHECK(dns_zone_create(&zone
, mctx
));
2265 CHECK(dns_zone_setorigin(zone
, origin
));
2266 dns_zone_setview(zone
, view
);
2267 if (view
->acache
!= NULL
)
2268 dns_zone_setacache(zone
, view
->acache
);
2269 CHECK(dns_zonemgr_managezone(ns_g_server
->zonemgr
, zone
));
2273 * If the zone contains a 'forwarders' statement, configure
2274 * selective forwarding.
2277 if (cfg_map_get(zoptions
, "forwarders", &forwarders
) == ISC_R_SUCCESS
)
2280 (void)cfg_map_get(zoptions
, "forward", &forwardtype
);
2281 CHECK(configure_forward(config
, view
, origin
, forwarders
,
2286 * Stub and forward zones may also refer to delegation only points.
2289 if (cfg_map_get(zoptions
, "delegation-only", &only
) == ISC_R_SUCCESS
)
2291 if (cfg_obj_asboolean(only
))
2292 CHECK(dns_view_adddelegationonly(view
, origin
));
2296 * Configure the zone.
2298 CHECK(ns_zone_configure(config
, vconfig
, zconfig
, aclconf
, zone
));
2301 * Add the zone to its view in the new view list.
2303 CHECK(dns_view_addzone(view
, zone
));
2307 dns_zone_detach(&zone
);
2309 dns_view_detach(&pview
);
2315 * Configure a single server quota.
2318 configure_server_quota(const cfg_obj_t
**maps
, const char *name
,
2321 const cfg_obj_t
*obj
= NULL
;
2322 isc_result_t result
;
2324 result
= ns_config_get(maps
, name
, &obj
);
2325 INSIST(result
== ISC_R_SUCCESS
);
2326 isc_quota_max(quota
, cfg_obj_asuint32(obj
));
2330 * This function is called as soon as the 'directory' statement has been
2331 * parsed. This can be extended to support other options if necessary.
2334 directory_callback(const char *clausename
, const cfg_obj_t
*obj
, void *arg
) {
2335 isc_result_t result
;
2336 const char *directory
;
2338 REQUIRE(strcasecmp("directory", clausename
) == 0);
2346 directory
= cfg_obj_asstring(obj
);
2348 if (! isc_file_ischdiridempotent(directory
))
2349 cfg_obj_log(obj
, ns_g_lctx
, ISC_LOG_WARNING
,
2350 "option 'directory' contains relative path '%s'",
2353 result
= isc_dir_chdir(directory
);
2354 if (result
!= ISC_R_SUCCESS
) {
2355 cfg_obj_log(obj
, ns_g_lctx
, ISC_LOG_ERROR
,
2356 "change directory to '%s' failed: %s",
2357 directory
, isc_result_totext(result
));
2361 return (ISC_R_SUCCESS
);
2365 scan_interfaces(ns_server_t
*server
, isc_boolean_t verbose
) {
2366 isc_boolean_t match_mapped
= server
->aclenv
.match_mapped
;
2368 ns_interfacemgr_scan(server
->interfacemgr
, verbose
);
2370 * Update the "localhost" and "localnets" ACLs to match the
2371 * current set of network interfaces.
2373 dns_aclenv_copy(&server
->aclenv
,
2374 ns_interfacemgr_getaclenv(server
->interfacemgr
));
2376 server
->aclenv
.match_mapped
= match_mapped
;
2380 add_listenelt(isc_mem_t
*mctx
, ns_listenlist_t
*list
, isc_sockaddr_t
*addr
,
2381 isc_boolean_t wcardport_ok
)
2383 ns_listenelt_t
*lelt
= NULL
;
2384 dns_acl_t
*src_acl
= NULL
;
2385 dns_aclelement_t aelt
;
2386 isc_result_t result
;
2387 isc_sockaddr_t any_sa6
;
2389 REQUIRE(isc_sockaddr_pf(addr
) == AF_INET6
);
2391 isc_sockaddr_any6(&any_sa6
);
2392 if (!isc_sockaddr_equal(&any_sa6
, addr
) &&
2393 (wcardport_ok
|| isc_sockaddr_getport(addr
) != 0)) {
2394 aelt
.type
= dns_aclelementtype_ipprefix
;
2395 aelt
.negative
= ISC_FALSE
;
2396 aelt
.u
.ip_prefix
.prefixlen
= 128;
2397 isc_netaddr_fromin6(&aelt
.u
.ip_prefix
.address
,
2398 &addr
->type
.sin6
.sin6_addr
);
2400 result
= dns_acl_create(mctx
, 1, &src_acl
);
2401 if (result
!= ISC_R_SUCCESS
)
2403 result
= dns_acl_appendelement(src_acl
, &aelt
);
2404 if (result
!= ISC_R_SUCCESS
)
2407 result
= ns_listenelt_create(mctx
, isc_sockaddr_getport(addr
),
2409 if (result
!= ISC_R_SUCCESS
)
2411 ISC_LIST_APPEND(list
->elts
, lelt
, link
);
2414 return (ISC_R_SUCCESS
);
2417 INSIST(lelt
== NULL
);
2418 dns_acl_detach(&src_acl
);
2424 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust()
2425 * to update the listening interfaces accordingly.
2426 * We currently only consider IPv6, because this only affects IPv6 wildcard
2430 adjust_interfaces(ns_server_t
*server
, isc_mem_t
*mctx
) {
2431 isc_result_t result
;
2432 ns_listenlist_t
*list
= NULL
;
2434 dns_zone_t
*zone
, *next
;
2435 isc_sockaddr_t addr
, *addrp
;
2437 result
= ns_listenlist_create(mctx
, &list
);
2438 if (result
!= ISC_R_SUCCESS
)
2441 for (view
= ISC_LIST_HEAD(server
->viewlist
);
2443 view
= ISC_LIST_NEXT(view
, link
)) {
2444 dns_dispatch_t
*dispatch6
;
2446 dispatch6
= dns_resolver_dispatchv6(view
->resolver
);
2447 if (dispatch6
== NULL
)
2449 result
= dns_dispatch_getlocaladdress(dispatch6
, &addr
);
2450 if (result
!= ISC_R_SUCCESS
)
2454 * We always add non-wildcard address regardless of whether
2455 * the port is 'any' (the fourth arg is TRUE): if the port is
2456 * specific, we need to add it since it may conflict with a
2457 * listening interface; if it's zero, we'll dynamically open
2458 * query ports, and some of them may override an existing
2459 * wildcard IPv6 port.
2461 result
= add_listenelt(mctx
, list
, &addr
, ISC_TRUE
);
2462 if (result
!= ISC_R_SUCCESS
)
2467 for (result
= dns_zone_first(server
->zonemgr
, &zone
);
2468 result
== ISC_R_SUCCESS
;
2469 next
= NULL
, result
= dns_zone_next(zone
, &next
), zone
= next
) {
2470 dns_view_t
*zoneview
;
2473 * At this point the zone list may contain a stale zone
2474 * just removed from the configuration. To see the validity,
2475 * check if the corresponding view is in our current view list.
2476 * There may also be old zones that are still in the process
2477 * of shutting down and have detached from their old view
2478 * (zoneview == NULL).
2480 zoneview
= dns_zone_getview(zone
);
2481 if (zoneview
== NULL
)
2483 for (view
= ISC_LIST_HEAD(server
->viewlist
);
2484 view
!= NULL
&& view
!= zoneview
;
2485 view
= ISC_LIST_NEXT(view
, link
))
2490 addrp
= dns_zone_getnotifysrc6(zone
);
2491 result
= add_listenelt(mctx
, list
, addrp
, ISC_FALSE
);
2492 if (result
!= ISC_R_SUCCESS
)
2495 addrp
= dns_zone_getxfrsource6(zone
);
2496 result
= add_listenelt(mctx
, list
, addrp
, ISC_FALSE
);
2497 if (result
!= ISC_R_SUCCESS
)
2501 ns_interfacemgr_adjust(server
->interfacemgr
, list
, ISC_TRUE
);
2504 ns_listenlist_detach(&list
);
2509 * Even when we failed the procedure, most of other interfaces
2510 * should work correctly. We therefore just warn it.
2512 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2513 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
2514 "could not adjust the listen-on list; "
2515 "some interfaces may not work");
2520 * This event callback is invoked to do periodic network
2521 * interface scanning.
2524 interface_timer_tick(isc_task_t
*task
, isc_event_t
*event
) {
2525 isc_result_t result
;
2526 ns_server_t
*server
= (ns_server_t
*) event
->ev_arg
;
2527 INSIST(task
== server
->task
);
2529 isc_event_free(&event
);
2531 * XXX should scan interfaces unlocked and get exclusive access
2532 * only to replace ACLs.
2534 result
= isc_task_beginexclusive(server
->task
);
2535 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2536 scan_interfaces(server
, ISC_FALSE
);
2537 isc_task_endexclusive(server
->task
);
2541 heartbeat_timer_tick(isc_task_t
*task
, isc_event_t
*event
) {
2542 ns_server_t
*server
= (ns_server_t
*) event
->ev_arg
;
2546 isc_event_free(&event
);
2547 view
= ISC_LIST_HEAD(server
->viewlist
);
2548 while (view
!= NULL
) {
2549 dns_view_dialup(view
);
2550 view
= ISC_LIST_NEXT(view
, link
);
2555 pps_timer_tick(isc_task_t
*task
, isc_event_t
*event
) {
2556 static unsigned int oldrequests
= 0;
2557 unsigned int requests
= ns_client_requests
;
2560 isc_event_free(&event
);
2563 * Don't worry about wrapping as the overflow result will be right.
2565 dns_pps
= (requests
- oldrequests
) / 1200;
2566 oldrequests
= requests
;
2570 * Replace the current value of '*field', a dynamically allocated
2571 * string or NULL, with a dynamically allocated copy of the
2572 * null-terminated string pointed to by 'value', or NULL.
2575 setstring(ns_server_t
*server
, char **field
, const char *value
) {
2578 if (value
!= NULL
) {
2579 copy
= isc_mem_strdup(server
->mctx
, value
);
2581 return (ISC_R_NOMEMORY
);
2587 isc_mem_free(server
->mctx
, *field
);
2590 return (ISC_R_SUCCESS
);
2594 * Replace the current value of '*field', a dynamically allocated
2595 * string or NULL, with another dynamically allocated string
2596 * or NULL if whether 'obj' is a string or void value, respectively.
2599 setoptstring(ns_server_t
*server
, char **field
, const cfg_obj_t
*obj
) {
2600 if (cfg_obj_isvoid(obj
))
2601 return (setstring(server
, field
, NULL
));
2603 return (setstring(server
, field
, cfg_obj_asstring(obj
)));
2607 set_limit(const cfg_obj_t
**maps
, const char *configname
,
2608 const char *description
, isc_resource_t resourceid
,
2609 isc_resourcevalue_t defaultvalue
)
2611 const cfg_obj_t
*obj
= NULL
;
2612 const char *resource
;
2613 isc_resourcevalue_t value
;
2614 isc_result_t result
;
2616 if (ns_config_get(maps
, configname
, &obj
) != ISC_R_SUCCESS
)
2619 if (cfg_obj_isstring(obj
)) {
2620 resource
= cfg_obj_asstring(obj
);
2621 if (strcasecmp(resource
, "unlimited") == 0)
2622 value
= ISC_RESOURCE_UNLIMITED
;
2624 INSIST(strcasecmp(resource
, "default") == 0);
2625 value
= defaultvalue
;
2628 value
= cfg_obj_asuint64(obj
);
2630 result
= isc_resource_setlimit(resourceid
, value
);
2631 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
2632 result
== ISC_R_SUCCESS
?
2633 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING
,
2634 "set maximum %s to %" ISC_PRINT_QUADFORMAT
"d: %s",
2635 description
, value
, isc_result_totext(result
));
2638 #define SETLIMIT(cfgvar, resource, description) \
2639 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \
2640 ns_g_init ## resource)
2643 set_limits(const cfg_obj_t
**maps
) {
2644 SETLIMIT("stacksize", stacksize
, "stack size");
2645 SETLIMIT("datasize", datasize
, "data size");
2646 SETLIMIT("coresize", coresize
, "core size");
2647 SETLIMIT("files", openfiles
, "open files");
2651 portlist_fromconf(dns_portlist_t
*portlist
, unsigned int family
,
2652 const cfg_obj_t
*ports
)
2654 const cfg_listelt_t
*element
;
2655 isc_result_t result
= ISC_R_SUCCESS
;
2657 for (element
= cfg_list_first(ports
);
2659 element
= cfg_list_next(element
)) {
2660 const cfg_obj_t
*obj
= cfg_listelt_value(element
);
2661 in_port_t port
= (in_port_t
)cfg_obj_asuint32(obj
);
2663 result
= dns_portlist_add(portlist
, family
, port
);
2664 if (result
!= ISC_R_SUCCESS
)
2671 removed(dns_zone_t
*zone
, void *uap
) {
2674 if (dns_zone_getview(zone
) != uap
)
2675 return (ISC_R_SUCCESS
);
2677 switch (dns_zone_gettype(zone
)) {
2678 case dns_zone_master
:
2681 case dns_zone_slave
:
2691 dns_zone_log(zone
, ISC_LOG_INFO
, "(%s) removed", type
);
2692 return (ISC_R_SUCCESS
);
2696 load_configuration(const char *filename
, ns_server_t
*server
,
2697 isc_boolean_t first_time
)
2699 cfg_aclconfctx_t aclconfctx
;
2701 cfg_parser_t
*parser
= NULL
;
2702 const cfg_listelt_t
*element
;
2703 const cfg_obj_t
*builtin_views
;
2704 const cfg_obj_t
*maps
[3];
2705 const cfg_obj_t
*obj
;
2706 const cfg_obj_t
*options
;
2707 const cfg_obj_t
*v4ports
, *v6ports
;
2708 const cfg_obj_t
*views
;
2709 dns_view_t
*view
= NULL
;
2710 dns_view_t
*view_next
;
2711 dns_viewlist_t tmpviewlist
;
2712 dns_viewlist_t viewlist
;
2713 in_port_t listen_port
;
2715 isc_interval_t interval
;
2716 isc_resourcevalue_t files
;
2717 isc_result_t result
;
2718 isc_uint32_t heartbeat_interval
;
2719 isc_uint32_t interface_interval
;
2720 isc_uint32_t reserved
;
2721 isc_uint32_t udpsize
;
2723 cfg_aclconfctx_init(&aclconfctx
);
2724 ISC_LIST_INIT(viewlist
);
2726 /* Ensure exclusive access to configuration data. */
2727 result
= isc_task_beginexclusive(server
->task
);
2728 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2731 * Parse the global default pseudo-config file.
2734 CHECK(ns_config_parsedefaults(ns_g_parser
, &ns_g_config
));
2735 RUNTIME_CHECK(cfg_map_get(ns_g_config
, "options",
2741 * Parse the configuration file using the new config code.
2743 result
= ISC_R_FAILURE
;
2747 * Unless this is lwresd with the -C option, parse the config file.
2749 if (!(ns_g_lwresdonly
&& lwresd_g_useresolvconf
)) {
2750 isc_log_write(ns_g_lctx
,
2751 NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
2752 ISC_LOG_INFO
, "loading configuration from '%s'",
2754 CHECK(cfg_parser_create(ns_g_mctx
, ns_g_lctx
, &parser
));
2755 cfg_parser_setcallback(parser
, directory_callback
, NULL
);
2756 result
= cfg_parse_file(parser
, filename
, &cfg_type_namedconf
,
2761 * If this is lwresd with the -C option, or lwresd with no -C or -c
2762 * option where the above parsing failed, parse resolv.conf.
2764 if (ns_g_lwresdonly
&&
2765 (lwresd_g_useresolvconf
||
2766 (!ns_g_conffileset
&& result
== ISC_R_FILENOTFOUND
)))
2768 isc_log_write(ns_g_lctx
,
2769 NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
2770 ISC_LOG_INFO
, "loading configuration from '%s'",
2771 lwresd_g_resolvconffile
);
2773 cfg_parser_destroy(&parser
);
2774 CHECK(cfg_parser_create(ns_g_mctx
, ns_g_lctx
, &parser
));
2775 result
= ns_lwresd_parseeresolvconf(ns_g_mctx
, parser
,
2781 * Check the validity of the configuration.
2783 CHECK(bind9_check_namedconf(config
, ns_g_lctx
, ns_g_mctx
));
2786 * Fill in the maps array, used for resolving defaults.
2790 result
= cfg_map_get(config
, "options", &options
);
2791 if (result
== ISC_R_SUCCESS
)
2792 maps
[i
++] = options
;
2793 maps
[i
++] = ns_g_defaults
;
2797 * Set process limits, which (usually) needs to be done as root.
2802 * Sanity check on "files" limit.
2804 result
= isc_resource_curlimit(isc_resource_openfiles
, &files
);
2805 if (result
== ISC_R_SUCCESS
&& files
< FD_SETSIZE
) {
2806 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2807 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
2808 "the 'files' limit (%" ISC_PRINT_QUADFORMAT
"u) "
2809 "is less than FD_SETSIZE (%d), increase "
2810 "'files' in named.conf or recompile with a "
2811 "smaller FD_SETSIZE.", files
, FD_SETSIZE
);
2812 if (files
> FD_SETSIZE
)
2818 * Set the number of socket reserved for TCP, stdio etc.
2821 result
= ns_config_get(maps
, "reserved-sockets", &obj
);
2822 INSIST(result
== ISC_R_SUCCESS
);
2823 reserved
= cfg_obj_asuint32(obj
);
2824 if (files
< 128U) /* Prevent underflow. */
2826 else if (reserved
> files
- 128U) /* Mimimum UDP space. */
2827 reserved
= files
- 128;
2828 if (reserved
< 128U) /* Mimimum TCP/stdio space. */
2830 if (reserved
+ 128U > files
) {
2831 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
2832 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
2833 "less than 128 UDP sockets available after "
2834 "applying 'reserved-sockets' and 'files'");
2836 isc__socketmgr_setreserved(ns_g_socketmgr
, reserved
);
2839 * Configure various server options.
2841 configure_server_quota(maps
, "transfers-out", &server
->xfroutquota
);
2842 configure_server_quota(maps
, "tcp-clients", &server
->tcpquota
);
2843 configure_server_quota(maps
, "recursive-clients",
2844 &server
->recursionquota
);
2845 if (server
->recursionquota
.max
> 1000)
2846 isc_quota_soft(&server
->recursionquota
,
2847 server
->recursionquota
.max
- 100);
2849 isc_quota_soft(&server
->recursionquota
, 0);
2851 CHECK(configure_view_acl(NULL
, config
, "blackhole", &aclconfctx
,
2852 ns_g_mctx
, &server
->blackholeacl
));
2853 if (server
->blackholeacl
!= NULL
)
2854 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr
,
2855 server
->blackholeacl
);
2858 result
= ns_config_get(maps
, "match-mapped-addresses", &obj
);
2859 INSIST(result
== ISC_R_SUCCESS
);
2860 server
->aclenv
.match_mapped
= cfg_obj_asboolean(obj
);
2864 (void)ns_config_get(maps
, "avoid-v4-udp-ports", &v4ports
);
2865 (void)ns_config_get(maps
, "avoid-v6-udp-ports", &v6ports
);
2866 if (v4ports
!= NULL
|| v6ports
!= NULL
) {
2867 dns_portlist_t
*portlist
= NULL
;
2868 result
= dns_portlist_create(ns_g_mctx
, &portlist
);
2869 if (result
== ISC_R_SUCCESS
&& v4ports
!= NULL
)
2870 result
= portlist_fromconf(portlist
, AF_INET
, v4ports
);
2871 if (result
== ISC_R_SUCCESS
&& v6ports
!= NULL
)
2872 portlist_fromconf(portlist
, AF_INET6
, v6ports
);
2873 if (result
== ISC_R_SUCCESS
)
2874 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr
, portlist
);
2875 if (portlist
!= NULL
)
2876 dns_portlist_detach(&portlist
);
2879 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr
, NULL
);
2882 * Set the EDNS UDP size when we don't match a view.
2885 result
= ns_config_get(maps
, "edns-udp-size", &obj
);
2886 INSIST(result
== ISC_R_SUCCESS
);
2887 udpsize
= cfg_obj_asuint32(obj
);
2892 ns_g_udpsize
= (isc_uint16_t
)udpsize
;
2895 * Configure the zone manager.
2898 result
= ns_config_get(maps
, "transfers-in", &obj
);
2899 INSIST(result
== ISC_R_SUCCESS
);
2900 dns_zonemgr_settransfersin(server
->zonemgr
, cfg_obj_asuint32(obj
));
2903 result
= ns_config_get(maps
, "transfers-per-ns", &obj
);
2904 INSIST(result
== ISC_R_SUCCESS
);
2905 dns_zonemgr_settransfersperns(server
->zonemgr
, cfg_obj_asuint32(obj
));
2908 result
= ns_config_get(maps
, "serial-query-rate", &obj
);
2909 INSIST(result
== ISC_R_SUCCESS
);
2910 dns_zonemgr_setserialqueryrate(server
->zonemgr
, cfg_obj_asuint32(obj
));
2913 * Determine which port to use for listening for incoming connections.
2916 listen_port
= ns_g_port
;
2918 CHECKM(ns_config_getport(config
, &listen_port
), "port");
2921 * Find the listen queue depth.
2924 result
= ns_config_get(maps
, "tcp-listen-queue", &obj
);
2925 INSIST(result
== ISC_R_SUCCESS
);
2926 ns_g_listen
= cfg_obj_asuint32(obj
);
2927 if (ns_g_listen
< 3)
2931 * Configure the interface manager according to the "listen-on"
2935 const cfg_obj_t
*clistenon
= NULL
;
2936 ns_listenlist_t
*listenon
= NULL
;
2940 * Even though listen-on is present in the default
2941 * configuration, we can't use it here, since it isn't
2942 * used if we're in lwresd mode. This way is easier.
2944 if (options
!= NULL
)
2945 (void)cfg_map_get(options
, "listen-on", &clistenon
);
2946 if (clistenon
!= NULL
) {
2947 result
= ns_listenlist_fromconfig(clistenon
,
2952 } else if (!ns_g_lwresdonly
) {
2954 * Not specified, use default.
2956 CHECK(ns_listenlist_default(ns_g_mctx
, listen_port
,
2957 ISC_TRUE
, &listenon
));
2959 if (listenon
!= NULL
) {
2960 ns_interfacemgr_setlistenon4(server
->interfacemgr
,
2962 ns_listenlist_detach(&listenon
);
2969 const cfg_obj_t
*clistenon
= NULL
;
2970 ns_listenlist_t
*listenon
= NULL
;
2972 if (options
!= NULL
)
2973 (void)cfg_map_get(options
, "listen-on-v6", &clistenon
);
2974 if (clistenon
!= NULL
) {
2975 result
= ns_listenlist_fromconfig(clistenon
,
2980 } else if (!ns_g_lwresdonly
) {
2982 * Not specified, use default.
2984 CHECK(ns_listenlist_default(ns_g_mctx
, listen_port
,
2985 ISC_FALSE
, &listenon
));
2987 if (listenon
!= NULL
) {
2988 ns_interfacemgr_setlistenon6(server
->interfacemgr
,
2990 ns_listenlist_detach(&listenon
);
2995 * Rescan the interface list to pick up changes in the
2996 * listen-on option. It's important that we do this before we try
2997 * to configure the query source, since the dispatcher we use might
2998 * be shared with an interface.
3000 scan_interfaces(server
, ISC_TRUE
);
3003 * Arrange for further interface scanning to occur periodically
3004 * as specified by the "interface-interval" option.
3007 result
= ns_config_get(maps
, "interface-interval", &obj
);
3008 INSIST(result
== ISC_R_SUCCESS
);
3009 interface_interval
= cfg_obj_asuint32(obj
) * 60;
3010 if (interface_interval
== 0) {
3011 CHECK(isc_timer_reset(server
->interface_timer
,
3012 isc_timertype_inactive
,
3013 NULL
, NULL
, ISC_TRUE
));
3014 } else if (server
->interface_interval
!= interface_interval
) {
3015 isc_interval_set(&interval
, interface_interval
, 0);
3016 CHECK(isc_timer_reset(server
->interface_timer
,
3017 isc_timertype_ticker
,
3018 NULL
, &interval
, ISC_FALSE
));
3020 server
->interface_interval
= interface_interval
;
3023 * Configure the dialup heartbeat timer.
3026 result
= ns_config_get(maps
, "heartbeat-interval", &obj
);
3027 INSIST(result
== ISC_R_SUCCESS
);
3028 heartbeat_interval
= cfg_obj_asuint32(obj
) * 60;
3029 if (heartbeat_interval
== 0) {
3030 CHECK(isc_timer_reset(server
->heartbeat_timer
,
3031 isc_timertype_inactive
,
3032 NULL
, NULL
, ISC_TRUE
));
3033 } else if (server
->heartbeat_interval
!= heartbeat_interval
) {
3034 isc_interval_set(&interval
, heartbeat_interval
, 0);
3035 CHECK(isc_timer_reset(server
->heartbeat_timer
,
3036 isc_timertype_ticker
,
3037 NULL
, &interval
, ISC_FALSE
));
3039 server
->heartbeat_interval
= heartbeat_interval
;
3041 isc_interval_set(&interval
, 1200, 0);
3042 CHECK(isc_timer_reset(server
->pps_timer
, isc_timertype_ticker
, NULL
,
3043 &interval
, ISC_FALSE
));
3046 * Configure and freeze all explicit views. Explicit
3047 * views that have zones were already created at parsing
3048 * time, but views with no zones must be created here.
3051 (void)cfg_map_get(config
, "view", &views
);
3052 for (element
= cfg_list_first(views
);
3054 element
= cfg_list_next(element
))
3056 const cfg_obj_t
*vconfig
= cfg_listelt_value(element
);
3059 CHECK(create_view(vconfig
, &viewlist
, &view
));
3060 INSIST(view
!= NULL
);
3061 CHECK(configure_view(view
, config
, vconfig
,
3062 ns_g_mctx
, &aclconfctx
, ISC_TRUE
));
3063 dns_view_freeze(view
);
3064 dns_view_detach(&view
);
3068 * Make sure we have a default view if and only if there
3069 * were no explicit views.
3071 if (views
== NULL
) {
3073 * No explicit views; there ought to be a default view.
3074 * There may already be one created as a side effect
3075 * of zone statements, or we may have to create one.
3076 * In either case, we need to configure and freeze it.
3078 CHECK(create_view(NULL
, &viewlist
, &view
));
3079 CHECK(configure_view(view
, config
, NULL
, ns_g_mctx
,
3080 &aclconfctx
, ISC_TRUE
));
3081 dns_view_freeze(view
);
3082 dns_view_detach(&view
);
3086 * Create (or recreate) the built-in views. Currently
3087 * there is only one, the _bind view.
3089 builtin_views
= NULL
;
3090 RUNTIME_CHECK(cfg_map_get(ns_g_config
, "view",
3091 &builtin_views
) == ISC_R_SUCCESS
);
3092 for (element
= cfg_list_first(builtin_views
);
3094 element
= cfg_list_next(element
))
3096 const cfg_obj_t
*vconfig
= cfg_listelt_value(element
);
3097 CHECK(create_view(vconfig
, &viewlist
, &view
));
3098 CHECK(configure_view(view
, config
, vconfig
, ns_g_mctx
,
3099 &aclconfctx
, ISC_FALSE
));
3100 dns_view_freeze(view
);
3101 dns_view_detach(&view
);
3106 * Swap our new view list with the production one.
3108 tmpviewlist
= server
->viewlist
;
3109 server
->viewlist
= viewlist
;
3110 viewlist
= tmpviewlist
;
3113 * Load the TKEY information from the configuration.
3115 if (options
!= NULL
) {
3116 dns_tkeyctx_t
*t
= NULL
;
3117 CHECKM(ns_tkeyctx_fromconfig(options
, ns_g_mctx
, ns_g_entropy
,
3119 "configuring TKEY");
3120 if (server
->tkeyctx
!= NULL
)
3121 dns_tkeyctx_destroy(&server
->tkeyctx
);
3122 server
->tkeyctx
= t
;
3126 * Bind the control port(s).
3128 CHECKM(ns_controls_configure(ns_g_server
->controls
, config
,
3130 "binding control channel(s)");
3133 * Bind the lwresd port(s).
3135 CHECKM(ns_lwresd_configure(ns_g_mctx
, config
),
3136 "binding lightweight resolver ports");
3139 * Open the source of entropy.
3143 result
= ns_config_get(maps
, "random-device", &obj
);
3144 if (result
!= ISC_R_SUCCESS
) {
3145 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
3146 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
3147 "no source of entropy found");
3149 const char *randomdev
= cfg_obj_asstring(obj
);
3150 result
= isc_entropy_createfilesource(ns_g_entropy
,
3152 if (result
!= ISC_R_SUCCESS
)
3153 isc_log_write(ns_g_lctx
,
3154 NS_LOGCATEGORY_GENERAL
,
3155 NS_LOGMODULE_SERVER
,
3157 "could not open entropy source "
3160 isc_result_totext(result
));
3161 #ifdef PATH_RANDOMDEV
3162 if (ns_g_fallbackentropy
!= NULL
) {
3163 if (result
!= ISC_R_SUCCESS
) {
3164 isc_log_write(ns_g_lctx
,
3165 NS_LOGCATEGORY_GENERAL
,
3166 NS_LOGMODULE_SERVER
,
3168 "using pre-chroot entropy source "
3171 isc_entropy_detach(&ns_g_entropy
);
3172 isc_entropy_attach(ns_g_fallbackentropy
,
3175 isc_entropy_detach(&ns_g_fallbackentropy
);
3182 * Relinquish root privileges.
3188 * Configure the logging system.
3190 * Do this after changing UID to make sure that any log
3191 * files specified in named.conf get created by the
3192 * unprivileged user, not root.
3194 if (ns_g_logstderr
) {
3195 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
3196 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
3197 "ignoring config file logging "
3198 "statement due to -g option");
3200 const cfg_obj_t
*logobj
= NULL
;
3201 isc_logconfig_t
*logc
= NULL
;
3203 CHECKM(isc_logconfig_create(ns_g_lctx
, &logc
),
3204 "creating new logging configuration");
3207 (void)cfg_map_get(config
, "logging", &logobj
);
3208 if (logobj
!= NULL
) {
3209 CHECKM(ns_log_configure(logc
, logobj
),
3210 "configuring logging");
3212 CHECKM(ns_log_setdefaultchannels(logc
),
3213 "setting up default logging channels");
3214 CHECKM(ns_log_setunmatchedcategory(logc
),
3215 "setting up default 'category unmatched'");
3216 CHECKM(ns_log_setdefaultcategory(logc
),
3217 "setting up default 'category default'");
3220 result
= isc_logconfig_use(ns_g_lctx
, logc
);
3221 if (result
!= ISC_R_SUCCESS
) {
3222 isc_logconfig_destroy(&logc
);
3223 CHECKM(result
, "installing logging configuration");
3226 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
3227 NS_LOGMODULE_SERVER
, ISC_LOG_DEBUG(1),
3228 "now using logging configuration from "
3233 * Set the default value of the query logging flag depending
3234 * whether a "queries" category has been defined. This is
3235 * a disgusting hack, but we need to do this for BIND 8
3239 const cfg_obj_t
*logobj
= NULL
;
3240 const cfg_obj_t
*categories
= NULL
;
3243 if (ns_config_get(maps
, "querylog", &obj
) == ISC_R_SUCCESS
) {
3244 server
->log_queries
= cfg_obj_asboolean(obj
);
3247 (void)cfg_map_get(config
, "logging", &logobj
);
3249 (void)cfg_map_get(logobj
, "category",
3251 if (categories
!= NULL
) {
3252 const cfg_listelt_t
*element
;
3253 for (element
= cfg_list_first(categories
);
3255 element
= cfg_list_next(element
))
3257 const cfg_obj_t
*catobj
;
3260 obj
= cfg_listelt_value(element
);
3261 catobj
= cfg_tuple_get(obj
, "name");
3262 str
= cfg_obj_asstring(catobj
);
3263 if (strcasecmp(str
, "queries") == 0)
3264 server
->log_queries
= ISC_TRUE
;
3271 if (ns_config_get(maps
, "pid-file", &obj
) == ISC_R_SUCCESS
)
3272 if (cfg_obj_isvoid(obj
))
3273 ns_os_writepidfile(NULL
, first_time
);
3275 ns_os_writepidfile(cfg_obj_asstring(obj
), first_time
);
3276 else if (ns_g_lwresdonly
)
3277 ns_os_writepidfile(lwresd_g_defaultpidfile
, first_time
);
3279 ns_os_writepidfile(ns_g_defaultpidfile
, first_time
);
3282 if (options
!= NULL
&&
3283 cfg_map_get(options
, "memstatistics-file", &obj
) == ISC_R_SUCCESS
)
3284 ns_main_setmemstats(cfg_obj_asstring(obj
));
3286 ns_main_setmemstats(NULL
);
3289 result
= ns_config_get(maps
, "statistics-file", &obj
);
3290 INSIST(result
== ISC_R_SUCCESS
);
3291 CHECKM(setstring(server
, &server
->statsfile
, cfg_obj_asstring(obj
)),
3295 result
= ns_config_get(maps
, "dump-file", &obj
);
3296 INSIST(result
== ISC_R_SUCCESS
);
3297 CHECKM(setstring(server
, &server
->dumpfile
, cfg_obj_asstring(obj
)),
3301 result
= ns_config_get(maps
, "recursing-file", &obj
);
3302 INSIST(result
== ISC_R_SUCCESS
);
3303 CHECKM(setstring(server
, &server
->recfile
, cfg_obj_asstring(obj
)),
3307 result
= ns_config_get(maps
, "version", &obj
);
3308 if (result
== ISC_R_SUCCESS
) {
3309 CHECKM(setoptstring(server
, &server
->version
, obj
), "strdup");
3310 server
->version_set
= ISC_TRUE
;
3312 server
->version_set
= ISC_FALSE
;
3316 result
= ns_config_get(maps
, "hostname", &obj
);
3317 if (result
== ISC_R_SUCCESS
) {
3318 CHECKM(setoptstring(server
, &server
->hostname
, obj
), "strdup");
3319 server
->hostname_set
= ISC_TRUE
;
3321 server
->hostname_set
= ISC_FALSE
;
3325 result
= ns_config_get(maps
, "server-id", &obj
);
3326 server
->server_usehostname
= ISC_FALSE
;
3327 if (result
== ISC_R_SUCCESS
&& cfg_obj_isboolean(obj
)) {
3328 server
->server_usehostname
= ISC_TRUE
;
3329 } else if (result
== ISC_R_SUCCESS
) {
3330 CHECKM(setoptstring(server
, &server
->server_id
, obj
), "strdup");
3332 result
= setstring(server
, &server
->server_id
, NULL
);
3333 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3337 result
= ns_config_get(maps
, "flush-zones-on-shutdown", &obj
);
3338 if (result
== ISC_R_SUCCESS
) {
3339 server
->flushonshutdown
= cfg_obj_asboolean(obj
);
3341 server
->flushonshutdown
= ISC_FALSE
;
3344 result
= ISC_R_SUCCESS
;
3347 cfg_aclconfctx_destroy(&aclconfctx
);
3349 if (parser
!= NULL
) {
3351 cfg_obj_destroy(parser
, &config
);
3352 cfg_parser_destroy(&parser
);
3356 dns_view_detach(&view
);
3359 * This cleans up either the old production view list
3360 * or our temporary list depending on whether they
3361 * were swapped above or not.
3363 for (view
= ISC_LIST_HEAD(viewlist
);
3366 view_next
= ISC_LIST_NEXT(view
, link
);
3367 ISC_LIST_UNLINK(viewlist
, view
, link
);
3368 if (result
== ISC_R_SUCCESS
&&
3369 strcmp(view
->name
, "_bind") != 0)
3370 (void)dns_zt_apply(view
->zonetable
, ISC_FALSE
,
3372 dns_view_detach(&view
);
3376 * Adjust the listening interfaces in accordance with the source
3377 * addresses specified in views and zones.
3379 if (isc_net_probeipv6() == ISC_R_SUCCESS
)
3380 adjust_interfaces(server
, ns_g_mctx
);
3382 /* Relinquish exclusive access to configuration data. */
3383 isc_task_endexclusive(server
->task
);
3385 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
3386 ISC_LOG_DEBUG(1), "load_configuration: %s",
3387 isc_result_totext(result
));
3393 load_zones(ns_server_t
*server
, isc_boolean_t stop
) {
3394 isc_result_t result
;
3397 result
= isc_task_beginexclusive(server
->task
);
3398 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3401 * Load zone data from disk.
3403 for (view
= ISC_LIST_HEAD(server
->viewlist
);
3405 view
= ISC_LIST_NEXT(view
, link
))
3407 CHECK(dns_view_load(view
, stop
));
3411 * Force zone maintenance. Do this after loading
3412 * so that we know when we need to force AXFR of
3413 * slave zones whose master files are missing.
3415 CHECK(dns_zonemgr_forcemaint(server
->zonemgr
));
3417 isc_task_endexclusive(server
->task
);
3422 load_new_zones(ns_server_t
*server
, isc_boolean_t stop
) {
3423 isc_result_t result
;
3426 result
= isc_task_beginexclusive(server
->task
);
3427 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3430 * Load zone data from disk.
3432 for (view
= ISC_LIST_HEAD(server
->viewlist
);
3434 view
= ISC_LIST_NEXT(view
, link
))
3436 CHECK(dns_view_loadnew(view
, stop
));
3439 * Force zone maintenance. Do this after loading
3440 * so that we know when we need to force AXFR of
3441 * slave zones whose master files are missing.
3443 dns_zonemgr_resumexfrs(server
->zonemgr
);
3445 isc_task_endexclusive(server
->task
);
3450 run_server(isc_task_t
*task
, isc_event_t
*event
) {
3451 isc_result_t result
;
3452 ns_server_t
*server
= (ns_server_t
*)event
->ev_arg
;
3454 INSIST(task
== server
->task
);
3456 isc_event_free(&event
);
3458 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx
, ns_g_entropy
,
3460 "creating dispatch manager");
3462 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx
, ns_g_taskmgr
,
3463 ns_g_socketmgr
, ns_g_dispatchmgr
,
3464 &server
->interfacemgr
),
3465 "creating interface manager");
3467 CHECKFATAL(isc_timer_create(ns_g_timermgr
, isc_timertype_inactive
,
3468 NULL
, NULL
, server
->task
,
3469 interface_timer_tick
,
3470 server
, &server
->interface_timer
),
3471 "creating interface timer");
3473 CHECKFATAL(isc_timer_create(ns_g_timermgr
, isc_timertype_inactive
,
3474 NULL
, NULL
, server
->task
,
3475 heartbeat_timer_tick
,
3476 server
, &server
->heartbeat_timer
),
3477 "creating heartbeat timer");
3479 CHECKFATAL(isc_timer_create(ns_g_timermgr
, isc_timertype_inactive
,
3480 NULL
, NULL
, server
->task
, pps_timer_tick
,
3481 server
, &server
->pps_timer
),
3482 "creating pps timer");
3484 CHECKFATAL(cfg_parser_create(ns_g_mctx
, NULL
, &ns_g_parser
),
3485 "creating default configuration parser");
3487 if (ns_g_lwresdonly
)
3488 CHECKFATAL(load_configuration(lwresd_g_conffile
, server
,
3490 "loading configuration");
3492 CHECKFATAL(load_configuration(ns_g_conffile
, server
, ISC_TRUE
),
3493 "loading configuration");
3497 CHECKFATAL(load_zones(server
, ISC_FALSE
), "loading zones");
3500 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
3501 ISC_LOG_NOTICE
, "running");
3505 ns_server_flushonshutdown(ns_server_t
*server
, isc_boolean_t flush
) {
3507 REQUIRE(NS_SERVER_VALID(server
));
3509 server
->flushonshutdown
= flush
;
3513 shutdown_server(isc_task_t
*task
, isc_event_t
*event
) {
3514 isc_result_t result
;
3515 dns_view_t
*view
, *view_next
;
3516 ns_server_t
*server
= (ns_server_t
*)event
->ev_arg
;
3517 isc_boolean_t flush
= server
->flushonshutdown
;
3520 INSIST(task
== server
->task
);
3522 result
= isc_task_beginexclusive(server
->task
);
3523 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3525 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
3526 ISC_LOG_INFO
, "shutting down%s",
3527 flush
? ": flushing changes" : "");
3529 ns_controls_shutdown(server
->controls
);
3530 end_reserved_dispatches(server
, ISC_TRUE
);
3532 cfg_obj_destroy(ns_g_parser
, &ns_g_config
);
3533 cfg_parser_destroy(&ns_g_parser
);
3535 for (view
= ISC_LIST_HEAD(server
->viewlist
);
3538 view_next
= ISC_LIST_NEXT(view
, link
);
3539 ISC_LIST_UNLINK(server
->viewlist
, view
, link
);
3541 dns_view_flushanddetach(&view
);
3543 dns_view_detach(&view
);
3546 isc_timer_detach(&server
->interface_timer
);
3547 isc_timer_detach(&server
->heartbeat_timer
);
3548 isc_timer_detach(&server
->pps_timer
);
3550 ns_interfacemgr_shutdown(server
->interfacemgr
);
3551 ns_interfacemgr_detach(&server
->interfacemgr
);
3553 dns_dispatchmgr_destroy(&ns_g_dispatchmgr
);
3555 dns_zonemgr_shutdown(server
->zonemgr
);
3557 if (server
->blackholeacl
!= NULL
)
3558 dns_acl_detach(&server
->blackholeacl
);
3560 dns_db_detach(&server
->in_roothints
);
3562 isc_task_endexclusive(server
->task
);
3564 isc_task_detach(&server
->task
);
3566 isc_event_free(&event
);
3570 ns_server_create(isc_mem_t
*mctx
, ns_server_t
**serverp
) {
3571 isc_result_t result
;
3573 ns_server_t
*server
= isc_mem_get(mctx
, sizeof(*server
));
3575 fatal("allocating server object", ISC_R_NOMEMORY
);
3577 server
->mctx
= mctx
;
3578 server
->task
= NULL
;
3580 /* Initialize configuration data with default values. */
3582 result
= isc_quota_init(&server
->xfroutquota
, 10);
3583 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3584 result
= isc_quota_init(&server
->tcpquota
, 10);
3585 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3586 result
= isc_quota_init(&server
->recursionquota
, 100);
3587 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3589 result
= dns_aclenv_init(mctx
, &server
->aclenv
);
3590 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3592 /* Initialize server data structures. */
3593 server
->zonemgr
= NULL
;
3594 server
->interfacemgr
= NULL
;
3595 ISC_LIST_INIT(server
->viewlist
);
3596 server
->in_roothints
= NULL
;
3597 server
->blackholeacl
= NULL
;
3599 CHECKFATAL(dns_rootns_create(mctx
, dns_rdataclass_in
, NULL
,
3600 &server
->in_roothints
),
3601 "setting up root hints");
3603 CHECKFATAL(isc_mutex_init(&server
->reload_event_lock
),
3604 "initializing reload event lock");
3605 server
->reload_event
=
3606 isc_event_allocate(ns_g_mctx
, server
,
3610 sizeof(isc_event_t
));
3611 CHECKFATAL(server
->reload_event
== NULL
?
3612 ISC_R_NOMEMORY
: ISC_R_SUCCESS
,
3613 "allocating reload event");
3615 CHECKFATAL(dst_lib_init(ns_g_mctx
, ns_g_entropy
, ISC_ENTROPY_GOODONLY
),
3616 "initializing DST");
3618 server
->tkeyctx
= NULL
;
3619 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx
, ns_g_entropy
,
3621 "creating TKEY context");
3624 * Setup the server task, which is responsible for coordinating
3625 * startup and shutdown of the server.
3627 CHECKFATAL(isc_task_create(ns_g_taskmgr
, 0, &server
->task
),
3628 "creating server task");
3629 isc_task_setname(server
->task
, "server", server
);
3630 CHECKFATAL(isc_task_onshutdown(server
->task
, shutdown_server
, server
),
3631 "isc_task_onshutdown");
3632 CHECKFATAL(isc_app_onrun(ns_g_mctx
, server
->task
, run_server
, server
),
3635 server
->interface_timer
= NULL
;
3636 server
->heartbeat_timer
= NULL
;
3637 server
->pps_timer
= NULL
;
3639 server
->interface_interval
= 0;
3640 server
->heartbeat_interval
= 0;
3642 CHECKFATAL(dns_zonemgr_create(ns_g_mctx
, ns_g_taskmgr
, ns_g_timermgr
,
3643 ns_g_socketmgr
, &server
->zonemgr
),
3644 "dns_zonemgr_create");
3646 server
->statsfile
= isc_mem_strdup(server
->mctx
, "named.stats");
3647 CHECKFATAL(server
->statsfile
== NULL
? ISC_R_NOMEMORY
: ISC_R_SUCCESS
,
3649 server
->querystats
= NULL
;
3651 server
->dumpfile
= isc_mem_strdup(server
->mctx
, "named_dump.db");
3652 CHECKFATAL(server
->dumpfile
== NULL
? ISC_R_NOMEMORY
: ISC_R_SUCCESS
,
3655 server
->recfile
= isc_mem_strdup(server
->mctx
, "named.recursing");
3656 CHECKFATAL(server
->recfile
== NULL
? ISC_R_NOMEMORY
: ISC_R_SUCCESS
,
3659 server
->hostname_set
= ISC_FALSE
;
3660 server
->hostname
= NULL
;
3661 server
->version_set
= ISC_FALSE
;
3662 server
->version
= NULL
;
3663 server
->server_usehostname
= ISC_FALSE
;
3664 server
->server_id
= NULL
;
3666 CHECKFATAL(dns_stats_alloccounters(ns_g_mctx
, &server
->querystats
),
3667 "dns_stats_alloccounters");
3669 server
->flushonshutdown
= ISC_FALSE
;
3670 server
->log_queries
= ISC_FALSE
;
3672 server
->controls
= NULL
;
3673 CHECKFATAL(ns_controls_create(server
, &server
->controls
),
3674 "ns_controls_create");
3675 server
->dispatchgen
= 0;
3676 ISC_LIST_INIT(server
->dispatches
);
3678 server
->magic
= NS_SERVER_MAGIC
;
3683 ns_server_destroy(ns_server_t
**serverp
) {
3684 ns_server_t
*server
= *serverp
;
3685 REQUIRE(NS_SERVER_VALID(server
));
3687 ns_controls_destroy(&server
->controls
);
3689 dns_stats_freecounters(server
->mctx
, &server
->querystats
);
3691 isc_mem_free(server
->mctx
, server
->statsfile
);
3692 isc_mem_free(server
->mctx
, server
->dumpfile
);
3693 isc_mem_free(server
->mctx
, server
->recfile
);
3695 if (server
->version
!= NULL
)
3696 isc_mem_free(server
->mctx
, server
->version
);
3697 if (server
->hostname
!= NULL
)
3698 isc_mem_free(server
->mctx
, server
->hostname
);
3699 if (server
->server_id
!= NULL
)
3700 isc_mem_free(server
->mctx
, server
->server_id
);
3702 dns_zonemgr_detach(&server
->zonemgr
);
3704 if (server
->tkeyctx
!= NULL
)
3705 dns_tkeyctx_destroy(&server
->tkeyctx
);
3709 isc_event_free(&server
->reload_event
);
3711 INSIST(ISC_LIST_EMPTY(server
->viewlist
));
3713 dns_aclenv_destroy(&server
->aclenv
);
3715 isc_quota_destroy(&server
->recursionquota
);
3716 isc_quota_destroy(&server
->tcpquota
);
3717 isc_quota_destroy(&server
->xfroutquota
);
3720 isc_mem_put(server
->mctx
, server
, sizeof(*server
));
3725 fatal(const char *msg
, isc_result_t result
) {
3726 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
3727 ISC_LOG_CRITICAL
, "%s: %s", msg
,
3728 isc_result_totext(result
));
3729 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
, NS_LOGMODULE_SERVER
,
3730 ISC_LOG_CRITICAL
, "exiting (due to fatal error)");
3735 start_reserved_dispatches(ns_server_t
*server
) {
3737 REQUIRE(NS_SERVER_VALID(server
));
3739 server
->dispatchgen
++;
3743 end_reserved_dispatches(ns_server_t
*server
, isc_boolean_t all
) {
3744 ns_dispatch_t
*dispatch
, *nextdispatch
;
3746 REQUIRE(NS_SERVER_VALID(server
));
3748 for (dispatch
= ISC_LIST_HEAD(server
->dispatches
);
3750 dispatch
= nextdispatch
) {
3751 nextdispatch
= ISC_LIST_NEXT(dispatch
, link
);
3752 if (!all
&& server
->dispatchgen
== dispatch
-> dispatchgen
)
3754 ISC_LIST_UNLINK(server
->dispatches
, dispatch
, link
);
3755 dns_dispatch_detach(&dispatch
->dispatch
);
3756 isc_mem_put(server
->mctx
, dispatch
, sizeof(*dispatch
));
3761 ns_add_reserved_dispatch(ns_server_t
*server
, const isc_sockaddr_t
*addr
) {
3762 ns_dispatch_t
*dispatch
;
3764 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
3765 isc_result_t result
;
3766 unsigned int attrs
, attrmask
;
3768 REQUIRE(NS_SERVER_VALID(server
));
3770 port
= isc_sockaddr_getport(addr
);
3771 if (port
== 0 || port
>= 1024)
3774 for (dispatch
= ISC_LIST_HEAD(server
->dispatches
);
3776 dispatch
= ISC_LIST_NEXT(dispatch
, link
)) {
3777 if (isc_sockaddr_equal(&dispatch
->addr
, addr
))
3780 if (dispatch
!= NULL
) {
3781 dispatch
->dispatchgen
= server
->dispatchgen
;
3785 dispatch
= isc_mem_get(server
->mctx
, sizeof(*dispatch
));
3786 if (dispatch
== NULL
) {
3787 result
= ISC_R_NOMEMORY
;
3791 dispatch
->addr
= *addr
;
3792 dispatch
->dispatchgen
= server
->dispatchgen
;
3793 dispatch
->dispatch
= NULL
;
3796 attrs
|= DNS_DISPATCHATTR_UDP
;
3797 switch (isc_sockaddr_pf(addr
)) {
3799 attrs
|= DNS_DISPATCHATTR_IPV4
;
3802 attrs
|= DNS_DISPATCHATTR_IPV6
;
3805 result
= ISC_R_NOTIMPLEMENTED
;
3809 attrmask
|= DNS_DISPATCHATTR_UDP
;
3810 attrmask
|= DNS_DISPATCHATTR_TCP
;
3811 attrmask
|= DNS_DISPATCHATTR_IPV4
;
3812 attrmask
|= DNS_DISPATCHATTR_IPV6
;
3814 result
= dns_dispatch_getudp(ns_g_dispatchmgr
, ns_g_socketmgr
,
3815 ns_g_taskmgr
, &dispatch
->addr
, 4096,
3816 1000, 32768, 16411, 16433,
3817 attrs
, attrmask
, &dispatch
->dispatch
);
3818 if (result
!= ISC_R_SUCCESS
)
3821 ISC_LIST_INITANDPREPEND(server
->dispatches
, dispatch
, link
);
3826 if (dispatch
!= NULL
)
3827 isc_mem_put(server
->mctx
, dispatch
, sizeof(*dispatch
));
3828 isc_sockaddr_format(addr
, addrbuf
, sizeof(addrbuf
));
3829 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
3830 NS_LOGMODULE_SERVER
, ISC_LOG_WARNING
,
3831 "unable to create dispatch for reserved port %s: %s",
3832 addrbuf
, isc_result_totext(result
));
3837 loadconfig(ns_server_t
*server
) {
3838 isc_result_t result
;
3839 start_reserved_dispatches(server
);
3840 result
= load_configuration(ns_g_lwresdonly
?
3841 lwresd_g_conffile
: ns_g_conffile
,
3843 if (result
== ISC_R_SUCCESS
)
3844 end_reserved_dispatches(server
, ISC_FALSE
);
3846 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
3847 NS_LOGMODULE_SERVER
, ISC_LOG_ERROR
,
3848 "reloading configuration failed: %s",
3849 isc_result_totext(result
));
3854 reload(ns_server_t
*server
) {
3855 isc_result_t result
;
3856 CHECK(loadconfig(server
));
3858 result
= load_zones(server
, ISC_FALSE
);
3859 if (result
!= ISC_R_SUCCESS
) {
3860 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
3861 NS_LOGMODULE_SERVER
, ISC_LOG_ERROR
,
3862 "reloading zones failed: %s",
3863 isc_result_totext(result
));
3870 reconfig(ns_server_t
*server
) {
3871 isc_result_t result
;
3872 CHECK(loadconfig(server
));
3874 result
= load_new_zones(server
, ISC_FALSE
);
3875 if (result
!= ISC_R_SUCCESS
) {
3876 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
3877 NS_LOGMODULE_SERVER
, ISC_LOG_ERROR
,
3878 "loading new zones failed: %s",
3879 isc_result_totext(result
));
3885 * Handle a reload event (from SIGHUP).
3888 ns_server_reload(isc_task_t
*task
, isc_event_t
*event
) {
3889 ns_server_t
*server
= (ns_server_t
*)event
->ev_arg
;
3891 INSIST(task
= server
->task
);
3894 (void)reload(server
);
3896 LOCK(&server
->reload_event_lock
);
3897 INSIST(server
->reload_event
== NULL
);
3898 server
->reload_event
= event
;
3899 UNLOCK(&server
->reload_event_lock
);
3903 ns_server_reloadwanted(ns_server_t
*server
) {
3904 LOCK(&server
->reload_event_lock
);
3905 if (server
->reload_event
!= NULL
)
3906 isc_task_send(server
->task
, &server
->reload_event
);
3907 UNLOCK(&server
->reload_event_lock
);
3911 next_token(char **stringp
, const char *delim
) {
3915 res
= strsep(stringp
, delim
);
3918 } while (*res
== '\0');
3923 * Find the zone specified in the control channel command 'args',
3924 * if any. If a zone is specified, point '*zonep' at it, otherwise
3925 * set '*zonep' to NULL.
3928 zone_from_args(ns_server_t
*server
, char *args
, dns_zone_t
**zonep
) {
3930 const char *zonetxt
;
3932 const char *viewtxt
= NULL
;
3933 dns_fixedname_t name
;
3934 isc_result_t result
;
3936 dns_view_t
*view
= NULL
;
3937 dns_rdataclass_t rdclass
;
3939 REQUIRE(zonep
!= NULL
&& *zonep
== NULL
);
3943 /* Skip the command name. */
3944 ptr
= next_token(&input
, " \t");
3946 return (ISC_R_UNEXPECTEDEND
);
3948 /* Look for the zone name. */
3949 zonetxt
= next_token(&input
, " \t");
3950 if (zonetxt
== NULL
)
3951 return (ISC_R_SUCCESS
);
3953 /* Look for the optional class name. */
3954 classtxt
= next_token(&input
, " \t");
3955 if (classtxt
!= NULL
) {
3956 /* Look for the optional view name. */
3957 viewtxt
= next_token(&input
, " \t");
3960 isc_buffer_init(&buf
, zonetxt
, strlen(zonetxt
));
3961 isc_buffer_add(&buf
, strlen(zonetxt
));
3962 dns_fixedname_init(&name
);
3963 result
= dns_name_fromtext(dns_fixedname_name(&name
),
3964 &buf
, dns_rootname
, ISC_FALSE
, NULL
);
3965 if (result
!= ISC_R_SUCCESS
)
3968 if (classtxt
!= NULL
) {
3971 r
.length
= strlen(classtxt
);
3972 result
= dns_rdataclass_fromtext(&rdclass
, &r
);
3973 if (result
!= ISC_R_SUCCESS
)
3976 rdclass
= dns_rdataclass_in
;
3979 if (viewtxt
== NULL
)
3980 viewtxt
= "_default";
3981 result
= dns_viewlist_find(&server
->viewlist
, viewtxt
,
3983 if (result
!= ISC_R_SUCCESS
)
3986 result
= dns_zt_find(view
->zonetable
, dns_fixedname_name(&name
),
3988 /* Partial match? */
3989 if (result
!= ISC_R_SUCCESS
&& *zonep
!= NULL
)
3990 dns_zone_detach(zonep
);
3991 dns_view_detach(&view
);
3997 * Act on a "retransfer" command from the command channel.
4000 ns_server_retransfercommand(ns_server_t
*server
, char *args
) {
4001 isc_result_t result
;
4002 dns_zone_t
*zone
= NULL
;
4003 dns_zonetype_t type
;
4005 result
= zone_from_args(server
, args
, &zone
);
4006 if (result
!= ISC_R_SUCCESS
)
4009 return (ISC_R_UNEXPECTEDEND
);
4010 type
= dns_zone_gettype(zone
);
4011 if (type
== dns_zone_slave
|| type
== dns_zone_stub
)
4012 dns_zone_forcereload(zone
);
4014 result
= ISC_R_NOTFOUND
;
4015 dns_zone_detach(&zone
);
4020 * Act on a "reload" command from the command channel.
4023 ns_server_reloadcommand(ns_server_t
*server
, char *args
, isc_buffer_t
*text
) {
4024 isc_result_t result
;
4025 dns_zone_t
*zone
= NULL
;
4026 dns_zonetype_t type
;
4027 const char *msg
= NULL
;
4029 result
= zone_from_args(server
, args
, &zone
);
4030 if (result
!= ISC_R_SUCCESS
)
4033 result
= reload(server
);
4034 if (result
== ISC_R_SUCCESS
)
4035 msg
= "server reload successful";
4037 type
= dns_zone_gettype(zone
);
4038 if (type
== dns_zone_slave
|| type
== dns_zone_stub
) {
4039 dns_zone_refresh(zone
);
4040 dns_zone_detach(&zone
);
4041 msg
= "zone refresh queued";
4043 result
= dns_zone_load(zone
);
4044 dns_zone_detach(&zone
);
4047 msg
= "zone reload successful";
4049 case DNS_R_CONTINUE
:
4050 msg
= "zone reload queued";
4051 result
= ISC_R_SUCCESS
;
4053 case DNS_R_UPTODATE
:
4054 msg
= "zone reload up-to-date";
4055 result
= ISC_R_SUCCESS
;
4058 /* failure message will be generated by rndc */
4063 if (msg
!= NULL
&& strlen(msg
) < isc_buffer_availablelength(text
))
4064 isc_buffer_putmem(text
, (const unsigned char *)msg
,
4070 * Act on a "reconfig" command from the command channel.
4073 ns_server_reconfigcommand(ns_server_t
*server
, char *args
) {
4077 return (ISC_R_SUCCESS
);
4081 * Act on a "notify" command from the command channel.
4084 ns_server_notifycommand(ns_server_t
*server
, char *args
, isc_buffer_t
*text
) {
4085 isc_result_t result
;
4086 dns_zone_t
*zone
= NULL
;
4087 const unsigned char msg
[] = "zone notify queued";
4089 result
= zone_from_args(server
, args
, &zone
);
4090 if (result
!= ISC_R_SUCCESS
)
4093 return (ISC_R_UNEXPECTEDEND
);
4095 dns_zone_notify(zone
);
4096 dns_zone_detach(&zone
);
4097 if (sizeof(msg
) <= isc_buffer_availablelength(text
))
4098 isc_buffer_putmem(text
, msg
, sizeof(msg
));
4100 return (ISC_R_SUCCESS
);
4104 * Act on a "refresh" command from the command channel.
4107 ns_server_refreshcommand(ns_server_t
*server
, char *args
, isc_buffer_t
*text
) {
4108 isc_result_t result
;
4109 dns_zone_t
*zone
= NULL
;
4110 const unsigned char msg1
[] = "zone refresh queued";
4111 const unsigned char msg2
[] = "not a slave or stub zone";
4112 dns_zonetype_t type
;
4114 result
= zone_from_args(server
, args
, &zone
);
4115 if (result
!= ISC_R_SUCCESS
)
4118 return (ISC_R_UNEXPECTEDEND
);
4120 type
= dns_zone_gettype(zone
);
4121 if (type
== dns_zone_slave
|| type
== dns_zone_stub
) {
4122 dns_zone_refresh(zone
);
4123 dns_zone_detach(&zone
);
4124 if (sizeof(msg1
) <= isc_buffer_availablelength(text
))
4125 isc_buffer_putmem(text
, msg1
, sizeof(msg1
));
4126 return (ISC_R_SUCCESS
);
4129 dns_zone_detach(&zone
);
4130 if (sizeof(msg2
) <= isc_buffer_availablelength(text
))
4131 isc_buffer_putmem(text
, msg2
, sizeof(msg2
));
4132 return (ISC_R_FAILURE
);
4136 ns_server_togglequerylog(ns_server_t
*server
) {
4137 server
->log_queries
= server
->log_queries
? ISC_FALSE
: ISC_TRUE
;
4139 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
4140 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
4141 "query logging is now %s",
4142 server
->log_queries
? "on" : "off");
4143 return (ISC_R_SUCCESS
);
4147 ns_listenlist_fromconfig(const cfg_obj_t
*listenlist
, const cfg_obj_t
*config
,
4148 cfg_aclconfctx_t
*actx
,
4149 isc_mem_t
*mctx
, ns_listenlist_t
**target
)
4151 isc_result_t result
;
4152 const cfg_listelt_t
*element
;
4153 ns_listenlist_t
*dlist
= NULL
;
4155 REQUIRE(target
!= NULL
&& *target
== NULL
);
4157 result
= ns_listenlist_create(mctx
, &dlist
);
4158 if (result
!= ISC_R_SUCCESS
)
4161 for (element
= cfg_list_first(listenlist
);
4163 element
= cfg_list_next(element
))
4165 ns_listenelt_t
*delt
= NULL
;
4166 const cfg_obj_t
*listener
= cfg_listelt_value(element
);
4167 result
= ns_listenelt_fromconfig(listener
, config
, actx
,
4169 if (result
!= ISC_R_SUCCESS
)
4171 ISC_LIST_APPEND(dlist
->elts
, delt
, link
);
4174 return (ISC_R_SUCCESS
);
4177 ns_listenlist_detach(&dlist
);
4182 * Create a listen list from the corresponding configuration
4186 ns_listenelt_fromconfig(const cfg_obj_t
*listener
, const cfg_obj_t
*config
,
4187 cfg_aclconfctx_t
*actx
,
4188 isc_mem_t
*mctx
, ns_listenelt_t
**target
)
4190 isc_result_t result
;
4191 const cfg_obj_t
*portobj
;
4193 ns_listenelt_t
*delt
= NULL
;
4194 REQUIRE(target
!= NULL
&& *target
== NULL
);
4196 portobj
= cfg_tuple_get(listener
, "port");
4197 if (!cfg_obj_isuint32(portobj
)) {
4198 if (ns_g_port
!= 0) {
4201 result
= ns_config_getport(config
, &port
);
4202 if (result
!= ISC_R_SUCCESS
)
4206 if (cfg_obj_asuint32(portobj
) >= ISC_UINT16_MAX
) {
4207 cfg_obj_log(portobj
, ns_g_lctx
, ISC_LOG_ERROR
,
4208 "port value '%u' is out of range",
4209 cfg_obj_asuint32(portobj
));
4210 return (ISC_R_RANGE
);
4212 port
= (in_port_t
)cfg_obj_asuint32(portobj
);
4215 result
= ns_listenelt_create(mctx
, port
, NULL
, &delt
);
4216 if (result
!= ISC_R_SUCCESS
)
4219 result
= cfg_acl_fromconfig(cfg_tuple_get(listener
, "acl"),
4220 config
, ns_g_lctx
, actx
, mctx
, &delt
->acl
);
4221 if (result
!= ISC_R_SUCCESS
) {
4222 ns_listenelt_destroy(delt
);
4226 return (ISC_R_SUCCESS
);
4230 ns_server_dumpstats(ns_server_t
*server
) {
4231 isc_result_t result
;
4232 dns_zone_t
*zone
, *next
;
4238 isc_stdtime_get(&now
);
4240 CHECKMF(isc_stdio_open(server
->statsfile
, "a", &fp
),
4241 "could not open statistics dump file", server
->statsfile
);
4243 ncounters
= DNS_STATS_NCOUNTERS
;
4244 fprintf(fp
, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now
);
4246 for (i
= 0; i
< ncounters
; i
++)
4247 fprintf(fp
, "%s %" ISC_PRINT_QUADFORMAT
"u\n",
4248 dns_statscounter_names
[i
],
4249 server
->querystats
[i
]);
4252 for (result
= dns_zone_first(server
->zonemgr
, &zone
);
4253 result
== ISC_R_SUCCESS
;
4254 next
= NULL
, result
= dns_zone_next(zone
, &next
), zone
= next
)
4256 isc_uint64_t
*zonestats
= dns_zone_getstatscounters(zone
);
4257 if (zonestats
!= NULL
) {
4258 char zonename
[DNS_NAME_FORMATSIZE
];
4262 dns_name_format(dns_zone_getorigin(zone
),
4263 zonename
, sizeof(zonename
));
4264 view
= dns_zone_getview(zone
);
4265 viewname
= view
->name
;
4266 for (i
= 0; i
< ncounters
; i
++) {
4267 fprintf(fp
, "%s %" ISC_PRINT_QUADFORMAT
4269 dns_statscounter_names
[i
],
4272 if (strcmp(viewname
, "_default") != 0)
4273 fprintf(fp
, " %s", viewname
);
4278 if (result
== ISC_R_NOMORE
)
4279 result
= ISC_R_SUCCESS
;
4282 fprintf(fp
, "--- Statistics Dump --- (%lu)\n", (unsigned long)now
);
4286 (void)isc_stdio_close(fp
);
4291 add_zone_tolist(dns_zone_t
*zone
, void *uap
) {
4292 struct dumpcontext
*dctx
= uap
;
4293 struct zonelistentry
*zle
;
4295 zle
= isc_mem_get(dctx
->mctx
, sizeof *zle
);
4297 return (ISC_R_NOMEMORY
);
4299 dns_zone_attach(zone
, &zle
->zone
);
4300 ISC_LINK_INIT(zle
, link
);
4301 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx
->viewlist
)->zonelist
, zle
, link
);
4302 return (ISC_R_SUCCESS
);
4306 add_view_tolist(struct dumpcontext
*dctx
, dns_view_t
*view
) {
4307 struct viewlistentry
*vle
;
4308 isc_result_t result
= ISC_R_SUCCESS
;
4311 * Prevent duplicate views.
4313 for (vle
= ISC_LIST_HEAD(dctx
->viewlist
);
4315 vle
= ISC_LIST_NEXT(vle
, link
))
4316 if (vle
->view
== view
)
4317 return (ISC_R_SUCCESS
);
4319 vle
= isc_mem_get(dctx
->mctx
, sizeof *vle
);
4321 return (ISC_R_NOMEMORY
);
4323 dns_view_attach(view
, &vle
->view
);
4324 ISC_LINK_INIT(vle
, link
);
4325 ISC_LIST_INIT(vle
->zonelist
);
4326 ISC_LIST_APPEND(dctx
->viewlist
, vle
, link
);
4327 if (dctx
->dumpzones
)
4328 result
= dns_zt_apply(view
->zonetable
, ISC_TRUE
,
4329 add_zone_tolist
, dctx
);
4334 dumpcontext_destroy(struct dumpcontext
*dctx
) {
4335 struct viewlistentry
*vle
;
4336 struct zonelistentry
*zle
;
4338 vle
= ISC_LIST_HEAD(dctx
->viewlist
);
4339 while (vle
!= NULL
) {
4340 ISC_LIST_UNLINK(dctx
->viewlist
, vle
, link
);
4341 zle
= ISC_LIST_HEAD(vle
->zonelist
);
4342 while (zle
!= NULL
) {
4343 ISC_LIST_UNLINK(vle
->zonelist
, zle
, link
);
4344 dns_zone_detach(&zle
->zone
);
4345 isc_mem_put(dctx
->mctx
, zle
, sizeof *zle
);
4346 zle
= ISC_LIST_HEAD(vle
->zonelist
);
4348 dns_view_detach(&vle
->view
);
4349 isc_mem_put(dctx
->mctx
, vle
, sizeof *vle
);
4350 vle
= ISC_LIST_HEAD(dctx
->viewlist
);
4352 if (dctx
->version
!= NULL
)
4353 dns_db_closeversion(dctx
->db
, &dctx
->version
, ISC_FALSE
);
4354 if (dctx
->db
!= NULL
)
4355 dns_db_detach(&dctx
->db
);
4356 if (dctx
->cache
!= NULL
)
4357 dns_db_detach(&dctx
->cache
);
4358 if (dctx
->task
!= NULL
)
4359 isc_task_detach(&dctx
->task
);
4360 if (dctx
->fp
!= NULL
)
4361 (void)isc_stdio_close(dctx
->fp
);
4362 if (dctx
->mdctx
!= NULL
)
4363 dns_dumpctx_detach(&dctx
->mdctx
);
4364 isc_mem_put(dctx
->mctx
, dctx
, sizeof *dctx
);
4368 dumpdone(void *arg
, isc_result_t result
) {
4369 struct dumpcontext
*dctx
= arg
;
4371 const dns_master_style_t
*style
;
4373 if (result
!= ISC_R_SUCCESS
)
4375 if (dctx
->mdctx
!= NULL
)
4376 dns_dumpctx_detach(&dctx
->mdctx
);
4377 if (dctx
->view
== NULL
) {
4378 dctx
->view
= ISC_LIST_HEAD(dctx
->viewlist
);
4379 if (dctx
->view
== NULL
)
4381 INSIST(dctx
->zone
== NULL
);
4385 fprintf(dctx
->fp
, ";\n; Start view %s\n;\n", dctx
->view
->view
->name
);
4387 if (dctx
->zone
== NULL
&& dctx
->cache
== NULL
&& dctx
->dumpcache
) {
4388 style
= &dns_master_style_cache
;
4389 /* start cache dump */
4390 if (dctx
->view
->view
->cachedb
!= NULL
)
4391 dns_db_attach(dctx
->view
->view
->cachedb
, &dctx
->cache
);
4392 if (dctx
->cache
!= NULL
) {
4394 fprintf(dctx
->fp
, ";\n; Cache dump of view '%s'\n;\n",
4395 dctx
->view
->view
->name
);
4396 result
= dns_master_dumptostreaminc(dctx
->mctx
,
4402 if (result
== DNS_R_CONTINUE
)
4404 if (result
== ISC_R_NOTIMPLEMENTED
)
4405 fprintf(dctx
->fp
, "; %s\n",
4406 dns_result_totext(result
));
4407 else if (result
!= ISC_R_SUCCESS
)
4411 if (dctx
->cache
!= NULL
) {
4412 dns_adb_dump(dctx
->view
->view
->adb
, dctx
->fp
);
4413 dns_db_detach(&dctx
->cache
);
4415 if (dctx
->dumpzones
) {
4416 style
= &dns_master_style_full
;
4418 if (dctx
->version
!= NULL
)
4419 dns_db_closeversion(dctx
->db
, &dctx
->version
,
4421 if (dctx
->db
!= NULL
)
4422 dns_db_detach(&dctx
->db
);
4423 if (dctx
->zone
== NULL
)
4424 dctx
->zone
= ISC_LIST_HEAD(dctx
->view
->zonelist
);
4426 dctx
->zone
= ISC_LIST_NEXT(dctx
->zone
, link
);
4427 if (dctx
->zone
!= NULL
) {
4428 /* start zone dump */
4429 dns_zone_name(dctx
->zone
->zone
, buf
, sizeof(buf
));
4430 fprintf(dctx
->fp
, ";\n; Zone dump of '%s'\n;\n", buf
);
4431 result
= dns_zone_getdb(dctx
->zone
->zone
, &dctx
->db
);
4432 if (result
!= ISC_R_SUCCESS
) {
4433 fprintf(dctx
->fp
, "; %s\n",
4434 dns_result_totext(result
));
4437 dns_db_currentversion(dctx
->db
, &dctx
->version
);
4438 result
= dns_master_dumptostreaminc(dctx
->mctx
,
4445 if (result
== DNS_R_CONTINUE
)
4447 if (result
== ISC_R_NOTIMPLEMENTED
) {
4448 fprintf(dctx
->fp
, "; %s\n",
4449 dns_result_totext(result
));
4450 result
= ISC_R_SUCCESS
;
4453 if (result
!= ISC_R_SUCCESS
)
4457 if (dctx
->view
!= NULL
)
4458 dctx
->view
= ISC_LIST_NEXT(dctx
->view
, link
);
4459 if (dctx
->view
!= NULL
)
4462 fprintf(dctx
->fp
, "; Dump complete\n");
4463 result
= isc_stdio_flush(dctx
->fp
);
4464 if (result
== ISC_R_SUCCESS
)
4465 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
4466 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
4469 if (result
!= ISC_R_SUCCESS
)
4470 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
4471 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
4472 "dumpdb failed: %s", dns_result_totext(result
));
4473 dumpcontext_destroy(dctx
);
4477 ns_server_dumpdb(ns_server_t
*server
, char *args
) {
4478 struct dumpcontext
*dctx
= NULL
;
4480 isc_result_t result
;
4484 /* Skip the command name. */
4485 ptr
= next_token(&args
, " \t");
4487 return (ISC_R_UNEXPECTEDEND
);
4489 dctx
= isc_mem_get(server
->mctx
, sizeof(*dctx
));
4491 return (ISC_R_NOMEMORY
);
4493 dctx
->mctx
= server
->mctx
;
4494 dctx
->dumpcache
= ISC_TRUE
;
4495 dctx
->dumpzones
= ISC_FALSE
;
4497 ISC_LIST_INIT(dctx
->viewlist
);
4505 dctx
->version
= NULL
;
4506 isc_task_attach(server
->task
, &dctx
->task
);
4508 CHECKMF(isc_stdio_open(server
->dumpfile
, "w", &dctx
->fp
),
4509 "could not open dump file", server
->dumpfile
);
4511 sep
= (args
== NULL
) ? "" : ": ";
4512 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
4513 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
4514 "dumpdb started%s%s", sep
, (args
!= NULL
) ? args
: "");
4516 ptr
= next_token(&args
, " \t");
4517 if (ptr
!= NULL
&& strcmp(ptr
, "-all") == 0) {
4518 dctx
->dumpzones
= ISC_TRUE
;
4519 dctx
->dumpcache
= ISC_TRUE
;
4520 ptr
= next_token(&args
, " \t");
4521 } else if (ptr
!= NULL
&& strcmp(ptr
, "-cache") == 0) {
4522 dctx
->dumpzones
= ISC_FALSE
;
4523 dctx
->dumpcache
= ISC_TRUE
;
4524 ptr
= next_token(&args
, " \t");
4525 } else if (ptr
!= NULL
&& strcmp(ptr
, "-zones") == 0) {
4526 dctx
->dumpzones
= ISC_TRUE
;
4527 dctx
->dumpcache
= ISC_FALSE
;
4528 ptr
= next_token(&args
, " \t");
4532 for (view
= ISC_LIST_HEAD(server
->viewlist
);
4534 view
= ISC_LIST_NEXT(view
, link
))
4536 if (ptr
!= NULL
&& strcmp(view
->name
, ptr
) != 0)
4538 CHECK(add_view_tolist(dctx
, view
));
4541 ptr
= next_token(&args
, " \t");
4545 dumpdone(dctx
, ISC_R_SUCCESS
);
4546 return (ISC_R_SUCCESS
);
4550 dumpcontext_destroy(dctx
);
4555 ns_server_dumprecursing(ns_server_t
*server
) {
4557 isc_result_t result
;
4559 CHECKMF(isc_stdio_open(server
->recfile
, "w", &fp
),
4560 "could not open dump file", server
->recfile
);
4561 fprintf(fp
,";\n; Recursing Queries\n;\n");
4562 ns_interfacemgr_dumprecursing(fp
, server
->interfacemgr
);
4563 fprintf(fp
, "; Dump complete\n");
4567 result
= isc_stdio_close(fp
);
4572 ns_server_setdebuglevel(ns_server_t
*server
, char *args
) {
4580 /* Skip the command name. */
4581 ptr
= next_token(&args
, " \t");
4583 return (ISC_R_UNEXPECTEDEND
);
4585 /* Look for the new level name. */
4586 levelstr
= next_token(&args
, " \t");
4587 if (levelstr
== NULL
) {
4588 if (ns_g_debuglevel
< 99)
4591 newlevel
= strtol(levelstr
, &endp
, 10);
4592 if (*endp
!= '\0' || newlevel
< 0 || newlevel
> 99)
4593 return (ISC_R_RANGE
);
4594 ns_g_debuglevel
= (unsigned int)newlevel
;
4596 isc_log_setdebuglevel(ns_g_lctx
, ns_g_debuglevel
);
4597 return (ISC_R_SUCCESS
);
4601 ns_server_validation(ns_server_t
*server
, char *args
) {
4602 char *ptr
, *viewname
;
4604 isc_boolean_t changed
= ISC_FALSE
;
4605 isc_result_t result
;
4606 isc_boolean_t enable
;
4608 /* Skip the command name. */
4609 ptr
= next_token(&args
, " \t");
4611 return (ISC_R_UNEXPECTEDEND
);
4613 /* Find out what we are to do. */
4614 ptr
= next_token(&args
, " \t");
4616 return (ISC_R_UNEXPECTEDEND
);
4618 if (!strcasecmp(ptr
, "on") || !strcasecmp(ptr
, "yes") ||
4619 !strcasecmp(ptr
, "enable") || !strcasecmp(ptr
, "true"))
4621 else if (!strcasecmp(ptr
, "off") || !strcasecmp(ptr
, "no") ||
4622 !strcasecmp(ptr
, "disable") || !strcasecmp(ptr
, "false"))
4625 return (DNS_R_SYNTAX
);
4627 /* Look for the view name. */
4628 viewname
= next_token(&args
, " \t");
4630 result
= isc_task_beginexclusive(server
->task
);
4631 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
4632 for (view
= ISC_LIST_HEAD(server
->viewlist
);
4634 view
= ISC_LIST_NEXT(view
, link
))
4636 if (viewname
!= NULL
&& strcasecmp(viewname
, view
->name
) != 0)
4638 result
= dns_view_flushcache(view
);
4639 if (result
!= ISC_R_SUCCESS
)
4641 view
->enablevalidation
= enable
;
4645 result
= ISC_R_SUCCESS
;
4647 result
= ISC_R_FAILURE
;
4649 isc_task_endexclusive(server
->task
);
4654 ns_server_flushcache(ns_server_t
*server
, char *args
) {
4655 char *ptr
, *viewname
;
4657 isc_boolean_t flushed
;
4658 isc_boolean_t found
;
4659 isc_result_t result
;
4661 /* Skip the command name. */
4662 ptr
= next_token(&args
, " \t");
4664 return (ISC_R_UNEXPECTEDEND
);
4666 /* Look for the view name. */
4667 viewname
= next_token(&args
, " \t");
4669 result
= isc_task_beginexclusive(server
->task
);
4670 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
4673 for (view
= ISC_LIST_HEAD(server
->viewlist
);
4675 view
= ISC_LIST_NEXT(view
, link
))
4677 if (viewname
!= NULL
&& strcasecmp(viewname
, view
->name
) != 0)
4680 result
= dns_view_flushcache(view
);
4681 if (result
!= ISC_R_SUCCESS
)
4682 flushed
= ISC_FALSE
;
4684 if (flushed
&& found
) {
4685 result
= ISC_R_SUCCESS
;
4688 result
= ISC_R_NOTFOUND
;
4690 result
= ISC_R_FAILURE
;
4692 isc_task_endexclusive(server
->task
);
4697 ns_server_flushname(ns_server_t
*server
, char *args
) {
4698 char *ptr
, *target
, *viewname
;
4700 isc_boolean_t flushed
;
4701 isc_boolean_t found
;
4702 isc_result_t result
;
4704 dns_fixedname_t fixed
;
4707 /* Skip the command name. */
4708 ptr
= next_token(&args
, " \t");
4710 return (ISC_R_UNEXPECTEDEND
);
4712 /* Find the domain name to flush. */
4713 target
= next_token(&args
, " \t");
4715 return (ISC_R_UNEXPECTEDEND
);
4717 isc_buffer_init(&b
, target
, strlen(target
));
4718 isc_buffer_add(&b
, strlen(target
));
4719 dns_fixedname_init(&fixed
);
4720 name
= dns_fixedname_name(&fixed
);
4721 result
= dns_name_fromtext(name
, &b
, dns_rootname
, ISC_FALSE
, NULL
);
4722 if (result
!= ISC_R_SUCCESS
)
4725 /* Look for the view name. */
4726 viewname
= next_token(&args
, " \t");
4728 result
= isc_task_beginexclusive(server
->task
);
4729 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
4732 for (view
= ISC_LIST_HEAD(server
->viewlist
);
4734 view
= ISC_LIST_NEXT(view
, link
))
4736 if (viewname
!= NULL
&& strcasecmp(viewname
, view
->name
) != 0)
4739 result
= dns_view_flushname(view
, name
);
4740 if (result
!= ISC_R_SUCCESS
)
4741 flushed
= ISC_FALSE
;
4743 if (flushed
&& found
)
4744 result
= ISC_R_SUCCESS
;
4746 result
= ISC_R_NOTFOUND
;
4748 result
= ISC_R_FAILURE
;
4749 isc_task_endexclusive(server
->task
);
4754 ns_server_status(ns_server_t
*server
, isc_buffer_t
*text
) {
4755 int zonecount
, xferrunning
, xferdeferred
, soaqueries
;
4758 zonecount
= dns_zonemgr_getcount(server
->zonemgr
, DNS_ZONESTATE_ANY
);
4759 xferrunning
= dns_zonemgr_getcount(server
->zonemgr
,
4760 DNS_ZONESTATE_XFERRUNNING
);
4761 xferdeferred
= dns_zonemgr_getcount(server
->zonemgr
,
4762 DNS_ZONESTATE_XFERDEFERRED
);
4763 soaqueries
= dns_zonemgr_getcount(server
->zonemgr
,
4764 DNS_ZONESTATE_SOAQUERY
);
4765 n
= snprintf((char *)isc_buffer_used(text
),
4766 isc_buffer_availablelength(text
),
4767 "number of zones: %u\n"
4769 "xfers running: %u\n"
4770 "xfers deferred: %u\n"
4771 "soa queries in progress: %u\n"
4772 "query logging is %s\n"
4773 "recursive clients: %d/%d/%d\n"
4774 "tcp clients: %d/%d\n"
4775 "server is up and running",
4776 zonecount
, ns_g_debuglevel
, xferrunning
, xferdeferred
,
4777 soaqueries
, server
->log_queries
? "ON" : "OFF",
4778 server
->recursionquota
.used
, server
->recursionquota
.soft
,
4779 server
->recursionquota
.max
,
4780 server
->tcpquota
.used
, server
->tcpquota
.max
);
4781 if (n
>= isc_buffer_availablelength(text
))
4782 return (ISC_R_NOSPACE
);
4783 isc_buffer_add(text
, n
);
4784 return (ISC_R_SUCCESS
);
4788 * Act on a "freeze" or "thaw" command from the command channel.
4791 ns_server_freeze(ns_server_t
*server
, isc_boolean_t freeze
, char *args
) {
4792 isc_result_t result
, tresult
;
4793 dns_zone_t
*zone
= NULL
;
4794 dns_zonetype_t type
;
4795 char classstr
[DNS_RDATACLASS_FORMATSIZE
];
4796 char zonename
[DNS_NAME_FORMATSIZE
];
4799 const char *vname
, *sep
;
4800 isc_boolean_t frozen
;
4802 result
= zone_from_args(server
, args
, &zone
);
4803 if (result
!= ISC_R_SUCCESS
)
4806 result
= isc_task_beginexclusive(server
->task
);
4807 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
4808 tresult
= ISC_R_SUCCESS
;
4809 for (view
= ISC_LIST_HEAD(server
->viewlist
);
4811 view
= ISC_LIST_NEXT(view
, link
)) {
4812 result
= dns_view_freezezones(view
, freeze
);
4813 if (result
!= ISC_R_SUCCESS
&&
4814 tresult
== ISC_R_SUCCESS
)
4817 isc_task_endexclusive(server
->task
);
4818 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
4819 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
4821 freeze
? "freezing" : "thawing",
4822 isc_result_totext(tresult
));
4825 type
= dns_zone_gettype(zone
);
4826 if (type
!= dns_zone_master
) {
4827 dns_zone_detach(&zone
);
4828 return (ISC_R_NOTFOUND
);
4831 frozen
= dns_zone_getupdatedisabled(zone
);
4834 result
= DNS_R_FROZEN
;
4835 if (result
== ISC_R_SUCCESS
)
4836 result
= dns_zone_flush(zone
);
4837 if (result
== ISC_R_SUCCESS
) {
4838 journal
= dns_zone_getjournal(zone
);
4839 if (journal
!= NULL
)
4840 (void)isc_file_remove(journal
);
4844 result
= dns_zone_load(zone
);
4845 if (result
== DNS_R_CONTINUE
||
4846 result
== DNS_R_UPTODATE
)
4847 result
= ISC_R_SUCCESS
;
4850 if (result
== ISC_R_SUCCESS
)
4851 dns_zone_setupdatedisabled(zone
, freeze
);
4853 view
= dns_zone_getview(zone
);
4854 if (strcmp(view
->name
, "_bind") == 0 ||
4855 strcmp(view
->name
, "_default") == 0)
4863 dns_rdataclass_format(dns_zone_getclass(zone
), classstr
,
4865 dns_name_format(dns_zone_getorigin(zone
),
4866 zonename
, sizeof(zonename
));
4867 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
4868 NS_LOGMODULE_SERVER
, ISC_LOG_INFO
,
4869 "%s zone '%s/%s'%s%s: %s",
4870 freeze
? "freezing" : "thawing",
4871 zonename
, classstr
, sep
, vname
,
4872 isc_result_totext(result
));
4873 dns_zone_detach(&zone
);
4879 * This function adds a message for rndc to echo if named
4880 * is managed by smf and is also running chroot.
4883 ns_smf_add_message(isc_buffer_t
*text
) {
4886 n
= snprintf((char *)isc_buffer_used(text
),
4887 isc_buffer_availablelength(text
),
4888 "use svcadm(1M) to manage named");
4889 if (n
>= isc_buffer_availablelength(text
))
4890 return (ISC_R_NOSPACE
);
4891 isc_buffer_add(text
, n
);
4892 return (ISC_R_SUCCESS
);
4894 #endif /* HAVE_LIBSCF */