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