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