server.c revision 218384
1/* 2 * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 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. 8 * 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. 16 */ 17 18/* $Id: server.c,v 1.520.12.21 2011-01-14 23:45:49 tbox Exp $ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <stdlib.h> 25#include <unistd.h> 26 27#include <isc/app.h> 28#include <isc/base64.h> 29#include <isc/dir.h> 30#include <isc/entropy.h> 31#include <isc/file.h> 32#include <isc/hash.h> 33#include <isc/httpd.h> 34#include <isc/lex.h> 35#include <isc/parseint.h> 36#include <isc/portset.h> 37#include <isc/print.h> 38#include <isc/resource.h> 39#include <isc/socket.h> 40#include <isc/stats.h> 41#include <isc/stdio.h> 42#include <isc/string.h> 43#include <isc/task.h> 44#include <isc/timer.h> 45#include <isc/util.h> 46#include <isc/xml.h> 47 48#include <isccfg/namedconf.h> 49 50#include <bind9/check.h> 51 52#include <dns/acache.h> 53#include <dns/adb.h> 54#include <dns/cache.h> 55#include <dns/db.h> 56#include <dns/dispatch.h> 57#ifdef DLZ 58#include <dns/dlz.h> 59#endif 60#include <dns/forward.h> 61#include <dns/journal.h> 62#include <dns/keytable.h> 63#include <dns/lib.h> 64#include <dns/master.h> 65#include <dns/masterdump.h> 66#include <dns/order.h> 67#include <dns/peer.h> 68#include <dns/portlist.h> 69#include <dns/rbt.h> 70#include <dns/rdataclass.h> 71#include <dns/rdataset.h> 72#include <dns/rdatastruct.h> 73#include <dns/resolver.h> 74#include <dns/rootns.h> 75#include <dns/secalg.h> 76#include <dns/stats.h> 77#include <dns/tkey.h> 78#include <dns/tsig.h> 79#include <dns/view.h> 80#include <dns/zone.h> 81#include <dns/zt.h> 82 83#include <dst/dst.h> 84#include <dst/result.h> 85 86#include <named/client.h> 87#include <named/config.h> 88#include <named/control.h> 89#include <named/interfacemgr.h> 90#include <named/log.h> 91#include <named/logconf.h> 92#include <named/lwresd.h> 93#include <named/main.h> 94#include <named/os.h> 95#include <named/server.h> 96#include <named/statschannel.h> 97#include <named/tkeyconf.h> 98#include <named/tsigconf.h> 99#include <named/zoneconf.h> 100#ifdef HAVE_LIBSCF 101#include <named/ns_smf_globals.h> 102#include <stdlib.h> 103#endif 104 105/*% 106 * Check an operation for failure. Assumes that the function 107 * using it has a 'result' variable and a 'cleanup' label. 108 */ 109#define CHECK(op) \ 110 do { result = (op); \ 111 if (result != ISC_R_SUCCESS) goto cleanup; \ 112 } while (0) 113 114#define CHECKM(op, msg) \ 115 do { result = (op); \ 116 if (result != ISC_R_SUCCESS) { \ 117 isc_log_write(ns_g_lctx, \ 118 NS_LOGCATEGORY_GENERAL, \ 119 NS_LOGMODULE_SERVER, \ 120 ISC_LOG_ERROR, \ 121 "%s: %s", msg, \ 122 isc_result_totext(result)); \ 123 goto cleanup; \ 124 } \ 125 } while (0) \ 126 127#define CHECKMF(op, msg, file) \ 128 do { result = (op); \ 129 if (result != ISC_R_SUCCESS) { \ 130 isc_log_write(ns_g_lctx, \ 131 NS_LOGCATEGORY_GENERAL, \ 132 NS_LOGMODULE_SERVER, \ 133 ISC_LOG_ERROR, \ 134 "%s '%s': %s", msg, file, \ 135 isc_result_totext(result)); \ 136 goto cleanup; \ 137 } \ 138 } while (0) \ 139 140#define CHECKFATAL(op, msg) \ 141 do { result = (op); \ 142 if (result != ISC_R_SUCCESS) \ 143 fatal(msg, result); \ 144 } while (0) \ 145 146struct ns_dispatch { 147 isc_sockaddr_t addr; 148 unsigned int dispatchgen; 149 dns_dispatch_t *dispatch; 150 ISC_LINK(struct ns_dispatch) link; 151}; 152 153struct dumpcontext { 154 isc_mem_t *mctx; 155 isc_boolean_t dumpcache; 156 isc_boolean_t dumpzones; 157 FILE *fp; 158 ISC_LIST(struct viewlistentry) viewlist; 159 struct viewlistentry *view; 160 struct zonelistentry *zone; 161 dns_dumpctx_t *mdctx; 162 dns_db_t *db; 163 dns_db_t *cache; 164 isc_task_t *task; 165 dns_dbversion_t *version; 166}; 167 168struct viewlistentry { 169 dns_view_t *view; 170 ISC_LINK(struct viewlistentry) link; 171 ISC_LIST(struct zonelistentry) zonelist; 172}; 173 174struct zonelistentry { 175 dns_zone_t *zone; 176 ISC_LINK(struct zonelistentry) link; 177}; 178 179/* 180 * These zones should not leak onto the Internet. 181 */ 182static const struct { 183 const char *zone; 184 isc_boolean_t rfc1918; 185} empty_zones[] = { 186#ifdef notyet 187 /* RFC 1918 */ 188 { "10.IN-ADDR.ARPA", ISC_TRUE }, 189 { "16.172.IN-ADDR.ARPA", ISC_TRUE }, 190 { "17.172.IN-ADDR.ARPA", ISC_TRUE }, 191 { "18.172.IN-ADDR.ARPA", ISC_TRUE }, 192 { "19.172.IN-ADDR.ARPA", ISC_TRUE }, 193 { "20.172.IN-ADDR.ARPA", ISC_TRUE }, 194 { "21.172.IN-ADDR.ARPA", ISC_TRUE }, 195 { "22.172.IN-ADDR.ARPA", ISC_TRUE }, 196 { "23.172.IN-ADDR.ARPA", ISC_TRUE }, 197 { "24.172.IN-ADDR.ARPA", ISC_TRUE }, 198 { "25.172.IN-ADDR.ARPA", ISC_TRUE }, 199 { "26.172.IN-ADDR.ARPA", ISC_TRUE }, 200 { "27.172.IN-ADDR.ARPA", ISC_TRUE }, 201 { "28.172.IN-ADDR.ARPA", ISC_TRUE }, 202 { "29.172.IN-ADDR.ARPA", ISC_TRUE }, 203 { "30.172.IN-ADDR.ARPA", ISC_TRUE }, 204 { "31.172.IN-ADDR.ARPA", ISC_TRUE }, 205 { "168.192.IN-ADDR.ARPA", ISC_TRUE }, 206#endif 207 208 /* RFC 5735 and RFC 5737 */ 209 { "0.IN-ADDR.ARPA", ISC_FALSE }, /* THIS NETWORK */ 210 { "127.IN-ADDR.ARPA", ISC_FALSE }, /* LOOPBACK */ 211 { "254.169.IN-ADDR.ARPA", ISC_FALSE }, /* LINK LOCAL */ 212 { "2.0.192.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET */ 213 { "100.51.198.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET 2 */ 214 { "113.0.203.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET 3 */ 215 { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE }, /* BROADCAST */ 216 217 /* Local IPv6 Unicast Addresses */ 218 { "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 }, 219 { "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 }, 220 /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ 221 { "D.F.IP6.ARPA", ISC_FALSE }, 222 { "8.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ 223 { "9.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ 224 { "A.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ 225 { "B.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ 226 227 /* Example Prefix, RFC 3849. */ 228 { "8.B.D.0.1.0.0.2.IP6.ARPA", ISC_FALSE }, 229 230 { NULL, ISC_FALSE } 231}; 232 233static void 234fatal(const char *msg, isc_result_t result); 235 236static void 237ns_server_reload(isc_task_t *task, isc_event_t *event); 238 239static isc_result_t 240ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 241 cfg_aclconfctx_t *actx, 242 isc_mem_t *mctx, ns_listenelt_t **target); 243static isc_result_t 244ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 245 cfg_aclconfctx_t *actx, 246 isc_mem_t *mctx, ns_listenlist_t **target); 247 248static isc_result_t 249configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, 250 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype); 251 252static isc_result_t 253configure_alternates(const cfg_obj_t *config, dns_view_t *view, 254 const cfg_obj_t *alternates); 255 256static isc_result_t 257configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 258 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 259 cfg_aclconfctx_t *aclconf); 260 261static void 262end_reserved_dispatches(ns_server_t *server, isc_boolean_t all); 263 264/*% 265 * Configure a single view ACL at '*aclp'. Get its configuration from 266 * 'vconfig' (for per-view configuration) and maybe from 'config' 267 */ 268static isc_result_t 269configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, 270 const char *aclname, cfg_aclconfctx_t *actx, 271 isc_mem_t *mctx, dns_acl_t **aclp) 272{ 273 isc_result_t result; 274 const cfg_obj_t *maps[3]; 275 const cfg_obj_t *aclobj = NULL; 276 int i = 0; 277 278 if (*aclp != NULL) 279 dns_acl_detach(aclp); 280 if (vconfig != NULL) 281 maps[i++] = cfg_tuple_get(vconfig, "options"); 282 if (config != NULL) { 283 const cfg_obj_t *options = NULL; 284 (void)cfg_map_get(config, "options", &options); 285 if (options != NULL) 286 maps[i++] = options; 287 } 288 maps[i] = NULL; 289 290 (void)ns_config_get(maps, aclname, &aclobj); 291 if (aclobj == NULL) 292 /* 293 * No value available. *aclp == NULL. 294 */ 295 return (ISC_R_SUCCESS); 296 297 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, 298 actx, mctx, 0, aclp); 299 300 return (result); 301} 302 303 304/*% 305 * Configure a sortlist at '*aclp'. Essentially the same as 306 * configure_view_acl() except it calls cfg_acl_fromconfig with a 307 * nest_level value of 2. 308 */ 309static isc_result_t 310configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, 311 cfg_aclconfctx_t *actx, isc_mem_t *mctx, 312 dns_acl_t **aclp) 313{ 314 isc_result_t result; 315 const cfg_obj_t *maps[3]; 316 const cfg_obj_t *aclobj = NULL; 317 int i = 0; 318 319 if (*aclp != NULL) 320 dns_acl_detach(aclp); 321 if (vconfig != NULL) 322 maps[i++] = cfg_tuple_get(vconfig, "options"); 323 if (config != NULL) { 324 const cfg_obj_t *options = NULL; 325 (void)cfg_map_get(config, "options", &options); 326 if (options != NULL) 327 maps[i++] = options; 328 } 329 maps[i] = NULL; 330 331 (void)ns_config_get(maps, "sortlist", &aclobj); 332 if (aclobj == NULL) 333 return (ISC_R_SUCCESS); 334 335 /* 336 * Use a nest level of 3 for the "top level" of the sortlist; 337 * this means each entry in the top three levels will be stored 338 * as lists of separate, nested ACLs, rather than merged together 339 * into IP tables as is usually done with ACLs. 340 */ 341 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, 342 actx, mctx, 3, aclp); 343 344 return (result); 345} 346 347static isc_result_t 348configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, 349 dns_keytable_t *keytable, isc_mem_t *mctx) 350{ 351 dns_rdataclass_t viewclass; 352 dns_rdata_dnskey_t keystruct; 353 isc_uint32_t flags, proto, alg; 354 const char *keystr, *keynamestr; 355 unsigned char keydata[4096]; 356 isc_buffer_t keydatabuf; 357 unsigned char rrdata[4096]; 358 isc_buffer_t rrdatabuf; 359 isc_region_t r; 360 dns_fixedname_t fkeyname; 361 dns_name_t *keyname; 362 isc_buffer_t namebuf; 363 isc_result_t result; 364 dst_key_t *dstkey = NULL; 365 366 flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); 367 proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); 368 alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); 369 keyname = dns_fixedname_name(&fkeyname); 370 keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 371 372 if (vconfig == NULL) 373 viewclass = dns_rdataclass_in; 374 else { 375 const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class"); 376 CHECK(ns_config_getclass(classobj, dns_rdataclass_in, 377 &viewclass)); 378 } 379 keystruct.common.rdclass = viewclass; 380 keystruct.common.rdtype = dns_rdatatype_dnskey; 381 /* 382 * The key data in keystruct is not dynamically allocated. 383 */ 384 keystruct.mctx = NULL; 385 386 ISC_LINK_INIT(&keystruct.common, link); 387 388 if (flags > 0xffff) 389 CHECKM(ISC_R_RANGE, "key flags"); 390 if (proto > 0xff) 391 CHECKM(ISC_R_RANGE, "key protocol"); 392 if (alg > 0xff) 393 CHECKM(ISC_R_RANGE, "key algorithm"); 394 keystruct.flags = (isc_uint16_t)flags; 395 keystruct.protocol = (isc_uint8_t)proto; 396 keystruct.algorithm = (isc_uint8_t)alg; 397 398 isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); 399 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 400 401 keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); 402 CHECK(isc_base64_decodestring(keystr, &keydatabuf)); 403 isc_buffer_usedregion(&keydatabuf, &r); 404 keystruct.datalen = r.length; 405 keystruct.data = r.base; 406 407 if ((keystruct.algorithm == DST_ALG_RSASHA1 || 408 keystruct.algorithm == DST_ALG_RSAMD5) && 409 r.length > 1 && r.base[0] == 1 && r.base[1] == 3) 410 cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, 411 "trusted key '%s' has a weak exponent", 412 keynamestr); 413 414 CHECK(dns_rdata_fromstruct(NULL, 415 keystruct.common.rdclass, 416 keystruct.common.rdtype, 417 &keystruct, &rrdatabuf)); 418 dns_fixedname_init(&fkeyname); 419 isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); 420 isc_buffer_add(&namebuf, strlen(keynamestr)); 421 CHECK(dns_name_fromtext(keyname, &namebuf, 422 dns_rootname, ISC_FALSE, 423 NULL)); 424 CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, 425 mctx, &dstkey)); 426 427 CHECK(dns_keytable_add(keytable, &dstkey)); 428 INSIST(dstkey == NULL); 429 return (ISC_R_SUCCESS); 430 431 cleanup: 432 if (result == DST_R_NOCRYPTO) { 433 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 434 "ignoring trusted key for '%s': no crypto support", 435 keynamestr); 436 result = ISC_R_SUCCESS; 437 } else { 438 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 439 "configuring trusted key for '%s': %s", 440 keynamestr, isc_result_totext(result)); 441 result = ISC_R_FAILURE; 442 } 443 444 if (dstkey != NULL) 445 dst_key_free(&dstkey); 446 447 return (result); 448} 449 450/*% 451 * Configure DNSSEC keys for a view. Currently used only for 452 * the security roots. 453 * 454 * The per-view configuration values and the server-global defaults are read 455 * from 'vconfig' and 'config'. The variable to be configured is '*target'. 456 */ 457static isc_result_t 458configure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config, 459 isc_mem_t *mctx, dns_keytable_t **target) 460{ 461 isc_result_t result; 462 const cfg_obj_t *keys = NULL; 463 const cfg_obj_t *voptions = NULL; 464 const cfg_listelt_t *element, *element2; 465 const cfg_obj_t *keylist; 466 const cfg_obj_t *key; 467 dns_keytable_t *keytable = NULL; 468 469 CHECK(dns_keytable_create(mctx, &keytable)); 470 471 if (vconfig != NULL) 472 voptions = cfg_tuple_get(vconfig, "options"); 473 474 keys = NULL; 475 if (voptions != NULL) 476 (void)cfg_map_get(voptions, "trusted-keys", &keys); 477 if (keys == NULL) 478 (void)cfg_map_get(config, "trusted-keys", &keys); 479 480 for (element = cfg_list_first(keys); 481 element != NULL; 482 element = cfg_list_next(element)) 483 { 484 keylist = cfg_listelt_value(element); 485 for (element2 = cfg_list_first(keylist); 486 element2 != NULL; 487 element2 = cfg_list_next(element2)) 488 { 489 key = cfg_listelt_value(element2); 490 CHECK(configure_view_dnsseckey(vconfig, key, 491 keytable, mctx)); 492 } 493 } 494 495 dns_keytable_detach(target); 496 *target = keytable; /* Transfer ownership. */ 497 keytable = NULL; 498 result = ISC_R_SUCCESS; 499 500 cleanup: 501 return (result); 502} 503 504static isc_result_t 505mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) 506{ 507 const cfg_listelt_t *element; 508 const cfg_obj_t *obj; 509 const char *str; 510 dns_fixedname_t fixed; 511 dns_name_t *name; 512 isc_boolean_t value; 513 isc_result_t result; 514 isc_buffer_t b; 515 516 dns_fixedname_init(&fixed); 517 name = dns_fixedname_name(&fixed); 518 for (element = cfg_list_first(mbs); 519 element != NULL; 520 element = cfg_list_next(element)) 521 { 522 obj = cfg_listelt_value(element); 523 str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 524 isc_buffer_init(&b, str, strlen(str)); 525 isc_buffer_add(&b, strlen(str)); 526 CHECK(dns_name_fromtext(name, &b, dns_rootname, 527 ISC_FALSE, NULL)); 528 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); 529 CHECK(dns_resolver_setmustbesecure(resolver, name, value)); 530 } 531 532 result = ISC_R_SUCCESS; 533 534 cleanup: 535 return (result); 536} 537 538/*% 539 * Get a dispatch appropriate for the resolver of a given view. 540 */ 541static isc_result_t 542get_view_querysource_dispatch(const cfg_obj_t **maps, 543 int af, dns_dispatch_t **dispatchp, 544 isc_boolean_t is_firstview) 545{ 546 isc_result_t result; 547 dns_dispatch_t *disp; 548 isc_sockaddr_t sa; 549 unsigned int attrs, attrmask; 550 const cfg_obj_t *obj = NULL; 551 unsigned int maxdispatchbuffers; 552 553 /* 554 * Make compiler happy. 555 */ 556 result = ISC_R_FAILURE; 557 558 switch (af) { 559 case AF_INET: 560 result = ns_config_get(maps, "query-source", &obj); 561 INSIST(result == ISC_R_SUCCESS); 562 break; 563 case AF_INET6: 564 result = ns_config_get(maps, "query-source-v6", &obj); 565 INSIST(result == ISC_R_SUCCESS); 566 break; 567 default: 568 INSIST(0); 569 } 570 571 sa = *(cfg_obj_assockaddr(obj)); 572 INSIST(isc_sockaddr_pf(&sa) == af); 573 574 /* 575 * If we don't support this address family, we're done! 576 */ 577 switch (af) { 578 case AF_INET: 579 result = isc_net_probeipv4(); 580 break; 581 case AF_INET6: 582 result = isc_net_probeipv6(); 583 break; 584 default: 585 INSIST(0); 586 } 587 if (result != ISC_R_SUCCESS) 588 return (ISC_R_SUCCESS); 589 590 /* 591 * Try to find a dispatcher that we can share. 592 */ 593 attrs = 0; 594 attrs |= DNS_DISPATCHATTR_UDP; 595 switch (af) { 596 case AF_INET: 597 attrs |= DNS_DISPATCHATTR_IPV4; 598 break; 599 case AF_INET6: 600 attrs |= DNS_DISPATCHATTR_IPV6; 601 break; 602 } 603 if (isc_sockaddr_getport(&sa) == 0) { 604 attrs |= DNS_DISPATCHATTR_EXCLUSIVE; 605 maxdispatchbuffers = 4096; 606 } else { 607 INSIST(obj != NULL); 608 if (is_firstview) { 609 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO, 610 "using specific query-source port " 611 "suppresses port randomization and can be " 612 "insecure."); 613 } 614 maxdispatchbuffers = 1000; 615 } 616 617 attrmask = 0; 618 attrmask |= DNS_DISPATCHATTR_UDP; 619 attrmask |= DNS_DISPATCHATTR_TCP; 620 attrmask |= DNS_DISPATCHATTR_IPV4; 621 attrmask |= DNS_DISPATCHATTR_IPV6; 622 623 disp = NULL; 624 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, 625 ns_g_taskmgr, &sa, 4096, 626 maxdispatchbuffers, 32768, 16411, 16433, 627 attrs, attrmask, &disp); 628 if (result != ISC_R_SUCCESS) { 629 isc_sockaddr_t any; 630 char buf[ISC_SOCKADDR_FORMATSIZE]; 631 632 switch (af) { 633 case AF_INET: 634 isc_sockaddr_any(&any); 635 break; 636 case AF_INET6: 637 isc_sockaddr_any6(&any); 638 break; 639 } 640 if (isc_sockaddr_equal(&sa, &any)) 641 return (ISC_R_SUCCESS); 642 isc_sockaddr_format(&sa, buf, sizeof(buf)); 643 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 644 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 645 "could not get query source dispatcher (%s)", 646 buf); 647 return (result); 648 } 649 650 *dispatchp = disp; 651 652 return (ISC_R_SUCCESS); 653} 654 655static isc_result_t 656configure_order(dns_order_t *order, const cfg_obj_t *ent) { 657 dns_rdataclass_t rdclass; 658 dns_rdatatype_t rdtype; 659 const cfg_obj_t *obj; 660 dns_fixedname_t fixed; 661 unsigned int mode = 0; 662 const char *str; 663 isc_buffer_t b; 664 isc_result_t result; 665 isc_boolean_t addroot; 666 667 result = ns_config_getclass(cfg_tuple_get(ent, "class"), 668 dns_rdataclass_any, &rdclass); 669 if (result != ISC_R_SUCCESS) 670 return (result); 671 672 result = ns_config_gettype(cfg_tuple_get(ent, "type"), 673 dns_rdatatype_any, &rdtype); 674 if (result != ISC_R_SUCCESS) 675 return (result); 676 677 obj = cfg_tuple_get(ent, "name"); 678 if (cfg_obj_isstring(obj)) 679 str = cfg_obj_asstring(obj); 680 else 681 str = "*"; 682 addroot = ISC_TF(strcmp(str, "*") == 0); 683 isc_buffer_init(&b, str, strlen(str)); 684 isc_buffer_add(&b, strlen(str)); 685 dns_fixedname_init(&fixed); 686 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, 687 dns_rootname, ISC_FALSE, NULL); 688 if (result != ISC_R_SUCCESS) 689 return (result); 690 691 obj = cfg_tuple_get(ent, "ordering"); 692 INSIST(cfg_obj_isstring(obj)); 693 str = cfg_obj_asstring(obj); 694 if (!strcasecmp(str, "fixed")) 695 mode = DNS_RDATASETATTR_FIXEDORDER; 696 else if (!strcasecmp(str, "random")) 697 mode = DNS_RDATASETATTR_RANDOMIZE; 698 else if (!strcasecmp(str, "cyclic")) 699 mode = 0; 700 else 701 INSIST(0); 702 703 /* 704 * "*" should match everything including the root (BIND 8 compat). 705 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a 706 * explicit entry for "." when the name is "*". 707 */ 708 if (addroot) { 709 result = dns_order_add(order, dns_rootname, 710 rdtype, rdclass, mode); 711 if (result != ISC_R_SUCCESS) 712 return (result); 713 } 714 715 return (dns_order_add(order, dns_fixedname_name(&fixed), 716 rdtype, rdclass, mode)); 717} 718 719static isc_result_t 720configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { 721 isc_netaddr_t na; 722 dns_peer_t *peer; 723 const cfg_obj_t *obj; 724 const char *str; 725 isc_result_t result; 726 unsigned int prefixlen; 727 728 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); 729 730 peer = NULL; 731 result = dns_peer_newprefix(mctx, &na, prefixlen, &peer); 732 if (result != ISC_R_SUCCESS) 733 return (result); 734 735 obj = NULL; 736 (void)cfg_map_get(cpeer, "bogus", &obj); 737 if (obj != NULL) 738 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); 739 740 obj = NULL; 741 (void)cfg_map_get(cpeer, "provide-ixfr", &obj); 742 if (obj != NULL) 743 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); 744 745 obj = NULL; 746 (void)cfg_map_get(cpeer, "request-ixfr", &obj); 747 if (obj != NULL) 748 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); 749 750 obj = NULL; 751 (void)cfg_map_get(cpeer, "request-nsid", &obj); 752 if (obj != NULL) 753 CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); 754 755 obj = NULL; 756 (void)cfg_map_get(cpeer, "edns", &obj); 757 if (obj != NULL) 758 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); 759 760 obj = NULL; 761 (void)cfg_map_get(cpeer, "edns-udp-size", &obj); 762 if (obj != NULL) { 763 isc_uint32_t udpsize = cfg_obj_asuint32(obj); 764 if (udpsize < 512) 765 udpsize = 512; 766 if (udpsize > 4096) 767 udpsize = 4096; 768 CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize)); 769 } 770 771 obj = NULL; 772 (void)cfg_map_get(cpeer, "max-udp-size", &obj); 773 if (obj != NULL) { 774 isc_uint32_t udpsize = cfg_obj_asuint32(obj); 775 if (udpsize < 512) 776 udpsize = 512; 777 if (udpsize > 4096) 778 udpsize = 4096; 779 CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize)); 780 } 781 782 obj = NULL; 783 (void)cfg_map_get(cpeer, "transfers", &obj); 784 if (obj != NULL) 785 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); 786 787 obj = NULL; 788 (void)cfg_map_get(cpeer, "transfer-format", &obj); 789 if (obj != NULL) { 790 str = cfg_obj_asstring(obj); 791 if (strcasecmp(str, "many-answers") == 0) 792 CHECK(dns_peer_settransferformat(peer, 793 dns_many_answers)); 794 else if (strcasecmp(str, "one-answer") == 0) 795 CHECK(dns_peer_settransferformat(peer, 796 dns_one_answer)); 797 else 798 INSIST(0); 799 } 800 801 obj = NULL; 802 (void)cfg_map_get(cpeer, "keys", &obj); 803 if (obj != NULL) { 804 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); 805 if (result != ISC_R_SUCCESS) 806 goto cleanup; 807 } 808 809 obj = NULL; 810 if (na.family == AF_INET) 811 (void)cfg_map_get(cpeer, "transfer-source", &obj); 812 else 813 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); 814 if (obj != NULL) { 815 result = dns_peer_settransfersource(peer, 816 cfg_obj_assockaddr(obj)); 817 if (result != ISC_R_SUCCESS) 818 goto cleanup; 819 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 820 } 821 822 obj = NULL; 823 if (na.family == AF_INET) 824 (void)cfg_map_get(cpeer, "notify-source", &obj); 825 else 826 (void)cfg_map_get(cpeer, "notify-source-v6", &obj); 827 if (obj != NULL) { 828 result = dns_peer_setnotifysource(peer, 829 cfg_obj_assockaddr(obj)); 830 if (result != ISC_R_SUCCESS) 831 goto cleanup; 832 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 833 } 834 835 obj = NULL; 836 if (na.family == AF_INET) 837 (void)cfg_map_get(cpeer, "query-source", &obj); 838 else 839 (void)cfg_map_get(cpeer, "query-source-v6", &obj); 840 if (obj != NULL) { 841 result = dns_peer_setquerysource(peer, 842 cfg_obj_assockaddr(obj)); 843 if (result != ISC_R_SUCCESS) 844 goto cleanup; 845 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 846 } 847 848 *peerp = peer; 849 return (ISC_R_SUCCESS); 850 851 cleanup: 852 dns_peer_detach(&peer); 853 return (result); 854} 855 856static isc_result_t 857disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 858 isc_result_t result; 859 const cfg_obj_t *algorithms; 860 const cfg_listelt_t *element; 861 const char *str; 862 dns_fixedname_t fixed; 863 dns_name_t *name; 864 isc_buffer_t b; 865 866 dns_fixedname_init(&fixed); 867 name = dns_fixedname_name(&fixed); 868 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 869 isc_buffer_init(&b, str, strlen(str)); 870 isc_buffer_add(&b, strlen(str)); 871 CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL)); 872 873 algorithms = cfg_tuple_get(disabled, "algorithms"); 874 for (element = cfg_list_first(algorithms); 875 element != NULL; 876 element = cfg_list_next(element)) 877 { 878 isc_textregion_t r; 879 dns_secalg_t alg; 880 881 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base); 882 r.length = strlen(r.base); 883 884 result = dns_secalg_fromtext(&alg, &r); 885 if (result != ISC_R_SUCCESS) { 886 isc_uint8_t ui; 887 result = isc_parse_uint8(&ui, r.base, 10); 888 alg = ui; 889 } 890 if (result != ISC_R_SUCCESS) { 891 cfg_obj_log(cfg_listelt_value(element), 892 ns_g_lctx, ISC_LOG_ERROR, 893 "invalid algorithm"); 894 CHECK(result); 895 } 896 CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); 897 } 898 cleanup: 899 return (result); 900} 901 902static isc_boolean_t 903on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { 904 const cfg_listelt_t *element; 905 dns_fixedname_t fixed; 906 dns_name_t *name; 907 isc_result_t result; 908 const cfg_obj_t *value; 909 const char *str; 910 isc_buffer_t b; 911 912 dns_fixedname_init(&fixed); 913 name = dns_fixedname_name(&fixed); 914 915 for (element = cfg_list_first(disablelist); 916 element != NULL; 917 element = cfg_list_next(element)) 918 { 919 value = cfg_listelt_value(element); 920 str = cfg_obj_asstring(value); 921 isc_buffer_init(&b, str, strlen(str)); 922 isc_buffer_add(&b, strlen(str)); 923 result = dns_name_fromtext(name, &b, dns_rootname, 924 ISC_TRUE, NULL); 925 RUNTIME_CHECK(result == ISC_R_SUCCESS); 926 if (dns_name_equal(name, zonename)) 927 return (ISC_TRUE); 928 } 929 return (ISC_FALSE); 930} 931 932static void 933check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv, 934 isc_mem_t *mctx) 935{ 936 char **argv = NULL; 937 unsigned int i; 938 isc_result_t result; 939 940 result = dns_zone_getdbtype(*zonep, &argv, mctx); 941 if (result != ISC_R_SUCCESS) { 942 dns_zone_detach(zonep); 943 return; 944 } 945 946 /* 947 * Check that all the arguments match. 948 */ 949 for (i = 0; i < dbtypec; i++) 950 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) { 951 dns_zone_detach(zonep); 952 break; 953 } 954 955 /* 956 * Check that there are not extra arguments. 957 */ 958 if (i == dbtypec && argv[i] != NULL) 959 dns_zone_detach(zonep); 960 isc_mem_free(mctx, argv); 961} 962 963static isc_result_t 964setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) { 965 isc_result_t result; 966 isc_stats_t *zoneqrystats; 967 968 zoneqrystats = NULL; 969 if (on) { 970 result = isc_stats_create(mctx, &zoneqrystats, 971 dns_nsstatscounter_max); 972 if (result != ISC_R_SUCCESS) 973 return (result); 974 } 975 dns_zone_setrequeststats(zone, zoneqrystats); 976 if (zoneqrystats != NULL) 977 isc_stats_detach(&zoneqrystats); 978 979 return (ISC_R_SUCCESS); 980} 981 982static isc_boolean_t 983cache_reusable(dns_view_t *originview, dns_view_t *view, 984 isc_boolean_t new_zero_no_soattl) 985{ 986 if (originview->checknames != view->checknames || 987 dns_resolver_getzeronosoattl(originview->resolver) != 988 new_zero_no_soattl || 989 originview->acceptexpired != view->acceptexpired || 990 originview->enablevalidation != view->enablevalidation || 991 originview->maxcachettl != view->maxcachettl || 992 originview->maxncachettl != view->maxncachettl) { 993 return (ISC_FALSE); 994 } 995 996 return (ISC_TRUE); 997} 998 999/* 1000 * Configure 'view' according to 'vconfig', taking defaults from 'config' 1001 * where values are missing in 'vconfig'. 1002 * 1003 * When configuring the default view, 'vconfig' will be NULL and the 1004 * global defaults in 'config' used exclusively. 1005 */ 1006static isc_result_t 1007configure_view(dns_view_t *view, const cfg_obj_t *config, 1008 const cfg_obj_t *vconfig, isc_mem_t *mctx, 1009 cfg_aclconfctx_t *actx, isc_boolean_t need_hints) 1010{ 1011 const cfg_obj_t *maps[4]; 1012 const cfg_obj_t *cfgmaps[3]; 1013 const cfg_obj_t *options = NULL; 1014 const cfg_obj_t *voptions = NULL; 1015 const cfg_obj_t *forwardtype; 1016 const cfg_obj_t *forwarders; 1017 const cfg_obj_t *alternates; 1018 const cfg_obj_t *zonelist; 1019#ifdef DLZ 1020 const cfg_obj_t *dlz; 1021 unsigned int dlzargc; 1022 char **dlzargv; 1023#endif 1024 const cfg_obj_t *disabled; 1025 const cfg_obj_t *obj; 1026 const cfg_listelt_t *element; 1027 in_port_t port; 1028 dns_cache_t *cache = NULL; 1029 isc_result_t result; 1030 isc_uint32_t max_adb_size; 1031 isc_uint32_t max_cache_size; 1032 isc_uint32_t max_acache_size; 1033 isc_uint32_t lame_ttl; 1034 dns_tsig_keyring_t *ring; 1035 dns_view_t *pview = NULL; /* Production view */ 1036 isc_mem_t *cmctx; 1037 dns_dispatch_t *dispatch4 = NULL; 1038 dns_dispatch_t *dispatch6 = NULL; 1039 isc_boolean_t reused_cache = ISC_FALSE; 1040 int i; 1041 const char *str; 1042 dns_order_t *order = NULL; 1043 isc_uint32_t udpsize; 1044 unsigned int resopts = 0; 1045 dns_zone_t *zone = NULL; 1046 isc_uint32_t max_clients_per_query; 1047 const char *sep = ": view "; 1048 const char *viewname = view->name; 1049 const char *forview = " for view "; 1050 isc_boolean_t rfc1918; 1051 isc_boolean_t empty_zones_enable; 1052 const cfg_obj_t *disablelist = NULL; 1053 isc_stats_t *resstats = NULL; 1054 dns_stats_t *resquerystats = NULL; 1055 isc_boolean_t zero_no_soattl; 1056 1057 REQUIRE(DNS_VIEW_VALID(view)); 1058 1059 cmctx = NULL; 1060 1061 if (config != NULL) 1062 (void)cfg_map_get(config, "options", &options); 1063 1064 i = 0; 1065 if (vconfig != NULL) { 1066 voptions = cfg_tuple_get(vconfig, "options"); 1067 maps[i++] = voptions; 1068 } 1069 if (options != NULL) 1070 maps[i++] = options; 1071 maps[i++] = ns_g_defaults; 1072 maps[i] = NULL; 1073 1074 i = 0; 1075 if (voptions != NULL) 1076 cfgmaps[i++] = voptions; 1077 if (config != NULL) 1078 cfgmaps[i++] = config; 1079 cfgmaps[i] = NULL; 1080 1081 if (!strcmp(viewname, "_default")) { 1082 sep = ""; 1083 viewname = ""; 1084 forview = ""; 1085 } 1086 1087 /* 1088 * Set the view's port number for outgoing queries. 1089 */ 1090 CHECKM(ns_config_getport(config, &port), "port"); 1091 dns_view_setdstport(view, port); 1092 1093 /* 1094 * Create additional cache for this view and zones under the view 1095 * if explicitly enabled. 1096 * XXX950 default to on. 1097 */ 1098 obj = NULL; 1099 (void)ns_config_get(maps, "acache-enable", &obj); 1100 if (obj != NULL && cfg_obj_asboolean(obj)) { 1101 cmctx = NULL; 1102 CHECK(isc_mem_create(0, 0, &cmctx)); 1103 CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr, 1104 ns_g_timermgr)); 1105 isc_mem_setname(cmctx, "acache", NULL); 1106 isc_mem_detach(&cmctx); 1107 } 1108 if (view->acache != NULL) { 1109 obj = NULL; 1110 result = ns_config_get(maps, "acache-cleaning-interval", &obj); 1111 INSIST(result == ISC_R_SUCCESS); 1112 dns_acache_setcleaninginterval(view->acache, 1113 cfg_obj_asuint32(obj) * 60); 1114 1115 obj = NULL; 1116 result = ns_config_get(maps, "max-acache-size", &obj); 1117 INSIST(result == ISC_R_SUCCESS); 1118 if (cfg_obj_isstring(obj)) { 1119 str = cfg_obj_asstring(obj); 1120 INSIST(strcasecmp(str, "unlimited") == 0); 1121 max_acache_size = ISC_UINT32_MAX; 1122 } else { 1123 isc_resourcevalue_t value; 1124 1125 value = cfg_obj_asuint64(obj); 1126 if (value > ISC_UINT32_MAX) { 1127 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 1128 "'max-acache-size " 1129 "%" ISC_PRINT_QUADFORMAT 1130 "d' is too large", 1131 value); 1132 result = ISC_R_RANGE; 1133 goto cleanup; 1134 } 1135 max_acache_size = (isc_uint32_t)value; 1136 } 1137 dns_acache_setcachesize(view->acache, max_acache_size); 1138 } 1139 1140 CHECK(configure_view_acl(vconfig, config, "allow-query", actx, 1141 ns_g_mctx, &view->queryacl)); 1142 1143 if (view->queryacl == NULL) { 1144 CHECK(configure_view_acl(NULL, ns_g_config, "allow-query", actx, 1145 ns_g_mctx, &view->queryacl)); 1146 } 1147 1148 /* 1149 * Configure the zones. 1150 */ 1151 zonelist = NULL; 1152 if (voptions != NULL) 1153 (void)cfg_map_get(voptions, "zone", &zonelist); 1154 else 1155 (void)cfg_map_get(config, "zone", &zonelist); 1156 for (element = cfg_list_first(zonelist); 1157 element != NULL; 1158 element = cfg_list_next(element)) 1159 { 1160 const cfg_obj_t *zconfig = cfg_listelt_value(element); 1161 CHECK(configure_zone(config, zconfig, vconfig, mctx, view, 1162 actx)); 1163 } 1164 1165#ifdef DLZ 1166 /* 1167 * Create Dynamically Loadable Zone driver. 1168 */ 1169 dlz = NULL; 1170 if (voptions != NULL) 1171 (void)cfg_map_get(voptions, "dlz", &dlz); 1172 else 1173 (void)cfg_map_get(config, "dlz", &dlz); 1174 1175 obj = NULL; 1176 if (dlz != NULL) { 1177 (void)cfg_map_get(cfg_tuple_get(dlz, "options"), 1178 "database", &obj); 1179 if (obj != NULL) { 1180 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 1181 if (s == NULL) { 1182 result = ISC_R_NOMEMORY; 1183 goto cleanup; 1184 } 1185 1186 result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv); 1187 if (result != ISC_R_SUCCESS) { 1188 isc_mem_free(mctx, s); 1189 goto cleanup; 1190 } 1191 1192 obj = cfg_tuple_get(dlz, "name"); 1193 result = dns_dlzcreate(mctx, cfg_obj_asstring(obj), 1194 dlzargv[0], dlzargc, dlzargv, 1195 &view->dlzdatabase); 1196 isc_mem_free(mctx, s); 1197 isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv)); 1198 if (result != ISC_R_SUCCESS) 1199 goto cleanup; 1200 } 1201 } 1202#endif 1203 1204 /* 1205 * Obtain configuration parameters that affect the decision of whether 1206 * we can reuse/share an existing cache. 1207 */ 1208 /* Check-names. */ 1209 obj = NULL; 1210 result = ns_checknames_get(maps, "response", &obj); 1211 INSIST(result == ISC_R_SUCCESS); 1212 1213 str = cfg_obj_asstring(obj); 1214 if (strcasecmp(str, "fail") == 0) { 1215 resopts |= DNS_RESOLVER_CHECKNAMES | 1216 DNS_RESOLVER_CHECKNAMESFAIL; 1217 view->checknames = ISC_TRUE; 1218 } else if (strcasecmp(str, "warn") == 0) { 1219 resopts |= DNS_RESOLVER_CHECKNAMES; 1220 view->checknames = ISC_FALSE; 1221 } else if (strcasecmp(str, "ignore") == 0) { 1222 view->checknames = ISC_FALSE; 1223 } else 1224 INSIST(0); 1225 1226 obj = NULL; 1227 result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj); 1228 INSIST(result == ISC_R_SUCCESS); 1229 zero_no_soattl = cfg_obj_asboolean(obj); 1230 1231 obj = NULL; 1232 result = ns_config_get(maps, "dnssec-accept-expired", &obj); 1233 INSIST(result == ISC_R_SUCCESS); 1234 view->acceptexpired = cfg_obj_asboolean(obj); 1235 1236 obj = NULL; 1237 result = ns_config_get(maps, "dnssec-validation", &obj); 1238 INSIST(result == ISC_R_SUCCESS); 1239 view->enablevalidation = cfg_obj_asboolean(obj); 1240 1241 obj = NULL; 1242 result = ns_config_get(maps, "max-cache-ttl", &obj); 1243 INSIST(result == ISC_R_SUCCESS); 1244 view->maxcachettl = cfg_obj_asuint32(obj); 1245 1246 obj = NULL; 1247 result = ns_config_get(maps, "max-ncache-ttl", &obj); 1248 INSIST(result == ISC_R_SUCCESS); 1249 view->maxncachettl = cfg_obj_asuint32(obj); 1250 if (view->maxncachettl > 7 * 24 * 3600) 1251 view->maxncachettl = 7 * 24 * 3600; 1252 1253 /* 1254 * Configure the view's cache. Try to reuse an existing 1255 * cache if possible, otherwise create a new cache. 1256 * Note that the ADB is not preserved in either case. 1257 * When a matching view is found, the associated statistics are 1258 * also retrieved and reused. 1259 * 1260 * XXX Determining when it is safe to reuse a cache is tricky. 1261 * When the view's configuration changes, the cached data may become 1262 * invalid because it reflects our old view of the world. We check 1263 * some of the configuration parameters that could invalidate the cache, 1264 * but there are other configuration options that should be checked. 1265 * For example, if a view uses a forwarder, changes in the forwarder 1266 * configuration may invalidate the cache. At the moment, it's the 1267 * administrator's responsibility to ensure these configuration options 1268 * don't invalidate reusing. 1269 */ 1270 result = dns_viewlist_find(&ns_g_server->viewlist, 1271 view->name, view->rdclass, 1272 &pview); 1273 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 1274 goto cleanup; 1275 if (pview != NULL) { 1276 if (cache_reusable(pview, view, zero_no_soattl)) { 1277 INSIST(pview->cache != NULL); 1278 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1279 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3), 1280 "reusing existing cache"); 1281 reused_cache = ISC_TRUE; 1282 dns_cache_attach(pview->cache, &cache); 1283 } else { 1284 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1285 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 1286 "cache cannot be reused for view %s " 1287 "due to configuration parameter mismatch", 1288 view->name); 1289 } 1290 dns_view_getresstats(pview, &resstats); 1291 dns_view_getresquerystats(pview, &resquerystats); 1292 dns_view_detach(&pview); 1293 } 1294 if (cache == NULL) { 1295 CHECK(isc_mem_create(0, 0, &cmctx)); 1296 CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr, 1297 view->rdclass, "rbt", 0, NULL, &cache)); 1298 isc_mem_setname(cmctx, "cache", NULL); 1299 } 1300 dns_view_setcache(view, cache); 1301 1302 /* 1303 * cache-file cannot be inherited if views are present, but this 1304 * should be caught by the configuration checking stage. 1305 */ 1306 obj = NULL; 1307 result = ns_config_get(maps, "cache-file", &obj); 1308 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) { 1309 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj))); 1310 if (!reused_cache) 1311 CHECK(dns_cache_load(cache)); 1312 } 1313 1314 obj = NULL; 1315 result = ns_config_get(maps, "cleaning-interval", &obj); 1316 INSIST(result == ISC_R_SUCCESS); 1317 dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60); 1318 1319 obj = NULL; 1320 result = ns_config_get(maps, "max-cache-size", &obj); 1321 INSIST(result == ISC_R_SUCCESS); 1322 if (cfg_obj_isstring(obj)) { 1323 str = cfg_obj_asstring(obj); 1324 INSIST(strcasecmp(str, "unlimited") == 0); 1325 max_cache_size = ISC_UINT32_MAX; 1326 } else { 1327 isc_resourcevalue_t value; 1328 value = cfg_obj_asuint64(obj); 1329 if (value > ISC_UINT32_MAX) { 1330 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 1331 "'max-cache-size " 1332 "%" ISC_PRINT_QUADFORMAT "d' is too large", 1333 value); 1334 result = ISC_R_RANGE; 1335 goto cleanup; 1336 } 1337 max_cache_size = (isc_uint32_t)value; 1338 } 1339 dns_cache_setcachesize(cache, max_cache_size); 1340 1341 dns_cache_detach(&cache); 1342 1343 /* 1344 * Resolver. 1345 * 1346 * XXXRTH Hardwired number of tasks. 1347 */ 1348 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4, 1349 ISC_TF(ISC_LIST_PREV(view, link) 1350 == NULL))); 1351 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6, 1352 ISC_TF(ISC_LIST_PREV(view, link) 1353 == NULL))); 1354 if (dispatch4 == NULL && dispatch6 == NULL) { 1355 UNEXPECTED_ERROR(__FILE__, __LINE__, 1356 "unable to obtain neither an IPv4 nor" 1357 " an IPv6 dispatch"); 1358 result = ISC_R_UNEXPECTED; 1359 goto cleanup; 1360 } 1361 CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, 1362 ns_g_socketmgr, ns_g_timermgr, 1363 resopts, ns_g_dispatchmgr, 1364 dispatch4, dispatch6)); 1365 1366 if (resstats == NULL) { 1367 CHECK(isc_stats_create(mctx, &resstats, 1368 dns_resstatscounter_max)); 1369 } 1370 dns_view_setresstats(view, resstats); 1371 if (resquerystats == NULL) 1372 CHECK(dns_rdatatypestats_create(mctx, &resquerystats)); 1373 dns_view_setresquerystats(view, resquerystats); 1374 1375 /* 1376 * Set the ADB cache size to 1/8th of the max-cache-size. 1377 */ 1378 max_adb_size = 0; 1379 if (max_cache_size != 0) { 1380 max_adb_size = max_cache_size / 8; 1381 if (max_adb_size == 0) 1382 max_adb_size = 1; /* Force minimum. */ 1383 } 1384 dns_adb_setadbsize(view->adb, max_adb_size); 1385 1386 /* 1387 * Set resolver's lame-ttl. 1388 */ 1389 obj = NULL; 1390 result = ns_config_get(maps, "lame-ttl", &obj); 1391 INSIST(result == ISC_R_SUCCESS); 1392 lame_ttl = cfg_obj_asuint32(obj); 1393 if (lame_ttl > 1800) 1394 lame_ttl = 1800; 1395 dns_resolver_setlamettl(view->resolver, lame_ttl); 1396 1397 /* 1398 * Set the resolver's EDNS UDP size. 1399 */ 1400 obj = NULL; 1401 result = ns_config_get(maps, "edns-udp-size", &obj); 1402 INSIST(result == ISC_R_SUCCESS); 1403 udpsize = cfg_obj_asuint32(obj); 1404 if (udpsize < 512) 1405 udpsize = 512; 1406 if (udpsize > 4096) 1407 udpsize = 4096; 1408 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize); 1409 1410 /* 1411 * Set the maximum UDP response size. 1412 */ 1413 obj = NULL; 1414 result = ns_config_get(maps, "max-udp-size", &obj); 1415 INSIST(result == ISC_R_SUCCESS); 1416 udpsize = cfg_obj_asuint32(obj); 1417 if (udpsize < 512) 1418 udpsize = 512; 1419 if (udpsize > 4096) 1420 udpsize = 4096; 1421 view->maxudp = udpsize; 1422 1423 /* 1424 * Set supported DNSSEC algorithms. 1425 */ 1426 dns_resolver_reset_algorithms(view->resolver); 1427 disabled = NULL; 1428 (void)ns_config_get(maps, "disable-algorithms", &disabled); 1429 if (disabled != NULL) { 1430 for (element = cfg_list_first(disabled); 1431 element != NULL; 1432 element = cfg_list_next(element)) 1433 CHECK(disable_algorithms(cfg_listelt_value(element), 1434 view->resolver)); 1435 } 1436 1437 /* 1438 * A global or view "forwarders" option, if present, 1439 * creates an entry for "." in the forwarding table. 1440 */ 1441 forwardtype = NULL; 1442 forwarders = NULL; 1443 (void)ns_config_get(maps, "forward", &forwardtype); 1444 (void)ns_config_get(maps, "forwarders", &forwarders); 1445 if (forwarders != NULL) 1446 CHECK(configure_forward(config, view, dns_rootname, 1447 forwarders, forwardtype)); 1448 1449 /* 1450 * Dual Stack Servers. 1451 */ 1452 alternates = NULL; 1453 (void)ns_config_get(maps, "dual-stack-servers", &alternates); 1454 if (alternates != NULL) 1455 CHECK(configure_alternates(config, view, alternates)); 1456 1457 /* 1458 * We have default hints for class IN if we need them. 1459 */ 1460 if (view->rdclass == dns_rdataclass_in && view->hints == NULL) 1461 dns_view_sethints(view, ns_g_server->in_roothints); 1462 1463 /* 1464 * If we still have no hints, this is a non-IN view with no 1465 * "hints zone" configured. Issue a warning, except if this 1466 * is a root server. Root servers never need to consult 1467 * their hints, so it's no point requiring users to configure 1468 * them. 1469 */ 1470 if (view->hints == NULL) { 1471 dns_zone_t *rootzone = NULL; 1472 (void)dns_view_findzone(view, dns_rootname, &rootzone); 1473 if (rootzone != NULL) { 1474 dns_zone_detach(&rootzone); 1475 need_hints = ISC_FALSE; 1476 } 1477 if (need_hints) 1478 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1479 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 1480 "no root hints for view '%s'", 1481 view->name); 1482 } 1483 1484 /* 1485 * Configure the view's TSIG keys. 1486 */ 1487 ring = NULL; 1488 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); 1489 dns_view_setkeyring(view, ring); 1490 1491 /* 1492 * Configure the view's peer list. 1493 */ 1494 { 1495 const cfg_obj_t *peers = NULL; 1496 const cfg_listelt_t *element; 1497 dns_peerlist_t *newpeers = NULL; 1498 1499 (void)ns_config_get(cfgmaps, "server", &peers); 1500 CHECK(dns_peerlist_new(mctx, &newpeers)); 1501 for (element = cfg_list_first(peers); 1502 element != NULL; 1503 element = cfg_list_next(element)) 1504 { 1505 const cfg_obj_t *cpeer = cfg_listelt_value(element); 1506 dns_peer_t *peer; 1507 1508 CHECK(configure_peer(cpeer, mctx, &peer)); 1509 dns_peerlist_addpeer(newpeers, peer); 1510 dns_peer_detach(&peer); 1511 } 1512 dns_peerlist_detach(&view->peers); 1513 view->peers = newpeers; /* Transfer ownership. */ 1514 } 1515 1516 /* 1517 * Configure the views rrset-order. 1518 */ 1519 { 1520 const cfg_obj_t *rrsetorder = NULL; 1521 const cfg_listelt_t *element; 1522 1523 (void)ns_config_get(maps, "rrset-order", &rrsetorder); 1524 CHECK(dns_order_create(mctx, &order)); 1525 for (element = cfg_list_first(rrsetorder); 1526 element != NULL; 1527 element = cfg_list_next(element)) 1528 { 1529 const cfg_obj_t *ent = cfg_listelt_value(element); 1530 1531 CHECK(configure_order(order, ent)); 1532 } 1533 if (view->order != NULL) 1534 dns_order_detach(&view->order); 1535 dns_order_attach(order, &view->order); 1536 dns_order_detach(&order); 1537 } 1538 /* 1539 * Copy the aclenv object. 1540 */ 1541 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv); 1542 1543 /* 1544 * Configure the "match-clients" and "match-destinations" ACL. 1545 */ 1546 CHECK(configure_view_acl(vconfig, config, "match-clients", actx, 1547 ns_g_mctx, &view->matchclients)); 1548 CHECK(configure_view_acl(vconfig, config, "match-destinations", actx, 1549 ns_g_mctx, &view->matchdestinations)); 1550 1551 /* 1552 * Configure the "match-recursive-only" option. 1553 */ 1554 obj = NULL; 1555 (void)ns_config_get(maps, "match-recursive-only", &obj); 1556 if (obj != NULL && cfg_obj_asboolean(obj)) 1557 view->matchrecursiveonly = ISC_TRUE; 1558 else 1559 view->matchrecursiveonly = ISC_FALSE; 1560 1561 /* 1562 * Configure other configurable data. 1563 */ 1564 obj = NULL; 1565 result = ns_config_get(maps, "recursion", &obj); 1566 INSIST(result == ISC_R_SUCCESS); 1567 view->recursion = cfg_obj_asboolean(obj); 1568 1569 obj = NULL; 1570 result = ns_config_get(maps, "auth-nxdomain", &obj); 1571 INSIST(result == ISC_R_SUCCESS); 1572 view->auth_nxdomain = cfg_obj_asboolean(obj); 1573 1574 obj = NULL; 1575 result = ns_config_get(maps, "minimal-responses", &obj); 1576 INSIST(result == ISC_R_SUCCESS); 1577 view->minimalresponses = cfg_obj_asboolean(obj); 1578 1579 obj = NULL; 1580 result = ns_config_get(maps, "transfer-format", &obj); 1581 INSIST(result == ISC_R_SUCCESS); 1582 str = cfg_obj_asstring(obj); 1583 if (strcasecmp(str, "many-answers") == 0) 1584 view->transfer_format = dns_many_answers; 1585 else if (strcasecmp(str, "one-answer") == 0) 1586 view->transfer_format = dns_one_answer; 1587 else 1588 INSIST(0); 1589 1590 /* 1591 * Set sources where additional data and CNAME/DNAME 1592 * targets for authoritative answers may be found. 1593 */ 1594 obj = NULL; 1595 result = ns_config_get(maps, "additional-from-auth", &obj); 1596 INSIST(result == ISC_R_SUCCESS); 1597 view->additionalfromauth = cfg_obj_asboolean(obj); 1598 if (view->recursion && ! view->additionalfromauth) { 1599 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 1600 "'additional-from-auth no' is only supported " 1601 "with 'recursion no'"); 1602 view->additionalfromauth = ISC_TRUE; 1603 } 1604 1605 obj = NULL; 1606 result = ns_config_get(maps, "additional-from-cache", &obj); 1607 INSIST(result == ISC_R_SUCCESS); 1608 view->additionalfromcache = cfg_obj_asboolean(obj); 1609 if (view->recursion && ! view->additionalfromcache) { 1610 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 1611 "'additional-from-cache no' is only supported " 1612 "with 'recursion no'"); 1613 view->additionalfromcache = ISC_TRUE; 1614 } 1615 1616 /* 1617 * Set "allow-query-cache", "allow-query-cache-on", 1618 * "allow-recursion", and "allow-recursion-on" acls if 1619 * configured in named.conf. 1620 */ 1621 CHECK(configure_view_acl(vconfig, config, "allow-query-cache", 1622 actx, ns_g_mctx, &view->cacheacl)); 1623 CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", 1624 actx, ns_g_mctx, &view->cacheonacl)); 1625 if (view->cacheonacl == NULL) 1626 CHECK(configure_view_acl(NULL, ns_g_config, 1627 "allow-query-cache-on", actx, 1628 ns_g_mctx, &view->cacheonacl)); 1629 if (strcmp(view->name, "_bind") != 0) { 1630 CHECK(configure_view_acl(vconfig, config, "allow-recursion", 1631 actx, ns_g_mctx, 1632 &view->recursionacl)); 1633 CHECK(configure_view_acl(vconfig, config, "allow-recursion-on", 1634 actx, ns_g_mctx, 1635 &view->recursiononacl)); 1636 } 1637 1638 /* 1639 * "allow-query-cache" inherits from "allow-recursion" if set, 1640 * otherwise from "allow-query" if set. 1641 * "allow-recursion" inherits from "allow-query-cache" if set, 1642 * otherwise from "allow-query" if set. 1643 */ 1644 if (view->cacheacl == NULL && view->recursionacl != NULL) 1645 dns_acl_attach(view->recursionacl, &view->cacheacl); 1646 if (view->cacheacl == NULL && view->recursion) 1647 CHECK(configure_view_acl(vconfig, config, "allow-query", 1648 actx, ns_g_mctx, &view->cacheacl)); 1649 if (view->recursion && 1650 view->recursionacl == NULL && view->cacheacl != NULL) 1651 dns_acl_attach(view->cacheacl, &view->recursionacl); 1652 1653 /* 1654 * Set default "allow-recursion", "allow-recursion-on" and 1655 * "allow-query-cache" acls. 1656 */ 1657 if (view->recursionacl == NULL && view->recursion) 1658 CHECK(configure_view_acl(NULL, ns_g_config, 1659 "allow-recursion", 1660 actx, ns_g_mctx, 1661 &view->recursionacl)); 1662 if (view->recursiononacl == NULL && view->recursion) 1663 CHECK(configure_view_acl(NULL, ns_g_config, 1664 "allow-recursion-on", 1665 actx, ns_g_mctx, 1666 &view->recursiononacl)); 1667 if (view->cacheacl == NULL) { 1668 if (view->recursion) 1669 CHECK(configure_view_acl(NULL, ns_g_config, 1670 "allow-query-cache", actx, 1671 ns_g_mctx, &view->cacheacl)); 1672 else 1673 CHECK(dns_acl_none(ns_g_mctx, &view->cacheacl)); 1674 } 1675 1676 /* 1677 * Configure sortlist, if set 1678 */ 1679 CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx, 1680 &view->sortlist)); 1681 1682 /* 1683 * Configure default allow-transfer, allow-notify, allow-update 1684 * and allow-update-forwarding ACLs, if set, so they can be 1685 * inherited by zones. 1686 */ 1687 if (view->notifyacl == NULL) 1688 CHECK(configure_view_acl(NULL, ns_g_config, 1689 "allow-notify", actx, 1690 ns_g_mctx, &view->notifyacl)); 1691 if (view->transferacl == NULL) 1692 CHECK(configure_view_acl(NULL, ns_g_config, 1693 "allow-transfer", actx, 1694 ns_g_mctx, &view->transferacl)); 1695 if (view->updateacl == NULL) 1696 CHECK(configure_view_acl(NULL, ns_g_config, 1697 "allow-update", actx, 1698 ns_g_mctx, &view->updateacl)); 1699 if (view->upfwdacl == NULL) 1700 CHECK(configure_view_acl(NULL, ns_g_config, 1701 "allow-update-forwarding", actx, 1702 ns_g_mctx, &view->upfwdacl)); 1703 1704 obj = NULL; 1705 result = ns_config_get(maps, "request-ixfr", &obj); 1706 INSIST(result == ISC_R_SUCCESS); 1707 view->requestixfr = cfg_obj_asboolean(obj); 1708 1709 obj = NULL; 1710 result = ns_config_get(maps, "provide-ixfr", &obj); 1711 INSIST(result == ISC_R_SUCCESS); 1712 view->provideixfr = cfg_obj_asboolean(obj); 1713 1714 obj = NULL; 1715 result = ns_config_get(maps, "request-nsid", &obj); 1716 INSIST(result == ISC_R_SUCCESS); 1717 view->requestnsid = cfg_obj_asboolean(obj); 1718 1719 obj = NULL; 1720 result = ns_config_get(maps, "max-clients-per-query", &obj); 1721 INSIST(result == ISC_R_SUCCESS); 1722 max_clients_per_query = cfg_obj_asuint32(obj); 1723 1724 obj = NULL; 1725 result = ns_config_get(maps, "clients-per-query", &obj); 1726 INSIST(result == ISC_R_SUCCESS); 1727 dns_resolver_setclientsperquery(view->resolver, 1728 cfg_obj_asuint32(obj), 1729 max_clients_per_query); 1730 1731 obj = NULL; 1732 result = ns_config_get(maps, "dnssec-enable", &obj); 1733 INSIST(result == ISC_R_SUCCESS); 1734 view->enablednssec = cfg_obj_asboolean(obj); 1735 1736 obj = NULL; 1737 result = ns_config_get(maps, "dnssec-lookaside", &obj); 1738 if (result == ISC_R_SUCCESS) { 1739 for (element = cfg_list_first(obj); 1740 element != NULL; 1741 element = cfg_list_next(element)) 1742 { 1743 const char *str; 1744 isc_buffer_t b; 1745 dns_name_t *dlv; 1746 1747 obj = cfg_listelt_value(element); 1748#if 0 1749 dns_fixedname_t fixed; 1750 dns_name_t *name; 1751 1752 /* 1753 * When we support multiple dnssec-lookaside 1754 * entries this is how to find the domain to be 1755 * checked. XXXMPA 1756 */ 1757 dns_fixedname_init(&fixed); 1758 name = dns_fixedname_name(&fixed); 1759 str = cfg_obj_asstring(cfg_tuple_get(obj, 1760 "domain")); 1761 isc_buffer_init(&b, str, strlen(str)); 1762 isc_buffer_add(&b, strlen(str)); 1763 CHECK(dns_name_fromtext(name, &b, dns_rootname, 1764 ISC_TRUE, NULL)); 1765#endif 1766 str = cfg_obj_asstring(cfg_tuple_get(obj, 1767 "trust-anchor")); 1768 isc_buffer_init(&b, str, strlen(str)); 1769 isc_buffer_add(&b, strlen(str)); 1770 dlv = dns_fixedname_name(&view->dlv_fixed); 1771 CHECK(dns_name_fromtext(dlv, &b, dns_rootname, 1772 ISC_TRUE, NULL)); 1773 view->dlv = dns_fixedname_name(&view->dlv_fixed); 1774 } 1775 } else 1776 view->dlv = NULL; 1777 1778 /* 1779 * For now, there is only one kind of trusted keys, the 1780 * "security roots". 1781 */ 1782 CHECK(configure_view_dnsseckeys(vconfig, config, mctx, 1783 &view->secroots)); 1784 dns_resolver_resetmustbesecure(view->resolver); 1785 obj = NULL; 1786 result = ns_config_get(maps, "dnssec-must-be-secure", &obj); 1787 if (result == ISC_R_SUCCESS) 1788 CHECK(mustbesecure(obj, view->resolver)); 1789 1790 obj = NULL; 1791 result = ns_config_get(maps, "preferred-glue", &obj); 1792 if (result == ISC_R_SUCCESS) { 1793 str = cfg_obj_asstring(obj); 1794 if (strcasecmp(str, "a") == 0) 1795 view->preferred_glue = dns_rdatatype_a; 1796 else if (strcasecmp(str, "aaaa") == 0) 1797 view->preferred_glue = dns_rdatatype_aaaa; 1798 else 1799 view->preferred_glue = 0; 1800 } else 1801 view->preferred_glue = 0; 1802 1803 obj = NULL; 1804 result = ns_config_get(maps, "root-delegation-only", &obj); 1805 if (result == ISC_R_SUCCESS) { 1806 dns_view_setrootdelonly(view, ISC_TRUE); 1807 if (!cfg_obj_isvoid(obj)) { 1808 dns_fixedname_t fixed; 1809 dns_name_t *name; 1810 isc_buffer_t b; 1811 const char *str; 1812 const cfg_obj_t *exclude; 1813 1814 dns_fixedname_init(&fixed); 1815 name = dns_fixedname_name(&fixed); 1816 for (element = cfg_list_first(obj); 1817 element != NULL; 1818 element = cfg_list_next(element)) { 1819 exclude = cfg_listelt_value(element); 1820 str = cfg_obj_asstring(exclude); 1821 isc_buffer_init(&b, str, strlen(str)); 1822 isc_buffer_add(&b, strlen(str)); 1823 CHECK(dns_name_fromtext(name, &b, dns_rootname, 1824 ISC_FALSE, NULL)); 1825 CHECK(dns_view_excludedelegationonly(view, 1826 name)); 1827 } 1828 } 1829 } else 1830 dns_view_setrootdelonly(view, ISC_FALSE); 1831 1832 /* 1833 * Setup automatic empty zones. If recursion is off then 1834 * they are disabled by default. 1835 */ 1836 obj = NULL; 1837 (void)ns_config_get(maps, "empty-zones-enable", &obj); 1838 (void)ns_config_get(maps, "disable-empty-zone", &disablelist); 1839 if (obj == NULL && disablelist == NULL && 1840 view->rdclass == dns_rdataclass_in) { 1841 rfc1918 = ISC_FALSE; 1842 empty_zones_enable = view->recursion; 1843 } else if (view->rdclass == dns_rdataclass_in) { 1844 rfc1918 = ISC_TRUE; 1845 if (obj != NULL) 1846 empty_zones_enable = cfg_obj_asboolean(obj); 1847 else 1848 empty_zones_enable = view->recursion; 1849 } else { 1850 rfc1918 = ISC_FALSE; 1851 empty_zones_enable = ISC_FALSE; 1852 } 1853 if (empty_zones_enable) { 1854 const char *empty; 1855 int empty_zone = 0; 1856 dns_fixedname_t fixed; 1857 dns_name_t *name; 1858 isc_buffer_t buffer; 1859 const char *str; 1860 char server[DNS_NAME_FORMATSIZE + 1]; 1861 char contact[DNS_NAME_FORMATSIZE + 1]; 1862 isc_boolean_t logit; 1863 const char *empty_dbtype[4] = 1864 { "_builtin", "empty", NULL, NULL }; 1865 int empty_dbtypec = 4; 1866 isc_boolean_t zonestats_on; 1867 1868 dns_fixedname_init(&fixed); 1869 name = dns_fixedname_name(&fixed); 1870 1871 obj = NULL; 1872 result = ns_config_get(maps, "empty-server", &obj); 1873 if (result == ISC_R_SUCCESS) { 1874 str = cfg_obj_asstring(obj); 1875 isc_buffer_init(&buffer, str, strlen(str)); 1876 isc_buffer_add(&buffer, strlen(str)); 1877 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 1878 ISC_FALSE, NULL)); 1879 isc_buffer_init(&buffer, server, sizeof(server) - 1); 1880 CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); 1881 server[isc_buffer_usedlength(&buffer)] = 0; 1882 empty_dbtype[2] = server; 1883 } else 1884 empty_dbtype[2] = "@"; 1885 1886 obj = NULL; 1887 result = ns_config_get(maps, "empty-contact", &obj); 1888 if (result == ISC_R_SUCCESS) { 1889 str = cfg_obj_asstring(obj); 1890 isc_buffer_init(&buffer, str, strlen(str)); 1891 isc_buffer_add(&buffer, strlen(str)); 1892 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 1893 ISC_FALSE, NULL)); 1894 isc_buffer_init(&buffer, contact, sizeof(contact) - 1); 1895 CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); 1896 contact[isc_buffer_usedlength(&buffer)] = 0; 1897 empty_dbtype[3] = contact; 1898 } else 1899 empty_dbtype[3] = "."; 1900 1901 obj = NULL; 1902 result = ns_config_get(maps, "zone-statistics", &obj); 1903 INSIST(result == ISC_R_SUCCESS); 1904 zonestats_on = cfg_obj_asboolean(obj); 1905 1906 logit = ISC_TRUE; 1907 for (empty = empty_zones[empty_zone].zone; 1908 empty != NULL; 1909 empty = empty_zones[++empty_zone].zone) 1910 { 1911 dns_forwarders_t *forwarders = NULL; 1912 dns_view_t *pview = NULL; 1913 1914 isc_buffer_init(&buffer, empty, strlen(empty)); 1915 isc_buffer_add(&buffer, strlen(empty)); 1916 /* 1917 * Look for zone on drop list. 1918 */ 1919 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 1920 ISC_FALSE, NULL)); 1921 if (disablelist != NULL && 1922 on_disable_list(disablelist, name)) 1923 continue; 1924 1925 /* 1926 * This zone already exists. 1927 */ 1928 (void)dns_view_findzone(view, name, &zone); 1929 if (zone != NULL) { 1930 CHECK(setquerystats(zone, mctx, zonestats_on)); 1931 dns_zone_detach(&zone); 1932 continue; 1933 } 1934 1935 /* 1936 * If we would forward this name don't add a 1937 * empty zone for it. 1938 */ 1939 result = dns_fwdtable_find(view->fwdtable, name, 1940 &forwarders); 1941 if (result == ISC_R_SUCCESS && 1942 forwarders->fwdpolicy == dns_fwdpolicy_only) 1943 continue; 1944 1945 if (!rfc1918 && empty_zones[empty_zone].rfc1918) { 1946 if (logit) { 1947 isc_log_write(ns_g_lctx, 1948 NS_LOGCATEGORY_GENERAL, 1949 NS_LOGMODULE_SERVER, 1950 ISC_LOG_WARNING, 1951 "Warning%s%s: " 1952 "'empty-zones-enable/" 1953 "disable-empty-zone' " 1954 "not set: disabling " 1955 "RFC 1918 empty zones", 1956 sep, viewname); 1957 logit = ISC_FALSE; 1958 } 1959 continue; 1960 } 1961 1962 /* 1963 * See if we can re-use a existing zone. 1964 */ 1965 result = dns_viewlist_find(&ns_g_server->viewlist, 1966 view->name, view->rdclass, 1967 &pview); 1968 if (result != ISC_R_NOTFOUND && 1969 result != ISC_R_SUCCESS) 1970 goto cleanup; 1971 1972 if (pview != NULL) { 1973 (void)dns_view_findzone(pview, name, &zone); 1974 dns_view_detach(&pview); 1975 if (zone != NULL) 1976 check_dbtype(&zone, empty_dbtypec, 1977 empty_dbtype, mctx); 1978 if (zone != NULL) { 1979 dns_zone_setview(zone, view); 1980 CHECK(dns_view_addzone(view, zone)); 1981 CHECK(setquerystats(zone, mctx, 1982 zonestats_on)); 1983 dns_zone_detach(&zone); 1984 continue; 1985 } 1986 } 1987 1988 CHECK(dns_zone_create(&zone, mctx)); 1989 CHECK(dns_zone_setorigin(zone, name)); 1990 dns_zone_setview(zone, view); 1991 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); 1992 dns_zone_setclass(zone, view->rdclass); 1993 dns_zone_settype(zone, dns_zone_master); 1994 dns_zone_setstats(zone, ns_g_server->zonestats); 1995 CHECK(dns_zone_setdbtype(zone, empty_dbtypec, 1996 empty_dbtype)); 1997 if (view->queryacl != NULL) 1998 dns_zone_setqueryacl(zone, view->queryacl); 1999 if (view->queryonacl != NULL) 2000 dns_zone_setqueryonacl(zone, view->queryonacl); 2001 dns_zone_setdialup(zone, dns_dialuptype_no); 2002 dns_zone_setnotifytype(zone, dns_notifytype_no); 2003 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, 2004 ISC_TRUE); 2005 CHECK(setquerystats(zone, mctx, zonestats_on)); 2006 CHECK(dns_view_addzone(view, zone)); 2007 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2008 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 2009 "automatic empty zone%s%s: %s", 2010 sep, viewname, empty); 2011 dns_zone_detach(&zone); 2012 } 2013 } 2014 2015 result = ISC_R_SUCCESS; 2016 2017 cleanup: 2018 if (zone != NULL) 2019 dns_zone_detach(&zone); 2020 if (dispatch4 != NULL) 2021 dns_dispatch_detach(&dispatch4); 2022 if (dispatch6 != NULL) 2023 dns_dispatch_detach(&dispatch6); 2024 if (resstats != NULL) 2025 isc_stats_detach(&resstats); 2026 if (resquerystats != NULL) 2027 dns_stats_detach(&resquerystats); 2028 if (order != NULL) 2029 dns_order_detach(&order); 2030 if (cmctx != NULL) 2031 isc_mem_detach(&cmctx); 2032 2033 if (cache != NULL) 2034 dns_cache_detach(&cache); 2035 2036 return (result); 2037} 2038 2039static isc_result_t 2040configure_hints(dns_view_t *view, const char *filename) { 2041 isc_result_t result; 2042 dns_db_t *db; 2043 2044 db = NULL; 2045 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); 2046 if (result == ISC_R_SUCCESS) { 2047 dns_view_sethints(view, db); 2048 dns_db_detach(&db); 2049 } 2050 2051 return (result); 2052} 2053 2054static isc_result_t 2055configure_alternates(const cfg_obj_t *config, dns_view_t *view, 2056 const cfg_obj_t *alternates) 2057{ 2058 const cfg_obj_t *portobj; 2059 const cfg_obj_t *addresses; 2060 const cfg_listelt_t *element; 2061 isc_result_t result = ISC_R_SUCCESS; 2062 in_port_t port; 2063 2064 /* 2065 * Determine which port to send requests to. 2066 */ 2067 if (ns_g_lwresdonly && ns_g_port != 0) 2068 port = ns_g_port; 2069 else 2070 CHECKM(ns_config_getport(config, &port), "port"); 2071 2072 if (alternates != NULL) { 2073 portobj = cfg_tuple_get(alternates, "port"); 2074 if (cfg_obj_isuint32(portobj)) { 2075 isc_uint32_t val = cfg_obj_asuint32(portobj); 2076 if (val > ISC_UINT16_MAX) { 2077 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 2078 "port '%u' out of range", val); 2079 return (ISC_R_RANGE); 2080 } 2081 port = (in_port_t) val; 2082 } 2083 } 2084 2085 addresses = NULL; 2086 if (alternates != NULL) 2087 addresses = cfg_tuple_get(alternates, "addresses"); 2088 2089 for (element = cfg_list_first(addresses); 2090 element != NULL; 2091 element = cfg_list_next(element)) 2092 { 2093 const cfg_obj_t *alternate = cfg_listelt_value(element); 2094 isc_sockaddr_t sa; 2095 2096 if (!cfg_obj_issockaddr(alternate)) { 2097 dns_fixedname_t fixed; 2098 dns_name_t *name; 2099 const char *str = cfg_obj_asstring(cfg_tuple_get( 2100 alternate, "name")); 2101 isc_buffer_t buffer; 2102 in_port_t myport = port; 2103 2104 isc_buffer_init(&buffer, str, strlen(str)); 2105 isc_buffer_add(&buffer, strlen(str)); 2106 dns_fixedname_init(&fixed); 2107 name = dns_fixedname_name(&fixed); 2108 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 2109 ISC_FALSE, NULL)); 2110 2111 portobj = cfg_tuple_get(alternate, "port"); 2112 if (cfg_obj_isuint32(portobj)) { 2113 isc_uint32_t val = cfg_obj_asuint32(portobj); 2114 if (val > ISC_UINT16_MAX) { 2115 cfg_obj_log(portobj, ns_g_lctx, 2116 ISC_LOG_ERROR, 2117 "port '%u' out of range", 2118 val); 2119 return (ISC_R_RANGE); 2120 } 2121 myport = (in_port_t) val; 2122 } 2123 CHECK(dns_resolver_addalternate(view->resolver, NULL, 2124 name, myport)); 2125 continue; 2126 } 2127 2128 sa = *cfg_obj_assockaddr(alternate); 2129 if (isc_sockaddr_getport(&sa) == 0) 2130 isc_sockaddr_setport(&sa, port); 2131 CHECK(dns_resolver_addalternate(view->resolver, &sa, 2132 NULL, 0)); 2133 } 2134 2135 cleanup: 2136 return (result); 2137} 2138 2139static isc_result_t 2140configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, 2141 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype) 2142{ 2143 const cfg_obj_t *portobj; 2144 const cfg_obj_t *faddresses; 2145 const cfg_listelt_t *element; 2146 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 2147 isc_sockaddrlist_t addresses; 2148 isc_sockaddr_t *sa; 2149 isc_result_t result; 2150 in_port_t port; 2151 2152 ISC_LIST_INIT(addresses); 2153 2154 /* 2155 * Determine which port to send forwarded requests to. 2156 */ 2157 if (ns_g_lwresdonly && ns_g_port != 0) 2158 port = ns_g_port; 2159 else 2160 CHECKM(ns_config_getport(config, &port), "port"); 2161 2162 if (forwarders != NULL) { 2163 portobj = cfg_tuple_get(forwarders, "port"); 2164 if (cfg_obj_isuint32(portobj)) { 2165 isc_uint32_t val = cfg_obj_asuint32(portobj); 2166 if (val > ISC_UINT16_MAX) { 2167 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 2168 "port '%u' out of range", val); 2169 return (ISC_R_RANGE); 2170 } 2171 port = (in_port_t) val; 2172 } 2173 } 2174 2175 faddresses = NULL; 2176 if (forwarders != NULL) 2177 faddresses = cfg_tuple_get(forwarders, "addresses"); 2178 2179 for (element = cfg_list_first(faddresses); 2180 element != NULL; 2181 element = cfg_list_next(element)) 2182 { 2183 const cfg_obj_t *forwarder = cfg_listelt_value(element); 2184 sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t)); 2185 if (sa == NULL) { 2186 result = ISC_R_NOMEMORY; 2187 goto cleanup; 2188 } 2189 *sa = *cfg_obj_assockaddr(forwarder); 2190 if (isc_sockaddr_getport(sa) == 0) 2191 isc_sockaddr_setport(sa, port); 2192 ISC_LINK_INIT(sa, link); 2193 ISC_LIST_APPEND(addresses, sa, link); 2194 } 2195 2196 if (ISC_LIST_EMPTY(addresses)) { 2197 if (forwardtype != NULL) 2198 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, 2199 "no forwarders seen; disabling " 2200 "forwarding"); 2201 fwdpolicy = dns_fwdpolicy_none; 2202 } else { 2203 if (forwardtype == NULL) 2204 fwdpolicy = dns_fwdpolicy_first; 2205 else { 2206 const char *forwardstr = cfg_obj_asstring(forwardtype); 2207 if (strcasecmp(forwardstr, "first") == 0) 2208 fwdpolicy = dns_fwdpolicy_first; 2209 else if (strcasecmp(forwardstr, "only") == 0) 2210 fwdpolicy = dns_fwdpolicy_only; 2211 else 2212 INSIST(0); 2213 } 2214 } 2215 2216 result = dns_fwdtable_add(view->fwdtable, origin, &addresses, 2217 fwdpolicy); 2218 if (result != ISC_R_SUCCESS) { 2219 char namebuf[DNS_NAME_FORMATSIZE]; 2220 dns_name_format(origin, namebuf, sizeof(namebuf)); 2221 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, 2222 "could not set up forwarding for domain '%s': %s", 2223 namebuf, isc_result_totext(result)); 2224 goto cleanup; 2225 } 2226 2227 result = ISC_R_SUCCESS; 2228 2229 cleanup: 2230 2231 while (!ISC_LIST_EMPTY(addresses)) { 2232 sa = ISC_LIST_HEAD(addresses); 2233 ISC_LIST_UNLINK(addresses, sa, link); 2234 isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t)); 2235 } 2236 2237 return (result); 2238} 2239 2240/* 2241 * Create a new view and add it to the list. 2242 * 2243 * If 'vconfig' is NULL, create the default view. 2244 * 2245 * The view created is attached to '*viewp'. 2246 */ 2247static isc_result_t 2248create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 2249 dns_view_t **viewp) 2250{ 2251 isc_result_t result; 2252 const char *viewname; 2253 dns_rdataclass_t viewclass; 2254 dns_view_t *view = NULL; 2255 2256 if (vconfig != NULL) { 2257 const cfg_obj_t *classobj = NULL; 2258 2259 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 2260 classobj = cfg_tuple_get(vconfig, "class"); 2261 result = ns_config_getclass(classobj, dns_rdataclass_in, 2262 &viewclass); 2263 } else { 2264 viewname = "_default"; 2265 viewclass = dns_rdataclass_in; 2266 } 2267 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 2268 if (result == ISC_R_SUCCESS) 2269 return (ISC_R_EXISTS); 2270 if (result != ISC_R_NOTFOUND) 2271 return (result); 2272 INSIST(view == NULL); 2273 2274 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view); 2275 if (result != ISC_R_SUCCESS) 2276 return (result); 2277 2278 ISC_LIST_APPEND(*viewlist, view, link); 2279 dns_view_attach(view, viewp); 2280 return (ISC_R_SUCCESS); 2281} 2282 2283/* 2284 * Configure or reconfigure a zone. 2285 */ 2286static isc_result_t 2287configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 2288 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 2289 cfg_aclconfctx_t *aclconf) 2290{ 2291 dns_view_t *pview = NULL; /* Production view */ 2292 dns_zone_t *zone = NULL; /* New or reused zone */ 2293 dns_zone_t *dupzone = NULL; 2294 const cfg_obj_t *options = NULL; 2295 const cfg_obj_t *zoptions = NULL; 2296 const cfg_obj_t *typeobj = NULL; 2297 const cfg_obj_t *forwarders = NULL; 2298 const cfg_obj_t *forwardtype = NULL; 2299 const cfg_obj_t *only = NULL; 2300 isc_result_t result; 2301 isc_result_t tresult; 2302 isc_buffer_t buffer; 2303 dns_fixedname_t fixorigin; 2304 dns_name_t *origin; 2305 const char *zname; 2306 dns_rdataclass_t zclass; 2307 const char *ztypestr; 2308 2309 options = NULL; 2310 (void)cfg_map_get(config, "options", &options); 2311 2312 zoptions = cfg_tuple_get(zconfig, "options"); 2313 2314 /* 2315 * Get the zone origin as a dns_name_t. 2316 */ 2317 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 2318 isc_buffer_init(&buffer, zname, strlen(zname)); 2319 isc_buffer_add(&buffer, strlen(zname)); 2320 dns_fixedname_init(&fixorigin); 2321 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), 2322 &buffer, dns_rootname, ISC_FALSE, NULL)); 2323 origin = dns_fixedname_name(&fixorigin); 2324 2325 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), 2326 view->rdclass, &zclass)); 2327 if (zclass != view->rdclass) { 2328 const char *vname = NULL; 2329 if (vconfig != NULL) 2330 vname = cfg_obj_asstring(cfg_tuple_get(vconfig, 2331 "name")); 2332 else 2333 vname = "<default view>"; 2334 2335 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2336 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 2337 "zone '%s': wrong class for view '%s'", 2338 zname, vname); 2339 result = ISC_R_FAILURE; 2340 goto cleanup; 2341 } 2342 2343 (void)cfg_map_get(zoptions, "type", &typeobj); 2344 if (typeobj == NULL) { 2345 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 2346 "zone '%s' 'type' not specified", zname); 2347 return (ISC_R_FAILURE); 2348 } 2349 ztypestr = cfg_obj_asstring(typeobj); 2350 2351 /* 2352 * "hints zones" aren't zones. If we've got one, 2353 * configure it and return. 2354 */ 2355 if (strcasecmp(ztypestr, "hint") == 0) { 2356 const cfg_obj_t *fileobj = NULL; 2357 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { 2358 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2359 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 2360 "zone '%s': 'file' not specified", 2361 zname); 2362 result = ISC_R_FAILURE; 2363 goto cleanup; 2364 } 2365 if (dns_name_equal(origin, dns_rootname)) { 2366 const char *hintsfile = cfg_obj_asstring(fileobj); 2367 2368 result = configure_hints(view, hintsfile); 2369 if (result != ISC_R_SUCCESS) { 2370 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2371 NS_LOGMODULE_SERVER, 2372 ISC_LOG_ERROR, 2373 "could not configure root hints " 2374 "from '%s': %s", hintsfile, 2375 isc_result_totext(result)); 2376 goto cleanup; 2377 } 2378 /* 2379 * Hint zones may also refer to delegation only points. 2380 */ 2381 only = NULL; 2382 tresult = cfg_map_get(zoptions, "delegation-only", 2383 &only); 2384 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) 2385 CHECK(dns_view_adddelegationonly(view, origin)); 2386 } else { 2387 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2388 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 2389 "ignoring non-root hint zone '%s'", 2390 zname); 2391 result = ISC_R_SUCCESS; 2392 } 2393 /* Skip ordinary zone processing. */ 2394 goto cleanup; 2395 } 2396 2397 /* 2398 * "forward zones" aren't zones either. Translate this syntax into 2399 * the appropriate selective forwarding configuration and return. 2400 */ 2401 if (strcasecmp(ztypestr, "forward") == 0) { 2402 forwardtype = NULL; 2403 forwarders = NULL; 2404 2405 (void)cfg_map_get(zoptions, "forward", &forwardtype); 2406 (void)cfg_map_get(zoptions, "forwarders", &forwarders); 2407 result = configure_forward(config, view, origin, forwarders, 2408 forwardtype); 2409 goto cleanup; 2410 } 2411 2412 /* 2413 * "delegation-only zones" aren't zones either. 2414 */ 2415 if (strcasecmp(ztypestr, "delegation-only") == 0) { 2416 result = dns_view_adddelegationonly(view, origin); 2417 goto cleanup; 2418 } 2419 2420 /* 2421 * Check for duplicates in the new zone table. 2422 */ 2423 result = dns_view_findzone(view, origin, &dupzone); 2424 if (result == ISC_R_SUCCESS) { 2425 /* 2426 * We already have this zone! 2427 */ 2428 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 2429 "zone '%s' already exists", zname); 2430 dns_zone_detach(&dupzone); 2431 result = ISC_R_EXISTS; 2432 goto cleanup; 2433 } 2434 INSIST(dupzone == NULL); 2435 2436 /* 2437 * See if we can reuse an existing zone. This is 2438 * only possible if all of these are true: 2439 * - The zone's view exists 2440 * - A zone with the right name exists in the view 2441 * - The zone is compatible with the config 2442 * options (e.g., an existing master zone cannot 2443 * be reused if the options specify a slave zone) 2444 */ 2445 result = dns_viewlist_find(&ns_g_server->viewlist, 2446 view->name, view->rdclass, 2447 &pview); 2448 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 2449 goto cleanup; 2450 if (pview != NULL) 2451 result = dns_view_findzone(pview, origin, &zone); 2452 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 2453 goto cleanup; 2454 if (zone != NULL && !ns_zone_reusable(zone, zconfig)) 2455 dns_zone_detach(&zone); 2456 2457 if (zone != NULL) { 2458 /* 2459 * We found a reusable zone. Make it use the 2460 * new view. 2461 */ 2462 dns_zone_setview(zone, view); 2463 if (view->acache != NULL) 2464 dns_zone_setacache(zone, view->acache); 2465 } else { 2466 /* 2467 * We cannot reuse an existing zone, we have 2468 * to create a new one. 2469 */ 2470 CHECK(dns_zone_create(&zone, mctx)); 2471 CHECK(dns_zone_setorigin(zone, origin)); 2472 dns_zone_setview(zone, view); 2473 if (view->acache != NULL) 2474 dns_zone_setacache(zone, view->acache); 2475 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); 2476 dns_zone_setstats(zone, ns_g_server->zonestats); 2477 } 2478 2479 /* 2480 * If the zone contains a 'forwarders' statement, configure 2481 * selective forwarding. 2482 */ 2483 forwarders = NULL; 2484 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) 2485 { 2486 forwardtype = NULL; 2487 (void)cfg_map_get(zoptions, "forward", &forwardtype); 2488 CHECK(configure_forward(config, view, origin, forwarders, 2489 forwardtype)); 2490 } 2491 2492 /* 2493 * Stub and forward zones may also refer to delegation only points. 2494 */ 2495 only = NULL; 2496 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) 2497 { 2498 if (cfg_obj_asboolean(only)) 2499 CHECK(dns_view_adddelegationonly(view, origin)); 2500 } 2501 2502 /* 2503 * Configure the zone. 2504 */ 2505 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone)); 2506 2507 /* 2508 * Add the zone to its view in the new view list. 2509 */ 2510 CHECK(dns_view_addzone(view, zone)); 2511 2512 cleanup: 2513 if (zone != NULL) 2514 dns_zone_detach(&zone); 2515 if (pview != NULL) 2516 dns_view_detach(&pview); 2517 2518 return (result); 2519} 2520 2521/* 2522 * Configure a single server quota. 2523 */ 2524static void 2525configure_server_quota(const cfg_obj_t **maps, const char *name, 2526 isc_quota_t *quota) 2527{ 2528 const cfg_obj_t *obj = NULL; 2529 isc_result_t result; 2530 2531 result = ns_config_get(maps, name, &obj); 2532 INSIST(result == ISC_R_SUCCESS); 2533 isc_quota_max(quota, cfg_obj_asuint32(obj)); 2534} 2535 2536/* 2537 * This function is called as soon as the 'directory' statement has been 2538 * parsed. This can be extended to support other options if necessary. 2539 */ 2540static isc_result_t 2541directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { 2542 isc_result_t result; 2543 const char *directory; 2544 2545 REQUIRE(strcasecmp("directory", clausename) == 0); 2546 2547 UNUSED(arg); 2548 UNUSED(clausename); 2549 2550 /* 2551 * Change directory. 2552 */ 2553 directory = cfg_obj_asstring(obj); 2554 2555 if (! isc_file_ischdiridempotent(directory)) 2556 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 2557 "option 'directory' contains relative path '%s'", 2558 directory); 2559 2560 result = isc_dir_chdir(directory); 2561 if (result != ISC_R_SUCCESS) { 2562 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 2563 "change directory to '%s' failed: %s", 2564 directory, isc_result_totext(result)); 2565 return (result); 2566 } 2567 2568 return (ISC_R_SUCCESS); 2569} 2570 2571static void 2572scan_interfaces(ns_server_t *server, isc_boolean_t verbose) { 2573 isc_boolean_t match_mapped = server->aclenv.match_mapped; 2574 2575 ns_interfacemgr_scan(server->interfacemgr, verbose); 2576 /* 2577 * Update the "localhost" and "localnets" ACLs to match the 2578 * current set of network interfaces. 2579 */ 2580 dns_aclenv_copy(&server->aclenv, 2581 ns_interfacemgr_getaclenv(server->interfacemgr)); 2582 2583 server->aclenv.match_mapped = match_mapped; 2584} 2585 2586static isc_result_t 2587add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr, 2588 isc_boolean_t wcardport_ok) 2589{ 2590 ns_listenelt_t *lelt = NULL; 2591 dns_acl_t *src_acl = NULL; 2592 isc_result_t result; 2593 isc_sockaddr_t any_sa6; 2594 isc_netaddr_t netaddr; 2595 2596 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6); 2597 2598 isc_sockaddr_any6(&any_sa6); 2599 if (!isc_sockaddr_equal(&any_sa6, addr) && 2600 (wcardport_ok || isc_sockaddr_getport(addr) != 0)) { 2601 isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr); 2602 2603 result = dns_acl_create(mctx, 0, &src_acl); 2604 if (result != ISC_R_SUCCESS) 2605 return (result); 2606 2607 result = dns_iptable_addprefix(src_acl->iptable, 2608 &netaddr, 128, ISC_TRUE); 2609 if (result != ISC_R_SUCCESS) 2610 goto clean; 2611 2612 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr), 2613 src_acl, &lelt); 2614 if (result != ISC_R_SUCCESS) 2615 goto clean; 2616 ISC_LIST_APPEND(list->elts, lelt, link); 2617 } 2618 2619 return (ISC_R_SUCCESS); 2620 2621 clean: 2622 INSIST(lelt == NULL); 2623 dns_acl_detach(&src_acl); 2624 2625 return (result); 2626} 2627 2628/* 2629 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust() 2630 * to update the listening interfaces accordingly. 2631 * We currently only consider IPv6, because this only affects IPv6 wildcard 2632 * sockets. 2633 */ 2634static void 2635adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) { 2636 isc_result_t result; 2637 ns_listenlist_t *list = NULL; 2638 dns_view_t *view; 2639 dns_zone_t *zone, *next; 2640 isc_sockaddr_t addr, *addrp; 2641 2642 result = ns_listenlist_create(mctx, &list); 2643 if (result != ISC_R_SUCCESS) 2644 return; 2645 2646 for (view = ISC_LIST_HEAD(server->viewlist); 2647 view != NULL; 2648 view = ISC_LIST_NEXT(view, link)) { 2649 dns_dispatch_t *dispatch6; 2650 2651 dispatch6 = dns_resolver_dispatchv6(view->resolver); 2652 if (dispatch6 == NULL) 2653 continue; 2654 result = dns_dispatch_getlocaladdress(dispatch6, &addr); 2655 if (result != ISC_R_SUCCESS) 2656 goto fail; 2657 2658 /* 2659 * We always add non-wildcard address regardless of whether 2660 * the port is 'any' (the fourth arg is TRUE): if the port is 2661 * specific, we need to add it since it may conflict with a 2662 * listening interface; if it's zero, we'll dynamically open 2663 * query ports, and some of them may override an existing 2664 * wildcard IPv6 port. 2665 */ 2666 result = add_listenelt(mctx, list, &addr, ISC_TRUE); 2667 if (result != ISC_R_SUCCESS) 2668 goto fail; 2669 } 2670 2671 zone = NULL; 2672 for (result = dns_zone_first(server->zonemgr, &zone); 2673 result == ISC_R_SUCCESS; 2674 next = NULL, result = dns_zone_next(zone, &next), zone = next) { 2675 dns_view_t *zoneview; 2676 2677 /* 2678 * At this point the zone list may contain a stale zone 2679 * just removed from the configuration. To see the validity, 2680 * check if the corresponding view is in our current view list. 2681 * There may also be old zones that are still in the process 2682 * of shutting down and have detached from their old view 2683 * (zoneview == NULL). 2684 */ 2685 zoneview = dns_zone_getview(zone); 2686 if (zoneview == NULL) 2687 continue; 2688 for (view = ISC_LIST_HEAD(server->viewlist); 2689 view != NULL && view != zoneview; 2690 view = ISC_LIST_NEXT(view, link)) 2691 ; 2692 if (view == NULL) 2693 continue; 2694 2695 addrp = dns_zone_getnotifysrc6(zone); 2696 result = add_listenelt(mctx, list, addrp, ISC_FALSE); 2697 if (result != ISC_R_SUCCESS) 2698 goto fail; 2699 2700 addrp = dns_zone_getxfrsource6(zone); 2701 result = add_listenelt(mctx, list, addrp, ISC_FALSE); 2702 if (result != ISC_R_SUCCESS) 2703 goto fail; 2704 } 2705 2706 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE); 2707 2708 clean: 2709 ns_listenlist_detach(&list); 2710 return; 2711 2712 fail: 2713 /* 2714 * Even when we failed the procedure, most of other interfaces 2715 * should work correctly. We therefore just warn it. 2716 */ 2717 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2718 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 2719 "could not adjust the listen-on list; " 2720 "some interfaces may not work"); 2721 goto clean; 2722} 2723 2724/* 2725 * This event callback is invoked to do periodic network 2726 * interface scanning. 2727 */ 2728static void 2729interface_timer_tick(isc_task_t *task, isc_event_t *event) { 2730 isc_result_t result; 2731 ns_server_t *server = (ns_server_t *) event->ev_arg; 2732 INSIST(task == server->task); 2733 UNUSED(task); 2734 isc_event_free(&event); 2735 /* 2736 * XXX should scan interfaces unlocked and get exclusive access 2737 * only to replace ACLs. 2738 */ 2739 result = isc_task_beginexclusive(server->task); 2740 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2741 scan_interfaces(server, ISC_FALSE); 2742 isc_task_endexclusive(server->task); 2743} 2744 2745static void 2746heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) { 2747 ns_server_t *server = (ns_server_t *) event->ev_arg; 2748 dns_view_t *view; 2749 2750 UNUSED(task); 2751 isc_event_free(&event); 2752 view = ISC_LIST_HEAD(server->viewlist); 2753 while (view != NULL) { 2754 dns_view_dialup(view); 2755 view = ISC_LIST_NEXT(view, link); 2756 } 2757} 2758 2759static void 2760pps_timer_tick(isc_task_t *task, isc_event_t *event) { 2761 static unsigned int oldrequests = 0; 2762 unsigned int requests = ns_client_requests; 2763 2764 UNUSED(task); 2765 isc_event_free(&event); 2766 2767 /* 2768 * Don't worry about wrapping as the overflow result will be right. 2769 */ 2770 dns_pps = (requests - oldrequests) / 1200; 2771 oldrequests = requests; 2772} 2773 2774/* 2775 * Replace the current value of '*field', a dynamically allocated 2776 * string or NULL, with a dynamically allocated copy of the 2777 * null-terminated string pointed to by 'value', or NULL. 2778 */ 2779static isc_result_t 2780setstring(ns_server_t *server, char **field, const char *value) { 2781 char *copy; 2782 2783 if (value != NULL) { 2784 copy = isc_mem_strdup(server->mctx, value); 2785 if (copy == NULL) 2786 return (ISC_R_NOMEMORY); 2787 } else { 2788 copy = NULL; 2789 } 2790 2791 if (*field != NULL) 2792 isc_mem_free(server->mctx, *field); 2793 2794 *field = copy; 2795 return (ISC_R_SUCCESS); 2796} 2797 2798/* 2799 * Replace the current value of '*field', a dynamically allocated 2800 * string or NULL, with another dynamically allocated string 2801 * or NULL if whether 'obj' is a string or void value, respectively. 2802 */ 2803static isc_result_t 2804setoptstring(ns_server_t *server, char **field, const cfg_obj_t *obj) { 2805 if (cfg_obj_isvoid(obj)) 2806 return (setstring(server, field, NULL)); 2807 else 2808 return (setstring(server, field, cfg_obj_asstring(obj))); 2809} 2810 2811static void 2812set_limit(const cfg_obj_t **maps, const char *configname, 2813 const char *description, isc_resource_t resourceid, 2814 isc_resourcevalue_t defaultvalue) 2815{ 2816 const cfg_obj_t *obj = NULL; 2817 const char *resource; 2818 isc_resourcevalue_t value; 2819 isc_result_t result; 2820 2821 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS) 2822 return; 2823 2824 if (cfg_obj_isstring(obj)) { 2825 resource = cfg_obj_asstring(obj); 2826 if (strcasecmp(resource, "unlimited") == 0) 2827 value = ISC_RESOURCE_UNLIMITED; 2828 else { 2829 INSIST(strcasecmp(resource, "default") == 0); 2830 value = defaultvalue; 2831 } 2832 } else 2833 value = cfg_obj_asuint64(obj); 2834 2835 result = isc_resource_setlimit(resourceid, value); 2836 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2837 result == ISC_R_SUCCESS ? 2838 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING, 2839 "set maximum %s to %" ISC_PRINT_QUADFORMAT "u: %s", 2840 description, value, isc_result_totext(result)); 2841} 2842 2843#define SETLIMIT(cfgvar, resource, description) \ 2844 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \ 2845 ns_g_init ## resource) 2846 2847static void 2848set_limits(const cfg_obj_t **maps) { 2849 SETLIMIT("stacksize", stacksize, "stack size"); 2850 SETLIMIT("datasize", datasize, "data size"); 2851 SETLIMIT("coresize", coresize, "core size"); 2852 SETLIMIT("files", openfiles, "open files"); 2853} 2854 2855static void 2856portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports, 2857 isc_boolean_t positive) 2858{ 2859 const cfg_listelt_t *element; 2860 2861 for (element = cfg_list_first(ports); 2862 element != NULL; 2863 element = cfg_list_next(element)) { 2864 const cfg_obj_t *obj = cfg_listelt_value(element); 2865 2866 if (cfg_obj_isuint32(obj)) { 2867 in_port_t port = (in_port_t)cfg_obj_asuint32(obj); 2868 2869 if (positive) 2870 isc_portset_add(portset, port); 2871 else 2872 isc_portset_remove(portset, port); 2873 } else { 2874 const cfg_obj_t *obj_loport, *obj_hiport; 2875 in_port_t loport, hiport; 2876 2877 obj_loport = cfg_tuple_get(obj, "loport"); 2878 loport = (in_port_t)cfg_obj_asuint32(obj_loport); 2879 obj_hiport = cfg_tuple_get(obj, "hiport"); 2880 hiport = (in_port_t)cfg_obj_asuint32(obj_hiport); 2881 2882 if (positive) 2883 isc_portset_addrange(portset, loport, hiport); 2884 else { 2885 isc_portset_removerange(portset, loport, 2886 hiport); 2887 } 2888 } 2889 } 2890} 2891 2892static isc_result_t 2893removed(dns_zone_t *zone, void *uap) { 2894 const char *type; 2895 2896 if (dns_zone_getview(zone) != uap) 2897 return (ISC_R_SUCCESS); 2898 2899 switch (dns_zone_gettype(zone)) { 2900 case dns_zone_master: 2901 type = "master"; 2902 break; 2903 case dns_zone_slave: 2904 type = "slave"; 2905 break; 2906 case dns_zone_stub: 2907 type = "stub"; 2908 break; 2909 default: 2910 type = "other"; 2911 break; 2912 } 2913 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type); 2914 return (ISC_R_SUCCESS); 2915} 2916 2917static isc_result_t 2918load_configuration(const char *filename, ns_server_t *server, 2919 isc_boolean_t first_time) 2920{ 2921 cfg_aclconfctx_t aclconfctx; 2922 cfg_obj_t *config; 2923 cfg_parser_t *parser = NULL; 2924 const cfg_listelt_t *element; 2925 const cfg_obj_t *builtin_views; 2926 const cfg_obj_t *maps[3]; 2927 const cfg_obj_t *obj; 2928 const cfg_obj_t *options; 2929 const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; 2930 const cfg_obj_t *views; 2931 dns_view_t *view = NULL; 2932 dns_view_t *view_next; 2933 dns_viewlist_t tmpviewlist; 2934 dns_viewlist_t viewlist; 2935 in_port_t listen_port, udpport_low, udpport_high; 2936 int i; 2937 isc_interval_t interval; 2938 isc_portset_t *v4portset = NULL; 2939 isc_portset_t *v6portset = NULL; 2940 isc_resourcevalue_t nfiles; 2941 isc_result_t result; 2942 isc_uint32_t heartbeat_interval; 2943 isc_uint32_t interface_interval; 2944 isc_uint32_t reserved; 2945 isc_uint32_t udpsize; 2946 unsigned int maxsocks; 2947 2948 cfg_aclconfctx_init(&aclconfctx); 2949 ISC_LIST_INIT(viewlist); 2950 2951 /* Ensure exclusive access to configuration data. */ 2952 result = isc_task_beginexclusive(server->task); 2953 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2954 2955 /* 2956 * Parse the global default pseudo-config file. 2957 */ 2958 if (first_time) { 2959 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config)); 2960 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", 2961 &ns_g_defaults) == 2962 ISC_R_SUCCESS); 2963 } 2964 2965 /* 2966 * Parse the configuration file using the new config code. 2967 */ 2968 result = ISC_R_FAILURE; 2969 config = NULL; 2970 2971 /* 2972 * Unless this is lwresd with the -C option, parse the config file. 2973 */ 2974 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) { 2975 isc_log_write(ns_g_lctx, 2976 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2977 ISC_LOG_INFO, "loading configuration from '%s'", 2978 filename); 2979 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); 2980 cfg_parser_setcallback(parser, directory_callback, NULL); 2981 result = cfg_parse_file(parser, filename, &cfg_type_namedconf, 2982 &config); 2983 } 2984 2985 /* 2986 * If this is lwresd with the -C option, or lwresd with no -C or -c 2987 * option where the above parsing failed, parse resolv.conf. 2988 */ 2989 if (ns_g_lwresdonly && 2990 (lwresd_g_useresolvconf || 2991 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND))) 2992 { 2993 isc_log_write(ns_g_lctx, 2994 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2995 ISC_LOG_INFO, "loading configuration from '%s'", 2996 lwresd_g_resolvconffile); 2997 if (parser != NULL) 2998 cfg_parser_destroy(&parser); 2999 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); 3000 result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser, 3001 &config); 3002 } 3003 CHECK(result); 3004 3005 /* 3006 * Check the validity of the configuration. 3007 */ 3008 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx)); 3009 3010 /* 3011 * Fill in the maps array, used for resolving defaults. 3012 */ 3013 i = 0; 3014 options = NULL; 3015 result = cfg_map_get(config, "options", &options); 3016 if (result == ISC_R_SUCCESS) 3017 maps[i++] = options; 3018 maps[i++] = ns_g_defaults; 3019 maps[i++] = NULL; 3020 3021 /* 3022 * Set process limits, which (usually) needs to be done as root. 3023 */ 3024 set_limits(maps); 3025 3026 /* 3027 * Check if max number of open sockets that the system allows is 3028 * sufficiently large. Failing this condition is not necessarily fatal, 3029 * but may cause subsequent runtime failures for a busy recursive 3030 * server. 3031 */ 3032 result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks); 3033 if (result != ISC_R_SUCCESS) 3034 maxsocks = 0; 3035 result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles); 3036 if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) { 3037 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3038 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 3039 "max open files (%" ISC_PRINT_QUADFORMAT "u)" 3040 " is smaller than max sockets (%u)", 3041 nfiles, maxsocks); 3042 } 3043 3044 /* 3045 * Set the number of socket reserved for TCP, stdio etc. 3046 */ 3047 obj = NULL; 3048 result = ns_config_get(maps, "reserved-sockets", &obj); 3049 INSIST(result == ISC_R_SUCCESS); 3050 reserved = cfg_obj_asuint32(obj); 3051 if (maxsocks != 0) { 3052 if (maxsocks < 128U) /* Prevent underflow. */ 3053 reserved = 0; 3054 else if (reserved > maxsocks - 128U) /* Minimum UDP space. */ 3055 reserved = maxsocks - 128; 3056 } 3057 /* Minimum TCP/stdio space. */ 3058 if (reserved < 128U) 3059 reserved = 128; 3060 if (reserved + 128U > maxsocks && maxsocks != 0) { 3061 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3062 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 3063 "less than 128 UDP sockets available after " 3064 "applying 'reserved-sockets' and 'maxsockets'"); 3065 } 3066 isc__socketmgr_setreserved(ns_g_socketmgr, reserved); 3067 3068 /* 3069 * Configure various server options. 3070 */ 3071 configure_server_quota(maps, "transfers-out", &server->xfroutquota); 3072 configure_server_quota(maps, "tcp-clients", &server->tcpquota); 3073 configure_server_quota(maps, "recursive-clients", 3074 &server->recursionquota); 3075 if (server->recursionquota.max > 1000) 3076 isc_quota_soft(&server->recursionquota, 3077 server->recursionquota.max - 100); 3078 else 3079 isc_quota_soft(&server->recursionquota, 0); 3080 3081 CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx, 3082 ns_g_mctx, &server->blackholeacl)); 3083 if (server->blackholeacl != NULL) 3084 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, 3085 server->blackholeacl); 3086 3087 obj = NULL; 3088 result = ns_config_get(maps, "match-mapped-addresses", &obj); 3089 INSIST(result == ISC_R_SUCCESS); 3090 server->aclenv.match_mapped = cfg_obj_asboolean(obj); 3091 3092 CHECKM(ns_statschannels_configure(ns_g_server, config, &aclconfctx), 3093 "configuring statistics server(s)"); 3094 3095 /* 3096 * Configure sets of UDP query source ports. 3097 */ 3098 CHECKM(isc_portset_create(ns_g_mctx, &v4portset), 3099 "creating UDP port set"); 3100 CHECKM(isc_portset_create(ns_g_mctx, &v6portset), 3101 "creating UDP port set"); 3102 3103 usev4ports = NULL; 3104 usev6ports = NULL; 3105 avoidv4ports = NULL; 3106 avoidv6ports = NULL; 3107 3108 (void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports); 3109 if (usev4ports != NULL) 3110 portset_fromconf(v4portset, usev4ports, ISC_TRUE); 3111 else { 3112 CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low, 3113 &udpport_high), 3114 "get the default UDP/IPv4 port range"); 3115 if (udpport_low == udpport_high) 3116 isc_portset_add(v4portset, udpport_low); 3117 else { 3118 isc_portset_addrange(v4portset, udpport_low, 3119 udpport_high); 3120 } 3121 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3122 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3123 "using default UDP/IPv4 port range: [%d, %d]", 3124 udpport_low, udpport_high); 3125 } 3126 (void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports); 3127 if (avoidv4ports != NULL) 3128 portset_fromconf(v4portset, avoidv4ports, ISC_FALSE); 3129 3130 (void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports); 3131 if (usev6ports != NULL) 3132 portset_fromconf(v6portset, usev6ports, ISC_TRUE); 3133 else { 3134 CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low, 3135 &udpport_high), 3136 "get the default UDP/IPv6 port range"); 3137 if (udpport_low == udpport_high) 3138 isc_portset_add(v6portset, udpport_low); 3139 else { 3140 isc_portset_addrange(v6portset, udpport_low, 3141 udpport_high); 3142 } 3143 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3144 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3145 "using default UDP/IPv6 port range: [%d, %d]", 3146 udpport_low, udpport_high); 3147 } 3148 (void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports); 3149 if (avoidv6ports != NULL) 3150 portset_fromconf(v6portset, avoidv6ports, ISC_FALSE); 3151 3152 dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset); 3153 3154 /* 3155 * Set the EDNS UDP size when we don't match a view. 3156 */ 3157 obj = NULL; 3158 result = ns_config_get(maps, "edns-udp-size", &obj); 3159 INSIST(result == ISC_R_SUCCESS); 3160 udpsize = cfg_obj_asuint32(obj); 3161 if (udpsize < 512) 3162 udpsize = 512; 3163 if (udpsize > 4096) 3164 udpsize = 4096; 3165 ns_g_udpsize = (isc_uint16_t)udpsize; 3166 3167 /* 3168 * Configure the zone manager. 3169 */ 3170 obj = NULL; 3171 result = ns_config_get(maps, "transfers-in", &obj); 3172 INSIST(result == ISC_R_SUCCESS); 3173 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); 3174 3175 obj = NULL; 3176 result = ns_config_get(maps, "transfers-per-ns", &obj); 3177 INSIST(result == ISC_R_SUCCESS); 3178 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); 3179 3180 obj = NULL; 3181 result = ns_config_get(maps, "serial-query-rate", &obj); 3182 INSIST(result == ISC_R_SUCCESS); 3183 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); 3184 3185 /* 3186 * Determine which port to use for listening for incoming connections. 3187 */ 3188 if (ns_g_port != 0) 3189 listen_port = ns_g_port; 3190 else 3191 CHECKM(ns_config_getport(config, &listen_port), "port"); 3192 3193 /* 3194 * Find the listen queue depth. 3195 */ 3196 obj = NULL; 3197 result = ns_config_get(maps, "tcp-listen-queue", &obj); 3198 INSIST(result == ISC_R_SUCCESS); 3199 ns_g_listen = cfg_obj_asuint32(obj); 3200 if (ns_g_listen < 3) 3201 ns_g_listen = 3; 3202 3203 /* 3204 * Configure the interface manager according to the "listen-on" 3205 * statement. 3206 */ 3207 { 3208 const cfg_obj_t *clistenon = NULL; 3209 ns_listenlist_t *listenon = NULL; 3210 3211 clistenon = NULL; 3212 /* 3213 * Even though listen-on is present in the default 3214 * configuration, we can't use it here, since it isn't 3215 * used if we're in lwresd mode. This way is easier. 3216 */ 3217 if (options != NULL) 3218 (void)cfg_map_get(options, "listen-on", &clistenon); 3219 if (clistenon != NULL) { 3220 result = ns_listenlist_fromconfig(clistenon, 3221 config, 3222 &aclconfctx, 3223 ns_g_mctx, 3224 &listenon); 3225 } else if (!ns_g_lwresdonly) { 3226 /* 3227 * Not specified, use default. 3228 */ 3229 CHECK(ns_listenlist_default(ns_g_mctx, listen_port, 3230 ISC_TRUE, &listenon)); 3231 } 3232 if (listenon != NULL) { 3233 ns_interfacemgr_setlistenon4(server->interfacemgr, 3234 listenon); 3235 ns_listenlist_detach(&listenon); 3236 } 3237 } 3238 /* 3239 * Ditto for IPv6. 3240 */ 3241 { 3242 const cfg_obj_t *clistenon = NULL; 3243 ns_listenlist_t *listenon = NULL; 3244 3245 if (options != NULL) 3246 (void)cfg_map_get(options, "listen-on-v6", &clistenon); 3247 if (clistenon != NULL) { 3248 result = ns_listenlist_fromconfig(clistenon, 3249 config, 3250 &aclconfctx, 3251 ns_g_mctx, 3252 &listenon); 3253 } else if (!ns_g_lwresdonly) { 3254 isc_boolean_t enable; 3255 /* 3256 * Not specified, use default. 3257 */ 3258 enable = ISC_TF(isc_net_probeipv4() != ISC_R_SUCCESS); 3259 CHECK(ns_listenlist_default(ns_g_mctx, listen_port, 3260 enable, &listenon)); 3261 } 3262 if (listenon != NULL) { 3263 ns_interfacemgr_setlistenon6(server->interfacemgr, 3264 listenon); 3265 ns_listenlist_detach(&listenon); 3266 } 3267 } 3268 3269 /* 3270 * Rescan the interface list to pick up changes in the 3271 * listen-on option. It's important that we do this before we try 3272 * to configure the query source, since the dispatcher we use might 3273 * be shared with an interface. 3274 */ 3275 scan_interfaces(server, ISC_TRUE); 3276 3277 /* 3278 * Arrange for further interface scanning to occur periodically 3279 * as specified by the "interface-interval" option. 3280 */ 3281 obj = NULL; 3282 result = ns_config_get(maps, "interface-interval", &obj); 3283 INSIST(result == ISC_R_SUCCESS); 3284 interface_interval = cfg_obj_asuint32(obj) * 60; 3285 if (interface_interval == 0) { 3286 CHECK(isc_timer_reset(server->interface_timer, 3287 isc_timertype_inactive, 3288 NULL, NULL, ISC_TRUE)); 3289 } else if (server->interface_interval != interface_interval) { 3290 isc_interval_set(&interval, interface_interval, 0); 3291 CHECK(isc_timer_reset(server->interface_timer, 3292 isc_timertype_ticker, 3293 NULL, &interval, ISC_FALSE)); 3294 } 3295 server->interface_interval = interface_interval; 3296 3297 /* 3298 * Configure the dialup heartbeat timer. 3299 */ 3300 obj = NULL; 3301 result = ns_config_get(maps, "heartbeat-interval", &obj); 3302 INSIST(result == ISC_R_SUCCESS); 3303 heartbeat_interval = cfg_obj_asuint32(obj) * 60; 3304 if (heartbeat_interval == 0) { 3305 CHECK(isc_timer_reset(server->heartbeat_timer, 3306 isc_timertype_inactive, 3307 NULL, NULL, ISC_TRUE)); 3308 } else if (server->heartbeat_interval != heartbeat_interval) { 3309 isc_interval_set(&interval, heartbeat_interval, 0); 3310 CHECK(isc_timer_reset(server->heartbeat_timer, 3311 isc_timertype_ticker, 3312 NULL, &interval, ISC_FALSE)); 3313 } 3314 server->heartbeat_interval = heartbeat_interval; 3315 3316 isc_interval_set(&interval, 1200, 0); 3317 CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL, 3318 &interval, ISC_FALSE)); 3319 3320 /* 3321 * Configure and freeze all explicit views. Explicit 3322 * views that have zones were already created at parsing 3323 * time, but views with no zones must be created here. 3324 */ 3325 views = NULL; 3326 (void)cfg_map_get(config, "view", &views); 3327 for (element = cfg_list_first(views); 3328 element != NULL; 3329 element = cfg_list_next(element)) 3330 { 3331 const cfg_obj_t *vconfig = cfg_listelt_value(element); 3332 view = NULL; 3333 3334 CHECK(create_view(vconfig, &viewlist, &view)); 3335 INSIST(view != NULL); 3336 CHECK(configure_view(view, config, vconfig, 3337 ns_g_mctx, &aclconfctx, ISC_TRUE)); 3338 dns_view_freeze(view); 3339 dns_view_detach(&view); 3340 } 3341 3342 /* 3343 * Make sure we have a default view if and only if there 3344 * were no explicit views. 3345 */ 3346 if (views == NULL) { 3347 /* 3348 * No explicit views; there ought to be a default view. 3349 * There may already be one created as a side effect 3350 * of zone statements, or we may have to create one. 3351 * In either case, we need to configure and freeze it. 3352 */ 3353 CHECK(create_view(NULL, &viewlist, &view)); 3354 CHECK(configure_view(view, config, NULL, ns_g_mctx, 3355 &aclconfctx, ISC_TRUE)); 3356 dns_view_freeze(view); 3357 dns_view_detach(&view); 3358 } 3359 3360 /* 3361 * Create (or recreate) the built-in views. Currently 3362 * there is only one, the _bind view. 3363 */ 3364 builtin_views = NULL; 3365 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view", 3366 &builtin_views) == ISC_R_SUCCESS); 3367 for (element = cfg_list_first(builtin_views); 3368 element != NULL; 3369 element = cfg_list_next(element)) 3370 { 3371 const cfg_obj_t *vconfig = cfg_listelt_value(element); 3372 CHECK(create_view(vconfig, &viewlist, &view)); 3373 CHECK(configure_view(view, config, vconfig, ns_g_mctx, 3374 &aclconfctx, ISC_FALSE)); 3375 dns_view_freeze(view); 3376 dns_view_detach(&view); 3377 view = NULL; 3378 } 3379 3380 /* 3381 * Swap our new view list with the production one. 3382 */ 3383 tmpviewlist = server->viewlist; 3384 server->viewlist = viewlist; 3385 viewlist = tmpviewlist; 3386 3387 /* 3388 * Load the TKEY information from the configuration. 3389 */ 3390 if (options != NULL) { 3391 dns_tkeyctx_t *t = NULL; 3392 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy, 3393 &t), 3394 "configuring TKEY"); 3395 if (server->tkeyctx != NULL) 3396 dns_tkeyctx_destroy(&server->tkeyctx); 3397 server->tkeyctx = t; 3398 } 3399 3400 /* 3401 * Bind the control port(s). 3402 */ 3403 CHECKM(ns_controls_configure(ns_g_server->controls, config, 3404 &aclconfctx), 3405 "binding control channel(s)"); 3406 3407 /* 3408 * Bind the lwresd port(s). 3409 */ 3410 CHECKM(ns_lwresd_configure(ns_g_mctx, config), 3411 "binding lightweight resolver ports"); 3412 3413 /* 3414 * Open the source of entropy. 3415 */ 3416 if (first_time) { 3417 obj = NULL; 3418 result = ns_config_get(maps, "random-device", &obj); 3419 if (result != ISC_R_SUCCESS) { 3420 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3421 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3422 "no source of entropy found"); 3423 } else { 3424 const char *randomdev = cfg_obj_asstring(obj); 3425 result = isc_entropy_createfilesource(ns_g_entropy, 3426 randomdev); 3427 if (result != ISC_R_SUCCESS) 3428 isc_log_write(ns_g_lctx, 3429 NS_LOGCATEGORY_GENERAL, 3430 NS_LOGMODULE_SERVER, 3431 ISC_LOG_INFO, 3432 "could not open entropy source " 3433 "%s: %s", 3434 randomdev, 3435 isc_result_totext(result)); 3436#ifdef PATH_RANDOMDEV 3437 if (ns_g_fallbackentropy != NULL) { 3438 if (result != ISC_R_SUCCESS) { 3439 isc_log_write(ns_g_lctx, 3440 NS_LOGCATEGORY_GENERAL, 3441 NS_LOGMODULE_SERVER, 3442 ISC_LOG_INFO, 3443 "using pre-chroot entropy source " 3444 "%s", 3445 PATH_RANDOMDEV); 3446 isc_entropy_detach(&ns_g_entropy); 3447 isc_entropy_attach(ns_g_fallbackentropy, 3448 &ns_g_entropy); 3449 } 3450 isc_entropy_detach(&ns_g_fallbackentropy); 3451 } 3452#endif 3453 } 3454 } 3455 3456 /* 3457 * Relinquish root privileges. 3458 */ 3459 if (first_time) 3460 ns_os_changeuser(); 3461 3462 /* 3463 * Check that the working directory is writable. 3464 */ 3465 if (access(".", W_OK) != 0) { 3466 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3467 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3468 "the working directory is not writable"); 3469 } 3470 3471 /* 3472 * Configure the logging system. 3473 * 3474 * Do this after changing UID to make sure that any log 3475 * files specified in named.conf get created by the 3476 * unprivileged user, not root. 3477 */ 3478 if (ns_g_logstderr) { 3479 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3480 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3481 "ignoring config file logging " 3482 "statement due to -g option"); 3483 } else { 3484 const cfg_obj_t *logobj = NULL; 3485 isc_logconfig_t *logc = NULL; 3486 3487 CHECKM(isc_logconfig_create(ns_g_lctx, &logc), 3488 "creating new logging configuration"); 3489 3490 logobj = NULL; 3491 (void)cfg_map_get(config, "logging", &logobj); 3492 if (logobj != NULL) { 3493 CHECKM(ns_log_configure(logc, logobj), 3494 "configuring logging"); 3495 } else { 3496 CHECKM(ns_log_setdefaultchannels(logc), 3497 "setting up default logging channels"); 3498 CHECKM(ns_log_setunmatchedcategory(logc), 3499 "setting up default 'category unmatched'"); 3500 CHECKM(ns_log_setdefaultcategory(logc), 3501 "setting up default 'category default'"); 3502 } 3503 3504 result = isc_logconfig_use(ns_g_lctx, logc); 3505 if (result != ISC_R_SUCCESS) { 3506 isc_logconfig_destroy(&logc); 3507 CHECKM(result, "installing logging configuration"); 3508 } 3509 3510 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3511 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 3512 "now using logging configuration from " 3513 "config file"); 3514 } 3515 3516 /* 3517 * Set the default value of the query logging flag depending 3518 * whether a "queries" category has been defined. This is 3519 * a disgusting hack, but we need to do this for BIND 8 3520 * compatibility. 3521 */ 3522 if (first_time) { 3523 const cfg_obj_t *logobj = NULL; 3524 const cfg_obj_t *categories = NULL; 3525 3526 obj = NULL; 3527 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { 3528 server->log_queries = cfg_obj_asboolean(obj); 3529 } else { 3530 3531 (void)cfg_map_get(config, "logging", &logobj); 3532 if (logobj != NULL) 3533 (void)cfg_map_get(logobj, "category", 3534 &categories); 3535 if (categories != NULL) { 3536 const cfg_listelt_t *element; 3537 for (element = cfg_list_first(categories); 3538 element != NULL; 3539 element = cfg_list_next(element)) 3540 { 3541 const cfg_obj_t *catobj; 3542 const char *str; 3543 3544 obj = cfg_listelt_value(element); 3545 catobj = cfg_tuple_get(obj, "name"); 3546 str = cfg_obj_asstring(catobj); 3547 if (strcasecmp(str, "queries") == 0) 3548 server->log_queries = ISC_TRUE; 3549 } 3550 } 3551 } 3552 } 3553 3554 obj = NULL; 3555 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) 3556 if (cfg_obj_isvoid(obj)) 3557 ns_os_writepidfile(NULL, first_time); 3558 else 3559 ns_os_writepidfile(cfg_obj_asstring(obj), first_time); 3560 else if (ns_g_lwresdonly) 3561 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); 3562 else 3563 ns_os_writepidfile(ns_g_defaultpidfile, first_time); 3564 3565 obj = NULL; 3566 if (options != NULL && 3567 cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS) 3568 ns_g_memstatistics = cfg_obj_asboolean(obj); 3569 else 3570 ns_g_memstatistics = 3571 ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0); 3572 3573 obj = NULL; 3574 if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS) 3575 ns_main_setmemstats(cfg_obj_asstring(obj)); 3576 else if (ns_g_memstatistics) 3577 ns_main_setmemstats("named.memstats"); 3578 else 3579 ns_main_setmemstats(NULL); 3580 3581 obj = NULL; 3582 result = ns_config_get(maps, "statistics-file", &obj); 3583 INSIST(result == ISC_R_SUCCESS); 3584 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)), 3585 "strdup"); 3586 3587 obj = NULL; 3588 result = ns_config_get(maps, "dump-file", &obj); 3589 INSIST(result == ISC_R_SUCCESS); 3590 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)), 3591 "strdup"); 3592 3593 obj = NULL; 3594 result = ns_config_get(maps, "recursing-file", &obj); 3595 INSIST(result == ISC_R_SUCCESS); 3596 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)), 3597 "strdup"); 3598 3599 obj = NULL; 3600 result = ns_config_get(maps, "version", &obj); 3601 if (result == ISC_R_SUCCESS) { 3602 CHECKM(setoptstring(server, &server->version, obj), "strdup"); 3603 server->version_set = ISC_TRUE; 3604 } else { 3605 server->version_set = ISC_FALSE; 3606 } 3607 3608 obj = NULL; 3609 result = ns_config_get(maps, "hostname", &obj); 3610 if (result == ISC_R_SUCCESS) { 3611 CHECKM(setoptstring(server, &server->hostname, obj), "strdup"); 3612 server->hostname_set = ISC_TRUE; 3613 } else { 3614 server->hostname_set = ISC_FALSE; 3615 } 3616 3617 obj = NULL; 3618 result = ns_config_get(maps, "server-id", &obj); 3619 server->server_usehostname = ISC_FALSE; 3620 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 3621 /* The parser translates "hostname" to ISC_TRUE */ 3622 server->server_usehostname = cfg_obj_asboolean(obj); 3623 result = setstring(server, &server->server_id, NULL); 3624 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3625 } else if (result == ISC_R_SUCCESS) { 3626 /* Found a quoted string */ 3627 CHECKM(setoptstring(server, &server->server_id, obj), "strdup"); 3628 } else { 3629 result = setstring(server, &server->server_id, NULL); 3630 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3631 } 3632 3633 obj = NULL; 3634 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj); 3635 if (result == ISC_R_SUCCESS) { 3636 server->flushonshutdown = cfg_obj_asboolean(obj); 3637 } else { 3638 server->flushonshutdown = ISC_FALSE; 3639 } 3640 3641 result = ISC_R_SUCCESS; 3642 3643 cleanup: 3644 if (v4portset != NULL) 3645 isc_portset_destroy(ns_g_mctx, &v4portset); 3646 3647 if (v6portset != NULL) 3648 isc_portset_destroy(ns_g_mctx, &v6portset); 3649 3650 cfg_aclconfctx_destroy(&aclconfctx); 3651 3652 if (parser != NULL) { 3653 if (config != NULL) 3654 cfg_obj_destroy(parser, &config); 3655 cfg_parser_destroy(&parser); 3656 } 3657 3658 if (view != NULL) 3659 dns_view_detach(&view); 3660 3661 /* 3662 * This cleans up either the old production view list 3663 * or our temporary list depending on whether they 3664 * were swapped above or not. 3665 */ 3666 for (view = ISC_LIST_HEAD(viewlist); 3667 view != NULL; 3668 view = view_next) { 3669 view_next = ISC_LIST_NEXT(view, link); 3670 ISC_LIST_UNLINK(viewlist, view, link); 3671 if (result == ISC_R_SUCCESS && 3672 strcmp(view->name, "_bind") != 0) 3673 (void)dns_zt_apply(view->zonetable, ISC_FALSE, 3674 removed, view); 3675 dns_view_detach(&view); 3676 } 3677 3678 /* 3679 * Adjust the listening interfaces in accordance with the source 3680 * addresses specified in views and zones. 3681 */ 3682 if (isc_net_probeipv6() == ISC_R_SUCCESS) 3683 adjust_interfaces(server, ns_g_mctx); 3684 3685 /* Relinquish exclusive access to configuration data. */ 3686 isc_task_endexclusive(server->task); 3687 3688 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3689 ISC_LOG_DEBUG(1), "load_configuration: %s", 3690 isc_result_totext(result)); 3691 3692 return (result); 3693} 3694 3695static isc_result_t 3696load_zones(ns_server_t *server, isc_boolean_t stop) { 3697 isc_result_t result; 3698 dns_view_t *view; 3699 3700 result = isc_task_beginexclusive(server->task); 3701 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3702 3703 /* 3704 * Load zone data from disk. 3705 */ 3706 for (view = ISC_LIST_HEAD(server->viewlist); 3707 view != NULL; 3708 view = ISC_LIST_NEXT(view, link)) 3709 { 3710 CHECK(dns_view_load(view, stop)); 3711 } 3712 3713 /* 3714 * Force zone maintenance. Do this after loading 3715 * so that we know when we need to force AXFR of 3716 * slave zones whose master files are missing. 3717 */ 3718 CHECK(dns_zonemgr_forcemaint(server->zonemgr)); 3719 cleanup: 3720 isc_task_endexclusive(server->task); 3721 return (result); 3722} 3723 3724static isc_result_t 3725load_new_zones(ns_server_t *server, isc_boolean_t stop) { 3726 isc_result_t result; 3727 dns_view_t *view; 3728 3729 result = isc_task_beginexclusive(server->task); 3730 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3731 3732 /* 3733 * Load zone data from disk. 3734 */ 3735 for (view = ISC_LIST_HEAD(server->viewlist); 3736 view != NULL; 3737 view = ISC_LIST_NEXT(view, link)) 3738 { 3739 CHECK(dns_view_loadnew(view, stop)); 3740 } 3741 /* 3742 * Force zone maintenance. Do this after loading 3743 * so that we know when we need to force AXFR of 3744 * slave zones whose master files are missing. 3745 */ 3746 dns_zonemgr_resumexfrs(server->zonemgr); 3747 cleanup: 3748 isc_task_endexclusive(server->task); 3749 return (result); 3750} 3751 3752static void 3753run_server(isc_task_t *task, isc_event_t *event) { 3754 isc_result_t result; 3755 ns_server_t *server = (ns_server_t *)event->ev_arg; 3756 3757 INSIST(task == server->task); 3758 3759 isc_event_free(&event); 3760 3761 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy, 3762 &ns_g_dispatchmgr), 3763 "creating dispatch manager"); 3764 3765 dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats); 3766 3767 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr, 3768 ns_g_socketmgr, ns_g_dispatchmgr, 3769 &server->interfacemgr), 3770 "creating interface manager"); 3771 3772 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 3773 NULL, NULL, server->task, 3774 interface_timer_tick, 3775 server, &server->interface_timer), 3776 "creating interface timer"); 3777 3778 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 3779 NULL, NULL, server->task, 3780 heartbeat_timer_tick, 3781 server, &server->heartbeat_timer), 3782 "creating heartbeat timer"); 3783 3784 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 3785 NULL, NULL, server->task, pps_timer_tick, 3786 server, &server->pps_timer), 3787 "creating pps timer"); 3788 3789 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser), 3790 "creating default configuration parser"); 3791 3792 if (ns_g_lwresdonly) 3793 CHECKFATAL(load_configuration(lwresd_g_conffile, server, 3794 ISC_TRUE), 3795 "loading configuration"); 3796 else 3797 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE), 3798 "loading configuration"); 3799 3800 isc_hash_init(); 3801 3802 CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones"); 3803 3804 ns_os_started(); 3805 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3806 ISC_LOG_NOTICE, "running"); 3807} 3808 3809void 3810ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) { 3811 3812 REQUIRE(NS_SERVER_VALID(server)); 3813 3814 server->flushonshutdown = flush; 3815} 3816 3817static void 3818shutdown_server(isc_task_t *task, isc_event_t *event) { 3819 isc_result_t result; 3820 dns_view_t *view, *view_next; 3821 ns_server_t *server = (ns_server_t *)event->ev_arg; 3822 isc_boolean_t flush = server->flushonshutdown; 3823 3824 UNUSED(task); 3825 INSIST(task == server->task); 3826 3827 result = isc_task_beginexclusive(server->task); 3828 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3829 3830 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3831 ISC_LOG_INFO, "shutting down%s", 3832 flush ? ": flushing changes" : ""); 3833 3834 ns_statschannels_shutdown(server); 3835 ns_controls_shutdown(server->controls); 3836 end_reserved_dispatches(server, ISC_TRUE); 3837 3838 cfg_obj_destroy(ns_g_parser, &ns_g_config); 3839 cfg_parser_destroy(&ns_g_parser); 3840 3841 for (view = ISC_LIST_HEAD(server->viewlist); 3842 view != NULL; 3843 view = view_next) { 3844 view_next = ISC_LIST_NEXT(view, link); 3845 ISC_LIST_UNLINK(server->viewlist, view, link); 3846 if (flush) 3847 dns_view_flushanddetach(&view); 3848 else 3849 dns_view_detach(&view); 3850 } 3851 3852 isc_timer_detach(&server->interface_timer); 3853 isc_timer_detach(&server->heartbeat_timer); 3854 isc_timer_detach(&server->pps_timer); 3855 3856 ns_interfacemgr_shutdown(server->interfacemgr); 3857 ns_interfacemgr_detach(&server->interfacemgr); 3858 3859 dns_dispatchmgr_destroy(&ns_g_dispatchmgr); 3860 3861 dns_zonemgr_shutdown(server->zonemgr); 3862 3863 if (server->blackholeacl != NULL) 3864 dns_acl_detach(&server->blackholeacl); 3865 3866 dns_db_detach(&server->in_roothints); 3867 3868 isc_task_endexclusive(server->task); 3869 3870 isc_task_detach(&server->task); 3871 3872 isc_event_free(&event); 3873} 3874 3875void 3876ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { 3877 isc_result_t result; 3878 3879 ns_server_t *server = isc_mem_get(mctx, sizeof(*server)); 3880 if (server == NULL) 3881 fatal("allocating server object", ISC_R_NOMEMORY); 3882 3883 server->mctx = mctx; 3884 server->task = NULL; 3885 3886 /* Initialize configuration data with default values. */ 3887 3888 result = isc_quota_init(&server->xfroutquota, 10); 3889 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3890 result = isc_quota_init(&server->tcpquota, 10); 3891 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3892 result = isc_quota_init(&server->recursionquota, 100); 3893 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3894 3895 result = dns_aclenv_init(mctx, &server->aclenv); 3896 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3897 3898 /* Initialize server data structures. */ 3899 server->zonemgr = NULL; 3900 server->interfacemgr = NULL; 3901 ISC_LIST_INIT(server->viewlist); 3902 server->in_roothints = NULL; 3903 server->blackholeacl = NULL; 3904 3905 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, 3906 &server->in_roothints), 3907 "setting up root hints"); 3908 3909 CHECKFATAL(isc_mutex_init(&server->reload_event_lock), 3910 "initializing reload event lock"); 3911 server->reload_event = 3912 isc_event_allocate(ns_g_mctx, server, 3913 NS_EVENT_RELOAD, 3914 ns_server_reload, 3915 server, 3916 sizeof(isc_event_t)); 3917 CHECKFATAL(server->reload_event == NULL ? 3918 ISC_R_NOMEMORY : ISC_R_SUCCESS, 3919 "allocating reload event"); 3920 3921 CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY), 3922 "initializing DST"); 3923 3924 server->tkeyctx = NULL; 3925 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy, 3926 &server->tkeyctx), 3927 "creating TKEY context"); 3928 3929 /* 3930 * Setup the server task, which is responsible for coordinating 3931 * startup and shutdown of the server. 3932 */ 3933 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task), 3934 "creating server task"); 3935 isc_task_setname(server->task, "server", server); 3936 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server), 3937 "isc_task_onshutdown"); 3938 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server), 3939 "isc_app_onrun"); 3940 3941 server->interface_timer = NULL; 3942 server->heartbeat_timer = NULL; 3943 server->pps_timer = NULL; 3944 3945 server->interface_interval = 0; 3946 server->heartbeat_interval = 0; 3947 3948 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, 3949 ns_g_socketmgr, &server->zonemgr), 3950 "dns_zonemgr_create"); 3951 3952 server->statsfile = isc_mem_strdup(server->mctx, "named.stats"); 3953 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3954 "isc_mem_strdup"); 3955 server->nsstats = NULL; 3956 server->rcvquerystats = NULL; 3957 server->opcodestats = NULL; 3958 server->zonestats = NULL; 3959 server->resolverstats = NULL; 3960 server->sockstats = NULL; 3961 CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats, 3962 isc_sockstatscounter_max), 3963 "isc_stats_create"); 3964 isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats); 3965 3966 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db"); 3967 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3968 "isc_mem_strdup"); 3969 3970 server->recfile = isc_mem_strdup(server->mctx, "named.recursing"); 3971 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3972 "isc_mem_strdup"); 3973 3974 server->hostname_set = ISC_FALSE; 3975 server->hostname = NULL; 3976 server->version_set = ISC_FALSE; 3977 server->version = NULL; 3978 server->server_usehostname = ISC_FALSE; 3979 server->server_id = NULL; 3980 3981 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->nsstats, 3982 dns_nsstatscounter_max), 3983 "dns_stats_create (server)"); 3984 3985 CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx, 3986 &server->rcvquerystats), 3987 "dns_stats_create (rcvquery)"); 3988 3989 CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats), 3990 "dns_stats_create (opcode)"); 3991 3992 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->zonestats, 3993 dns_zonestatscounter_max), 3994 "dns_stats_create (zone)"); 3995 3996 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->resolverstats, 3997 dns_resstatscounter_max), 3998 "dns_stats_create (resolver)"); 3999 4000 server->flushonshutdown = ISC_FALSE; 4001 server->log_queries = ISC_FALSE; 4002 4003 server->controls = NULL; 4004 CHECKFATAL(ns_controls_create(server, &server->controls), 4005 "ns_controls_create"); 4006 server->dispatchgen = 0; 4007 ISC_LIST_INIT(server->dispatches); 4008 4009 ISC_LIST_INIT(server->statschannels); 4010 4011 server->magic = NS_SERVER_MAGIC; 4012 *serverp = server; 4013} 4014 4015void 4016ns_server_destroy(ns_server_t **serverp) { 4017 ns_server_t *server = *serverp; 4018 REQUIRE(NS_SERVER_VALID(server)); 4019 4020 ns_controls_destroy(&server->controls); 4021 4022 isc_stats_detach(&server->nsstats); 4023 dns_stats_detach(&server->rcvquerystats); 4024 dns_stats_detach(&server->opcodestats); 4025 isc_stats_detach(&server->zonestats); 4026 isc_stats_detach(&server->resolverstats); 4027 isc_stats_detach(&server->sockstats); 4028 4029 isc_mem_free(server->mctx, server->statsfile); 4030 isc_mem_free(server->mctx, server->dumpfile); 4031 isc_mem_free(server->mctx, server->recfile); 4032 4033 if (server->version != NULL) 4034 isc_mem_free(server->mctx, server->version); 4035 if (server->hostname != NULL) 4036 isc_mem_free(server->mctx, server->hostname); 4037 if (server->server_id != NULL) 4038 isc_mem_free(server->mctx, server->server_id); 4039 4040 dns_zonemgr_detach(&server->zonemgr); 4041 4042 if (server->tkeyctx != NULL) 4043 dns_tkeyctx_destroy(&server->tkeyctx); 4044 4045 dst_lib_destroy(); 4046 4047 isc_event_free(&server->reload_event); 4048 4049 INSIST(ISC_LIST_EMPTY(server->viewlist)); 4050 4051 dns_aclenv_destroy(&server->aclenv); 4052 4053 isc_quota_destroy(&server->recursionquota); 4054 isc_quota_destroy(&server->tcpquota); 4055 isc_quota_destroy(&server->xfroutquota); 4056 4057 server->magic = 0; 4058 isc_mem_put(server->mctx, server, sizeof(*server)); 4059 *serverp = NULL; 4060} 4061 4062static void 4063fatal(const char *msg, isc_result_t result) { 4064 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 4065 ISC_LOG_CRITICAL, "%s: %s", msg, 4066 isc_result_totext(result)); 4067 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 4068 ISC_LOG_CRITICAL, "exiting (due to fatal error)"); 4069 exit(1); 4070} 4071 4072static void 4073start_reserved_dispatches(ns_server_t *server) { 4074 4075 REQUIRE(NS_SERVER_VALID(server)); 4076 4077 server->dispatchgen++; 4078} 4079 4080static void 4081end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) { 4082 ns_dispatch_t *dispatch, *nextdispatch; 4083 4084 REQUIRE(NS_SERVER_VALID(server)); 4085 4086 for (dispatch = ISC_LIST_HEAD(server->dispatches); 4087 dispatch != NULL; 4088 dispatch = nextdispatch) { 4089 nextdispatch = ISC_LIST_NEXT(dispatch, link); 4090 if (!all && server->dispatchgen == dispatch-> dispatchgen) 4091 continue; 4092 ISC_LIST_UNLINK(server->dispatches, dispatch, link); 4093 dns_dispatch_detach(&dispatch->dispatch); 4094 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 4095 } 4096} 4097 4098void 4099ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) { 4100 ns_dispatch_t *dispatch; 4101 in_port_t port; 4102 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 4103 isc_result_t result; 4104 unsigned int attrs, attrmask; 4105 4106 REQUIRE(NS_SERVER_VALID(server)); 4107 4108 port = isc_sockaddr_getport(addr); 4109 if (port == 0 || port >= 1024) 4110 return; 4111 4112 for (dispatch = ISC_LIST_HEAD(server->dispatches); 4113 dispatch != NULL; 4114 dispatch = ISC_LIST_NEXT(dispatch, link)) { 4115 if (isc_sockaddr_equal(&dispatch->addr, addr)) 4116 break; 4117 } 4118 if (dispatch != NULL) { 4119 dispatch->dispatchgen = server->dispatchgen; 4120 return; 4121 } 4122 4123 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch)); 4124 if (dispatch == NULL) { 4125 result = ISC_R_NOMEMORY; 4126 goto cleanup; 4127 } 4128 4129 dispatch->addr = *addr; 4130 dispatch->dispatchgen = server->dispatchgen; 4131 dispatch->dispatch = NULL; 4132 4133 attrs = 0; 4134 attrs |= DNS_DISPATCHATTR_UDP; 4135 switch (isc_sockaddr_pf(addr)) { 4136 case AF_INET: 4137 attrs |= DNS_DISPATCHATTR_IPV4; 4138 break; 4139 case AF_INET6: 4140 attrs |= DNS_DISPATCHATTR_IPV6; 4141 break; 4142 default: 4143 result = ISC_R_NOTIMPLEMENTED; 4144 goto cleanup; 4145 } 4146 attrmask = 0; 4147 attrmask |= DNS_DISPATCHATTR_UDP; 4148 attrmask |= DNS_DISPATCHATTR_TCP; 4149 attrmask |= DNS_DISPATCHATTR_IPV4; 4150 attrmask |= DNS_DISPATCHATTR_IPV6; 4151 4152 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, 4153 ns_g_taskmgr, &dispatch->addr, 4096, 4154 1000, 32768, 16411, 16433, 4155 attrs, attrmask, &dispatch->dispatch); 4156 if (result != ISC_R_SUCCESS) 4157 goto cleanup; 4158 4159 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link); 4160 4161 return; 4162 4163 cleanup: 4164 if (dispatch != NULL) 4165 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 4166 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 4167 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4168 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 4169 "unable to create dispatch for reserved port %s: %s", 4170 addrbuf, isc_result_totext(result)); 4171} 4172 4173 4174static isc_result_t 4175loadconfig(ns_server_t *server) { 4176 isc_result_t result; 4177 start_reserved_dispatches(server); 4178 result = load_configuration(ns_g_lwresdonly ? 4179 lwresd_g_conffile : ns_g_conffile, 4180 server, ISC_FALSE); 4181 if (result == ISC_R_SUCCESS) { 4182 end_reserved_dispatches(server, ISC_FALSE); 4183 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4184 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4185 "reloading configuration succeeded"); 4186 } else { 4187 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4188 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 4189 "reloading configuration failed: %s", 4190 isc_result_totext(result)); 4191 } 4192 return (result); 4193} 4194 4195static isc_result_t 4196reload(ns_server_t *server) { 4197 isc_result_t result; 4198 CHECK(loadconfig(server)); 4199 4200 result = load_zones(server, ISC_FALSE); 4201 if (result == ISC_R_SUCCESS) 4202 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4203 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4204 "reloading zones succeeded"); 4205 else 4206 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4207 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 4208 "reloading zones failed: %s", 4209 isc_result_totext(result)); 4210 4211 cleanup: 4212 return (result); 4213} 4214 4215static void 4216reconfig(ns_server_t *server) { 4217 isc_result_t result; 4218 CHECK(loadconfig(server)); 4219 4220 result = load_new_zones(server, ISC_FALSE); 4221 if (result == ISC_R_SUCCESS) 4222 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4223 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4224 "any newly configured zones are now loaded"); 4225 else 4226 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4227 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 4228 "loading new zones failed: %s", 4229 isc_result_totext(result)); 4230 4231 cleanup: ; 4232} 4233 4234/* 4235 * Handle a reload event (from SIGHUP). 4236 */ 4237static void 4238ns_server_reload(isc_task_t *task, isc_event_t *event) { 4239 ns_server_t *server = (ns_server_t *)event->ev_arg; 4240 4241 INSIST(task = server->task); 4242 UNUSED(task); 4243 4244 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4245 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4246 "received SIGHUP signal to reload zones"); 4247 (void)reload(server); 4248 4249 LOCK(&server->reload_event_lock); 4250 INSIST(server->reload_event == NULL); 4251 server->reload_event = event; 4252 UNLOCK(&server->reload_event_lock); 4253} 4254 4255void 4256ns_server_reloadwanted(ns_server_t *server) { 4257 LOCK(&server->reload_event_lock); 4258 if (server->reload_event != NULL) 4259 isc_task_send(server->task, &server->reload_event); 4260 UNLOCK(&server->reload_event_lock); 4261} 4262 4263static char * 4264next_token(char **stringp, const char *delim) { 4265 char *res; 4266 4267 do { 4268 res = strsep(stringp, delim); 4269 if (res == NULL) 4270 break; 4271 } while (*res == '\0'); 4272 return (res); 4273} 4274 4275/* 4276 * Find the zone specified in the control channel command 'args', 4277 * if any. If a zone is specified, point '*zonep' at it, otherwise 4278 * set '*zonep' to NULL. 4279 */ 4280static isc_result_t 4281zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { 4282 char *input, *ptr; 4283 const char *zonetxt; 4284 char *classtxt; 4285 const char *viewtxt = NULL; 4286 dns_fixedname_t name; 4287 isc_result_t result; 4288 isc_buffer_t buf; 4289 dns_view_t *view = NULL; 4290 dns_rdataclass_t rdclass; 4291 4292 REQUIRE(zonep != NULL && *zonep == NULL); 4293 4294 input = args; 4295 4296 /* Skip the command name. */ 4297 ptr = next_token(&input, " \t"); 4298 if (ptr == NULL) 4299 return (ISC_R_UNEXPECTEDEND); 4300 4301 /* Look for the zone name. */ 4302 zonetxt = next_token(&input, " \t"); 4303 if (zonetxt == NULL) 4304 return (ISC_R_SUCCESS); 4305 4306 /* Look for the optional class name. */ 4307 classtxt = next_token(&input, " \t"); 4308 if (classtxt != NULL) { 4309 /* Look for the optional view name. */ 4310 viewtxt = next_token(&input, " \t"); 4311 } 4312 4313 isc_buffer_init(&buf, zonetxt, strlen(zonetxt)); 4314 isc_buffer_add(&buf, strlen(zonetxt)); 4315 dns_fixedname_init(&name); 4316 result = dns_name_fromtext(dns_fixedname_name(&name), 4317 &buf, dns_rootname, ISC_FALSE, NULL); 4318 if (result != ISC_R_SUCCESS) 4319 goto fail1; 4320 4321 if (classtxt != NULL) { 4322 isc_textregion_t r; 4323 r.base = classtxt; 4324 r.length = strlen(classtxt); 4325 result = dns_rdataclass_fromtext(&rdclass, &r); 4326 if (result != ISC_R_SUCCESS) 4327 goto fail1; 4328 } else 4329 rdclass = dns_rdataclass_in; 4330 4331 if (viewtxt == NULL) { 4332 result = dns_viewlist_findzone(&server->viewlist, 4333 dns_fixedname_name(&name), 4334 ISC_TF(classtxt == NULL), 4335 rdclass, zonep); 4336 } else { 4337 result = dns_viewlist_find(&server->viewlist, viewtxt, 4338 rdclass, &view); 4339 if (result != ISC_R_SUCCESS) 4340 goto fail1; 4341 4342 result = dns_zt_find(view->zonetable, dns_fixedname_name(&name), 4343 0, NULL, zonep); 4344 dns_view_detach(&view); 4345 } 4346 4347 /* Partial match? */ 4348 if (result != ISC_R_SUCCESS && *zonep != NULL) 4349 dns_zone_detach(zonep); 4350 if (result == DNS_R_PARTIALMATCH) 4351 result = ISC_R_NOTFOUND; 4352 fail1: 4353 return (result); 4354} 4355 4356/* 4357 * Act on a "retransfer" command from the command channel. 4358 */ 4359isc_result_t 4360ns_server_retransfercommand(ns_server_t *server, char *args) { 4361 isc_result_t result; 4362 dns_zone_t *zone = NULL; 4363 dns_zonetype_t type; 4364 4365 result = zone_from_args(server, args, &zone); 4366 if (result != ISC_R_SUCCESS) 4367 return (result); 4368 if (zone == NULL) 4369 return (ISC_R_UNEXPECTEDEND); 4370 type = dns_zone_gettype(zone); 4371 if (type == dns_zone_slave || type == dns_zone_stub) 4372 dns_zone_forcereload(zone); 4373 else 4374 result = ISC_R_NOTFOUND; 4375 dns_zone_detach(&zone); 4376 return (result); 4377} 4378 4379/* 4380 * Act on a "reload" command from the command channel. 4381 */ 4382isc_result_t 4383ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) { 4384 isc_result_t result; 4385 dns_zone_t *zone = NULL; 4386 dns_zonetype_t type; 4387 const char *msg = NULL; 4388 4389 result = zone_from_args(server, args, &zone); 4390 if (result != ISC_R_SUCCESS) 4391 return (result); 4392 if (zone == NULL) { 4393 result = reload(server); 4394 if (result == ISC_R_SUCCESS) 4395 msg = "server reload successful"; 4396 } else { 4397 type = dns_zone_gettype(zone); 4398 if (type == dns_zone_slave || type == dns_zone_stub) { 4399 dns_zone_refresh(zone); 4400 dns_zone_detach(&zone); 4401 msg = "zone refresh queued"; 4402 } else { 4403 result = dns_zone_load(zone); 4404 dns_zone_detach(&zone); 4405 switch (result) { 4406 case ISC_R_SUCCESS: 4407 msg = "zone reload successful"; 4408 break; 4409 case DNS_R_CONTINUE: 4410 msg = "zone reload queued"; 4411 result = ISC_R_SUCCESS; 4412 break; 4413 case DNS_R_UPTODATE: 4414 msg = "zone reload up-to-date"; 4415 result = ISC_R_SUCCESS; 4416 break; 4417 default: 4418 /* failure message will be generated by rndc */ 4419 break; 4420 } 4421 } 4422 } 4423 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) 4424 isc_buffer_putmem(text, (const unsigned char *)msg, 4425 strlen(msg) + 1); 4426 return (result); 4427} 4428 4429/* 4430 * Act on a "reconfig" command from the command channel. 4431 */ 4432isc_result_t 4433ns_server_reconfigcommand(ns_server_t *server, char *args) { 4434 UNUSED(args); 4435 4436 reconfig(server); 4437 return (ISC_R_SUCCESS); 4438} 4439 4440/* 4441 * Act on a "notify" command from the command channel. 4442 */ 4443isc_result_t 4444ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) { 4445 isc_result_t result; 4446 dns_zone_t *zone = NULL; 4447 const unsigned char msg[] = "zone notify queued"; 4448 4449 result = zone_from_args(server, args, &zone); 4450 if (result != ISC_R_SUCCESS) 4451 return (result); 4452 if (zone == NULL) 4453 return (ISC_R_UNEXPECTEDEND); 4454 4455 dns_zone_notify(zone); 4456 dns_zone_detach(&zone); 4457 if (sizeof(msg) <= isc_buffer_availablelength(text)) 4458 isc_buffer_putmem(text, msg, sizeof(msg)); 4459 4460 return (ISC_R_SUCCESS); 4461} 4462 4463/* 4464 * Act on a "refresh" command from the command channel. 4465 */ 4466isc_result_t 4467ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) { 4468 isc_result_t result; 4469 dns_zone_t *zone = NULL; 4470 const unsigned char msg1[] = "zone refresh queued"; 4471 const unsigned char msg2[] = "not a slave or stub zone"; 4472 dns_zonetype_t type; 4473 4474 result = zone_from_args(server, args, &zone); 4475 if (result != ISC_R_SUCCESS) 4476 return (result); 4477 if (zone == NULL) 4478 return (ISC_R_UNEXPECTEDEND); 4479 4480 type = dns_zone_gettype(zone); 4481 if (type == dns_zone_slave || type == dns_zone_stub) { 4482 dns_zone_refresh(zone); 4483 dns_zone_detach(&zone); 4484 if (sizeof(msg1) <= isc_buffer_availablelength(text)) 4485 isc_buffer_putmem(text, msg1, sizeof(msg1)); 4486 return (ISC_R_SUCCESS); 4487 } 4488 4489 dns_zone_detach(&zone); 4490 if (sizeof(msg2) <= isc_buffer_availablelength(text)) 4491 isc_buffer_putmem(text, msg2, sizeof(msg2)); 4492 return (ISC_R_FAILURE); 4493} 4494 4495isc_result_t 4496ns_server_togglequerylog(ns_server_t *server) { 4497 server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE; 4498 4499 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4500 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4501 "query logging is now %s", 4502 server->log_queries ? "on" : "off"); 4503 return (ISC_R_SUCCESS); 4504} 4505 4506static isc_result_t 4507ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 4508 cfg_aclconfctx_t *actx, 4509 isc_mem_t *mctx, ns_listenlist_t **target) 4510{ 4511 isc_result_t result; 4512 const cfg_listelt_t *element; 4513 ns_listenlist_t *dlist = NULL; 4514 4515 REQUIRE(target != NULL && *target == NULL); 4516 4517 result = ns_listenlist_create(mctx, &dlist); 4518 if (result != ISC_R_SUCCESS) 4519 return (result); 4520 4521 for (element = cfg_list_first(listenlist); 4522 element != NULL; 4523 element = cfg_list_next(element)) 4524 { 4525 ns_listenelt_t *delt = NULL; 4526 const cfg_obj_t *listener = cfg_listelt_value(element); 4527 result = ns_listenelt_fromconfig(listener, config, actx, 4528 mctx, &delt); 4529 if (result != ISC_R_SUCCESS) 4530 goto cleanup; 4531 ISC_LIST_APPEND(dlist->elts, delt, link); 4532 } 4533 *target = dlist; 4534 return (ISC_R_SUCCESS); 4535 4536 cleanup: 4537 ns_listenlist_detach(&dlist); 4538 return (result); 4539} 4540 4541/* 4542 * Create a listen list from the corresponding configuration 4543 * data structure. 4544 */ 4545static isc_result_t 4546ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 4547 cfg_aclconfctx_t *actx, 4548 isc_mem_t *mctx, ns_listenelt_t **target) 4549{ 4550 isc_result_t result; 4551 const cfg_obj_t *portobj; 4552 in_port_t port; 4553 ns_listenelt_t *delt = NULL; 4554 REQUIRE(target != NULL && *target == NULL); 4555 4556 portobj = cfg_tuple_get(listener, "port"); 4557 if (!cfg_obj_isuint32(portobj)) { 4558 if (ns_g_port != 0) { 4559 port = ns_g_port; 4560 } else { 4561 result = ns_config_getport(config, &port); 4562 if (result != ISC_R_SUCCESS) 4563 return (result); 4564 } 4565 } else { 4566 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { 4567 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 4568 "port value '%u' is out of range", 4569 cfg_obj_asuint32(portobj)); 4570 return (ISC_R_RANGE); 4571 } 4572 port = (in_port_t)cfg_obj_asuint32(portobj); 4573 } 4574 4575 result = ns_listenelt_create(mctx, port, NULL, &delt); 4576 if (result != ISC_R_SUCCESS) 4577 return (result); 4578 4579 result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"), 4580 config, ns_g_lctx, actx, mctx, 0, 4581 &delt->acl); 4582 if (result != ISC_R_SUCCESS) { 4583 ns_listenelt_destroy(delt); 4584 return (result); 4585 } 4586 *target = delt; 4587 return (ISC_R_SUCCESS); 4588} 4589 4590isc_result_t 4591ns_server_dumpstats(ns_server_t *server) { 4592 isc_result_t result; 4593 FILE *fp = NULL; 4594 4595 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), 4596 "could not open statistics dump file", server->statsfile); 4597 4598 result = ns_stats_dump(server, fp); 4599 CHECK(result); 4600 4601 cleanup: 4602 if (fp != NULL) 4603 (void)isc_stdio_close(fp); 4604 if (result == ISC_R_SUCCESS) 4605 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4606 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4607 "dumpstats complete"); 4608 else 4609 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4610 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 4611 "dumpstats failed: %s", 4612 dns_result_totext(result)); 4613 return (result); 4614} 4615 4616static isc_result_t 4617add_zone_tolist(dns_zone_t *zone, void *uap) { 4618 struct dumpcontext *dctx = uap; 4619 struct zonelistentry *zle; 4620 4621 zle = isc_mem_get(dctx->mctx, sizeof *zle); 4622 if (zle == NULL) 4623 return (ISC_R_NOMEMORY); 4624 zle->zone = NULL; 4625 dns_zone_attach(zone, &zle->zone); 4626 ISC_LINK_INIT(zle, link); 4627 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); 4628 return (ISC_R_SUCCESS); 4629} 4630 4631static isc_result_t 4632add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { 4633 struct viewlistentry *vle; 4634 isc_result_t result = ISC_R_SUCCESS; 4635 4636 /* 4637 * Prevent duplicate views. 4638 */ 4639 for (vle = ISC_LIST_HEAD(dctx->viewlist); 4640 vle != NULL; 4641 vle = ISC_LIST_NEXT(vle, link)) 4642 if (vle->view == view) 4643 return (ISC_R_SUCCESS); 4644 4645 vle = isc_mem_get(dctx->mctx, sizeof *vle); 4646 if (vle == NULL) 4647 return (ISC_R_NOMEMORY); 4648 vle->view = NULL; 4649 dns_view_attach(view, &vle->view); 4650 ISC_LINK_INIT(vle, link); 4651 ISC_LIST_INIT(vle->zonelist); 4652 ISC_LIST_APPEND(dctx->viewlist, vle, link); 4653 if (dctx->dumpzones) 4654 result = dns_zt_apply(view->zonetable, ISC_TRUE, 4655 add_zone_tolist, dctx); 4656 return (result); 4657} 4658 4659static void 4660dumpcontext_destroy(struct dumpcontext *dctx) { 4661 struct viewlistentry *vle; 4662 struct zonelistentry *zle; 4663 4664 vle = ISC_LIST_HEAD(dctx->viewlist); 4665 while (vle != NULL) { 4666 ISC_LIST_UNLINK(dctx->viewlist, vle, link); 4667 zle = ISC_LIST_HEAD(vle->zonelist); 4668 while (zle != NULL) { 4669 ISC_LIST_UNLINK(vle->zonelist, zle, link); 4670 dns_zone_detach(&zle->zone); 4671 isc_mem_put(dctx->mctx, zle, sizeof *zle); 4672 zle = ISC_LIST_HEAD(vle->zonelist); 4673 } 4674 dns_view_detach(&vle->view); 4675 isc_mem_put(dctx->mctx, vle, sizeof *vle); 4676 vle = ISC_LIST_HEAD(dctx->viewlist); 4677 } 4678 if (dctx->version != NULL) 4679 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE); 4680 if (dctx->db != NULL) 4681 dns_db_detach(&dctx->db); 4682 if (dctx->cache != NULL) 4683 dns_db_detach(&dctx->cache); 4684 if (dctx->task != NULL) 4685 isc_task_detach(&dctx->task); 4686 if (dctx->fp != NULL) 4687 (void)isc_stdio_close(dctx->fp); 4688 if (dctx->mdctx != NULL) 4689 dns_dumpctx_detach(&dctx->mdctx); 4690 isc_mem_put(dctx->mctx, dctx, sizeof *dctx); 4691} 4692 4693static void 4694dumpdone(void *arg, isc_result_t result) { 4695 struct dumpcontext *dctx = arg; 4696 char buf[1024+32]; 4697 const dns_master_style_t *style; 4698 4699 if (result != ISC_R_SUCCESS) 4700 goto cleanup; 4701 if (dctx->mdctx != NULL) 4702 dns_dumpctx_detach(&dctx->mdctx); 4703 if (dctx->view == NULL) { 4704 dctx->view = ISC_LIST_HEAD(dctx->viewlist); 4705 if (dctx->view == NULL) 4706 goto done; 4707 INSIST(dctx->zone == NULL); 4708 } else 4709 goto resume; 4710 nextview: 4711 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); 4712 resume: 4713 if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) { 4714 style = &dns_master_style_cache; 4715 /* start cache dump */ 4716 if (dctx->view->view->cachedb != NULL) 4717 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 4718 if (dctx->cache != NULL) { 4719 4720 fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n", 4721 dctx->view->view->name); 4722 result = dns_master_dumptostreaminc(dctx->mctx, 4723 dctx->cache, NULL, 4724 style, dctx->fp, 4725 dctx->task, 4726 dumpdone, dctx, 4727 &dctx->mdctx); 4728 if (result == DNS_R_CONTINUE) 4729 return; 4730 if (result == ISC_R_NOTIMPLEMENTED) 4731 fprintf(dctx->fp, "; %s\n", 4732 dns_result_totext(result)); 4733 else if (result != ISC_R_SUCCESS) 4734 goto cleanup; 4735 } 4736 } 4737 if (dctx->cache != NULL) { 4738 dns_adb_dump(dctx->view->view->adb, dctx->fp); 4739 dns_resolver_printbadcache(dctx->view->view->resolver, 4740 dctx->fp); 4741 dns_db_detach(&dctx->cache); 4742 } 4743 if (dctx->dumpzones) { 4744 style = &dns_master_style_full; 4745 nextzone: 4746 if (dctx->version != NULL) 4747 dns_db_closeversion(dctx->db, &dctx->version, 4748 ISC_FALSE); 4749 if (dctx->db != NULL) 4750 dns_db_detach(&dctx->db); 4751 if (dctx->zone == NULL) 4752 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); 4753 else 4754 dctx->zone = ISC_LIST_NEXT(dctx->zone, link); 4755 if (dctx->zone != NULL) { 4756 /* start zone dump */ 4757 dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); 4758 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); 4759 result = dns_zone_getdb(dctx->zone->zone, &dctx->db); 4760 if (result != ISC_R_SUCCESS) { 4761 fprintf(dctx->fp, "; %s\n", 4762 dns_result_totext(result)); 4763 goto nextzone; 4764 } 4765 dns_db_currentversion(dctx->db, &dctx->version); 4766 result = dns_master_dumptostreaminc(dctx->mctx, 4767 dctx->db, 4768 dctx->version, 4769 style, dctx->fp, 4770 dctx->task, 4771 dumpdone, dctx, 4772 &dctx->mdctx); 4773 if (result == DNS_R_CONTINUE) 4774 return; 4775 if (result == ISC_R_NOTIMPLEMENTED) { 4776 fprintf(dctx->fp, "; %s\n", 4777 dns_result_totext(result)); 4778 result = ISC_R_SUCCESS; 4779 goto nextzone; 4780 } 4781 if (result != ISC_R_SUCCESS) 4782 goto cleanup; 4783 } 4784 } 4785 if (dctx->view != NULL) 4786 dctx->view = ISC_LIST_NEXT(dctx->view, link); 4787 if (dctx->view != NULL) 4788 goto nextview; 4789 done: 4790 fprintf(dctx->fp, "; Dump complete\n"); 4791 result = isc_stdio_flush(dctx->fp); 4792 if (result == ISC_R_SUCCESS) 4793 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4794 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4795 "dumpdb complete"); 4796 cleanup: 4797 if (result != ISC_R_SUCCESS) 4798 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4799 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 4800 "dumpdb failed: %s", dns_result_totext(result)); 4801 dumpcontext_destroy(dctx); 4802} 4803 4804isc_result_t 4805ns_server_dumpdb(ns_server_t *server, char *args) { 4806 struct dumpcontext *dctx = NULL; 4807 dns_view_t *view; 4808 isc_result_t result; 4809 char *ptr; 4810 const char *sep; 4811 4812 /* Skip the command name. */ 4813 ptr = next_token(&args, " \t"); 4814 if (ptr == NULL) 4815 return (ISC_R_UNEXPECTEDEND); 4816 4817 dctx = isc_mem_get(server->mctx, sizeof(*dctx)); 4818 if (dctx == NULL) 4819 return (ISC_R_NOMEMORY); 4820 4821 dctx->mctx = server->mctx; 4822 dctx->dumpcache = ISC_TRUE; 4823 dctx->dumpzones = ISC_FALSE; 4824 dctx->fp = NULL; 4825 ISC_LIST_INIT(dctx->viewlist); 4826 dctx->view = NULL; 4827 dctx->zone = NULL; 4828 dctx->cache = NULL; 4829 dctx->mdctx = NULL; 4830 dctx->db = NULL; 4831 dctx->cache = NULL; 4832 dctx->task = NULL; 4833 dctx->version = NULL; 4834 isc_task_attach(server->task, &dctx->task); 4835 4836 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), 4837 "could not open dump file", server->dumpfile); 4838 4839 sep = (args == NULL) ? "" : ": "; 4840 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4841 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4842 "dumpdb started%s%s", sep, (args != NULL) ? args : ""); 4843 4844 ptr = next_token(&args, " \t"); 4845 if (ptr != NULL && strcmp(ptr, "-all") == 0) { 4846 dctx->dumpzones = ISC_TRUE; 4847 dctx->dumpcache = ISC_TRUE; 4848 ptr = next_token(&args, " \t"); 4849 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { 4850 dctx->dumpzones = ISC_FALSE; 4851 dctx->dumpcache = ISC_TRUE; 4852 ptr = next_token(&args, " \t"); 4853 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { 4854 dctx->dumpzones = ISC_TRUE; 4855 dctx->dumpcache = ISC_FALSE; 4856 ptr = next_token(&args, " \t"); 4857 } 4858 4859 nextview: 4860 for (view = ISC_LIST_HEAD(server->viewlist); 4861 view != NULL; 4862 view = ISC_LIST_NEXT(view, link)) 4863 { 4864 if (ptr != NULL && strcmp(view->name, ptr) != 0) 4865 continue; 4866 CHECK(add_view_tolist(dctx, view)); 4867 } 4868 if (ptr != NULL) { 4869 ptr = next_token(&args, " \t"); 4870 if (ptr != NULL) 4871 goto nextview; 4872 } 4873 dumpdone(dctx, ISC_R_SUCCESS); 4874 return (ISC_R_SUCCESS); 4875 4876 cleanup: 4877 if (dctx != NULL) 4878 dumpcontext_destroy(dctx); 4879 return (result); 4880} 4881 4882isc_result_t 4883ns_server_dumprecursing(ns_server_t *server) { 4884 FILE *fp = NULL; 4885 isc_result_t result; 4886 4887 CHECKMF(isc_stdio_open(server->recfile, "w", &fp), 4888 "could not open dump file", server->recfile); 4889 fprintf(fp,";\n; Recursing Queries\n;\n"); 4890 ns_interfacemgr_dumprecursing(fp, server->interfacemgr); 4891 fprintf(fp, "; Dump complete\n"); 4892 4893 cleanup: 4894 if (fp != NULL) 4895 result = isc_stdio_close(fp); 4896 if (result == ISC_R_SUCCESS) 4897 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4898 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4899 "dumprecursing complete"); 4900 else 4901 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4902 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 4903 "dumprecursing failed: %s", 4904 dns_result_totext(result)); 4905 return (result); 4906} 4907 4908isc_result_t 4909ns_server_setdebuglevel(ns_server_t *server, char *args) { 4910 char *ptr; 4911 char *levelstr; 4912 char *endp; 4913 long newlevel; 4914 4915 UNUSED(server); 4916 4917 /* Skip the command name. */ 4918 ptr = next_token(&args, " \t"); 4919 if (ptr == NULL) 4920 return (ISC_R_UNEXPECTEDEND); 4921 4922 /* Look for the new level name. */ 4923 levelstr = next_token(&args, " \t"); 4924 if (levelstr == NULL) { 4925 if (ns_g_debuglevel < 99) 4926 ns_g_debuglevel++; 4927 } else { 4928 newlevel = strtol(levelstr, &endp, 10); 4929 if (*endp != '\0' || newlevel < 0 || newlevel > 99) 4930 return (ISC_R_RANGE); 4931 ns_g_debuglevel = (unsigned int)newlevel; 4932 } 4933 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); 4934 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4935 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4936 "debug level is now %d", ns_g_debuglevel); 4937 return (ISC_R_SUCCESS); 4938} 4939 4940isc_result_t 4941ns_server_validation(ns_server_t *server, char *args) { 4942 char *ptr, *viewname; 4943 dns_view_t *view; 4944 isc_boolean_t changed = ISC_FALSE; 4945 isc_result_t result; 4946 isc_boolean_t enable; 4947 4948 /* Skip the command name. */ 4949 ptr = next_token(&args, " \t"); 4950 if (ptr == NULL) 4951 return (ISC_R_UNEXPECTEDEND); 4952 4953 /* Find out what we are to do. */ 4954 ptr = next_token(&args, " \t"); 4955 if (ptr == NULL) 4956 return (ISC_R_UNEXPECTEDEND); 4957 4958 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 4959 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 4960 enable = ISC_TRUE; 4961 else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 4962 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 4963 enable = ISC_FALSE; 4964 else 4965 return (DNS_R_SYNTAX); 4966 4967 /* Look for the view name. */ 4968 viewname = next_token(&args, " \t"); 4969 4970 result = isc_task_beginexclusive(server->task); 4971 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4972 for (view = ISC_LIST_HEAD(server->viewlist); 4973 view != NULL; 4974 view = ISC_LIST_NEXT(view, link)) 4975 { 4976 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 4977 continue; 4978 result = dns_view_flushcache(view); 4979 if (result != ISC_R_SUCCESS) 4980 goto out; 4981 view->enablevalidation = enable; 4982 changed = ISC_TRUE; 4983 } 4984 if (changed) 4985 result = ISC_R_SUCCESS; 4986 else 4987 result = ISC_R_FAILURE; 4988 out: 4989 isc_task_endexclusive(server->task); 4990 return (result); 4991} 4992 4993isc_result_t 4994ns_server_flushcache(ns_server_t *server, char *args) { 4995 char *ptr, *viewname; 4996 dns_view_t *view; 4997 isc_boolean_t flushed; 4998 isc_boolean_t found; 4999 isc_result_t result; 5000 5001 /* Skip the command name. */ 5002 ptr = next_token(&args, " \t"); 5003 if (ptr == NULL) 5004 return (ISC_R_UNEXPECTEDEND); 5005 5006 /* Look for the view name. */ 5007 viewname = next_token(&args, " \t"); 5008 5009 result = isc_task_beginexclusive(server->task); 5010 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5011 flushed = ISC_TRUE; 5012 found = ISC_FALSE; 5013 for (view = ISC_LIST_HEAD(server->viewlist); 5014 view != NULL; 5015 view = ISC_LIST_NEXT(view, link)) 5016 { 5017 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 5018 continue; 5019 found = ISC_TRUE; 5020 result = dns_view_flushcache(view); 5021 if (result != ISC_R_SUCCESS) { 5022 flushed = ISC_FALSE; 5023 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5024 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 5025 "flushing cache in view '%s' failed: %s", 5026 view->name, isc_result_totext(result)); 5027 } 5028 } 5029 if (flushed && found) { 5030 if (viewname != NULL) 5031 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5032 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5033 "flushing cache in view '%s' succeeded", 5034 viewname); 5035 else 5036 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5037 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5038 "flushing caches in all views succeeded"); 5039 result = ISC_R_SUCCESS; 5040 } else { 5041 if (!found) { 5042 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5043 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 5044 "flushing cache in view '%s' failed: " 5045 "view not found", viewname); 5046 result = ISC_R_NOTFOUND; 5047 } else 5048 result = ISC_R_FAILURE; 5049 } 5050 isc_task_endexclusive(server->task); 5051 return (result); 5052} 5053 5054isc_result_t 5055ns_server_flushname(ns_server_t *server, char *args) { 5056 char *ptr, *target, *viewname; 5057 dns_view_t *view; 5058 isc_boolean_t flushed; 5059 isc_boolean_t found; 5060 isc_result_t result; 5061 isc_buffer_t b; 5062 dns_fixedname_t fixed; 5063 dns_name_t *name; 5064 5065 /* Skip the command name. */ 5066 ptr = next_token(&args, " \t"); 5067 if (ptr == NULL) 5068 return (ISC_R_UNEXPECTEDEND); 5069 5070 /* Find the domain name to flush. */ 5071 target = next_token(&args, " \t"); 5072 if (target == NULL) 5073 return (ISC_R_UNEXPECTEDEND); 5074 5075 isc_buffer_init(&b, target, strlen(target)); 5076 isc_buffer_add(&b, strlen(target)); 5077 dns_fixedname_init(&fixed); 5078 name = dns_fixedname_name(&fixed); 5079 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); 5080 if (result != ISC_R_SUCCESS) 5081 return (result); 5082 5083 /* Look for the view name. */ 5084 viewname = next_token(&args, " \t"); 5085 5086 result = isc_task_beginexclusive(server->task); 5087 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5088 flushed = ISC_TRUE; 5089 found = ISC_FALSE; 5090 for (view = ISC_LIST_HEAD(server->viewlist); 5091 view != NULL; 5092 view = ISC_LIST_NEXT(view, link)) 5093 { 5094 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 5095 continue; 5096 found = ISC_TRUE; 5097 result = dns_view_flushname(view, name); 5098 if (result != ISC_R_SUCCESS) { 5099 flushed = ISC_FALSE; 5100 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5101 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 5102 "flushing name '%s' in cache view '%s' " 5103 "failed: %s", target, view->name, 5104 isc_result_totext(result)); 5105 } 5106 } 5107 if (flushed && found) { 5108 if (viewname != NULL) 5109 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5110 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5111 "flushing name '%s' in cache view '%s' " 5112 "succeeded", target, viewname); 5113 else 5114 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5115 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5116 "flushing name '%s' in all cache views " 5117 "succeeded", target); 5118 result = ISC_R_SUCCESS; 5119 } else { 5120 if (!found) 5121 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5122 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 5123 "flushing name '%s' in cache view '%s' " 5124 "failed: view not found", target, 5125 viewname); 5126 result = ISC_R_FAILURE; 5127 } 5128 isc_task_endexclusive(server->task); 5129 return (result); 5130} 5131 5132isc_result_t 5133ns_server_status(ns_server_t *server, isc_buffer_t *text) { 5134 int zonecount, xferrunning, xferdeferred, soaqueries; 5135 unsigned int n; 5136 const char *ob = "", *cb = "", *alt = ""; 5137 5138 if (ns_g_server->version_set) { 5139 ob = " ("; 5140 cb = ")"; 5141 if (ns_g_server->version == NULL) 5142 alt = "version.bind/txt/ch disabled"; 5143 else 5144 alt = ns_g_server->version; 5145 } 5146 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); 5147 xferrunning = dns_zonemgr_getcount(server->zonemgr, 5148 DNS_ZONESTATE_XFERRUNNING); 5149 xferdeferred = dns_zonemgr_getcount(server->zonemgr, 5150 DNS_ZONESTATE_XFERDEFERRED); 5151 soaqueries = dns_zonemgr_getcount(server->zonemgr, 5152 DNS_ZONESTATE_SOAQUERY); 5153 5154 n = snprintf((char *)isc_buffer_used(text), 5155 isc_buffer_availablelength(text), 5156 "version: %s%s%s%s\n" 5157#ifdef ISC_PLATFORM_USETHREADS 5158 "CPUs found: %u\n" 5159 "worker threads: %u\n" 5160#endif 5161 "number of zones: %u\n" 5162 "debug level: %d\n" 5163 "xfers running: %u\n" 5164 "xfers deferred: %u\n" 5165 "soa queries in progress: %u\n" 5166 "query logging is %s\n" 5167 "recursive clients: %d/%d/%d\n" 5168 "tcp clients: %d/%d\n" 5169 "server is up and running", 5170 ns_g_version, ob, alt, cb, 5171#ifdef ISC_PLATFORM_USETHREADS 5172 ns_g_cpus_detected, ns_g_cpus, 5173#endif 5174 zonecount, ns_g_debuglevel, xferrunning, xferdeferred, 5175 soaqueries, server->log_queries ? "ON" : "OFF", 5176 server->recursionquota.used, server->recursionquota.soft, 5177 server->recursionquota.max, 5178 server->tcpquota.used, server->tcpquota.max); 5179 if (n >= isc_buffer_availablelength(text)) 5180 return (ISC_R_NOSPACE); 5181 isc_buffer_add(text, n); 5182 return (ISC_R_SUCCESS); 5183} 5184 5185static isc_result_t 5186delete_keynames(dns_tsig_keyring_t *ring, char *target, 5187 unsigned int *foundkeys) 5188{ 5189 char namestr[DNS_NAME_FORMATSIZE]; 5190 isc_result_t result; 5191 dns_rbtnodechain_t chain; 5192 dns_name_t foundname; 5193 dns_fixedname_t fixedorigin; 5194 dns_name_t *origin; 5195 dns_rbtnode_t *node; 5196 dns_tsigkey_t *tkey; 5197 5198 dns_name_init(&foundname, NULL); 5199 dns_fixedname_init(&fixedorigin); 5200 origin = dns_fixedname_name(&fixedorigin); 5201 5202 again: 5203 dns_rbtnodechain_init(&chain, ring->mctx); 5204 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, 5205 origin); 5206 if (result == ISC_R_NOTFOUND) { 5207 dns_rbtnodechain_invalidate(&chain); 5208 return (ISC_R_SUCCESS); 5209 } 5210 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 5211 dns_rbtnodechain_invalidate(&chain); 5212 return (result); 5213 } 5214 5215 for (;;) { 5216 node = NULL; 5217 dns_rbtnodechain_current(&chain, &foundname, origin, &node); 5218 tkey = node->data; 5219 5220 if (tkey != NULL) { 5221 if (!tkey->generated) 5222 goto nextkey; 5223 5224 dns_name_format(&tkey->name, namestr, sizeof(namestr)); 5225 if (strcmp(namestr, target) == 0) { 5226 (*foundkeys)++; 5227 dns_rbtnodechain_invalidate(&chain); 5228 (void)dns_rbt_deletename(ring->keys, 5229 &tkey->name, 5230 ISC_FALSE); 5231 goto again; 5232 } 5233 } 5234 5235 nextkey: 5236 result = dns_rbtnodechain_next(&chain, &foundname, origin); 5237 if (result == ISC_R_NOMORE) 5238 break; 5239 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 5240 dns_rbtnodechain_invalidate(&chain); 5241 return (result); 5242 } 5243 } 5244 5245 return (ISC_R_SUCCESS); 5246} 5247 5248isc_result_t 5249ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) { 5250 isc_result_t result; 5251 unsigned int n; 5252 dns_view_t *view; 5253 unsigned int foundkeys = 0; 5254 char *target; 5255 char *viewname; 5256 5257 (void)next_token(&command, " \t"); /* skip command name */ 5258 target = next_token(&command, " \t"); 5259 if (target == NULL) 5260 return (ISC_R_UNEXPECTEDEND); 5261 viewname = next_token(&command, " \t"); 5262 5263 result = isc_task_beginexclusive(server->task); 5264 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5265 for (view = ISC_LIST_HEAD(server->viewlist); 5266 view != NULL; 5267 view = ISC_LIST_NEXT(view, link)) { 5268 if (viewname == NULL || strcmp(view->name, viewname) == 0) { 5269 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write); 5270 result = delete_keynames(view->dynamickeys, target, 5271 &foundkeys); 5272 RWUNLOCK(&view->dynamickeys->lock, 5273 isc_rwlocktype_write); 5274 if (result != ISC_R_SUCCESS) { 5275 isc_task_endexclusive(server->task); 5276 return (result); 5277 } 5278 } 5279 } 5280 isc_task_endexclusive(server->task); 5281 5282 n = snprintf((char *)isc_buffer_used(text), 5283 isc_buffer_availablelength(text), 5284 "%d tsig keys deleted.\n", foundkeys); 5285 if (n >= isc_buffer_availablelength(text)) 5286 return (ISC_R_NOSPACE); 5287 isc_buffer_add(text, n); 5288 5289 return (ISC_R_SUCCESS); 5290} 5291 5292static isc_result_t 5293list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text, 5294 unsigned int *foundkeys) 5295{ 5296 char namestr[DNS_NAME_FORMATSIZE]; 5297 char creatorstr[DNS_NAME_FORMATSIZE]; 5298 isc_result_t result; 5299 dns_rbtnodechain_t chain; 5300 dns_name_t foundname; 5301 dns_fixedname_t fixedorigin; 5302 dns_name_t *origin; 5303 dns_rbtnode_t *node; 5304 dns_tsigkey_t *tkey; 5305 unsigned int n; 5306 const char *viewname; 5307 5308 if (view != NULL) 5309 viewname = view->name; 5310 else 5311 viewname = "(global)"; 5312 5313 dns_name_init(&foundname, NULL); 5314 dns_fixedname_init(&fixedorigin); 5315 origin = dns_fixedname_name(&fixedorigin); 5316 dns_rbtnodechain_init(&chain, ring->mctx); 5317 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, 5318 origin); 5319 if (result == ISC_R_NOTFOUND) { 5320 dns_rbtnodechain_invalidate(&chain); 5321 return (ISC_R_SUCCESS); 5322 } 5323 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 5324 dns_rbtnodechain_invalidate(&chain); 5325 return (result); 5326 } 5327 5328 for (;;) { 5329 node = NULL; 5330 dns_rbtnodechain_current(&chain, &foundname, origin, &node); 5331 tkey = node->data; 5332 5333 if (tkey != NULL) { 5334 (*foundkeys)++; 5335 dns_name_format(&tkey->name, namestr, sizeof(namestr)); 5336 if (tkey->generated) { 5337 dns_name_format(tkey->creator, creatorstr, 5338 sizeof(creatorstr)); 5339 n = snprintf((char *)isc_buffer_used(text), 5340 isc_buffer_availablelength(text), 5341 "view \"%s\"; type \"dynamic\"; key \"%s\"; creator \"%s\";\n", 5342 viewname, namestr, creatorstr); 5343 } else { 5344 n = snprintf((char *)isc_buffer_used(text), 5345 isc_buffer_availablelength(text), 5346 "view \"%s\"; type \"static\"; key \"%s\";\n", 5347 viewname, namestr); 5348 } 5349 if (n >= isc_buffer_availablelength(text)) { 5350 dns_rbtnodechain_invalidate(&chain); 5351 return (ISC_R_NOSPACE); 5352 } 5353 isc_buffer_add(text, n); 5354 } 5355 result = dns_rbtnodechain_next(&chain, &foundname, origin); 5356 if (result == ISC_R_NOMORE) 5357 break; 5358 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 5359 dns_rbtnodechain_invalidate(&chain); 5360 return (result); 5361 } 5362 } 5363 5364 return (ISC_R_SUCCESS); 5365} 5366 5367isc_result_t 5368ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) { 5369 isc_result_t result; 5370 unsigned int n; 5371 dns_view_t *view; 5372 unsigned int foundkeys = 0; 5373 5374 result = isc_task_beginexclusive(server->task); 5375 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5376 for (view = ISC_LIST_HEAD(server->viewlist); 5377 view != NULL; 5378 view = ISC_LIST_NEXT(view, link)) { 5379 RWLOCK(&view->statickeys->lock, isc_rwlocktype_read); 5380 result = list_keynames(view, view->statickeys, text, 5381 &foundkeys); 5382 RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read); 5383 if (result != ISC_R_SUCCESS) { 5384 isc_task_endexclusive(server->task); 5385 return (result); 5386 } 5387 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read); 5388 result = list_keynames(view, view->dynamickeys, text, 5389 &foundkeys); 5390 RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read); 5391 if (result != ISC_R_SUCCESS) { 5392 isc_task_endexclusive(server->task); 5393 return (result); 5394 } 5395 } 5396 isc_task_endexclusive(server->task); 5397 5398 if (foundkeys == 0) { 5399 n = snprintf((char *)isc_buffer_used(text), 5400 isc_buffer_availablelength(text), 5401 "no tsig keys found.\n"); 5402 if (n >= isc_buffer_availablelength(text)) 5403 return (ISC_R_NOSPACE); 5404 isc_buffer_add(text, n); 5405 } 5406 5407 return (ISC_R_SUCCESS); 5408} 5409 5410/* 5411 * Act on a "freeze" or "thaw" command from the command channel. 5412 */ 5413isc_result_t 5414ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, 5415 isc_buffer_t *text) 5416{ 5417 isc_result_t result, tresult; 5418 dns_zone_t *zone = NULL; 5419 dns_zonetype_t type; 5420 char classstr[DNS_RDATACLASS_FORMATSIZE]; 5421 char zonename[DNS_NAME_FORMATSIZE]; 5422 dns_view_t *view; 5423 char *journal; 5424 const char *vname, *sep; 5425 isc_boolean_t frozen; 5426 const char *msg = NULL; 5427 5428 result = zone_from_args(server, args, &zone); 5429 if (result != ISC_R_SUCCESS) 5430 return (result); 5431 if (zone == NULL) { 5432 result = isc_task_beginexclusive(server->task); 5433 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5434 tresult = ISC_R_SUCCESS; 5435 for (view = ISC_LIST_HEAD(server->viewlist); 5436 view != NULL; 5437 view = ISC_LIST_NEXT(view, link)) { 5438 result = dns_view_freezezones(view, freeze); 5439 if (result != ISC_R_SUCCESS && 5440 tresult == ISC_R_SUCCESS) 5441 tresult = result; 5442 } 5443 isc_task_endexclusive(server->task); 5444 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5445 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5446 "%s all zones: %s", 5447 freeze ? "freezing" : "thawing", 5448 isc_result_totext(tresult)); 5449 return (tresult); 5450 } 5451 type = dns_zone_gettype(zone); 5452 if (type != dns_zone_master) { 5453 dns_zone_detach(&zone); 5454 return (ISC_R_NOTFOUND); 5455 } 5456 5457 result = isc_task_beginexclusive(server->task); 5458 RUNTIME_CHECK(result == ISC_R_SUCCESS); 5459 frozen = dns_zone_getupdatedisabled(zone); 5460 if (freeze) { 5461 if (frozen) { 5462 msg = "WARNING: The zone was already frozen.\n" 5463 "Someone else may be editing it or " 5464 "it may still be re-loading."; 5465 result = DNS_R_FROZEN; 5466 } 5467 if (result == ISC_R_SUCCESS) { 5468 result = dns_zone_flush(zone); 5469 if (result != ISC_R_SUCCESS) 5470 msg = "Flushing the zone updates to " 5471 "disk failed."; 5472 } 5473 if (result == ISC_R_SUCCESS) { 5474 journal = dns_zone_getjournal(zone); 5475 if (journal != NULL) 5476 (void)isc_file_remove(journal); 5477 } 5478 if (result == ISC_R_SUCCESS) 5479 dns_zone_setupdatedisabled(zone, freeze); 5480 } else { 5481 if (frozen) { 5482 result = dns_zone_loadandthaw(zone); 5483 switch (result) { 5484 case ISC_R_SUCCESS: 5485 case DNS_R_UPTODATE: 5486 msg = "The zone reload and thaw was " 5487 "successful."; 5488 result = ISC_R_SUCCESS; 5489 break; 5490 case DNS_R_CONTINUE: 5491 msg = "A zone reload and thaw was started.\n" 5492 "Check the logs to see the result."; 5493 result = ISC_R_SUCCESS; 5494 break; 5495 } 5496 } 5497 } 5498 isc_task_endexclusive(server->task); 5499 5500 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) 5501 isc_buffer_putmem(text, (const unsigned char *)msg, 5502 strlen(msg) + 1); 5503 5504 view = dns_zone_getview(zone); 5505 if (strcmp(view->name, "_bind") == 0 || 5506 strcmp(view->name, "_default") == 0) 5507 { 5508 vname = ""; 5509 sep = ""; 5510 } else { 5511 vname = view->name; 5512 sep = " "; 5513 } 5514 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 5515 sizeof(classstr)); 5516 dns_name_format(dns_zone_getorigin(zone), 5517 zonename, sizeof(zonename)); 5518 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 5519 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 5520 "%s zone '%s/%s'%s%s: %s", 5521 freeze ? "freezing" : "thawing", 5522 zonename, classstr, sep, vname, 5523 isc_result_totext(result)); 5524 dns_zone_detach(&zone); 5525 return (result); 5526} 5527 5528#ifdef HAVE_LIBSCF 5529/* 5530 * This function adds a message for rndc to echo if named 5531 * is managed by smf and is also running chroot. 5532 */ 5533isc_result_t 5534ns_smf_add_message(isc_buffer_t *text) { 5535 unsigned int n; 5536 5537 n = snprintf((char *)isc_buffer_used(text), 5538 isc_buffer_availablelength(text), 5539 "use svcadm(1M) to manage named"); 5540 if (n >= isc_buffer_availablelength(text)) 5541 return (ISC_R_NOSPACE); 5542 isc_buffer_add(text, n); 5543 return (ISC_R_SUCCESS); 5544} 5545#endif /* HAVE_LIBSCF */ 5546