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