server.c revision 143731
1/* 2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 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.339.2.15.2.59 2004/11/10 22:13:56 marka Exp $ */ 19 20#include <config.h> 21 22#include <stdlib.h> 23 24#include <isc/app.h> 25#include <isc/base64.h> 26#include <isc/dir.h> 27#include <isc/entropy.h> 28#include <isc/file.h> 29#include <isc/hash.h> 30#include <isc/lex.h> 31#include <isc/parseint.h> 32#include <isc/print.h> 33#include <isc/resource.h> 34#include <isc/stdio.h> 35#include <isc/string.h> 36#include <isc/task.h> 37#include <isc/timer.h> 38#include <isc/util.h> 39 40#include <isccfg/namedconf.h> 41 42#include <bind9/check.h> 43 44#include <dns/adb.h> 45#include <dns/cache.h> 46#include <dns/db.h> 47#include <dns/dispatch.h> 48#include <dns/forward.h> 49#include <dns/journal.h> 50#include <dns/keytable.h> 51#include <dns/master.h> 52#include <dns/masterdump.h> 53#include <dns/order.h> 54#include <dns/peer.h> 55#include <dns/portlist.h> 56#include <dns/rdataclass.h> 57#include <dns/rdataset.h> 58#include <dns/rdatastruct.h> 59#include <dns/resolver.h> 60#include <dns/rootns.h> 61#include <dns/secalg.h> 62#include <dns/stats.h> 63#include <dns/tkey.h> 64#include <dns/view.h> 65#include <dns/zone.h> 66#include <dns/zt.h> 67 68#include <dst/dst.h> 69#include <dst/result.h> 70 71#include <named/client.h> 72#include <named/config.h> 73#include <named/control.h> 74#include <named/interfacemgr.h> 75#include <named/log.h> 76#include <named/logconf.h> 77#include <named/lwresd.h> 78#include <named/main.h> 79#include <named/os.h> 80#include <named/server.h> 81#include <named/tkeyconf.h> 82#include <named/tsigconf.h> 83#include <named/zoneconf.h> 84 85/* 86 * Check an operation for failure. Assumes that the function 87 * using it has a 'result' variable and a 'cleanup' label. 88 */ 89#define CHECK(op) \ 90 do { result = (op); \ 91 if (result != ISC_R_SUCCESS) goto cleanup; \ 92 } while (0) 93 94#define CHECKM(op, msg) \ 95 do { result = (op); \ 96 if (result != ISC_R_SUCCESS) { \ 97 isc_log_write(ns_g_lctx, \ 98 NS_LOGCATEGORY_GENERAL, \ 99 NS_LOGMODULE_SERVER, \ 100 ISC_LOG_ERROR, \ 101 "%s: %s", msg, \ 102 isc_result_totext(result)); \ 103 goto cleanup; \ 104 } \ 105 } while (0) \ 106 107#define CHECKMF(op, msg, file) \ 108 do { result = (op); \ 109 if (result != ISC_R_SUCCESS) { \ 110 isc_log_write(ns_g_lctx, \ 111 NS_LOGCATEGORY_GENERAL, \ 112 NS_LOGMODULE_SERVER, \ 113 ISC_LOG_ERROR, \ 114 "%s '%s': %s", msg, file, \ 115 isc_result_totext(result)); \ 116 goto cleanup; \ 117 } \ 118 } while (0) \ 119 120#define CHECKFATAL(op, msg) \ 121 do { result = (op); \ 122 if (result != ISC_R_SUCCESS) \ 123 fatal(msg, result); \ 124 } while (0) \ 125 126struct ns_dispatch { 127 isc_sockaddr_t addr; 128 unsigned int dispatchgen; 129 dns_dispatch_t *dispatch; 130 ISC_LINK(struct ns_dispatch) link; 131}; 132 133struct dumpcontext { 134 isc_mem_t *mctx; 135 isc_boolean_t dumpcache; 136 isc_boolean_t dumpzones; 137 FILE *fp; 138 ISC_LIST(struct viewlistentry) viewlist; 139 struct viewlistentry *view; 140 struct zonelistentry *zone; 141 dns_dumpctx_t *mdctx; 142 dns_db_t *db; 143 dns_db_t *cache; 144 isc_task_t *task; 145 dns_dbversion_t *version; 146}; 147 148struct viewlistentry { 149 dns_view_t *view; 150 ISC_LINK(struct viewlistentry) link; 151 ISC_LIST(struct zonelistentry) zonelist; 152}; 153 154struct zonelistentry { 155 dns_zone_t *zone; 156 ISC_LINK(struct zonelistentry) link; 157}; 158 159static void 160fatal(const char *msg, isc_result_t result); 161 162static void 163ns_server_reload(isc_task_t *task, isc_event_t *event); 164 165static isc_result_t 166ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config, 167 ns_aclconfctx_t *actx, 168 isc_mem_t *mctx, ns_listenelt_t **target); 169static isc_result_t 170ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config, 171 ns_aclconfctx_t *actx, 172 isc_mem_t *mctx, ns_listenlist_t **target); 173 174static isc_result_t 175configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, 176 cfg_obj_t *forwarders, cfg_obj_t *forwardtype); 177 178static isc_result_t 179configure_alternates(cfg_obj_t *config, dns_view_t *view, 180 cfg_obj_t *alternates); 181 182static isc_result_t 183configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, 184 isc_mem_t *mctx, dns_view_t *view, 185 ns_aclconfctx_t *aclconf); 186 187static void 188end_reserved_dispatches(ns_server_t *server, isc_boolean_t all); 189 190/* 191 * Configure a single view ACL at '*aclp'. Get its configuration by 192 * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl' 193 * (for a global default). 194 */ 195static isc_result_t 196configure_view_acl(cfg_obj_t *vconfig, cfg_obj_t *config, 197 const char *aclname, ns_aclconfctx_t *actx, 198 isc_mem_t *mctx, dns_acl_t **aclp) 199{ 200 isc_result_t result; 201 cfg_obj_t *maps[3]; 202 cfg_obj_t *aclobj = NULL; 203 int i = 0; 204 205 if (*aclp != NULL) 206 dns_acl_detach(aclp); 207 if (vconfig != NULL) 208 maps[i++] = cfg_tuple_get(vconfig, "options"); 209 if (config != NULL) { 210 cfg_obj_t *options = NULL; 211 (void)cfg_map_get(config, "options", &options); 212 if (options != NULL) 213 maps[i++] = options; 214 } 215 maps[i] = NULL; 216 217 result = ns_config_get(maps, aclname, &aclobj); 218 if (aclobj == NULL) 219 /* 220 * No value available. *aclp == NULL. 221 */ 222 return (ISC_R_SUCCESS); 223 224 result = ns_acl_fromconfig(aclobj, config, actx, mctx, aclp); 225 226 return (result); 227} 228 229static isc_result_t 230configure_view_dnsseckey(cfg_obj_t *vconfig, cfg_obj_t *key, 231 dns_keytable_t *keytable, isc_mem_t *mctx) 232{ 233 dns_rdataclass_t viewclass; 234 dns_rdata_dnskey_t keystruct; 235 isc_uint32_t flags, proto, alg; 236 char *keystr, *keynamestr; 237 unsigned char keydata[4096]; 238 isc_buffer_t keydatabuf; 239 unsigned char rrdata[4096]; 240 isc_buffer_t rrdatabuf; 241 isc_region_t r; 242 dns_fixedname_t fkeyname; 243 dns_name_t *keyname; 244 isc_buffer_t namebuf; 245 isc_result_t result; 246 dst_key_t *dstkey = NULL; 247 248 flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); 249 proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); 250 alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); 251 keyname = dns_fixedname_name(&fkeyname); 252 keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 253 254 if (vconfig == NULL) 255 viewclass = dns_rdataclass_in; 256 else { 257 cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class"); 258 CHECK(ns_config_getclass(classobj, dns_rdataclass_in, 259 &viewclass)); 260 } 261 keystruct.common.rdclass = viewclass; 262 keystruct.common.rdtype = dns_rdatatype_dnskey; 263 /* 264 * The key data in keystruct is not dynamically allocated. 265 */ 266 keystruct.mctx = NULL; 267 268 ISC_LINK_INIT(&keystruct.common, link); 269 270 if (flags > 0xffff) 271 CHECKM(ISC_R_RANGE, "key flags"); 272 if (proto > 0xff) 273 CHECKM(ISC_R_RANGE, "key protocol"); 274 if (alg > 0xff) 275 CHECKM(ISC_R_RANGE, "key algorithm"); 276 keystruct.flags = (isc_uint16_t)flags; 277 keystruct.protocol = (isc_uint8_t)proto; 278 keystruct.algorithm = (isc_uint8_t)alg; 279 280 isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); 281 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 282 283 keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); 284 CHECK(isc_base64_decodestring(keystr, &keydatabuf)); 285 isc_buffer_usedregion(&keydatabuf, &r); 286 keystruct.datalen = r.length; 287 keystruct.data = r.base; 288 289 CHECK(dns_rdata_fromstruct(NULL, 290 keystruct.common.rdclass, 291 keystruct.common.rdtype, 292 &keystruct, &rrdatabuf)); 293 dns_fixedname_init(&fkeyname); 294 isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); 295 isc_buffer_add(&namebuf, strlen(keynamestr)); 296 CHECK(dns_name_fromtext(keyname, &namebuf, 297 dns_rootname, ISC_FALSE, 298 NULL)); 299 CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, 300 mctx, &dstkey)); 301 302 CHECK(dns_keytable_add(keytable, &dstkey)); 303 INSIST(dstkey == NULL); 304 return (ISC_R_SUCCESS); 305 306 cleanup: 307 if (result == DST_R_NOCRYPTO) { 308 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 309 "ignoring trusted key for '%s': no crypto support", 310 keynamestr); 311 result = ISC_R_SUCCESS; 312 } else { 313 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 314 "configuring trusted key for '%s': %s", 315 keynamestr, isc_result_totext(result)); 316 result = ISC_R_FAILURE; 317 } 318 319 if (dstkey != NULL) 320 dst_key_free(&dstkey); 321 322 return (result); 323} 324 325/* 326 * Configure DNSSEC keys for a view. Currently used only for 327 * the security roots. 328 * 329 * The per-view configuration values and the server-global defaults are read 330 * from 'vconfig' and 'config'. The variable to be configured is '*target'. 331 */ 332static isc_result_t 333configure_view_dnsseckeys(cfg_obj_t *vconfig, cfg_obj_t *config, 334 isc_mem_t *mctx, dns_keytable_t **target) 335{ 336 isc_result_t result; 337 cfg_obj_t *keys = NULL; 338 cfg_obj_t *voptions = NULL; 339 cfg_listelt_t *element, *element2; 340 cfg_obj_t *keylist; 341 cfg_obj_t *key; 342 dns_keytable_t *keytable = NULL; 343 344 CHECK(dns_keytable_create(mctx, &keytable)); 345 346 if (vconfig != NULL) 347 voptions = cfg_tuple_get(vconfig, "options"); 348 349 keys = NULL; 350 if (voptions != NULL) 351 (void)cfg_map_get(voptions, "trusted-keys", &keys); 352 if (keys == NULL) 353 (void)cfg_map_get(config, "trusted-keys", &keys); 354 355 for (element = cfg_list_first(keys); 356 element != NULL; 357 element = cfg_list_next(element)) 358 { 359 keylist = cfg_listelt_value(element); 360 for (element2 = cfg_list_first(keylist); 361 element2 != NULL; 362 element2 = cfg_list_next(element2)) 363 { 364 key = cfg_listelt_value(element2); 365 CHECK(configure_view_dnsseckey(vconfig, key, 366 keytable, mctx)); 367 } 368 } 369 370 dns_keytable_detach(target); 371 *target = keytable; /* Transfer ownership. */ 372 keytable = NULL; 373 result = ISC_R_SUCCESS; 374 375 cleanup: 376 return (result); 377} 378 379static isc_result_t 380mustbesecure(cfg_obj_t *mbs, dns_resolver_t *resolver) 381{ 382 cfg_listelt_t *element; 383 cfg_obj_t *obj; 384 const char *str; 385 dns_fixedname_t fixed; 386 dns_name_t *name; 387 isc_boolean_t value; 388 isc_result_t result; 389 isc_buffer_t b; 390 391 dns_fixedname_init(&fixed); 392 name = dns_fixedname_name(&fixed); 393 for (element = cfg_list_first(mbs); 394 element != NULL; 395 element = cfg_list_next(element)) 396 { 397 obj = cfg_listelt_value(element); 398 str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 399 isc_buffer_init(&b, str, strlen(str)); 400 isc_buffer_add(&b, strlen(str)); 401 CHECK(dns_name_fromtext(name, &b, dns_rootname, 402 ISC_FALSE, NULL)); 403 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); 404 CHECK(dns_resolver_setmustbesecure(resolver, name, value)); 405 } 406 407 result = ISC_R_SUCCESS; 408 409 cleanup: 410 return (result); 411} 412 413/* 414 * Get a dispatch appropriate for the resolver of a given view. 415 */ 416static isc_result_t 417get_view_querysource_dispatch(cfg_obj_t **maps, 418 int af, dns_dispatch_t **dispatchp) 419{ 420 isc_result_t result; 421 dns_dispatch_t *disp; 422 isc_sockaddr_t sa; 423 unsigned int attrs, attrmask; 424 cfg_obj_t *obj = NULL; 425 426 /* 427 * Make compiler happy. 428 */ 429 result = ISC_R_FAILURE; 430 431 switch (af) { 432 case AF_INET: 433 result = ns_config_get(maps, "query-source", &obj); 434 INSIST(result == ISC_R_SUCCESS); 435 436 break; 437 case AF_INET6: 438 result = ns_config_get(maps, "query-source-v6", &obj); 439 INSIST(result == ISC_R_SUCCESS); 440 break; 441 default: 442 INSIST(0); 443 } 444 445 sa = *(cfg_obj_assockaddr(obj)); 446 INSIST(isc_sockaddr_pf(&sa) == af); 447 448 /* 449 * If we don't support this address family, we're done! 450 */ 451 switch (af) { 452 case AF_INET: 453 result = isc_net_probeipv4(); 454 break; 455 case AF_INET6: 456 result = isc_net_probeipv6(); 457 break; 458 default: 459 INSIST(0); 460 } 461 if (result != ISC_R_SUCCESS) 462 return (ISC_R_SUCCESS); 463 464 /* 465 * Try to find a dispatcher that we can share. 466 */ 467 attrs = 0; 468 attrs |= DNS_DISPATCHATTR_UDP; 469 switch (af) { 470 case AF_INET: 471 attrs |= DNS_DISPATCHATTR_IPV4; 472 break; 473 case AF_INET6: 474 attrs |= DNS_DISPATCHATTR_IPV6; 475 break; 476 } 477 attrmask = 0; 478 attrmask |= DNS_DISPATCHATTR_UDP; 479 attrmask |= DNS_DISPATCHATTR_TCP; 480 attrmask |= DNS_DISPATCHATTR_IPV4; 481 attrmask |= DNS_DISPATCHATTR_IPV6; 482 483 disp = NULL; 484 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, 485 ns_g_taskmgr, &sa, 4096, 486 1000, 32768, 16411, 16433, 487 attrs, attrmask, &disp); 488 if (result != ISC_R_SUCCESS) { 489 isc_sockaddr_t any; 490 char buf[ISC_SOCKADDR_FORMATSIZE]; 491 492 switch (af) { 493 case AF_INET: 494 isc_sockaddr_any(&any); 495 break; 496 case AF_INET6: 497 isc_sockaddr_any6(&any); 498 break; 499 } 500 if (isc_sockaddr_equal(&sa, &any)) 501 return (ISC_R_SUCCESS); 502 isc_sockaddr_format(&sa, buf, sizeof(buf)); 503 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 504 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 505 "could not get query source dispatcher (%s)", 506 buf); 507 return (result); 508 } 509 510 *dispatchp = disp; 511 512 return (ISC_R_SUCCESS); 513} 514 515static isc_result_t 516configure_order(dns_order_t *order, cfg_obj_t *ent) { 517 dns_rdataclass_t rdclass; 518 dns_rdatatype_t rdtype; 519 cfg_obj_t *obj; 520 dns_fixedname_t fixed; 521 unsigned int mode = 0; 522 const char *str; 523 isc_buffer_t b; 524 isc_result_t result; 525 isc_boolean_t addroot; 526 527 result = ns_config_getclass(cfg_tuple_get(ent, "class"), 528 dns_rdataclass_any, &rdclass); 529 if (result != ISC_R_SUCCESS) 530 return (result); 531 532 result = ns_config_gettype(cfg_tuple_get(ent, "type"), 533 dns_rdatatype_any, &rdtype); 534 if (result != ISC_R_SUCCESS) 535 return (result); 536 537 obj = cfg_tuple_get(ent, "name"); 538 if (cfg_obj_isstring(obj)) 539 str = cfg_obj_asstring(obj); 540 else 541 str = "*"; 542 addroot = ISC_TF(strcmp(str, "*") == 0); 543 isc_buffer_init(&b, str, strlen(str)); 544 isc_buffer_add(&b, strlen(str)); 545 dns_fixedname_init(&fixed); 546 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, 547 dns_rootname, ISC_FALSE, NULL); 548 if (result != ISC_R_SUCCESS) 549 return (result); 550 551 obj = cfg_tuple_get(ent, "ordering"); 552 INSIST(cfg_obj_isstring(obj)); 553 str = cfg_obj_asstring(obj); 554 if (!strcasecmp(str, "fixed")) 555 mode = DNS_RDATASETATTR_FIXEDORDER; 556 else if (!strcasecmp(str, "random")) 557 mode = DNS_RDATASETATTR_RANDOMIZE; 558 else if (!strcasecmp(str, "cyclic")) 559 mode = 0; 560 else 561 INSIST(0); 562 563 /* 564 * "*" should match everything including the root (BIND 8 compat). 565 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a 566 * explict entry for "." when the name is "*". 567 */ 568 if (addroot) { 569 result = dns_order_add(order, dns_rootname, 570 rdtype, rdclass, mode); 571 if (result != ISC_R_SUCCESS) 572 return (result); 573 } 574 575 return (dns_order_add(order, dns_fixedname_name(&fixed), 576 rdtype, rdclass, mode)); 577} 578 579static isc_result_t 580configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { 581 isc_sockaddr_t *sa; 582 isc_netaddr_t na; 583 dns_peer_t *peer; 584 cfg_obj_t *obj; 585 char *str; 586 isc_result_t result; 587 588 sa = cfg_obj_assockaddr(cfg_map_getname(cpeer)); 589 isc_netaddr_fromsockaddr(&na, sa); 590 591 peer = NULL; 592 result = dns_peer_new(mctx, &na, &peer); 593 if (result != ISC_R_SUCCESS) 594 return (result); 595 596 obj = NULL; 597 (void)cfg_map_get(cpeer, "bogus", &obj); 598 if (obj != NULL) 599 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); 600 601 obj = NULL; 602 (void)cfg_map_get(cpeer, "provide-ixfr", &obj); 603 if (obj != NULL) 604 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); 605 606 obj = NULL; 607 (void)cfg_map_get(cpeer, "request-ixfr", &obj); 608 if (obj != NULL) 609 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); 610 611 obj = NULL; 612 (void)cfg_map_get(cpeer, "edns", &obj); 613 if (obj != NULL) 614 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); 615 616 obj = NULL; 617 (void)cfg_map_get(cpeer, "transfers", &obj); 618 if (obj != NULL) 619 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); 620 621 obj = NULL; 622 (void)cfg_map_get(cpeer, "transfer-format", &obj); 623 if (obj != NULL) { 624 str = cfg_obj_asstring(obj); 625 if (strcasecmp(str, "many-answers") == 0) 626 CHECK(dns_peer_settransferformat(peer, 627 dns_many_answers)); 628 else if (strcasecmp(str, "one-answer") == 0) 629 CHECK(dns_peer_settransferformat(peer, 630 dns_one_answer)); 631 else 632 INSIST(0); 633 } 634 635 obj = NULL; 636 (void)cfg_map_get(cpeer, "keys", &obj); 637 if (obj != NULL) { 638 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); 639 if (result != ISC_R_SUCCESS) 640 goto cleanup; 641 } 642 643 obj = NULL; 644 if (isc_sockaddr_pf(sa) == AF_INET) 645 (void)cfg_map_get(cpeer, "transfer-source", &obj); 646 else 647 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); 648 if (obj != NULL) { 649 result = dns_peer_settransfersource(peer, 650 cfg_obj_assockaddr(obj)); 651 if (result != ISC_R_SUCCESS) 652 goto cleanup; 653 } 654 *peerp = peer; 655 return (ISC_R_SUCCESS); 656 657 cleanup: 658 dns_peer_detach(&peer); 659 return (result); 660} 661 662static isc_result_t 663disable_algorithms(cfg_obj_t *disabled, dns_resolver_t *resolver) { 664 isc_result_t result; 665 cfg_obj_t *algorithms; 666 cfg_listelt_t *element; 667 const char *str; 668 dns_fixedname_t fixed; 669 dns_name_t *name; 670 isc_buffer_t b; 671 672 dns_fixedname_init(&fixed); 673 name = dns_fixedname_name(&fixed); 674 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 675 isc_buffer_init(&b, str, strlen(str)); 676 isc_buffer_add(&b, strlen(str)); 677 CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL)); 678 679 algorithms = cfg_tuple_get(disabled, "algorithms"); 680 for (element = cfg_list_first(algorithms); 681 element != NULL; 682 element = cfg_list_next(element)) 683 { 684 isc_textregion_t r; 685 dns_secalg_t alg; 686 687 r.base = cfg_obj_asstring(cfg_listelt_value(element)); 688 r.length = strlen(r.base); 689 690 result = dns_secalg_fromtext(&alg, &r); 691 if (result != ISC_R_SUCCESS) { 692 isc_uint8_t ui; 693 result = isc_parse_uint8(&ui, r.base, 10); 694 alg = ui; 695 } 696 if (result != ISC_R_SUCCESS) { 697 cfg_obj_log(cfg_listelt_value(element), 698 ns_g_lctx, ISC_LOG_ERROR, 699 "invalid algorithm"); 700 CHECK(result); 701 } 702 CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); 703 } 704 cleanup: 705 return (result); 706} 707 708/* 709 * Configure 'view' according to 'vconfig', taking defaults from 'config' 710 * where values are missing in 'vconfig'. 711 * 712 * When configuring the default view, 'vconfig' will be NULL and the 713 * global defaults in 'config' used exclusively. 714 */ 715static isc_result_t 716configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 717 isc_mem_t *mctx, ns_aclconfctx_t *actx, 718 isc_boolean_t need_hints) 719{ 720 cfg_obj_t *maps[4]; 721 cfg_obj_t *cfgmaps[3]; 722 cfg_obj_t *options = NULL; 723 cfg_obj_t *voptions = NULL; 724 cfg_obj_t *forwardtype; 725 cfg_obj_t *forwarders; 726 cfg_obj_t *alternates; 727 cfg_obj_t *zonelist; 728 cfg_obj_t *disabled; 729 cfg_obj_t *obj; 730 cfg_listelt_t *element; 731 in_port_t port; 732 dns_cache_t *cache = NULL; 733 isc_result_t result; 734 isc_uint32_t max_adb_size; 735 isc_uint32_t max_cache_size; 736 isc_uint32_t lame_ttl; 737 dns_tsig_keyring_t *ring; 738 dns_view_t *pview = NULL; /* Production view */ 739 isc_mem_t *cmctx; 740 dns_dispatch_t *dispatch4 = NULL; 741 dns_dispatch_t *dispatch6 = NULL; 742 isc_boolean_t reused_cache = ISC_FALSE; 743 int i; 744 const char *str; 745 dns_order_t *order = NULL; 746 isc_uint32_t udpsize; 747 unsigned int check = 0; 748 749 REQUIRE(DNS_VIEW_VALID(view)); 750 751 cmctx = NULL; 752 753 if (config != NULL) 754 (void)cfg_map_get(config, "options", &options); 755 756 i = 0; 757 if (vconfig != NULL) { 758 voptions = cfg_tuple_get(vconfig, "options"); 759 maps[i++] = voptions; 760 } 761 if (options != NULL) 762 maps[i++] = options; 763 maps[i++] = ns_g_defaults; 764 maps[i] = NULL; 765 766 i = 0; 767 if (voptions != NULL) 768 cfgmaps[i++] = voptions; 769 if (config != NULL) 770 cfgmaps[i++] = config; 771 cfgmaps[i] = NULL; 772 773 /* 774 * Set the view's port number for outgoing queries. 775 */ 776 CHECKM(ns_config_getport(config, &port), "port"); 777 dns_view_setdstport(view, port); 778 779 /* 780 * Configure the zones. 781 */ 782 zonelist = NULL; 783 if (voptions != NULL) 784 (void)cfg_map_get(voptions, "zone", &zonelist); 785 else 786 (void)cfg_map_get(config, "zone", &zonelist); 787 for (element = cfg_list_first(zonelist); 788 element != NULL; 789 element = cfg_list_next(element)) 790 { 791 cfg_obj_t *zconfig = cfg_listelt_value(element); 792 CHECK(configure_zone(config, zconfig, vconfig, mctx, view, 793 actx)); 794 } 795 796 /* 797 * Configure the view's cache. Try to reuse an existing 798 * cache if possible, otherwise create a new cache. 799 * Note that the ADB is not preserved in either case. 800 * 801 * XXX Determining when it is safe to reuse a cache is 802 * tricky. When the view's configuration changes, the cached 803 * data may become invalid because it reflects our old 804 * view of the world. As more view attributes become 805 * configurable, we will have to add code here to check 806 * whether they have changed in ways that could 807 * invalidate the cache. 808 */ 809 result = dns_viewlist_find(&ns_g_server->viewlist, 810 view->name, view->rdclass, 811 &pview); 812 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 813 goto cleanup; 814 if (pview != NULL) { 815 INSIST(pview->cache != NULL); 816 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 817 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3), 818 "reusing existing cache"); 819 reused_cache = ISC_TRUE; 820 dns_cache_attach(pview->cache, &cache); 821 dns_view_detach(&pview); 822 } else { 823 CHECK(isc_mem_create(0, 0, &cmctx)); 824 CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr, 825 view->rdclass, "rbt", 0, NULL, &cache)); 826 } 827 dns_view_setcache(view, cache); 828 829 /* 830 * cache-file cannot be inherited if views are present, but this 831 * should be caught by the configuration checking stage. 832 */ 833 obj = NULL; 834 result = ns_config_get(maps, "cache-file", &obj); 835 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) { 836 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj))); 837 if (!reused_cache) 838 CHECK(dns_cache_load(cache)); 839 } 840 841 obj = NULL; 842 result = ns_config_get(maps, "cleaning-interval", &obj); 843 INSIST(result == ISC_R_SUCCESS); 844 dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60); 845 846 obj = NULL; 847 result = ns_config_get(maps, "max-cache-size", &obj); 848 INSIST(result == ISC_R_SUCCESS); 849 if (cfg_obj_isstring(obj)) { 850 str = cfg_obj_asstring(obj); 851 INSIST(strcasecmp(str, "unlimited") == 0); 852 max_cache_size = ISC_UINT32_MAX; 853 } else { 854 isc_resourcevalue_t value; 855 value = cfg_obj_asuint64(obj); 856 if (value > ISC_UINT32_MAX) { 857 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 858 "'max-cache-size " 859 "%" ISC_PRINT_QUADFORMAT "d' is too large", 860 value); 861 result = ISC_R_RANGE; 862 goto cleanup; 863 } 864 max_cache_size = (isc_uint32_t)value; 865 } 866 dns_cache_setcachesize(cache, max_cache_size); 867 868 dns_cache_detach(&cache); 869 870 /* 871 * Check-names. 872 */ 873 obj = NULL; 874 result = ns_checknames_get(maps, "response", &obj); 875 INSIST(result == ISC_R_SUCCESS); 876 877 str = cfg_obj_asstring(obj); 878 if (strcasecmp(str, "fail") == 0) { 879 check = DNS_RESOLVER_CHECKNAMES | 880 DNS_RESOLVER_CHECKNAMESFAIL; 881 view->checknames = ISC_TRUE; 882 } else if (strcasecmp(str, "warn") == 0) { 883 check = DNS_RESOLVER_CHECKNAMES; 884 view->checknames = ISC_FALSE; 885 } else if (strcasecmp(str, "ignore") == 0) { 886 check = 0; 887 view->checknames = ISC_FALSE; 888 } else 889 INSIST(0); 890 891 /* 892 * Resolver. 893 * 894 * XXXRTH Hardwired number of tasks. 895 */ 896 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4)); 897 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6)); 898 if (dispatch4 == NULL && dispatch6 == NULL) { 899 UNEXPECTED_ERROR(__FILE__, __LINE__, 900 "unable to obtain neither an IPv4 nor" 901 " an IPv6 dispatch"); 902 result = ISC_R_UNEXPECTED; 903 goto cleanup; 904 } 905 CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, 906 ns_g_socketmgr, ns_g_timermgr, 907 check, ns_g_dispatchmgr, 908 dispatch4, dispatch6)); 909 910 /* 911 * Set the ADB cache size to 1/8th of the max-cache-size. 912 */ 913 max_adb_size = 0; 914 if (max_cache_size != 0) { 915 max_adb_size = max_cache_size / 8; 916 if (max_adb_size == 0) 917 max_adb_size = 1; /* Force minimum. */ 918 } 919 dns_adb_setadbsize(view->adb, max_adb_size); 920 921 /* 922 * Set resolver's lame-ttl. 923 */ 924 obj = NULL; 925 result = ns_config_get(maps, "lame-ttl", &obj); 926 INSIST(result == ISC_R_SUCCESS); 927 lame_ttl = cfg_obj_asuint32(obj); 928 if (lame_ttl > 1800) 929 lame_ttl = 1800; 930 dns_resolver_setlamettl(view->resolver, lame_ttl); 931 932 /* 933 * Set the resolver's EDNS UDP size. 934 */ 935 obj = NULL; 936 result = ns_config_get(maps, "edns-udp-size", &obj); 937 INSIST(result == ISC_R_SUCCESS); 938 udpsize = cfg_obj_asuint32(obj); 939 if (udpsize < 512) 940 udpsize = 512; 941 if (udpsize > 4096) 942 udpsize = 4096; 943 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize); 944 945 /* 946 * Set supported DNSSEC algorithms. 947 */ 948 dns_resolver_reset_algorithms(view->resolver); 949 disabled = NULL; 950 (void)ns_config_get(maps, "disable-algorithms", &disabled); 951 if (disabled != NULL) { 952 for (element = cfg_list_first(disabled); 953 element != NULL; 954 element = cfg_list_next(element)) 955 CHECK(disable_algorithms(cfg_listelt_value(element), 956 view->resolver)); 957 } 958 959 /* 960 * A global or view "forwarders" option, if present, 961 * creates an entry for "." in the forwarding table. 962 */ 963 forwardtype = NULL; 964 forwarders = NULL; 965 (void)ns_config_get(maps, "forward", &forwardtype); 966 (void)ns_config_get(maps, "forwarders", &forwarders); 967 if (forwarders != NULL) 968 CHECK(configure_forward(config, view, dns_rootname, 969 forwarders, forwardtype)); 970 971 /* 972 * Dual Stack Servers. 973 */ 974 alternates = NULL; 975 (void)ns_config_get(maps, "dual-stack-servers", &alternates); 976 if (alternates != NULL) 977 CHECK(configure_alternates(config, view, alternates)); 978 979 /* 980 * We have default hints for class IN if we need them. 981 */ 982 if (view->rdclass == dns_rdataclass_in && view->hints == NULL) 983 dns_view_sethints(view, ns_g_server->in_roothints); 984 985 /* 986 * If we still have no hints, this is a non-IN view with no 987 * "hints zone" configured. Issue a warning, except if this 988 * is a root server. Root servers never need to consult 989 * their hints, so it's no point requiring users to configure 990 * them. 991 */ 992 if (view->hints == NULL) { 993 dns_zone_t *rootzone = NULL; 994 (void)dns_view_findzone(view, dns_rootname, &rootzone); 995 if (rootzone != NULL) { 996 dns_zone_detach(&rootzone); 997 need_hints = ISC_FALSE; 998 } 999 if (need_hints) 1000 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1001 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 1002 "no root hints for view '%s'", 1003 view->name); 1004 } 1005 1006 /* 1007 * Configure the view's TSIG keys. 1008 */ 1009 ring = NULL; 1010 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); 1011 dns_view_setkeyring(view, ring); 1012 1013 /* 1014 * Configure the view's peer list. 1015 */ 1016 { 1017 cfg_obj_t *peers = NULL; 1018 cfg_listelt_t *element; 1019 dns_peerlist_t *newpeers = NULL; 1020 1021 (void)ns_config_get(cfgmaps, "server", &peers); 1022 CHECK(dns_peerlist_new(mctx, &newpeers)); 1023 for (element = cfg_list_first(peers); 1024 element != NULL; 1025 element = cfg_list_next(element)) 1026 { 1027 cfg_obj_t *cpeer = cfg_listelt_value(element); 1028 dns_peer_t *peer; 1029 1030 CHECK(configure_peer(cpeer, mctx, &peer)); 1031 dns_peerlist_addpeer(newpeers, peer); 1032 dns_peer_detach(&peer); 1033 } 1034 dns_peerlist_detach(&view->peers); 1035 view->peers = newpeers; /* Transfer ownership. */ 1036 } 1037 1038 /* 1039 * Configure the views rrset-order. 1040 */ 1041 { 1042 cfg_obj_t *rrsetorder = NULL; 1043 cfg_listelt_t *element; 1044 1045 (void)ns_config_get(maps, "rrset-order", &rrsetorder); 1046 CHECK(dns_order_create(mctx, &order)); 1047 for (element = cfg_list_first(rrsetorder); 1048 element != NULL; 1049 element = cfg_list_next(element)) 1050 { 1051 cfg_obj_t *ent = cfg_listelt_value(element); 1052 1053 CHECK(configure_order(order, ent)); 1054 } 1055 if (view->order != NULL) 1056 dns_order_detach(&view->order); 1057 dns_order_attach(order, &view->order); 1058 dns_order_detach(&order); 1059 } 1060 /* 1061 * Copy the aclenv object. 1062 */ 1063 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv); 1064 1065 /* 1066 * Configure the "match-clients" and "match-destinations" ACL. 1067 */ 1068 CHECK(configure_view_acl(vconfig, config, "match-clients", actx, 1069 ns_g_mctx, &view->matchclients)); 1070 CHECK(configure_view_acl(vconfig, config, "match-destinations", actx, 1071 ns_g_mctx, &view->matchdestinations)); 1072 1073 /* 1074 * Configure the "match-recursive-only" option. 1075 */ 1076 obj = NULL; 1077 (void) ns_config_get(maps, "match-recursive-only", &obj); 1078 if (obj != NULL && cfg_obj_asboolean(obj)) 1079 view->matchrecursiveonly = ISC_TRUE; 1080 else 1081 view->matchrecursiveonly = ISC_FALSE; 1082 1083 /* 1084 * Configure other configurable data. 1085 */ 1086 obj = NULL; 1087 result = ns_config_get(maps, "recursion", &obj); 1088 INSIST(result == ISC_R_SUCCESS); 1089 view->recursion = cfg_obj_asboolean(obj); 1090 1091 obj = NULL; 1092 result = ns_config_get(maps, "auth-nxdomain", &obj); 1093 INSIST(result == ISC_R_SUCCESS); 1094 view->auth_nxdomain = cfg_obj_asboolean(obj); 1095 1096 obj = NULL; 1097 result = ns_config_get(maps, "minimal-responses", &obj); 1098 INSIST(result == ISC_R_SUCCESS); 1099 view->minimalresponses = cfg_obj_asboolean(obj); 1100 1101 obj = NULL; 1102 result = ns_config_get(maps, "transfer-format", &obj); 1103 INSIST(result == ISC_R_SUCCESS); 1104 str = cfg_obj_asstring(obj); 1105 if (strcasecmp(str, "many-answers") == 0) 1106 view->transfer_format = dns_many_answers; 1107 else if (strcasecmp(str, "one-answer") == 0) 1108 view->transfer_format = dns_one_answer; 1109 else 1110 INSIST(0); 1111 1112 /* 1113 * Set sources where additional data and CNAME/DNAME 1114 * targets for authoritative answers may be found. 1115 */ 1116 obj = NULL; 1117 result = ns_config_get(maps, "additional-from-auth", &obj); 1118 INSIST(result == ISC_R_SUCCESS); 1119 view->additionalfromauth = cfg_obj_asboolean(obj); 1120 if (view->recursion && ! view->additionalfromauth) { 1121 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 1122 "'additional-from-auth no' is only supported " 1123 "with 'recursion no'"); 1124 view->additionalfromauth = ISC_TRUE; 1125 } 1126 1127 obj = NULL; 1128 result = ns_config_get(maps, "additional-from-cache", &obj); 1129 INSIST(result == ISC_R_SUCCESS); 1130 view->additionalfromcache = cfg_obj_asboolean(obj); 1131 if (view->recursion && ! view->additionalfromcache) { 1132 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 1133 "'additional-from-cache no' is only supported " 1134 "with 'recursion no'"); 1135 view->additionalfromcache = ISC_TRUE; 1136 } 1137 1138 CHECK(configure_view_acl(vconfig, config, "allow-query", 1139 actx, ns_g_mctx, &view->queryacl)); 1140 1141 if (strcmp(view->name, "_bind") != 0) 1142 CHECK(configure_view_acl(vconfig, config, "allow-recursion", 1143 actx, ns_g_mctx, &view->recursionacl)); 1144 1145 /* 1146 * Warning if both "recursion no;" and allow-recursion are active 1147 * except for "allow-recursion { none; };". 1148 */ 1149 if (!view->recursion && view->recursionacl != NULL && 1150 (view->recursionacl->length != 1 || 1151 view->recursionacl->elements[0].type != dns_aclelementtype_any || 1152 view->recursionacl->elements[0].negative != ISC_TRUE)) { 1153 const char *forview = " for view "; 1154 const char *viewname = view->name; 1155 1156 if (!strcmp(view->name, "_bind") || 1157 !strcmp(view->name, "_default")) { 1158 forview = ""; 1159 viewname = ""; 1160 } 1161 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1162 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 1163 "both \"recursion no;\" and \"allow-recursion\" " 1164 "active%s%s", forview, viewname); 1165 } 1166 1167 CHECK(configure_view_acl(vconfig, config, "sortlist", 1168 actx, ns_g_mctx, &view->sortlist)); 1169 1170 obj = NULL; 1171 result = ns_config_get(maps, "request-ixfr", &obj); 1172 INSIST(result == ISC_R_SUCCESS); 1173 view->requestixfr = cfg_obj_asboolean(obj); 1174 1175 obj = NULL; 1176 result = ns_config_get(maps, "provide-ixfr", &obj); 1177 INSIST(result == ISC_R_SUCCESS); 1178 view->provideixfr = cfg_obj_asboolean(obj); 1179 1180 obj = NULL; 1181 result = ns_config_get(maps, "dnssec-enable", &obj); 1182 INSIST(result == ISC_R_SUCCESS); 1183 view->enablednssec = cfg_obj_asboolean(obj); 1184 1185 obj = NULL; 1186 result = ns_config_get(maps, "dnssec-lookaside", &obj); 1187 if (result == ISC_R_SUCCESS) { 1188 for (element = cfg_list_first(obj); 1189 element != NULL; 1190 element = cfg_list_next(element)) 1191 { 1192 const char *str; 1193 isc_buffer_t b; 1194 dns_name_t *dlv; 1195 1196 obj = cfg_listelt_value(element); 1197#if 0 1198 dns_fixedname_t fixed; 1199 dns_name_t *name; 1200 1201 /* 1202 * When we support multiple dnssec-lookaside 1203 * entries this is how to find the domain to be 1204 * checked. XXXMPA 1205 */ 1206 dns_fixedname_init(&fixed); 1207 name = dns_fixedname_name(&fixed); 1208 str = cfg_obj_asstring(cfg_tuple_get(obj, 1209 "domain")); 1210 isc_buffer_init(&b, str, strlen(str)); 1211 isc_buffer_add(&b, strlen(str)); 1212 CHECK(dns_name_fromtext(name, &b, dns_rootname, 1213 ISC_TRUE, NULL)); 1214#endif 1215 str = cfg_obj_asstring(cfg_tuple_get(obj, 1216 "trust-anchor")); 1217 isc_buffer_init(&b, str, strlen(str)); 1218 isc_buffer_add(&b, strlen(str)); 1219 dlv = dns_fixedname_name(&view->dlv_fixed); 1220 CHECK(dns_name_fromtext(dlv, &b, dns_rootname, 1221 ISC_TRUE, NULL)); 1222 view->dlv = dns_fixedname_name(&view->dlv_fixed); 1223 } 1224 } else 1225 view->dlv = NULL; 1226 1227 /* 1228 * For now, there is only one kind of trusted keys, the 1229 * "security roots". 1230 */ 1231 if (view->enablednssec) { 1232 CHECK(configure_view_dnsseckeys(vconfig, config, mctx, 1233 &view->secroots)); 1234 dns_resolver_resetmustbesecure(view->resolver); 1235 obj = NULL; 1236 result = ns_config_get(maps, "dnssec-must-be-secure", &obj); 1237 if (result == ISC_R_SUCCESS) 1238 CHECK(mustbesecure(obj, view->resolver)); 1239 } 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 obj = NULL; 1254 result = ns_config_get(maps, "preferred-glue", &obj); 1255 if (result == ISC_R_SUCCESS) { 1256 str = cfg_obj_asstring(obj); 1257 if (strcasecmp(str, "a") == 0) 1258 view->preferred_glue = dns_rdatatype_a; 1259 else if (strcasecmp(str, "aaaa") == 0) 1260 view->preferred_glue = dns_rdatatype_aaaa; 1261 else 1262 view->preferred_glue = 0; 1263 } else 1264 view->preferred_glue = 0; 1265 1266 obj = NULL; 1267 result = ns_config_get(maps, "root-delegation-only", &obj); 1268 if (result == ISC_R_SUCCESS) { 1269 dns_view_setrootdelonly(view, ISC_TRUE); 1270 if (!cfg_obj_isvoid(obj)) { 1271 dns_fixedname_t fixed; 1272 dns_name_t *name; 1273 isc_buffer_t b; 1274 char *str; 1275 cfg_obj_t *exclude; 1276 1277 dns_fixedname_init(&fixed); 1278 name = dns_fixedname_name(&fixed); 1279 for (element = cfg_list_first(obj); 1280 element != NULL; 1281 element = cfg_list_next(element)) { 1282 exclude = cfg_listelt_value(element); 1283 str = cfg_obj_asstring(exclude); 1284 isc_buffer_init(&b, str, strlen(str)); 1285 isc_buffer_add(&b, strlen(str)); 1286 CHECK(dns_name_fromtext(name, &b, dns_rootname, 1287 ISC_FALSE, NULL)); 1288 CHECK(dns_view_excludedelegationonly(view, 1289 name)); 1290 } 1291 } 1292 } else 1293 dns_view_setrootdelonly(view, ISC_FALSE); 1294 1295 result = ISC_R_SUCCESS; 1296 1297 cleanup: 1298 if (dispatch4 != NULL) 1299 dns_dispatch_detach(&dispatch4); 1300 if (dispatch6 != NULL) 1301 dns_dispatch_detach(&dispatch6); 1302 if (order != NULL) 1303 dns_order_detach(&order); 1304 if (cmctx != NULL) 1305 isc_mem_detach(&cmctx); 1306 1307 if (cache != NULL) 1308 dns_cache_detach(&cache); 1309 1310 return (result); 1311} 1312 1313static isc_result_t 1314configure_hints(dns_view_t *view, const char *filename) { 1315 isc_result_t result; 1316 dns_db_t *db; 1317 1318 db = NULL; 1319 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); 1320 if (result == ISC_R_SUCCESS) { 1321 dns_view_sethints(view, db); 1322 dns_db_detach(&db); 1323 } 1324 1325 return (result); 1326} 1327 1328static isc_result_t 1329configure_alternates(cfg_obj_t *config, dns_view_t *view, 1330 cfg_obj_t *alternates) 1331{ 1332 cfg_obj_t *portobj; 1333 cfg_obj_t *addresses; 1334 cfg_listelt_t *element; 1335 isc_result_t result = ISC_R_SUCCESS; 1336 in_port_t port; 1337 1338 /* 1339 * Determine which port to send requests to. 1340 */ 1341 if (ns_g_lwresdonly && ns_g_port != 0) 1342 port = ns_g_port; 1343 else 1344 CHECKM(ns_config_getport(config, &port), "port"); 1345 1346 if (alternates != NULL) { 1347 portobj = cfg_tuple_get(alternates, "port"); 1348 if (cfg_obj_isuint32(portobj)) { 1349 isc_uint32_t val = cfg_obj_asuint32(portobj); 1350 if (val > ISC_UINT16_MAX) { 1351 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 1352 "port '%u' out of range", val); 1353 return (ISC_R_RANGE); 1354 } 1355 port = (in_port_t) val; 1356 } 1357 } 1358 1359 addresses = NULL; 1360 if (alternates != NULL) 1361 addresses = cfg_tuple_get(alternates, "addresses"); 1362 1363 for (element = cfg_list_first(addresses); 1364 element != NULL; 1365 element = cfg_list_next(element)) 1366 { 1367 cfg_obj_t *alternate = cfg_listelt_value(element); 1368 isc_sockaddr_t sa; 1369 1370 if (!cfg_obj_issockaddr(alternate)) { 1371 dns_fixedname_t fixed; 1372 dns_name_t *name; 1373 char *str = cfg_obj_asstring(cfg_tuple_get(alternate, 1374 "name")); 1375 isc_buffer_t buffer; 1376 in_port_t myport = port; 1377 1378 isc_buffer_init(&buffer, str, strlen(str)); 1379 isc_buffer_add(&buffer, strlen(str)); 1380 dns_fixedname_init(&fixed); 1381 name = dns_fixedname_name(&fixed); 1382 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 1383 ISC_FALSE, NULL)); 1384 1385 portobj = cfg_tuple_get(alternate, "port"); 1386 if (cfg_obj_isuint32(portobj)) { 1387 isc_uint32_t val = cfg_obj_asuint32(portobj); 1388 if (val > ISC_UINT16_MAX) { 1389 cfg_obj_log(portobj, ns_g_lctx, 1390 ISC_LOG_ERROR, 1391 "port '%u' out of range", 1392 val); 1393 return (ISC_R_RANGE); 1394 } 1395 myport = (in_port_t) val; 1396 } 1397 CHECK(dns_resolver_addalternate(view->resolver, NULL, 1398 name, myport)); 1399 continue; 1400 } 1401 1402 sa = *cfg_obj_assockaddr(alternate); 1403 if (isc_sockaddr_getport(&sa) == 0) 1404 isc_sockaddr_setport(&sa, port); 1405 CHECK(dns_resolver_addalternate(view->resolver, &sa, 1406 NULL, 0)); 1407 } 1408 1409 cleanup: 1410 return (result); 1411} 1412 1413static isc_result_t 1414configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, 1415 cfg_obj_t *forwarders, cfg_obj_t *forwardtype) 1416{ 1417 cfg_obj_t *portobj; 1418 cfg_obj_t *faddresses; 1419 cfg_listelt_t *element; 1420 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 1421 isc_sockaddrlist_t addresses; 1422 isc_sockaddr_t *sa; 1423 isc_result_t result; 1424 in_port_t port; 1425 1426 /* 1427 * Determine which port to send forwarded requests to. 1428 */ 1429 if (ns_g_lwresdonly && ns_g_port != 0) 1430 port = ns_g_port; 1431 else 1432 CHECKM(ns_config_getport(config, &port), "port"); 1433 1434 if (forwarders != NULL) { 1435 portobj = cfg_tuple_get(forwarders, "port"); 1436 if (cfg_obj_isuint32(portobj)) { 1437 isc_uint32_t val = cfg_obj_asuint32(portobj); 1438 if (val > ISC_UINT16_MAX) { 1439 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 1440 "port '%u' out of range", val); 1441 return (ISC_R_RANGE); 1442 } 1443 port = (in_port_t) val; 1444 } 1445 } 1446 1447 faddresses = NULL; 1448 if (forwarders != NULL) 1449 faddresses = cfg_tuple_get(forwarders, "addresses"); 1450 1451 ISC_LIST_INIT(addresses); 1452 1453 for (element = cfg_list_first(faddresses); 1454 element != NULL; 1455 element = cfg_list_next(element)) 1456 { 1457 cfg_obj_t *forwarder = cfg_listelt_value(element); 1458 sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t)); 1459 if (sa == NULL) { 1460 result = ISC_R_NOMEMORY; 1461 goto cleanup; 1462 } 1463 *sa = *cfg_obj_assockaddr(forwarder); 1464 if (isc_sockaddr_getport(sa) == 0) 1465 isc_sockaddr_setport(sa, port); 1466 ISC_LINK_INIT(sa, link); 1467 ISC_LIST_APPEND(addresses, sa, link); 1468 } 1469 1470 if (ISC_LIST_EMPTY(addresses)) { 1471 if (forwardtype != NULL) 1472 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, 1473 "no forwarders seen; disabling " 1474 "forwarding"); 1475 fwdpolicy = dns_fwdpolicy_none; 1476 } else { 1477 if (forwardtype == NULL) 1478 fwdpolicy = dns_fwdpolicy_first; 1479 else { 1480 char *forwardstr = cfg_obj_asstring(forwardtype); 1481 if (strcasecmp(forwardstr, "first") == 0) 1482 fwdpolicy = dns_fwdpolicy_first; 1483 else if (strcasecmp(forwardstr, "only") == 0) 1484 fwdpolicy = dns_fwdpolicy_only; 1485 else 1486 INSIST(0); 1487 } 1488 } 1489 1490 result = dns_fwdtable_add(view->fwdtable, origin, &addresses, 1491 fwdpolicy); 1492 if (result != ISC_R_SUCCESS) { 1493 char namebuf[DNS_NAME_FORMATSIZE]; 1494 dns_name_format(origin, namebuf, sizeof(namebuf)); 1495 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, 1496 "could not set up forwarding for domain '%s': %s", 1497 namebuf, isc_result_totext(result)); 1498 goto cleanup; 1499 } 1500 1501 result = ISC_R_SUCCESS; 1502 1503 cleanup: 1504 1505 while (!ISC_LIST_EMPTY(addresses)) { 1506 sa = ISC_LIST_HEAD(addresses); 1507 ISC_LIST_UNLINK(addresses, sa, link); 1508 isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t)); 1509 } 1510 1511 return (result); 1512} 1513 1514/* 1515 * Create a new view and add it to the list. 1516 * 1517 * If 'vconfig' is NULL, create the default view. 1518 * 1519 * The view created is attached to '*viewp'. 1520 */ 1521static isc_result_t 1522create_view(cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) { 1523 isc_result_t result; 1524 const char *viewname; 1525 dns_rdataclass_t viewclass; 1526 dns_view_t *view = NULL; 1527 1528 if (vconfig != NULL) { 1529 cfg_obj_t *classobj = NULL; 1530 1531 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 1532 classobj = cfg_tuple_get(vconfig, "class"); 1533 result = ns_config_getclass(classobj, dns_rdataclass_in, 1534 &viewclass); 1535 } else { 1536 viewname = "_default"; 1537 viewclass = dns_rdataclass_in; 1538 } 1539 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 1540 if (result == ISC_R_SUCCESS) 1541 return (ISC_R_EXISTS); 1542 if (result != ISC_R_NOTFOUND) 1543 return (result); 1544 INSIST(view == NULL); 1545 1546 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view); 1547 if (result != ISC_R_SUCCESS) 1548 return (result); 1549 1550 ISC_LIST_APPEND(*viewlist, view, link); 1551 dns_view_attach(view, viewp); 1552 return (ISC_R_SUCCESS); 1553} 1554 1555/* 1556 * Configure or reconfigure a zone. 1557 */ 1558static isc_result_t 1559configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, 1560 isc_mem_t *mctx, dns_view_t *view, 1561 ns_aclconfctx_t *aclconf) 1562{ 1563 dns_view_t *pview = NULL; /* Production view */ 1564 dns_zone_t *zone = NULL; /* New or reused zone */ 1565 dns_zone_t *dupzone = NULL; 1566 cfg_obj_t *options = NULL; 1567 cfg_obj_t *zoptions = NULL; 1568 cfg_obj_t *typeobj = NULL; 1569 cfg_obj_t *forwarders = NULL; 1570 cfg_obj_t *forwardtype = NULL; 1571 cfg_obj_t *only = NULL; 1572 isc_result_t result; 1573 isc_result_t tresult; 1574 isc_buffer_t buffer; 1575 dns_fixedname_t fixorigin; 1576 dns_name_t *origin; 1577 const char *zname; 1578 dns_rdataclass_t zclass; 1579 const char *ztypestr; 1580 1581 options = NULL; 1582 (void)cfg_map_get(config, "options", &options); 1583 1584 zoptions = cfg_tuple_get(zconfig, "options"); 1585 1586 /* 1587 * Get the zone origin as a dns_name_t. 1588 */ 1589 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 1590 isc_buffer_init(&buffer, zname, strlen(zname)); 1591 isc_buffer_add(&buffer, strlen(zname)); 1592 dns_fixedname_init(&fixorigin); 1593 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), 1594 &buffer, dns_rootname, ISC_FALSE, NULL)); 1595 origin = dns_fixedname_name(&fixorigin); 1596 1597 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), 1598 view->rdclass, &zclass)); 1599 if (zclass != view->rdclass) { 1600 const char *vname = NULL; 1601 if (vconfig != NULL) 1602 vname = cfg_obj_asstring(cfg_tuple_get(vconfig, 1603 "name")); 1604 else 1605 vname = "<default view>"; 1606 1607 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1608 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 1609 "zone '%s': wrong class for view '%s'", 1610 zname, vname); 1611 result = ISC_R_FAILURE; 1612 goto cleanup; 1613 } 1614 1615 (void)cfg_map_get(zoptions, "type", &typeobj); 1616 if (typeobj == NULL) { 1617 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 1618 "zone '%s' 'type' not specified", zname); 1619 return (ISC_R_FAILURE); 1620 } 1621 ztypestr = cfg_obj_asstring(typeobj); 1622 1623 /* 1624 * "hints zones" aren't zones. If we've got one, 1625 * configure it and return. 1626 */ 1627 if (strcasecmp(ztypestr, "hint") == 0) { 1628 cfg_obj_t *fileobj = NULL; 1629 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { 1630 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1631 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 1632 "zone '%s': 'file' not specified", 1633 zname); 1634 result = ISC_R_FAILURE; 1635 goto cleanup; 1636 } 1637 if (dns_name_equal(origin, dns_rootname)) { 1638 char *hintsfile = cfg_obj_asstring(fileobj); 1639 1640 result = configure_hints(view, hintsfile); 1641 if (result != ISC_R_SUCCESS) { 1642 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1643 NS_LOGMODULE_SERVER, 1644 ISC_LOG_ERROR, 1645 "could not configure root hints " 1646 "from '%s': %s", hintsfile, 1647 isc_result_totext(result)); 1648 goto cleanup; 1649 } 1650 /* 1651 * Hint zones may also refer to delegation only points. 1652 */ 1653 only = NULL; 1654 tresult = cfg_map_get(zoptions, "delegation-only", 1655 &only); 1656 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) 1657 CHECK(dns_view_adddelegationonly(view, origin)); 1658 } else { 1659 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1660 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 1661 "ignoring non-root hint zone '%s'", 1662 zname); 1663 result = ISC_R_SUCCESS; 1664 } 1665 /* Skip ordinary zone processing. */ 1666 goto cleanup; 1667 } 1668 1669 /* 1670 * "forward zones" aren't zones either. Translate this syntax into 1671 * the appropriate selective forwarding configuration and return. 1672 */ 1673 if (strcasecmp(ztypestr, "forward") == 0) { 1674 forwardtype = NULL; 1675 forwarders = NULL; 1676 1677 (void)cfg_map_get(zoptions, "forward", &forwardtype); 1678 (void)cfg_map_get(zoptions, "forwarders", &forwarders); 1679 result = configure_forward(config, view, origin, forwarders, 1680 forwardtype); 1681 goto cleanup; 1682 } 1683 1684 /* 1685 * "delegation-only zones" aren't zones either. 1686 */ 1687 if (strcasecmp(ztypestr, "delegation-only") == 0) { 1688 result = dns_view_adddelegationonly(view, origin); 1689 goto cleanup; 1690 } 1691 1692 /* 1693 * Check for duplicates in the new zone table. 1694 */ 1695 result = dns_view_findzone(view, origin, &dupzone); 1696 if (result == ISC_R_SUCCESS) { 1697 /* 1698 * We already have this zone! 1699 */ 1700 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 1701 "zone '%s' already exists", zname); 1702 dns_zone_detach(&dupzone); 1703 result = ISC_R_EXISTS; 1704 goto cleanup; 1705 } 1706 INSIST(dupzone == NULL); 1707 1708 /* 1709 * See if we can reuse an existing zone. This is 1710 * only possible if all of these are true: 1711 * - The zone's view exists 1712 * - A zone with the right name exists in the view 1713 * - The zone is compatible with the config 1714 * options (e.g., an existing master zone cannot 1715 * be reused if the options specify a slave zone) 1716 */ 1717 result = dns_viewlist_find(&ns_g_server->viewlist, 1718 view->name, view->rdclass, 1719 &pview); 1720 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 1721 goto cleanup; 1722 if (pview != NULL) 1723 result = dns_view_findzone(pview, origin, &zone); 1724 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 1725 goto cleanup; 1726 if (zone != NULL) { 1727 if (! ns_zone_reusable(zone, zconfig)) 1728 dns_zone_detach(&zone); 1729 } 1730 1731 if (zone != NULL) { 1732 /* 1733 * We found a reusable zone. Make it use the 1734 * new view. 1735 */ 1736 dns_zone_setview(zone, view); 1737 } else { 1738 /* 1739 * We cannot reuse an existing zone, we have 1740 * to create a new one. 1741 */ 1742 CHECK(dns_zone_create(&zone, mctx)); 1743 CHECK(dns_zone_setorigin(zone, origin)); 1744 dns_zone_setview(zone, view); 1745 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); 1746 } 1747 1748 /* 1749 * If the zone contains a 'forwarders' statement, configure 1750 * selective forwarding. 1751 */ 1752 forwarders = NULL; 1753 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) 1754 { 1755 forwardtype = NULL; 1756 (void)cfg_map_get(zoptions, "forward", &forwardtype); 1757 CHECK(configure_forward(config, view, origin, forwarders, 1758 forwardtype)); 1759 } 1760 1761 /* 1762 * Stub and forward zones may also refer to delegation only points. 1763 */ 1764 only = NULL; 1765 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) 1766 { 1767 if (cfg_obj_asboolean(only)) 1768 CHECK(dns_view_adddelegationonly(view, origin)); 1769 } 1770 1771 /* 1772 * Configure the zone. 1773 */ 1774 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone)); 1775 1776 /* 1777 * Add the zone to its view in the new view list. 1778 */ 1779 CHECK(dns_view_addzone(view, zone)); 1780 1781 cleanup: 1782 if (zone != NULL) 1783 dns_zone_detach(&zone); 1784 if (pview != NULL) 1785 dns_view_detach(&pview); 1786 1787 return (result); 1788} 1789 1790/* 1791 * Configure a single server quota. 1792 */ 1793static void 1794configure_server_quota(cfg_obj_t **maps, const char *name, isc_quota_t *quota) 1795{ 1796 cfg_obj_t *obj = NULL; 1797 isc_result_t result; 1798 1799 result = ns_config_get(maps, name, &obj); 1800 INSIST(result == ISC_R_SUCCESS); 1801 quota->max = cfg_obj_asuint32(obj); 1802} 1803 1804/* 1805 * This function is called as soon as the 'directory' statement has been 1806 * parsed. This can be extended to support other options if necessary. 1807 */ 1808static isc_result_t 1809directory_callback(const char *clausename, cfg_obj_t *obj, void *arg) { 1810 isc_result_t result; 1811 char *directory; 1812 1813 REQUIRE(strcasecmp("directory", clausename) == 0); 1814 1815 UNUSED(arg); 1816 UNUSED(clausename); 1817 1818 /* 1819 * Change directory. 1820 */ 1821 directory = cfg_obj_asstring(obj); 1822 1823 if (! isc_file_ischdiridempotent(directory)) 1824 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 1825 "option 'directory' contains relative path '%s'", 1826 directory); 1827 1828 result = isc_dir_chdir(directory); 1829 if (result != ISC_R_SUCCESS) { 1830 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 1831 "change directory to '%s' failed: %s", 1832 directory, isc_result_totext(result)); 1833 return (result); 1834 } 1835 1836 return (ISC_R_SUCCESS); 1837} 1838 1839static void 1840scan_interfaces(ns_server_t *server, isc_boolean_t verbose) { 1841 isc_boolean_t match_mapped = server->aclenv.match_mapped; 1842 1843 ns_interfacemgr_scan(server->interfacemgr, verbose); 1844 /* 1845 * Update the "localhost" and "localnets" ACLs to match the 1846 * current set of network interfaces. 1847 */ 1848 dns_aclenv_copy(&server->aclenv, 1849 ns_interfacemgr_getaclenv(server->interfacemgr)); 1850 1851 server->aclenv.match_mapped = match_mapped; 1852} 1853 1854static isc_result_t 1855add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr) { 1856 ns_listenelt_t *lelt = NULL; 1857 dns_acl_t *src_acl = NULL; 1858 dns_aclelement_t aelt; 1859 isc_result_t result; 1860 isc_sockaddr_t any_sa6; 1861 1862 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6); 1863 1864 isc_sockaddr_any6(&any_sa6); 1865 if (!isc_sockaddr_equal(&any_sa6, addr)) { 1866 aelt.type = dns_aclelementtype_ipprefix; 1867 aelt.negative = ISC_FALSE; 1868 aelt.u.ip_prefix.prefixlen = 128; 1869 isc_netaddr_fromin6(&aelt.u.ip_prefix.address, 1870 &addr->type.sin6.sin6_addr); 1871 1872 result = dns_acl_create(mctx, 1, &src_acl); 1873 if (result != ISC_R_SUCCESS) 1874 return (result); 1875 result = dns_acl_appendelement(src_acl, &aelt); 1876 if (result != ISC_R_SUCCESS) 1877 goto clean; 1878 1879 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr), 1880 src_acl, &lelt); 1881 if (result != ISC_R_SUCCESS) 1882 goto clean; 1883 ISC_LIST_APPEND(list->elts, lelt, link); 1884 } 1885 1886 return (ISC_R_SUCCESS); 1887 1888 clean: 1889 INSIST(lelt == NULL); 1890 if (src_acl != NULL) 1891 dns_acl_detach(&src_acl); 1892 1893 return (result); 1894} 1895 1896/* 1897 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust() 1898 * to update the listening interfaces accordingly. 1899 * We currently only consider IPv6, because this only affects IPv6 wildcard 1900 * sockets. 1901 */ 1902static void 1903adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) { 1904 isc_result_t result; 1905 ns_listenlist_t *list = NULL; 1906 dns_view_t *view; 1907 dns_zone_t *zone, *next; 1908 isc_sockaddr_t addr, *addrp; 1909 1910 result = ns_listenlist_create(mctx, &list); 1911 if (result != ISC_R_SUCCESS) 1912 return; 1913 1914 for (view = ISC_LIST_HEAD(server->viewlist); 1915 view != NULL; 1916 view = ISC_LIST_NEXT(view, link)) { 1917 dns_dispatch_t *dispatch6; 1918 1919 dispatch6 = dns_resolver_dispatchv6(view->resolver); 1920 if (dispatch6 == NULL) 1921 continue; 1922 result = dns_dispatch_getlocaladdress(dispatch6, &addr); 1923 if (result != ISC_R_SUCCESS) 1924 goto fail; 1925 result = add_listenelt(mctx, list, &addr); 1926 if (result != ISC_R_SUCCESS) 1927 goto fail; 1928 } 1929 1930 zone = NULL; 1931 for (result = dns_zone_first(server->zonemgr, &zone); 1932 result == ISC_R_SUCCESS; 1933 next = NULL, result = dns_zone_next(zone, &next), zone = next) { 1934 dns_view_t *zoneview; 1935 1936 /* 1937 * At this point the zone list may contain a stale zone 1938 * just removed from the configuration. To see the validity, 1939 * check if the corresponding view is in our current view list. 1940 */ 1941 zoneview = dns_zone_getview(zone); 1942 INSIST(zoneview != NULL); 1943 for (view = ISC_LIST_HEAD(server->viewlist); 1944 view != NULL && view != zoneview; 1945 view = ISC_LIST_NEXT(view, link)) 1946 ; 1947 if (view == NULL) 1948 continue; 1949 1950 addrp = dns_zone_getnotifysrc6(zone); 1951 result = add_listenelt(mctx, list, addrp); 1952 if (result != ISC_R_SUCCESS) 1953 goto fail; 1954 1955 addrp = dns_zone_getxfrsource6(zone); 1956 result = add_listenelt(mctx, list, addrp); 1957 if (result != ISC_R_SUCCESS) 1958 goto fail; 1959 } 1960 1961 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE); 1962 1963 clean: 1964 ns_listenlist_detach(&list); 1965 return; 1966 1967 fail: 1968 /* 1969 * Even when we failed the procedure, most of other interfaces 1970 * should work correctly. We therefore just warn it. 1971 */ 1972 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1973 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 1974 "could not adjust the listen-on list; " 1975 "some interfaces may not work"); 1976 goto clean; 1977} 1978 1979/* 1980 * This event callback is invoked to do periodic network 1981 * interface scanning. 1982 */ 1983static void 1984interface_timer_tick(isc_task_t *task, isc_event_t *event) { 1985 isc_result_t result; 1986 ns_server_t *server = (ns_server_t *) event->ev_arg; 1987 INSIST(task == server->task); 1988 UNUSED(task); 1989 isc_event_free(&event); 1990 /* 1991 * XXX should scan interfaces unlocked and get exclusive access 1992 * only to replace ACLs. 1993 */ 1994 result = isc_task_beginexclusive(server->task); 1995 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1996 scan_interfaces(server, ISC_FALSE); 1997 isc_task_endexclusive(server->task); 1998} 1999 2000static void 2001heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) { 2002 ns_server_t *server = (ns_server_t *) event->ev_arg; 2003 dns_view_t *view; 2004 2005 UNUSED(task); 2006 isc_event_free(&event); 2007 view = ISC_LIST_HEAD(server->viewlist); 2008 while (view != NULL) { 2009 dns_view_dialup(view); 2010 view = ISC_LIST_NEXT(view, link); 2011 } 2012} 2013 2014/* 2015 * Replace the current value of '*field', a dynamically allocated 2016 * string or NULL, with a dynamically allocated copy of the 2017 * null-terminated string pointed to by 'value', or NULL. 2018 */ 2019static isc_result_t 2020setstring(ns_server_t *server, char **field, const char *value) { 2021 char *copy; 2022 2023 if (value != NULL) { 2024 copy = isc_mem_strdup(server->mctx, value); 2025 if (copy == NULL) 2026 return (ISC_R_NOMEMORY); 2027 } else { 2028 copy = NULL; 2029 } 2030 2031 if (*field != NULL) 2032 isc_mem_free(server->mctx, *field); 2033 2034 *field = copy; 2035 return (ISC_R_SUCCESS); 2036} 2037 2038/* 2039 * Replace the current value of '*field', a dynamically allocated 2040 * string or NULL, with another dynamically allocated string 2041 * or NULL if whether 'obj' is a string or void value, respectively. 2042 */ 2043static isc_result_t 2044setoptstring(ns_server_t *server, char **field, cfg_obj_t *obj) { 2045 if (cfg_obj_isvoid(obj)) 2046 return (setstring(server, field, NULL)); 2047 else 2048 return (setstring(server, field, cfg_obj_asstring(obj))); 2049} 2050 2051static void 2052set_limit(cfg_obj_t **maps, const char *configname, const char *description, 2053 isc_resource_t resourceid, isc_resourcevalue_t defaultvalue) 2054{ 2055 cfg_obj_t *obj = NULL; 2056 char *resource; 2057 isc_resourcevalue_t value; 2058 isc_result_t result; 2059 2060 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS) 2061 return; 2062 2063 if (cfg_obj_isstring(obj)) { 2064 resource = cfg_obj_asstring(obj); 2065 if (strcasecmp(resource, "unlimited") == 0) 2066 value = ISC_RESOURCE_UNLIMITED; 2067 else { 2068 INSIST(strcasecmp(resource, "default") == 0); 2069 value = defaultvalue; 2070 } 2071 } else 2072 value = cfg_obj_asuint64(obj); 2073 2074 result = isc_resource_setlimit(resourceid, value); 2075 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2076 result == ISC_R_SUCCESS ? 2077 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING, 2078 "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s", 2079 description, value, isc_result_totext(result)); 2080} 2081 2082#define SETLIMIT(cfgvar, resource, description) \ 2083 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \ 2084 ns_g_init ## resource) 2085 2086static void 2087set_limits(cfg_obj_t **maps) { 2088 SETLIMIT("stacksize", stacksize, "stack size"); 2089 SETLIMIT("datasize", datasize, "data size"); 2090 SETLIMIT("coresize", coresize, "core size"); 2091 SETLIMIT("files", openfiles, "open files"); 2092} 2093 2094static isc_result_t 2095portlist_fromconf(dns_portlist_t *portlist, unsigned int family, 2096 cfg_obj_t *ports) 2097{ 2098 cfg_listelt_t *element; 2099 isc_result_t result = ISC_R_SUCCESS; 2100 2101 for (element = cfg_list_first(ports); 2102 element != NULL; 2103 element = cfg_list_next(element)) { 2104 cfg_obj_t *obj = cfg_listelt_value(element); 2105 in_port_t port = (in_port_t)cfg_obj_asuint32(obj); 2106 2107 result = dns_portlist_add(portlist, family, port); 2108 if (result != ISC_R_SUCCESS) 2109 break; 2110 } 2111 return (result); 2112} 2113 2114static isc_result_t 2115load_configuration(const char *filename, ns_server_t *server, 2116 isc_boolean_t first_time) 2117{ 2118 isc_result_t result; 2119 cfg_parser_t *parser = NULL; 2120 cfg_obj_t *config; 2121 cfg_obj_t *options; 2122 cfg_obj_t *views; 2123 cfg_obj_t *obj; 2124 cfg_obj_t *v4ports, *v6ports; 2125 cfg_obj_t *maps[3]; 2126 cfg_obj_t *builtin_views; 2127 cfg_listelt_t *element; 2128 dns_view_t *view = NULL; 2129 dns_view_t *view_next; 2130 dns_viewlist_t viewlist; 2131 dns_viewlist_t tmpviewlist; 2132 ns_aclconfctx_t aclconfctx; 2133 isc_uint32_t interface_interval; 2134 isc_uint32_t heartbeat_interval; 2135 isc_uint32_t udpsize; 2136 in_port_t listen_port; 2137 int i; 2138 2139 ns_aclconfctx_init(&aclconfctx); 2140 ISC_LIST_INIT(viewlist); 2141 2142 /* Ensure exclusive access to configuration data. */ 2143 result = isc_task_beginexclusive(server->task); 2144 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2145 2146 /* 2147 * Parse the global default pseudo-config file. 2148 */ 2149 if (first_time) { 2150 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config)); 2151 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", 2152 &ns_g_defaults) == 2153 ISC_R_SUCCESS); 2154 } 2155 2156 /* 2157 * Parse the configuration file using the new config code. 2158 */ 2159 result = ISC_R_FAILURE; 2160 config = NULL; 2161 2162 /* 2163 * Unless this is lwresd with the -C option, parse the config file. 2164 */ 2165 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) { 2166 isc_log_write(ns_g_lctx, 2167 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2168 ISC_LOG_INFO, "loading configuration from '%s'", 2169 filename); 2170 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); 2171 cfg_parser_setcallback(parser, directory_callback, NULL); 2172 result = cfg_parse_file(parser, filename, &cfg_type_namedconf, 2173 &config); 2174 } 2175 2176 /* 2177 * If this is lwresd with the -C option, or lwresd with no -C or -c 2178 * option where the above parsing failed, parse resolv.conf. 2179 */ 2180 if (ns_g_lwresdonly && 2181 (lwresd_g_useresolvconf || 2182 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND))) 2183 { 2184 isc_log_write(ns_g_lctx, 2185 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2186 ISC_LOG_INFO, "loading configuration from '%s'", 2187 lwresd_g_resolvconffile); 2188 if (parser != NULL) 2189 cfg_parser_destroy(&parser); 2190 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); 2191 result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser, 2192 &config); 2193 } 2194 CHECK(result); 2195 2196 /* 2197 * Check the validity of the configuration. 2198 */ 2199 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx)); 2200 2201 /* 2202 * Fill in the maps array, used for resolving defaults. 2203 */ 2204 i = 0; 2205 options = NULL; 2206 result = cfg_map_get(config, "options", &options); 2207 if (result == ISC_R_SUCCESS) 2208 maps[i++] = options; 2209 maps[i++] = ns_g_defaults; 2210 maps[i++] = NULL; 2211 2212 /* 2213 * Set process limits, which (usually) needs to be done as root. 2214 */ 2215 set_limits(maps); 2216 2217 /* 2218 * Configure various server options. 2219 */ 2220 configure_server_quota(maps, "transfers-out", &server->xfroutquota); 2221 configure_server_quota(maps, "tcp-clients", &server->tcpquota); 2222 configure_server_quota(maps, "recursive-clients", 2223 &server->recursionquota); 2224 2225 CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx, 2226 ns_g_mctx, &server->blackholeacl)); 2227 if (server->blackholeacl != NULL) 2228 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, 2229 server->blackholeacl); 2230 2231 obj = NULL; 2232 result = ns_config_get(maps, "match-mapped-addresses", &obj); 2233 INSIST(result == ISC_R_SUCCESS); 2234 server->aclenv.match_mapped = cfg_obj_asboolean(obj); 2235 2236 v4ports = NULL; 2237 v6ports = NULL; 2238 (void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports); 2239 (void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports); 2240 if (v4ports != NULL || v6ports != NULL) { 2241 dns_portlist_t *portlist = NULL; 2242 result = dns_portlist_create(ns_g_mctx, &portlist); 2243 if (result == ISC_R_SUCCESS && v4ports != NULL) 2244 result = portlist_fromconf(portlist, AF_INET, v4ports); 2245 if (result == ISC_R_SUCCESS && v6ports != NULL) 2246 portlist_fromconf(portlist, AF_INET6, v6ports); 2247 if (result == ISC_R_SUCCESS) 2248 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist); 2249 if (portlist != NULL) 2250 dns_portlist_detach(&portlist); 2251 CHECK(result); 2252 } else 2253 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL); 2254 2255 /* 2256 * Set the EDNS UDP size when we don't match a view. 2257 */ 2258 obj = NULL; 2259 result = ns_config_get(maps, "edns-udp-size", &obj); 2260 INSIST(result == ISC_R_SUCCESS); 2261 udpsize = cfg_obj_asuint32(obj); 2262 if (udpsize < 512) 2263 udpsize = 512; 2264 if (udpsize > 4096) 2265 udpsize = 4096; 2266 ns_g_udpsize = (isc_uint16_t)udpsize; 2267 2268 /* 2269 * Configure the zone manager. 2270 */ 2271 obj = NULL; 2272 result = ns_config_get(maps, "transfers-in", &obj); 2273 INSIST(result == ISC_R_SUCCESS); 2274 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); 2275 2276 obj = NULL; 2277 result = ns_config_get(maps, "transfers-per-ns", &obj); 2278 INSIST(result == ISC_R_SUCCESS); 2279 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); 2280 2281 obj = NULL; 2282 result = ns_config_get(maps, "serial-query-rate", &obj); 2283 INSIST(result == ISC_R_SUCCESS); 2284 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); 2285 2286 /* 2287 * Determine which port to use for listening for incoming connections. 2288 */ 2289 if (ns_g_port != 0) 2290 listen_port = ns_g_port; 2291 else 2292 CHECKM(ns_config_getport(config, &listen_port), "port"); 2293 2294 /* 2295 * Find the listen queue depth. 2296 */ 2297 obj = NULL; 2298 result = ns_config_get(maps, "tcp-listen-queue", &obj); 2299 INSIST(result == ISC_R_SUCCESS); 2300 ns_g_listen = cfg_obj_asuint32(obj); 2301 if (ns_g_listen < 3) 2302 ns_g_listen = 3; 2303 2304 /* 2305 * Configure the interface manager according to the "listen-on" 2306 * statement. 2307 */ 2308 { 2309 cfg_obj_t *clistenon = NULL; 2310 ns_listenlist_t *listenon = NULL; 2311 2312 clistenon = NULL; 2313 /* 2314 * Even though listen-on is present in the default 2315 * configuration, we can't use it here, since it isn't 2316 * used if we're in lwresd mode. This way is easier. 2317 */ 2318 if (options != NULL) 2319 (void)cfg_map_get(options, "listen-on", &clistenon); 2320 if (clistenon != NULL) { 2321 result = ns_listenlist_fromconfig(clistenon, 2322 config, 2323 &aclconfctx, 2324 ns_g_mctx, 2325 &listenon); 2326 } else if (!ns_g_lwresdonly) { 2327 /* 2328 * Not specified, use default. 2329 */ 2330 CHECK(ns_listenlist_default(ns_g_mctx, listen_port, 2331 ISC_TRUE, &listenon)); 2332 } 2333 if (listenon != NULL) { 2334 ns_interfacemgr_setlistenon4(server->interfacemgr, 2335 listenon); 2336 ns_listenlist_detach(&listenon); 2337 } 2338 } 2339 /* 2340 * Ditto for IPv6. 2341 */ 2342 { 2343 cfg_obj_t *clistenon = NULL; 2344 ns_listenlist_t *listenon = NULL; 2345 2346 if (options != NULL) 2347 (void)cfg_map_get(options, "listen-on-v6", &clistenon); 2348 if (clistenon != NULL) { 2349 result = ns_listenlist_fromconfig(clistenon, 2350 config, 2351 &aclconfctx, 2352 ns_g_mctx, 2353 &listenon); 2354 } else if (!ns_g_lwresdonly) { 2355 /* 2356 * Not specified, use default. 2357 */ 2358 CHECK(ns_listenlist_default(ns_g_mctx, listen_port, 2359 ISC_FALSE, &listenon)); 2360 } 2361 if (listenon != NULL) { 2362 ns_interfacemgr_setlistenon6(server->interfacemgr, 2363 listenon); 2364 ns_listenlist_detach(&listenon); 2365 } 2366 } 2367 2368 /* 2369 * Rescan the interface list to pick up changes in the 2370 * listen-on option. It's important that we do this before we try 2371 * to configure the query source, since the dispatcher we use might 2372 * be shared with an interface. 2373 */ 2374 scan_interfaces(server, ISC_TRUE); 2375 2376 /* 2377 * Arrange for further interface scanning to occur periodically 2378 * as specified by the "interface-interval" option. 2379 */ 2380 obj = NULL; 2381 result = ns_config_get(maps, "interface-interval", &obj); 2382 INSIST(result == ISC_R_SUCCESS); 2383 interface_interval = cfg_obj_asuint32(obj) * 60; 2384 if (interface_interval == 0) { 2385 CHECK(isc_timer_reset(server->interface_timer, 2386 isc_timertype_inactive, 2387 NULL, NULL, ISC_TRUE)); 2388 } else if (server->interface_interval != interface_interval) { 2389 isc_interval_t interval; 2390 isc_interval_set(&interval, interface_interval, 0); 2391 CHECK(isc_timer_reset(server->interface_timer, 2392 isc_timertype_ticker, 2393 NULL, &interval, ISC_FALSE)); 2394 } 2395 server->interface_interval = interface_interval; 2396 2397 /* 2398 * Configure the dialup heartbeat timer. 2399 */ 2400 obj = NULL; 2401 result = ns_config_get(maps, "heartbeat-interval", &obj); 2402 INSIST(result == ISC_R_SUCCESS); 2403 heartbeat_interval = cfg_obj_asuint32(obj) * 60; 2404 if (heartbeat_interval == 0) { 2405 CHECK(isc_timer_reset(server->heartbeat_timer, 2406 isc_timertype_inactive, 2407 NULL, NULL, ISC_TRUE)); 2408 } else if (server->heartbeat_interval != heartbeat_interval) { 2409 isc_interval_t interval; 2410 isc_interval_set(&interval, heartbeat_interval, 0); 2411 CHECK(isc_timer_reset(server->heartbeat_timer, 2412 isc_timertype_ticker, 2413 NULL, &interval, ISC_FALSE)); 2414 } 2415 server->heartbeat_interval = heartbeat_interval; 2416 2417 /* 2418 * Configure and freeze all explicit views. Explicit 2419 * views that have zones were already created at parsing 2420 * time, but views with no zones must be created here. 2421 */ 2422 views = NULL; 2423 (void)cfg_map_get(config, "view", &views); 2424 for (element = cfg_list_first(views); 2425 element != NULL; 2426 element = cfg_list_next(element)) 2427 { 2428 cfg_obj_t *vconfig = cfg_listelt_value(element); 2429 view = NULL; 2430 2431 CHECK(create_view(vconfig, &viewlist, &view)); 2432 INSIST(view != NULL); 2433 CHECK(configure_view(view, config, vconfig, 2434 ns_g_mctx, &aclconfctx, ISC_TRUE)); 2435 dns_view_freeze(view); 2436 dns_view_detach(&view); 2437 } 2438 2439 /* 2440 * Make sure we have a default view if and only if there 2441 * were no explicit views. 2442 */ 2443 if (views == NULL) { 2444 /* 2445 * No explicit views; there ought to be a default view. 2446 * There may already be one created as a side effect 2447 * of zone statements, or we may have to create one. 2448 * In either case, we need to configure and freeze it. 2449 */ 2450 CHECK(create_view(NULL, &viewlist, &view)); 2451 CHECK(configure_view(view, config, NULL, ns_g_mctx, 2452 &aclconfctx, ISC_TRUE)); 2453 dns_view_freeze(view); 2454 dns_view_detach(&view); 2455 } 2456 2457 /* 2458 * Create (or recreate) the built-in views. Currently 2459 * there is only one, the _bind view. 2460 */ 2461 builtin_views = NULL; 2462 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view", 2463 &builtin_views) == ISC_R_SUCCESS); 2464 for (element = cfg_list_first(builtin_views); 2465 element != NULL; 2466 element = cfg_list_next(element)) 2467 { 2468 cfg_obj_t *vconfig = cfg_listelt_value(element); 2469 CHECK(create_view(vconfig, &viewlist, &view)); 2470 CHECK(configure_view(view, config, vconfig, ns_g_mctx, 2471 &aclconfctx, ISC_FALSE)); 2472 dns_view_freeze(view); 2473 dns_view_detach(&view); 2474 view = NULL; 2475 } 2476 2477 /* 2478 * Swap our new view list with the production one. 2479 */ 2480 tmpviewlist = server->viewlist; 2481 server->viewlist = viewlist; 2482 viewlist = tmpviewlist; 2483 2484 /* 2485 * Load the TKEY information from the configuration. 2486 */ 2487 if (options != NULL) { 2488 dns_tkeyctx_t *t = NULL; 2489 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy, 2490 &t), 2491 "configuring TKEY"); 2492 if (server->tkeyctx != NULL) 2493 dns_tkeyctx_destroy(&server->tkeyctx); 2494 server->tkeyctx = t; 2495 } 2496 2497 /* 2498 * Bind the control port(s). 2499 */ 2500 CHECKM(ns_controls_configure(ns_g_server->controls, config, 2501 &aclconfctx), 2502 "binding control channel(s)"); 2503 2504 /* 2505 * Bind the lwresd port(s). 2506 */ 2507 CHECKM(ns_lwresd_configure(ns_g_mctx, config), 2508 "binding lightweight resolver ports"); 2509 2510 /* 2511 * Open the source of entropy. 2512 */ 2513 if (first_time) { 2514 obj = NULL; 2515 result = ns_config_get(maps, "random-device", &obj); 2516 if (result != ISC_R_SUCCESS) { 2517 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2518 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 2519 "no source of entropy found"); 2520 } else { 2521 const char *randomdev = cfg_obj_asstring(obj); 2522 result = isc_entropy_createfilesource(ns_g_entropy, 2523 randomdev); 2524 if (result != ISC_R_SUCCESS) 2525 isc_log_write(ns_g_lctx, 2526 NS_LOGCATEGORY_GENERAL, 2527 NS_LOGMODULE_SERVER, 2528 ISC_LOG_INFO, 2529 "could not open entropy source " 2530 "%s: %s", 2531 randomdev, 2532 isc_result_totext(result)); 2533#ifdef PATH_RANDOMDEV 2534 if (ns_g_fallbackentropy != NULL) { 2535 if (result != ISC_R_SUCCESS) { 2536 isc_log_write(ns_g_lctx, 2537 NS_LOGCATEGORY_GENERAL, 2538 NS_LOGMODULE_SERVER, 2539 ISC_LOG_INFO, 2540 "using pre-chroot entropy source " 2541 "%s", 2542 PATH_RANDOMDEV); 2543 isc_entropy_detach(&ns_g_entropy); 2544 isc_entropy_attach(ns_g_fallbackentropy, 2545 &ns_g_entropy); 2546 } 2547 isc_entropy_detach(&ns_g_fallbackentropy); 2548 } 2549#endif 2550 } 2551 } 2552 2553 /* 2554 * Relinquish root privileges. 2555 */ 2556 if (first_time) 2557 ns_os_changeuser(); 2558 2559 /* 2560 * Configure the logging system. 2561 * 2562 * Do this after changing UID to make sure that any log 2563 * files specified in named.conf get created by the 2564 * unprivileged user, not root. 2565 */ 2566 if (ns_g_logstderr) { 2567 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2568 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 2569 "ignoring config file logging " 2570 "statement due to -g option"); 2571 } else { 2572 cfg_obj_t *logobj = NULL; 2573 isc_logconfig_t *logc = NULL; 2574 2575 CHECKM(isc_logconfig_create(ns_g_lctx, &logc), 2576 "creating new logging configuration"); 2577 2578 logobj = NULL; 2579 (void)cfg_map_get(config, "logging", &logobj); 2580 if (logobj != NULL) { 2581 CHECKM(ns_log_configure(logc, logobj), 2582 "configuring logging"); 2583 } else { 2584 CHECKM(ns_log_setdefaultchannels(logc), 2585 "setting up default logging channels"); 2586 CHECKM(ns_log_setunmatchedcategory(logc), 2587 "setting up default 'category unmatched'"); 2588 CHECKM(ns_log_setdefaultcategory(logc), 2589 "setting up default 'category default'"); 2590 } 2591 2592 result = isc_logconfig_use(ns_g_lctx, logc); 2593 if (result != ISC_R_SUCCESS) { 2594 isc_logconfig_destroy(&logc); 2595 CHECKM(result, "installing logging configuration"); 2596 } 2597 2598 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2599 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 2600 "now using logging configuration from " 2601 "config file"); 2602 } 2603 2604 /* 2605 * Set the default value of the query logging flag depending 2606 * whether a "queries" category has been defined. This is 2607 * a disgusting hack, but we need to do this for BIND 8 2608 * compatibility. 2609 */ 2610 if (first_time) { 2611 cfg_obj_t *logobj = NULL; 2612 cfg_obj_t *categories = NULL; 2613 2614 obj = NULL; 2615 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { 2616 server->log_queries = cfg_obj_asboolean(obj); 2617 } else { 2618 2619 (void)cfg_map_get(config, "logging", &logobj); 2620 if (logobj != NULL) 2621 (void)cfg_map_get(logobj, "category", 2622 &categories); 2623 if (categories != NULL) { 2624 cfg_listelt_t *element; 2625 for (element = cfg_list_first(categories); 2626 element != NULL; 2627 element = cfg_list_next(element)) 2628 { 2629 cfg_obj_t *catobj; 2630 char *str; 2631 2632 obj = cfg_listelt_value(element); 2633 catobj = cfg_tuple_get(obj, "name"); 2634 str = cfg_obj_asstring(catobj); 2635 if (strcasecmp(str, "queries") == 0) 2636 server->log_queries = ISC_TRUE; 2637 } 2638 } 2639 } 2640 } 2641 2642 obj = NULL; 2643 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) 2644 if (cfg_obj_isvoid(obj)) 2645 ns_os_writepidfile(NULL, first_time); 2646 else 2647 ns_os_writepidfile(cfg_obj_asstring(obj), first_time); 2648 else if (ns_g_lwresdonly) 2649 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); 2650 else 2651 ns_os_writepidfile(ns_g_defaultpidfile, first_time); 2652 2653 obj = NULL; 2654 if (options != NULL && 2655 cfg_map_get(options, "memstatistics-file", &obj) == ISC_R_SUCCESS) 2656 ns_main_setmemstats(cfg_obj_asstring(obj)); 2657 else 2658 ns_main_setmemstats(NULL); 2659 2660 obj = NULL; 2661 result = ns_config_get(maps, "statistics-file", &obj); 2662 INSIST(result == ISC_R_SUCCESS); 2663 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)), 2664 "strdup"); 2665 2666 obj = NULL; 2667 result = ns_config_get(maps, "dump-file", &obj); 2668 INSIST(result == ISC_R_SUCCESS); 2669 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)), 2670 "strdup"); 2671 2672 obj = NULL; 2673 result = ns_config_get(maps, "recursing-file", &obj); 2674 INSIST(result == ISC_R_SUCCESS); 2675 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)), 2676 "strdup"); 2677 2678 obj = NULL; 2679 result = ns_config_get(maps, "version", &obj); 2680 if (result == ISC_R_SUCCESS) { 2681 CHECKM(setoptstring(server, &server->version, obj), "strdup"); 2682 server->version_set = ISC_TRUE; 2683 } else { 2684 server->version_set = ISC_FALSE; 2685 } 2686 2687 obj = NULL; 2688 result = ns_config_get(maps, "hostname", &obj); 2689 if (result == ISC_R_SUCCESS) { 2690 CHECKM(setoptstring(server, &server->hostname, obj), "strdup"); 2691 server->hostname_set = ISC_TRUE; 2692 } else { 2693 server->hostname_set = ISC_FALSE; 2694 } 2695 2696 obj = NULL; 2697 result = ns_config_get(maps, "server-id", &obj); 2698 server->server_usehostname = ISC_FALSE; 2699 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 2700 server->server_usehostname = ISC_TRUE; 2701 } else if (result == ISC_R_SUCCESS) { 2702 CHECKM(setoptstring(server, &server->server_id, obj), "strdup"); 2703 } else { 2704 result = setoptstring(server, &server->server_id, NULL); 2705 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2706 } 2707 2708 obj = NULL; 2709 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj); 2710 if (result == ISC_R_SUCCESS) { 2711 server->flushonshutdown = cfg_obj_asboolean(obj); 2712 } else { 2713 server->flushonshutdown = ISC_FALSE; 2714 } 2715 2716 result = ISC_R_SUCCESS; 2717 2718 cleanup: 2719 ns_aclconfctx_destroy(&aclconfctx); 2720 2721 if (parser != NULL) { 2722 if (config != NULL) 2723 cfg_obj_destroy(parser, &config); 2724 cfg_parser_destroy(&parser); 2725 } 2726 2727 if (view != NULL) 2728 dns_view_detach(&view); 2729 2730 /* 2731 * This cleans up either the old production view list 2732 * or our temporary list depending on whether they 2733 * were swapped above or not. 2734 */ 2735 for (view = ISC_LIST_HEAD(viewlist); 2736 view != NULL; 2737 view = view_next) { 2738 view_next = ISC_LIST_NEXT(view, link); 2739 ISC_LIST_UNLINK(viewlist, view, link); 2740 dns_view_detach(&view); 2741 2742 } 2743 2744 /* 2745 * Adjust the listening interfaces in accordance with the source 2746 * addresses specified in views and zones. 2747 */ 2748 if (isc_net_probeipv6() == ISC_R_SUCCESS) 2749 adjust_interfaces(server, ns_g_mctx); 2750 2751 /* Relinquish exclusive access to configuration data. */ 2752 isc_task_endexclusive(server->task); 2753 2754 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2755 ISC_LOG_DEBUG(1), "load_configuration: %s", 2756 isc_result_totext(result)); 2757 2758 return (result); 2759} 2760 2761static isc_result_t 2762load_zones(ns_server_t *server, isc_boolean_t stop) { 2763 isc_result_t result; 2764 dns_view_t *view; 2765 2766 result = isc_task_beginexclusive(server->task); 2767 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2768 2769 /* 2770 * Load zone data from disk. 2771 */ 2772 for (view = ISC_LIST_HEAD(server->viewlist); 2773 view != NULL; 2774 view = ISC_LIST_NEXT(view, link)) 2775 { 2776 CHECK(dns_view_load(view, stop)); 2777 } 2778 2779 /* 2780 * Force zone maintenance. Do this after loading 2781 * so that we know when we need to force AXFR of 2782 * slave zones whose master files are missing. 2783 */ 2784 CHECK(dns_zonemgr_forcemaint(server->zonemgr)); 2785 cleanup: 2786 isc_task_endexclusive(server->task); 2787 return (result); 2788} 2789 2790static isc_result_t 2791load_new_zones(ns_server_t *server, isc_boolean_t stop) { 2792 isc_result_t result; 2793 dns_view_t *view; 2794 2795 result = isc_task_beginexclusive(server->task); 2796 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2797 2798 /* 2799 * Load zone data from disk. 2800 */ 2801 for (view = ISC_LIST_HEAD(server->viewlist); 2802 view != NULL; 2803 view = ISC_LIST_NEXT(view, link)) 2804 { 2805 CHECK(dns_view_loadnew(view, stop)); 2806 } 2807 /* 2808 * Force zone maintenance. Do this after loading 2809 * so that we know when we need to force AXFR of 2810 * slave zones whose master files are missing. 2811 */ 2812 dns_zonemgr_resumexfrs(server->zonemgr); 2813 cleanup: 2814 isc_task_endexclusive(server->task); 2815 return (result); 2816} 2817 2818static void 2819run_server(isc_task_t *task, isc_event_t *event) { 2820 isc_result_t result; 2821 ns_server_t *server = (ns_server_t *)event->ev_arg; 2822 2823 INSIST(task == server->task); 2824 2825 isc_event_free(&event); 2826 2827 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy, 2828 &ns_g_dispatchmgr), 2829 "creating dispatch manager"); 2830 2831 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr, 2832 ns_g_socketmgr, ns_g_dispatchmgr, 2833 &server->interfacemgr), 2834 "creating interface manager"); 2835 2836 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 2837 NULL, NULL, server->task, 2838 interface_timer_tick, 2839 server, &server->interface_timer), 2840 "creating interface timer"); 2841 2842 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 2843 NULL, NULL, server->task, 2844 heartbeat_timer_tick, 2845 server, &server->heartbeat_timer), 2846 "creating heartbeat timer"); 2847 2848 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser), 2849 "creating default configuration parser"); 2850 2851 if (ns_g_lwresdonly) 2852 CHECKFATAL(load_configuration(lwresd_g_conffile, server, 2853 ISC_TRUE), 2854 "loading configuration"); 2855 else 2856 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE), 2857 "loading configuration"); 2858 2859 isc_hash_init(); 2860 2861 CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones"); 2862 2863 ns_os_started(); 2864 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2865 ISC_LOG_NOTICE, "running"); 2866} 2867 2868void 2869ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) { 2870 2871 REQUIRE(NS_SERVER_VALID(server)); 2872 2873 server->flushonshutdown = flush; 2874} 2875 2876static void 2877shutdown_server(isc_task_t *task, isc_event_t *event) { 2878 isc_result_t result; 2879 dns_view_t *view, *view_next; 2880 ns_server_t *server = (ns_server_t *)event->ev_arg; 2881 isc_boolean_t flush = server->flushonshutdown; 2882 2883 UNUSED(task); 2884 INSIST(task == server->task); 2885 2886 result = isc_task_beginexclusive(server->task); 2887 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2888 2889 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2890 ISC_LOG_INFO, "shutting down%s", 2891 flush ? ": flushing changes" : ""); 2892 2893 ns_controls_shutdown(server->controls); 2894 end_reserved_dispatches(server, ISC_TRUE); 2895 2896 cfg_obj_destroy(ns_g_parser, &ns_g_config); 2897 cfg_parser_destroy(&ns_g_parser); 2898 2899 for (view = ISC_LIST_HEAD(server->viewlist); 2900 view != NULL; 2901 view = view_next) { 2902 view_next = ISC_LIST_NEXT(view, link); 2903 ISC_LIST_UNLINK(server->viewlist, view, link); 2904 if (flush) 2905 dns_view_flushanddetach(&view); 2906 else 2907 dns_view_detach(&view); 2908 } 2909 2910 isc_timer_detach(&server->interface_timer); 2911 isc_timer_detach(&server->heartbeat_timer); 2912 2913 ns_interfacemgr_shutdown(server->interfacemgr); 2914 ns_interfacemgr_detach(&server->interfacemgr); 2915 2916 dns_dispatchmgr_destroy(&ns_g_dispatchmgr); 2917 2918 dns_zonemgr_shutdown(server->zonemgr); 2919 2920 if (server->blackholeacl != NULL) 2921 dns_acl_detach(&server->blackholeacl); 2922 2923 dns_db_detach(&server->in_roothints); 2924 2925 isc_task_endexclusive(server->task); 2926 2927 isc_task_detach(&server->task); 2928 2929 isc_event_free(&event); 2930} 2931 2932void 2933ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { 2934 isc_result_t result; 2935 2936 ns_server_t *server = isc_mem_get(mctx, sizeof(*server)); 2937 if (server == NULL) 2938 fatal("allocating server object", ISC_R_NOMEMORY); 2939 2940 server->mctx = mctx; 2941 server->task = NULL; 2942 2943 /* Initialize configuration data with default values. */ 2944 2945 result = isc_quota_init(&server->xfroutquota, 10); 2946 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2947 result = isc_quota_init(&server->tcpquota, 10); 2948 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2949 result = isc_quota_init(&server->recursionquota, 100); 2950 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2951 isc_quota_soft(&server->recursionquota, ISC_FALSE); 2952 2953 result = dns_aclenv_init(mctx, &server->aclenv); 2954 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2955 2956 /* Initialize server data structures. */ 2957 server->zonemgr = NULL; 2958 server->interfacemgr = NULL; 2959 ISC_LIST_INIT(server->viewlist); 2960 server->in_roothints = NULL; 2961 server->blackholeacl = NULL; 2962 2963 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, 2964 &server->in_roothints), 2965 "setting up root hints"); 2966 2967 CHECKFATAL(isc_mutex_init(&server->reload_event_lock), 2968 "initializing reload event lock"); 2969 server->reload_event = 2970 isc_event_allocate(ns_g_mctx, server, 2971 NS_EVENT_RELOAD, 2972 ns_server_reload, 2973 server, 2974 sizeof(isc_event_t)); 2975 CHECKFATAL(server->reload_event == NULL ? 2976 ISC_R_NOMEMORY : ISC_R_SUCCESS, 2977 "allocating reload event"); 2978 2979 CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY), 2980 "initializing DST"); 2981 2982 server->tkeyctx = NULL; 2983 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy, 2984 &server->tkeyctx), 2985 "creating TKEY context"); 2986 2987 /* 2988 * Setup the server task, which is responsible for coordinating 2989 * startup and shutdown of the server. 2990 */ 2991 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task), 2992 "creating server task"); 2993 isc_task_setname(server->task, "server", server); 2994 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server), 2995 "isc_task_onshutdown"); 2996 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server), 2997 "isc_app_onrun"); 2998 2999 server->interface_timer = NULL; 3000 server->heartbeat_timer = NULL; 3001 3002 server->interface_interval = 0; 3003 server->heartbeat_interval = 0; 3004 3005 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, 3006 ns_g_socketmgr, &server->zonemgr), 3007 "dns_zonemgr_create"); 3008 3009 server->statsfile = isc_mem_strdup(server->mctx, "named.stats"); 3010 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3011 "isc_mem_strdup"); 3012 server->querystats = NULL; 3013 3014 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db"); 3015 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3016 "isc_mem_strdup"); 3017 3018 server->recfile = isc_mem_strdup(server->mctx, "named.recursing"); 3019 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3020 "isc_mem_strdup"); 3021 3022 server->hostname_set = ISC_FALSE; 3023 server->hostname = NULL; 3024 server->version_set = ISC_FALSE; 3025 server->version = NULL; 3026 server->server_usehostname = ISC_FALSE; 3027 server->server_id = NULL; 3028 3029 CHECKFATAL(dns_stats_alloccounters(ns_g_mctx, &server->querystats), 3030 "dns_stats_alloccounters"); 3031 3032 server->flushonshutdown = ISC_FALSE; 3033 server->log_queries = ISC_FALSE; 3034 3035 server->controls = NULL; 3036 CHECKFATAL(ns_controls_create(server, &server->controls), 3037 "ns_controls_create"); 3038 server->dispatchgen = 0; 3039 ISC_LIST_INIT(server->dispatches); 3040 3041 server->magic = NS_SERVER_MAGIC; 3042 *serverp = server; 3043} 3044 3045void 3046ns_server_destroy(ns_server_t **serverp) { 3047 ns_server_t *server = *serverp; 3048 REQUIRE(NS_SERVER_VALID(server)); 3049 3050 ns_controls_destroy(&server->controls); 3051 3052 dns_stats_freecounters(server->mctx, &server->querystats); 3053 3054 isc_mem_free(server->mctx, server->statsfile); 3055 isc_mem_free(server->mctx, server->dumpfile); 3056 isc_mem_free(server->mctx, server->recfile); 3057 3058 if (server->version != NULL) 3059 isc_mem_free(server->mctx, server->version); 3060 if (server->hostname != NULL) 3061 isc_mem_free(server->mctx, server->hostname); 3062 if (server->server_id != NULL) 3063 isc_mem_free(server->mctx, server->server_id); 3064 3065 dns_zonemgr_detach(&server->zonemgr); 3066 3067 if (server->tkeyctx != NULL) 3068 dns_tkeyctx_destroy(&server->tkeyctx); 3069 3070 dst_lib_destroy(); 3071 3072 isc_event_free(&server->reload_event); 3073 3074 INSIST(ISC_LIST_EMPTY(server->viewlist)); 3075 3076 dns_aclenv_destroy(&server->aclenv); 3077 3078 isc_quota_destroy(&server->recursionquota); 3079 isc_quota_destroy(&server->tcpquota); 3080 isc_quota_destroy(&server->xfroutquota); 3081 3082 server->magic = 0; 3083 isc_mem_put(server->mctx, server, sizeof(*server)); 3084 *serverp = NULL; 3085} 3086 3087static void 3088fatal(const char *msg, isc_result_t result) { 3089 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3090 ISC_LOG_CRITICAL, "%s: %s", msg, 3091 isc_result_totext(result)); 3092 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3093 ISC_LOG_CRITICAL, "exiting (due to fatal error)"); 3094 exit(1); 3095} 3096 3097static void 3098start_reserved_dispatches(ns_server_t *server) { 3099 3100 REQUIRE(NS_SERVER_VALID(server)); 3101 3102 server->dispatchgen++; 3103} 3104 3105static void 3106end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) { 3107 ns_dispatch_t *dispatch, *nextdispatch; 3108 3109 REQUIRE(NS_SERVER_VALID(server)); 3110 3111 for (dispatch = ISC_LIST_HEAD(server->dispatches); 3112 dispatch != NULL; 3113 dispatch = nextdispatch) { 3114 nextdispatch = ISC_LIST_NEXT(dispatch, link); 3115 if (!all && server->dispatchgen == dispatch-> dispatchgen) 3116 continue; 3117 ISC_LIST_UNLINK(server->dispatches, dispatch, link); 3118 dns_dispatch_detach(&dispatch->dispatch); 3119 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 3120 } 3121} 3122 3123void 3124ns_add_reserved_dispatch(ns_server_t *server, isc_sockaddr_t *addr) { 3125 ns_dispatch_t *dispatch; 3126 in_port_t port; 3127 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 3128 isc_result_t result; 3129 unsigned int attrs, attrmask; 3130 3131 REQUIRE(NS_SERVER_VALID(server)); 3132 3133 port = isc_sockaddr_getport(addr); 3134 if (port == 0 || port >= 1024) 3135 return; 3136 3137 for (dispatch = ISC_LIST_HEAD(server->dispatches); 3138 dispatch != NULL; 3139 dispatch = ISC_LIST_NEXT(dispatch, link)) { 3140 if (isc_sockaddr_equal(&dispatch->addr, addr)) 3141 break; 3142 } 3143 if (dispatch != NULL) { 3144 dispatch->dispatchgen = server->dispatchgen; 3145 return; 3146 } 3147 3148 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch)); 3149 if (dispatch == NULL) { 3150 result = ISC_R_NOMEMORY; 3151 goto cleanup; 3152 } 3153 3154 dispatch->addr = *addr; 3155 dispatch->dispatchgen = server->dispatchgen; 3156 dispatch->dispatch = NULL; 3157 3158 attrs = 0; 3159 attrs |= DNS_DISPATCHATTR_UDP; 3160 switch (isc_sockaddr_pf(addr)) { 3161 case AF_INET: 3162 attrs |= DNS_DISPATCHATTR_IPV4; 3163 break; 3164 case AF_INET6: 3165 attrs |= DNS_DISPATCHATTR_IPV6; 3166 break; 3167 default: 3168 result = ISC_R_NOTIMPLEMENTED; 3169 goto cleanup; 3170 } 3171 attrmask = 0; 3172 attrmask |= DNS_DISPATCHATTR_UDP; 3173 attrmask |= DNS_DISPATCHATTR_TCP; 3174 attrmask |= DNS_DISPATCHATTR_IPV4; 3175 attrmask |= DNS_DISPATCHATTR_IPV6; 3176 3177 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, 3178 ns_g_taskmgr, &dispatch->addr, 4096, 3179 1000, 32768, 16411, 16433, 3180 attrs, attrmask, &dispatch->dispatch); 3181 if (result != ISC_R_SUCCESS) 3182 goto cleanup; 3183 3184 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link); 3185 3186 return; 3187 3188 cleanup: 3189 if (dispatch != NULL) 3190 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 3191 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 3192 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3193 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 3194 "unable to create dispatch for reserved port %s: %s", 3195 addrbuf, isc_result_totext(result)); 3196} 3197 3198 3199static isc_result_t 3200loadconfig(ns_server_t *server) { 3201 isc_result_t result; 3202 start_reserved_dispatches(server); 3203 result = load_configuration(ns_g_lwresdonly ? 3204 lwresd_g_conffile : ns_g_conffile, 3205 server, ISC_FALSE); 3206 if (result == ISC_R_SUCCESS) 3207 end_reserved_dispatches(server, ISC_FALSE); 3208 else 3209 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3210 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3211 "reloading configuration failed: %s", 3212 isc_result_totext(result)); 3213 return (result); 3214} 3215 3216static isc_result_t 3217reload(ns_server_t *server) { 3218 isc_result_t result; 3219 CHECK(loadconfig(server)); 3220 3221 result = load_zones(server, ISC_FALSE); 3222 if (result != ISC_R_SUCCESS) { 3223 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3224 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3225 "reloading zones failed: %s", 3226 isc_result_totext(result)); 3227 } 3228 cleanup: 3229 return (result); 3230} 3231 3232static void 3233reconfig(ns_server_t *server) { 3234 isc_result_t result; 3235 CHECK(loadconfig(server)); 3236 3237 result = load_new_zones(server, ISC_FALSE); 3238 if (result != ISC_R_SUCCESS) { 3239 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3240 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3241 "loading new zones failed: %s", 3242 isc_result_totext(result)); 3243 } 3244 cleanup: ; 3245} 3246 3247/* 3248 * Handle a reload event (from SIGHUP). 3249 */ 3250static void 3251ns_server_reload(isc_task_t *task, isc_event_t *event) { 3252 ns_server_t *server = (ns_server_t *)event->ev_arg; 3253 3254 INSIST(task = server->task); 3255 UNUSED(task); 3256 3257 (void)reload(server); 3258 3259 LOCK(&server->reload_event_lock); 3260 INSIST(server->reload_event == NULL); 3261 server->reload_event = event; 3262 UNLOCK(&server->reload_event_lock); 3263} 3264 3265void 3266ns_server_reloadwanted(ns_server_t *server) { 3267 LOCK(&server->reload_event_lock); 3268 if (server->reload_event != NULL) 3269 isc_task_send(server->task, &server->reload_event); 3270 UNLOCK(&server->reload_event_lock); 3271} 3272 3273static char * 3274next_token(char **stringp, const char *delim) { 3275 char *res; 3276 3277 do { 3278 res = strsep(stringp, delim); 3279 if (res == NULL) 3280 break; 3281 } while (*res == '\0'); 3282 return (res); 3283} 3284 3285/* 3286 * Find the zone specified in the control channel command 'args', 3287 * if any. If a zone is specified, point '*zonep' at it, otherwise 3288 * set '*zonep' to NULL. 3289 */ 3290static isc_result_t 3291zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { 3292 char *input, *ptr; 3293 const char *zonetxt; 3294 char *classtxt; 3295 const char *viewtxt = NULL; 3296 dns_fixedname_t name; 3297 isc_result_t result; 3298 isc_buffer_t buf; 3299 dns_view_t *view = NULL; 3300 dns_rdataclass_t rdclass; 3301 3302 REQUIRE(zonep != NULL && *zonep == NULL); 3303 3304 input = args; 3305 3306 /* Skip the command name. */ 3307 ptr = next_token(&input, " \t"); 3308 if (ptr == NULL) 3309 return (ISC_R_UNEXPECTEDEND); 3310 3311 /* Look for the zone name. */ 3312 zonetxt = next_token(&input, " \t"); 3313 if (zonetxt == NULL) 3314 return (ISC_R_SUCCESS); 3315 3316 /* Look for the optional class name. */ 3317 classtxt = next_token(&input, " \t"); 3318 if (classtxt != NULL) { 3319 /* Look for the optional view name. */ 3320 viewtxt = next_token(&input, " \t"); 3321 } 3322 3323 isc_buffer_init(&buf, zonetxt, strlen(zonetxt)); 3324 isc_buffer_add(&buf, strlen(zonetxt)); 3325 dns_fixedname_init(&name); 3326 result = dns_name_fromtext(dns_fixedname_name(&name), 3327 &buf, dns_rootname, ISC_FALSE, NULL); 3328 if (result != ISC_R_SUCCESS) 3329 goto fail1; 3330 3331 if (classtxt != NULL) { 3332 isc_textregion_t r; 3333 r.base = classtxt; 3334 r.length = strlen(classtxt); 3335 result = dns_rdataclass_fromtext(&rdclass, &r); 3336 if (result != ISC_R_SUCCESS) 3337 goto fail1; 3338 } else { 3339 rdclass = dns_rdataclass_in; 3340 } 3341 3342 if (viewtxt == NULL) 3343 viewtxt = "_default"; 3344 result = dns_viewlist_find(&server->viewlist, viewtxt, 3345 rdclass, &view); 3346 if (result != ISC_R_SUCCESS) 3347 goto fail1; 3348 3349 result = dns_zt_find(view->zonetable, dns_fixedname_name(&name), 3350 0, NULL, zonep); 3351 /* Partial match? */ 3352 if (result != ISC_R_SUCCESS && *zonep != NULL) 3353 dns_zone_detach(zonep); 3354 dns_view_detach(&view); 3355 fail1: 3356 return (result); 3357} 3358 3359/* 3360 * Act on a "retransfer" command from the command channel. 3361 */ 3362isc_result_t 3363ns_server_retransfercommand(ns_server_t *server, char *args) { 3364 isc_result_t result; 3365 dns_zone_t *zone = NULL; 3366 dns_zonetype_t type; 3367 3368 result = zone_from_args(server, args, &zone); 3369 if (result != ISC_R_SUCCESS) 3370 return (result); 3371 if (zone == NULL) 3372 return (ISC_R_UNEXPECTEDEND); 3373 type = dns_zone_gettype(zone); 3374 if (type == dns_zone_slave || type == dns_zone_stub) 3375 dns_zone_forcereload(zone); 3376 else 3377 result = ISC_R_NOTFOUND; 3378 dns_zone_detach(&zone); 3379 return (result); 3380} 3381 3382/* 3383 * Act on a "reload" command from the command channel. 3384 */ 3385isc_result_t 3386ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) { 3387 isc_result_t result; 3388 dns_zone_t *zone = NULL; 3389 dns_zonetype_t type; 3390 const char *msg = NULL; 3391 3392 result = zone_from_args(server, args, &zone); 3393 if (result != ISC_R_SUCCESS) 3394 return (result); 3395 if (zone == NULL) { 3396 result = reload(server); 3397 if (result == ISC_R_SUCCESS) 3398 msg = "server reload successful"; 3399 } else { 3400 type = dns_zone_gettype(zone); 3401 if (type == dns_zone_slave || type == dns_zone_stub) { 3402 dns_zone_refresh(zone); 3403 msg = "zone refresh queued"; 3404 } else { 3405 result = dns_zone_load(zone); 3406 dns_zone_detach(&zone); 3407 switch (result) { 3408 case ISC_R_SUCCESS: 3409 msg = "zone reload successful"; 3410 break; 3411 case DNS_R_CONTINUE: 3412 msg = "zone reload queued"; 3413 result = ISC_R_SUCCESS; 3414 break; 3415 case DNS_R_UPTODATE: 3416 msg = "zone reload up-to-date"; 3417 result = ISC_R_SUCCESS; 3418 break; 3419 default: 3420 /* failure message will be generated by rndc */ 3421 break; 3422 } 3423 } 3424 } 3425 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) 3426 isc_buffer_putmem(text, (const unsigned char *)msg, 3427 strlen(msg) + 1); 3428 return (result); 3429} 3430 3431/* 3432 * Act on a "reconfig" command from the command channel. 3433 */ 3434isc_result_t 3435ns_server_reconfigcommand(ns_server_t *server, char *args) { 3436 UNUSED(args); 3437 3438 reconfig(server); 3439 return (ISC_R_SUCCESS); 3440} 3441 3442/* 3443 * Act on a "refresh" command from the command channel. 3444 */ 3445isc_result_t 3446ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) { 3447 isc_result_t result; 3448 dns_zone_t *zone = NULL; 3449 const unsigned char msg[] = "zone refresh queued"; 3450 3451 result = zone_from_args(server, args, &zone); 3452 if (result != ISC_R_SUCCESS) 3453 return (result); 3454 if (zone == NULL) 3455 return (ISC_R_UNEXPECTEDEND); 3456 3457 dns_zone_refresh(zone); 3458 dns_zone_detach(&zone); 3459 if (sizeof(msg) <= isc_buffer_availablelength(text)) 3460 isc_buffer_putmem(text, msg, sizeof(msg)); 3461 3462 return (ISC_R_SUCCESS); 3463} 3464 3465isc_result_t 3466ns_server_togglequerylog(ns_server_t *server) { 3467 server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE; 3468 3469 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3470 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3471 "query logging is now %s", 3472 server->log_queries ? "on" : "off"); 3473 return (ISC_R_SUCCESS); 3474} 3475 3476static isc_result_t 3477ns_listenlist_fromconfig(cfg_obj_t *listenlist, cfg_obj_t *config, 3478 ns_aclconfctx_t *actx, 3479 isc_mem_t *mctx, ns_listenlist_t **target) 3480{ 3481 isc_result_t result; 3482 cfg_listelt_t *element; 3483 ns_listenlist_t *dlist = NULL; 3484 3485 REQUIRE(target != NULL && *target == NULL); 3486 3487 result = ns_listenlist_create(mctx, &dlist); 3488 if (result != ISC_R_SUCCESS) 3489 return (result); 3490 3491 for (element = cfg_list_first(listenlist); 3492 element != NULL; 3493 element = cfg_list_next(element)) 3494 { 3495 ns_listenelt_t *delt = NULL; 3496 cfg_obj_t *listener = cfg_listelt_value(element); 3497 result = ns_listenelt_fromconfig(listener, config, actx, 3498 mctx, &delt); 3499 if (result != ISC_R_SUCCESS) 3500 goto cleanup; 3501 ISC_LIST_APPEND(dlist->elts, delt, link); 3502 } 3503 *target = dlist; 3504 return (ISC_R_SUCCESS); 3505 3506 cleanup: 3507 ns_listenlist_detach(&dlist); 3508 return (result); 3509} 3510 3511/* 3512 * Create a listen list from the corresponding configuration 3513 * data structure. 3514 */ 3515static isc_result_t 3516ns_listenelt_fromconfig(cfg_obj_t *listener, cfg_obj_t *config, 3517 ns_aclconfctx_t *actx, 3518 isc_mem_t *mctx, ns_listenelt_t **target) 3519{ 3520 isc_result_t result; 3521 cfg_obj_t *portobj; 3522 in_port_t port; 3523 ns_listenelt_t *delt = NULL; 3524 REQUIRE(target != NULL && *target == NULL); 3525 3526 portobj = cfg_tuple_get(listener, "port"); 3527 if (!cfg_obj_isuint32(portobj)) { 3528 if (ns_g_port != 0) { 3529 port = ns_g_port; 3530 } else { 3531 result = ns_config_getport(config, &port); 3532 if (result != ISC_R_SUCCESS) 3533 return (result); 3534 } 3535 } else { 3536 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { 3537 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 3538 "port value '%u' is out of range", 3539 cfg_obj_asuint32(portobj)); 3540 return (ISC_R_RANGE); 3541 } 3542 port = (in_port_t)cfg_obj_asuint32(portobj); 3543 } 3544 3545 result = ns_listenelt_create(mctx, port, NULL, &delt); 3546 if (result != ISC_R_SUCCESS) 3547 return (result); 3548 3549 result = ns_acl_fromconfig(cfg_tuple_get(listener, "acl"), 3550 config, actx, mctx, &delt->acl); 3551 if (result != ISC_R_SUCCESS) { 3552 ns_listenelt_destroy(delt); 3553 return (result); 3554 } 3555 *target = delt; 3556 return (ISC_R_SUCCESS); 3557} 3558 3559isc_result_t 3560ns_server_dumpstats(ns_server_t *server) { 3561 isc_result_t result; 3562 dns_zone_t *zone, *next; 3563 isc_stdtime_t now; 3564 FILE *fp = NULL; 3565 int i; 3566 int ncounters; 3567 3568 isc_stdtime_get(&now); 3569 3570 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), 3571 "could not open statistics dump file", server->statsfile); 3572 3573 ncounters = DNS_STATS_NCOUNTERS; 3574 fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now); 3575 3576 for (i = 0; i < ncounters; i++) 3577 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT "u\n", 3578 dns_statscounter_names[i], 3579 server->querystats[i]); 3580 3581 zone = NULL; 3582 for (result = dns_zone_first(server->zonemgr, &zone); 3583 result == ISC_R_SUCCESS; 3584 next = NULL, result = dns_zone_next(zone, &next), zone = next) 3585 { 3586 isc_uint64_t *zonestats = dns_zone_getstatscounters(zone); 3587 if (zonestats != NULL) { 3588 char zonename[DNS_NAME_FORMATSIZE]; 3589 dns_view_t *view; 3590 char *viewname; 3591 3592 dns_name_format(dns_zone_getorigin(zone), 3593 zonename, sizeof(zonename)); 3594 view = dns_zone_getview(zone); 3595 viewname = view->name; 3596 for (i = 0; i < ncounters; i++) { 3597 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT 3598 "u %s", 3599 dns_statscounter_names[i], 3600 zonestats[i], 3601 zonename); 3602 if (strcmp(viewname, "_default") != 0) 3603 fprintf(fp, " %s", viewname); 3604 fprintf(fp, "\n"); 3605 } 3606 } 3607 } 3608 if (result == ISC_R_NOMORE) 3609 result = ISC_R_SUCCESS; 3610 CHECK(result); 3611 3612 fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now); 3613 3614 cleanup: 3615 if (fp != NULL) 3616 (void)isc_stdio_close(fp); 3617 return (result); 3618} 3619 3620static isc_result_t 3621add_zone_tolist(dns_zone_t *zone, void *uap) { 3622 struct dumpcontext *dctx = uap; 3623 struct zonelistentry *zle; 3624 3625 zle = isc_mem_get(dctx->mctx, sizeof *zle); 3626 if (zle == NULL) 3627 return (ISC_R_NOMEMORY); 3628 zle->zone = NULL; 3629 dns_zone_attach(zone, &zle->zone); 3630 ISC_LINK_INIT(zle, link); 3631 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); 3632 return (ISC_R_SUCCESS); 3633} 3634 3635static isc_result_t 3636add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { 3637 struct viewlistentry *vle; 3638 isc_result_t result = ISC_R_SUCCESS; 3639 3640 vle = isc_mem_get(dctx->mctx, sizeof *vle); 3641 if (vle == NULL) 3642 return (ISC_R_NOMEMORY); 3643 vle->view = NULL; 3644 dns_view_attach(view, &vle->view); 3645 ISC_LINK_INIT(vle, link); 3646 ISC_LIST_INIT(vle->zonelist); 3647 ISC_LIST_APPEND(dctx->viewlist, vle, link); 3648 if (dctx->dumpzones) 3649 result = dns_zt_apply(view->zonetable, ISC_TRUE, 3650 add_zone_tolist, dctx); 3651 return (result); 3652} 3653 3654static void 3655dumpcontext_destroy(struct dumpcontext *dctx) { 3656 struct viewlistentry *vle; 3657 struct zonelistentry *zle; 3658 3659 vle = ISC_LIST_HEAD(dctx->viewlist); 3660 while (vle != NULL) { 3661 ISC_LIST_UNLINK(dctx->viewlist, vle, link); 3662 zle = ISC_LIST_HEAD(vle->zonelist); 3663 while (zle != NULL) { 3664 ISC_LIST_UNLINK(vle->zonelist, zle, link); 3665 dns_zone_detach(&zle->zone); 3666 isc_mem_put(dctx->mctx, zle, sizeof *zle); 3667 zle = ISC_LIST_HEAD(vle->zonelist); 3668 } 3669 dns_view_detach(&vle->view); 3670 isc_mem_put(dctx->mctx, vle, sizeof *vle); 3671 vle = ISC_LIST_HEAD(dctx->viewlist); 3672 } 3673 if (dctx->version != NULL) 3674 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE); 3675 if (dctx->db != NULL) 3676 dns_db_detach(&dctx->db); 3677 if (dctx->cache != NULL) 3678 dns_db_detach(&dctx->cache); 3679 if (dctx->task != NULL) 3680 isc_task_detach(&dctx->task); 3681 if (dctx->fp != NULL) 3682 (void)isc_stdio_close(dctx->fp); 3683 if (dctx->mdctx != NULL) 3684 dns_dumpctx_detach(&dctx->mdctx); 3685 isc_mem_put(dctx->mctx, dctx, sizeof *dctx); 3686} 3687 3688static void 3689dumpdone(void *arg, isc_result_t result) { 3690 struct dumpcontext *dctx = arg; 3691 char buf[1024+32]; 3692 const dns_master_style_t *style; 3693 3694 if (result != ISC_R_SUCCESS) 3695 goto cleanup; 3696 if (dctx->mdctx != NULL) 3697 dns_dumpctx_detach(&dctx->mdctx); 3698 if (dctx->view == NULL) { 3699 dctx->view = ISC_LIST_HEAD(dctx->viewlist); 3700 if (dctx->view == NULL) 3701 goto done; 3702 INSIST(dctx->zone == NULL); 3703 } 3704 nextview: 3705 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); 3706 if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) { 3707 style = &dns_master_style_cache; 3708 /* start cache dump */ 3709 if (dctx->view->view->cachedb != NULL) 3710 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 3711 if (dctx->cache != NULL) { 3712 3713 fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n", 3714 dctx->view->view->name); 3715 result = dns_master_dumptostreaminc(dctx->mctx, 3716 dctx->cache, NULL, 3717 style, dctx->fp, 3718 dctx->task, 3719 dumpdone, dctx, 3720 &dctx->mdctx); 3721 if (result == DNS_R_CONTINUE) 3722 return; 3723 if (result == ISC_R_NOTIMPLEMENTED) 3724 fprintf(dctx->fp, "; %s\n", 3725 dns_result_totext(result)); 3726 else if (result != ISC_R_SUCCESS) 3727 goto cleanup; 3728 } 3729 } 3730 if (dctx->cache != NULL) { 3731 dns_adb_dump(dctx->view->view->adb, dctx->fp); 3732 dns_db_detach(&dctx->cache); 3733 } 3734 if (dctx->dumpzones) { 3735 style = &dns_master_style_full; 3736 nextzone: 3737 if (dctx->version != NULL) 3738 dns_db_closeversion(dctx->db, &dctx->version, 3739 ISC_FALSE); 3740 if (dctx->db != NULL) 3741 dns_db_detach(&dctx->db); 3742 if (dctx->zone == NULL) 3743 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); 3744 else 3745 dctx->zone = ISC_LIST_NEXT(dctx->zone, link); 3746 if (dctx->zone != NULL) { 3747 /* start zone dump */ 3748 dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); 3749 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); 3750 result = dns_zone_getdb(dctx->zone->zone, &dctx->db); 3751 if (result != ISC_R_SUCCESS) { 3752 fprintf(dctx->fp, "; %s\n", 3753 dns_result_totext(result)); 3754 goto nextzone; 3755 } 3756 dns_db_currentversion(dctx->db, &dctx->version); 3757 result = dns_master_dumptostreaminc(dctx->mctx, 3758 dctx->db, 3759 dctx->version, 3760 style, dctx->fp, 3761 dctx->task, 3762 dumpdone, dctx, 3763 &dctx->mdctx); 3764 if (result == DNS_R_CONTINUE) 3765 return; 3766 if (result == ISC_R_NOTIMPLEMENTED) 3767 fprintf(dctx->fp, "; %s\n", 3768 dns_result_totext(result)); 3769 if (result != ISC_R_SUCCESS) 3770 goto cleanup; 3771 } 3772 } 3773 if (dctx->view != NULL) 3774 dctx->view = ISC_LIST_NEXT(dctx->view, link); 3775 if (dctx->view != NULL) 3776 goto nextview; 3777 done: 3778 fprintf(dctx->fp, "; Dump complete\n"); 3779 result = isc_stdio_flush(dctx->fp); 3780 if (result == ISC_R_SUCCESS) 3781 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3782 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3783 "dumpdb complete"); 3784 cleanup: 3785 if (result != ISC_R_SUCCESS) 3786 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3787 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3788 "dumpdb failed: %s", dns_result_totext(result)); 3789 dumpcontext_destroy(dctx); 3790} 3791 3792 3793isc_result_t 3794ns_server_dumpdb(ns_server_t *server, char *args) { 3795 struct dumpcontext *dctx = NULL; 3796 dns_view_t *view; 3797 isc_result_t result; 3798 char *ptr; 3799 const char *sep; 3800 3801 dctx = isc_mem_get(server->mctx, sizeof(*dctx)); 3802 if (dctx == NULL) 3803 return (ISC_R_NOMEMORY); 3804 3805 dctx->mctx = server->mctx; 3806 dctx->dumpcache = ISC_TRUE; 3807 dctx->dumpzones = ISC_FALSE; 3808 dctx->fp = NULL; 3809 ISC_LIST_INIT(dctx->viewlist); 3810 dctx->view = NULL; 3811 dctx->zone = NULL; 3812 dctx->cache = NULL; 3813 dctx->mdctx = NULL; 3814 dctx->db = NULL; 3815 dctx->cache = NULL; 3816 dctx->task = NULL; 3817 dctx->version = NULL; 3818 isc_task_attach(server->task, &dctx->task); 3819 3820 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), 3821 "could not open dump file", server->dumpfile); 3822 3823 /* Skip the command name. */ 3824 ptr = next_token(&args, " \t"); 3825 if (ptr == NULL) 3826 return (ISC_R_UNEXPECTEDEND); 3827 3828 sep = (args == NULL) ? "" : ": "; 3829 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3830 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3831 "dumpdb started%s%s", sep, (args != NULL) ? args : ""); 3832 3833 ptr = next_token(&args, " \t"); 3834 if (ptr != NULL && strcmp(ptr, "-all") == 0) { 3835 dctx->dumpzones = ISC_TRUE; 3836 dctx->dumpcache = ISC_TRUE; 3837 ptr = next_token(&args, " \t"); 3838 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { 3839 dctx->dumpzones = ISC_FALSE; 3840 dctx->dumpcache = ISC_TRUE; 3841 ptr = next_token(&args, " \t"); 3842 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { 3843 dctx->dumpzones = ISC_TRUE; 3844 dctx->dumpcache = ISC_FALSE; 3845 ptr = next_token(&args, " \t"); 3846 } 3847 3848 for (view = ISC_LIST_HEAD(server->viewlist); 3849 view != NULL; 3850 view = ISC_LIST_NEXT(view, link)) 3851 { 3852 if (ptr != NULL && strcmp(view->name, ptr) != 0) 3853 continue; 3854 CHECK(add_view_tolist(dctx, view)); 3855 } 3856 dumpdone(dctx, ISC_R_SUCCESS); 3857 return (ISC_R_SUCCESS); 3858 3859 cleanup: 3860 if (dctx != NULL) 3861 dumpcontext_destroy(dctx); 3862 return (result); 3863} 3864 3865isc_result_t 3866ns_server_dumprecursing(ns_server_t *server) { 3867 FILE *fp = NULL; 3868 isc_result_t result; 3869 3870 CHECKMF(isc_stdio_open(server->recfile, "w", &fp), 3871 "could not open dump file", server->recfile); 3872 fprintf(fp,";\n; Recursing Queries\n;\n"); 3873 ns_interfacemgr_dumprecursing(fp, server->interfacemgr); 3874 fprintf(fp, "; Dump complete\n"); 3875 3876 cleanup: 3877 if (fp != NULL) 3878 result = isc_stdio_close(fp); 3879 return (result); 3880} 3881 3882isc_result_t 3883ns_server_setdebuglevel(ns_server_t *server, char *args) { 3884 char *ptr; 3885 char *levelstr; 3886 char *endp; 3887 long newlevel; 3888 3889 UNUSED(server); 3890 3891 /* Skip the command name. */ 3892 ptr = next_token(&args, " \t"); 3893 if (ptr == NULL) 3894 return (ISC_R_UNEXPECTEDEND); 3895 3896 /* Look for the new level name. */ 3897 levelstr = next_token(&args, " \t"); 3898 if (levelstr == NULL) { 3899 if (ns_g_debuglevel < 99) 3900 ns_g_debuglevel++; 3901 } else { 3902 newlevel = strtol(levelstr, &endp, 10); 3903 if (*endp != '\0' || newlevel < 0 || newlevel > 99) 3904 return (ISC_R_RANGE); 3905 ns_g_debuglevel = (unsigned int)newlevel; 3906 } 3907 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); 3908 return (ISC_R_SUCCESS); 3909} 3910 3911isc_result_t 3912ns_server_flushcache(ns_server_t *server, char *args) { 3913 char *ptr, *viewname; 3914 dns_view_t *view; 3915 isc_boolean_t flushed = ISC_FALSE; 3916 isc_result_t result; 3917 3918 /* Skip the command name. */ 3919 ptr = next_token(&args, " \t"); 3920 if (ptr == NULL) 3921 return (ISC_R_UNEXPECTEDEND); 3922 3923 /* Look for the view name. */ 3924 viewname = next_token(&args, " \t"); 3925 3926 result = isc_task_beginexclusive(server->task); 3927 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3928 for (view = ISC_LIST_HEAD(server->viewlist); 3929 view != NULL; 3930 view = ISC_LIST_NEXT(view, link)) 3931 { 3932 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 3933 continue; 3934 result = dns_view_flushcache(view); 3935 if (result != ISC_R_SUCCESS) 3936 goto out; 3937 flushed = ISC_TRUE; 3938 } 3939 if (flushed) 3940 result = ISC_R_SUCCESS; 3941 else 3942 result = ISC_R_FAILURE; 3943 out: 3944 isc_task_endexclusive(server->task); 3945 return (result); 3946} 3947 3948isc_result_t 3949ns_server_flushname(ns_server_t *server, char *args) { 3950 char *ptr, *target, *viewname; 3951 dns_view_t *view; 3952 isc_boolean_t flushed = ISC_FALSE; 3953 isc_result_t result; 3954 isc_buffer_t b; 3955 dns_fixedname_t fixed; 3956 dns_name_t *name; 3957 3958 /* Skip the command name. */ 3959 ptr = next_token(&args, " \t"); 3960 if (ptr == NULL) 3961 return (ISC_R_UNEXPECTEDEND); 3962 3963 /* Find the domain name to flush. */ 3964 target = next_token(&args, " \t"); 3965 if (target == NULL) 3966 return (ISC_R_UNEXPECTEDEND); 3967 3968 isc_buffer_init(&b, target, strlen(target)); 3969 isc_buffer_add(&b, strlen(target)); 3970 dns_fixedname_init(&fixed); 3971 name = dns_fixedname_name(&fixed); 3972 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); 3973 if (result != ISC_R_SUCCESS) 3974 return (result); 3975 3976 /* Look for the view name. */ 3977 viewname = next_token(&args, " \t"); 3978 3979 result = isc_task_beginexclusive(server->task); 3980 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3981 flushed = ISC_TRUE; 3982 for (view = ISC_LIST_HEAD(server->viewlist); 3983 view != NULL; 3984 view = ISC_LIST_NEXT(view, link)) 3985 { 3986 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 3987 continue; 3988 result = dns_view_flushname(view, name); 3989 if (result != ISC_R_SUCCESS) 3990 flushed = ISC_FALSE; 3991 } 3992 if (flushed) 3993 result = ISC_R_SUCCESS; 3994 else 3995 result = ISC_R_FAILURE; 3996 isc_task_endexclusive(server->task); 3997 return (result); 3998} 3999 4000isc_result_t 4001ns_server_status(ns_server_t *server, isc_buffer_t *text) { 4002 int zonecount, xferrunning, xferdeferred, soaqueries; 4003 unsigned int n; 4004 4005 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); 4006 xferrunning = dns_zonemgr_getcount(server->zonemgr, 4007 DNS_ZONESTATE_XFERRUNNING); 4008 xferdeferred = dns_zonemgr_getcount(server->zonemgr, 4009 DNS_ZONESTATE_XFERDEFERRED); 4010 soaqueries = dns_zonemgr_getcount(server->zonemgr, 4011 DNS_ZONESTATE_SOAQUERY); 4012 n = snprintf((char *)isc_buffer_used(text), 4013 isc_buffer_availablelength(text), 4014 "number of zones: %u\n" 4015 "debug level: %d\n" 4016 "xfers running: %u\n" 4017 "xfers deferred: %u\n" 4018 "soa queries in progress: %u\n" 4019 "query logging is %s\n" 4020 "recursive clients: %d/%d\n" 4021 "tcp clients: %d/%d\n" 4022 "server is up and running", 4023 zonecount, ns_g_debuglevel, xferrunning, xferdeferred, 4024 soaqueries, server->log_queries ? "ON" : "OFF", 4025 server->recursionquota.used, server->recursionquota.max, 4026 server->tcpquota.used, server->tcpquota.max); 4027 if (n >= isc_buffer_availablelength(text)) 4028 return (ISC_R_NOSPACE); 4029 isc_buffer_add(text, n); 4030 return (ISC_R_SUCCESS); 4031} 4032 4033/* 4034 * Act on a "freeze" or "unfreeze" command from the command channel. 4035 */ 4036isc_result_t 4037ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { 4038 isc_result_t result; 4039 dns_zone_t *zone = NULL; 4040 dns_zonetype_t type; 4041 char classstr[DNS_RDATACLASS_FORMATSIZE]; 4042 char zonename[DNS_NAME_FORMATSIZE]; 4043 dns_view_t *view; 4044 char *journal; 4045 const char *vname, *sep; 4046 isc_boolean_t frozen; 4047 4048 result = zone_from_args(server, args, &zone); 4049 if (result != ISC_R_SUCCESS) 4050 return (result); 4051 if (zone == NULL) 4052 return (ISC_R_UNEXPECTEDEND); 4053 type = dns_zone_gettype(zone); 4054 if (type != dns_zone_master) { 4055 dns_zone_detach(&zone); 4056 return (ISC_R_NOTFOUND); 4057 } 4058 4059 frozen = dns_zone_getupdatedisabled(zone); 4060 if (freeze) { 4061 if (frozen) 4062 result = DNS_R_FROZEN; 4063 if (result == ISC_R_SUCCESS) 4064 result = dns_zone_flush(zone); 4065 if (result == ISC_R_SUCCESS) { 4066 journal = dns_zone_getjournal(zone); 4067 if (journal != NULL) 4068 (void)isc_file_remove(journal); 4069 } 4070 } else { 4071 if (frozen) { 4072 result = dns_zone_load(zone); 4073 if (result == DNS_R_CONTINUE || 4074 result == DNS_R_UPTODATE) 4075 result = ISC_R_SUCCESS; 4076 } 4077 } 4078 if (result == ISC_R_SUCCESS) 4079 dns_zone_setupdatedisabled(zone, freeze); 4080 4081 view = dns_zone_getview(zone); 4082 if (strcmp(view->name, "_bind") == 0 || 4083 strcmp(view->name, "_default") == 0) 4084 { 4085 vname = ""; 4086 sep = ""; 4087 } else { 4088 vname = view->name; 4089 sep = " "; 4090 } 4091 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 4092 sizeof(classstr)); 4093 dns_name_format(dns_zone_getorigin(zone), 4094 zonename, sizeof(zonename)); 4095 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4096 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4097 "%s zone '%s/%s'%s%s: %s", 4098 freeze ? "freezing" : "unfreezing", 4099 zonename, classstr, sep, vname, 4100 isc_result_totext(result)); 4101 dns_zone_detach(&zone); 4102 return (result); 4103} 4104