1 /* $NetBSD: server.c,v 1.23 2025/01/26 16:24:33 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #include <ctype.h> 19 #include <inttypes.h> 20 #include <limits.h> 21 #include <signal.h> 22 #include <stdbool.h> 23 #include <stdint.h> 24 #include <stdlib.h> 25 #include <sys/stat.h> 26 #include <sys/types.h> 27 #include <unistd.h> 28 29 #ifdef HAVE_DNSTAP 30 #include <fstrm.h> 31 #endif 32 33 #ifdef HAVE_LIBSYSTEMD 34 #include <systemd/sd-daemon.h> 35 #endif 36 37 #include <isc/async.h> 38 #include <isc/attributes.h> 39 #include <isc/base64.h> 40 #include <isc/commandline.h> 41 #include <isc/dir.h> 42 #include <isc/file.h> 43 #include <isc/fips.h> 44 #include <isc/hash.h> 45 #include <isc/hex.h> 46 #include <isc/hmac.h> 47 #include <isc/httpd.h> 48 #include <isc/job.h> 49 #include <isc/lex.h> 50 #include <isc/loop.h> 51 #include <isc/meminfo.h> 52 #include <isc/netmgr.h> 53 #include <isc/nonce.h> 54 #include <isc/parseint.h> 55 #include <isc/portset.h> 56 #include <isc/refcount.h> 57 #include <isc/result.h> 58 #include <isc/signal.h> 59 #include <isc/siphash.h> 60 #include <isc/stats.h> 61 #include <isc/stdio.h> 62 #include <isc/string.h> 63 #include <isc/time.h> 64 #include <isc/timer.h> 65 #include <isc/util.h> 66 67 #include <dns/adb.h> 68 #include <dns/badcache.h> 69 #include <dns/cache.h> 70 #include <dns/catz.h> 71 #include <dns/db.h> 72 #include <dns/dispatch.h> 73 #include <dns/dlz.h> 74 #include <dns/dns64.h> 75 #include <dns/dnsrps.h> 76 #include <dns/dnssec.h> 77 #include <dns/dyndb.h> 78 #include <dns/fixedname.h> 79 #include <dns/forward.h> 80 #include <dns/geoip.h> 81 #include <dns/journal.h> 82 #include <dns/kasp.h> 83 #include <dns/keymgr.h> 84 #include <dns/keystore.h> 85 #include <dns/keytable.h> 86 #include <dns/keyvalues.h> 87 #include <dns/master.h> 88 #include <dns/masterdump.h> 89 #include <dns/nametree.h> 90 #include <dns/nsec3.h> 91 #include <dns/nta.h> 92 #include <dns/order.h> 93 #include <dns/peer.h> 94 #include <dns/private.h> 95 #include <dns/rbt.h> 96 #include <dns/rdataclass.h> 97 #include <dns/rdatalist.h> 98 #include <dns/rdataset.h> 99 #include <dns/rdatastruct.h> 100 #include <dns/resolver.h> 101 #include <dns/rootns.h> 102 #include <dns/rriterator.h> 103 #include <dns/secalg.h> 104 #include <dns/soa.h> 105 #include <dns/stats.h> 106 #include <dns/time.h> 107 #include <dns/tkey.h> 108 #include <dns/tsig.h> 109 #include <dns/ttl.h> 110 #include <dns/view.h> 111 #include <dns/zone.h> 112 #include <dns/zt.h> 113 114 #include <dst/dst.h> 115 116 #include <isccfg/check.h> 117 #include <isccfg/grammar.h> 118 #include <isccfg/kaspconf.h> 119 #include <isccfg/namedconf.h> 120 121 #include <ns/client.h> 122 #include <ns/hooks.h> 123 #include <ns/interfacemgr.h> 124 #include <ns/listenlist.h> 125 126 #include <named/config.h> 127 #include <named/control.h> 128 #if defined(HAVE_GEOIP2) 129 #include <named/geoip.h> 130 #endif /* HAVE_GEOIP2 */ 131 #include <named/log.h> 132 #include <named/logconf.h> 133 #include <named/main.h> 134 #include <named/os.h> 135 #include <named/server.h> 136 #include <named/statschannel.h> 137 #include <named/tkeyconf.h> 138 #include <named/transportconf.h> 139 #include <named/tsigconf.h> 140 #include <named/zoneconf.h> 141 #ifdef HAVE_LIBSCF 142 #include <stdlib.h> 143 144 #include <named/smf_globals.h> 145 #endif /* ifdef HAVE_LIBSCF */ 146 147 #ifdef HAVE_LMDB 148 #include <lmdb.h> 149 #define configure_newzones configure_newzones_db 150 #define dumpzone dumpzone_db 151 #else /* HAVE_LMDB */ 152 #define configure_newzones configure_newzones_file 153 #define dumpzone dumpzone_file 154 #endif /* HAVE_LMDB */ 155 156 #ifndef SIZE_MAX 157 #define SIZE_MAX ((size_t)-1) 158 #endif /* ifndef SIZE_MAX */ 159 160 #ifndef SIZE_AS_PERCENT 161 #define SIZE_AS_PERCENT ((size_t)-2) 162 #endif /* ifndef SIZE_AS_PERCENT */ 163 164 /* RFC7828 defines timeout as 16-bit value specified in units of 100 165 * milliseconds, so the maximum and minimum advertised and keepalive 166 * timeouts are capped by the data type (it's ~109 minutes) 167 */ 168 #define MIN_INITIAL_TIMEOUT UINT32_C(2500) /* 2.5 seconds */ 169 #define MAX_INITIAL_TIMEOUT UINT32_C(120000) /* 2 minutes */ 170 #define MIN_IDLE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ 171 #define MAX_IDLE_TIMEOUT UINT32_C(120000) /* 2 minutes */ 172 #define MIN_KEEPALIVE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ 173 #define MAX_KEEPALIVE_TIMEOUT UINT32_C(UINT16_MAX * 100) 174 #define MIN_ADVERTISED_TIMEOUT UINT32_C(0) /* No minimum */ 175 #define MAX_ADVERTISED_TIMEOUT UINT32_C(UINT16_MAX * 100) 176 177 /*% 178 * Check an operation for failure. Assumes that the function 179 * using it has a 'result' variable and a 'cleanup' label. 180 */ 181 #define CHECK(op) \ 182 do { \ 183 result = (op); \ 184 if (result != ISC_R_SUCCESS) \ 185 goto cleanup; \ 186 } while (0) 187 188 #define TCHECK(op) \ 189 do { \ 190 tresult = (op); \ 191 if (tresult != ISC_R_SUCCESS) { \ 192 isc_buffer_clear(*text); \ 193 goto cleanup; \ 194 } \ 195 } while (0) 196 197 #define CHECKM(op, msg) \ 198 do { \ 199 result = (op); \ 200 if (result != ISC_R_SUCCESS) { \ 201 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ 202 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \ 203 "%s: %s", msg, \ 204 isc_result_totext(result)); \ 205 goto cleanup; \ 206 } \ 207 } while (0) 208 209 #define CHECKMF(op, msg, file) \ 210 do { \ 211 result = (op); \ 212 if (result != ISC_R_SUCCESS) { \ 213 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ 214 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \ 215 "%s '%s': %s", msg, file, \ 216 isc_result_totext(result)); \ 217 goto cleanup; \ 218 } \ 219 } while (0) 220 221 #define CHECKFATAL(op, msg) \ 222 { \ 223 result = (op); \ 224 if (result != ISC_R_SUCCESS) { \ 225 fatal(msg, result); \ 226 } \ 227 } 228 229 /*% 230 * Maximum ADB size for views that share a cache. Use this limit to suppress 231 * the total of memory footprint, which should be the main reason for sharing 232 * a cache. Only effective when a finite max-cache-size is specified. 233 * This is currently defined to be 8MB. 234 */ 235 #define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U 236 237 struct named_dispatch { 238 isc_sockaddr_t addr; 239 unsigned int dispatchgen; 240 dns_dispatch_t *dispatch; 241 ISC_LINK(struct named_dispatch) link; 242 }; 243 244 struct named_cache { 245 dns_cache_t *cache; 246 dns_view_t *primaryview; 247 bool needflush; 248 bool adbsizeadjusted; 249 dns_rdataclass_t rdclass; 250 ISC_LINK(named_cache_t) link; 251 }; 252 253 struct dumpcontext { 254 isc_mem_t *mctx; 255 bool dumpcache; 256 bool dumpzones; 257 bool dumpadb; 258 bool dumpexpired; 259 bool dumpfail; 260 FILE *fp; 261 ISC_LIST(struct viewlistentry) viewlist; 262 struct viewlistentry *view; 263 struct zonelistentry *zone; 264 dns_dumpctx_t *mdctx; 265 dns_db_t *db; 266 dns_db_t *cache; 267 isc_loop_t *loop; 268 dns_dbversion_t *version; 269 }; 270 271 struct viewlistentry { 272 dns_view_t *view; 273 ISC_LINK(struct viewlistentry) link; 274 ISC_LIST(struct zonelistentry) zonelist; 275 }; 276 277 struct zonelistentry { 278 dns_zone_t *zone; 279 ISC_LINK(struct zonelistentry) link; 280 }; 281 282 /*% 283 * Message-to-view matching context to run message signature validation 284 * asynchronously. 285 */ 286 typedef struct matching_view_ctx { 287 isc_netaddr_t *srcaddr; 288 isc_netaddr_t *destaddr; 289 dns_message_t *message; 290 dns_aclenv_t *env; 291 ns_server_t *sctx; 292 isc_loop_t *loop; 293 isc_job_cb cb; 294 void *cbarg; 295 isc_result_t *sigresult; 296 isc_result_t *viewmatchresult; 297 isc_result_t quota_result; 298 dns_view_t **viewp; 299 dns_view_t *view; 300 } matching_view_ctx_t; 301 302 /*% 303 * Configuration context to retain for each view that allows 304 * new zones to be added at runtime. 305 */ 306 typedef struct ns_cfgctx { 307 isc_mem_t *mctx; 308 cfg_parser_t *conf_parser; 309 cfg_parser_t *add_parser; 310 cfg_obj_t *config; 311 cfg_obj_t *vconfig; 312 cfg_obj_t *nzf_config; 313 cfg_aclconfctx_t *actx; 314 } ns_cfgctx_t; 315 316 /*% 317 * A function to write out added-zone configuration to the new_zone_file 318 * specified in 'view'. Maybe called by delete_zoneconf(). 319 */ 320 typedef isc_result_t (*nzfwriter_t)(const cfg_obj_t *config, dns_view_t *view); 321 322 /*% 323 * Holds state information for the initial zone loading process. 324 * Uses the isc_refcount structure to count the number of views 325 * with pending zone loads, dereferencing as each view finishes. 326 */ 327 typedef struct { 328 named_server_t *server; 329 bool reconfig; 330 isc_refcount_t refs; 331 } ns_zoneload_t; 332 333 typedef struct { 334 named_server_t *server; 335 } catz_cb_data_t; 336 337 typedef struct catz_chgzone { 338 isc_mem_t *mctx; 339 dns_catz_entry_t *entry; 340 dns_catz_zone_t *origin; 341 dns_view_t *view; 342 catz_cb_data_t *cbd; 343 bool mod; 344 } catz_chgzone_t; 345 346 typedef struct catz_reconfig_data { 347 dns_catz_zone_t *catz; 348 const cfg_obj_t *config; 349 catz_cb_data_t *cbd; 350 } catz_reconfig_data_t; 351 352 typedef enum { 353 CATZ_ADDZONE, 354 CATZ_MODZONE, 355 CATZ_DELZONE, 356 } catz_type_t; 357 358 typedef struct { 359 unsigned int magic; 360 #define DZARG_MAGIC ISC_MAGIC('D', 'z', 'a', 'r') 361 isc_buffer_t **text; 362 isc_result_t result; 363 } ns_dzarg_t; 364 365 /* 366 * These zones should not leak onto the Internet. 367 */ 368 const char *empty_zones[] = { 369 /* RFC 1918 */ 370 "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA", 371 "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA", 372 "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA", 373 "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA", 374 "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA", 375 "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA", 376 377 /* RFC 6598 */ 378 "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA", 379 "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA", 380 "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA", 381 "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA", 382 "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA", 383 "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA", 384 "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA", 385 "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA", 386 "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA", 387 "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA", 388 "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA", 389 "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA", 390 "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA", "102.100.IN-ADDR.ARPA", 391 "103.100.IN-ADDR.ARPA", "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA", 392 "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA", "108.100.IN-ADDR.ARPA", 393 "109.100.IN-ADDR.ARPA", "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA", 394 "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA", "114.100.IN-ADDR.ARPA", 395 "115.100.IN-ADDR.ARPA", "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA", 396 "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA", "120.100.IN-ADDR.ARPA", 397 "121.100.IN-ADDR.ARPA", "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA", 398 "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA", "126.100.IN-ADDR.ARPA", 399 "127.100.IN-ADDR.ARPA", 400 401 /* RFC 5735 and RFC 5737 */ 402 "0.IN-ADDR.ARPA", /* THIS NETWORK */ 403 "127.IN-ADDR.ARPA", /* LOOPBACK */ 404 "254.169.IN-ADDR.ARPA", /* LINK LOCAL */ 405 "2.0.192.IN-ADDR.ARPA", /* TEST NET */ 406 "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */ 407 "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */ 408 "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */ 409 410 /* Local IPv6 Unicast Addresses */ 411 "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." 412 "ARPA", 413 "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." 414 "ARPA", 415 /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ 416 "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", /* LINK LOCAL */ 417 "9.E.F.IP6.ARPA", /* LINK LOCAL */ 418 "A.E.F.IP6.ARPA", /* LINK LOCAL */ 419 "B.E.F.IP6.ARPA", /* LINK LOCAL */ 420 421 /* Example Prefix, RFC 3849. */ 422 "8.B.D.0.1.0.0.2.IP6.ARPA", 423 424 /* RFC 7534 */ 425 "EMPTY.AS112.ARPA", 426 427 /* RFC 8375 */ 428 "HOME.ARPA", 429 430 /* RFC 9462 */ 431 "RESOLVER.ARPA", 432 433 NULL 434 }; 435 436 noreturn static void 437 fatal(const char *msg, isc_result_t result); 438 439 static void 440 named_server_reload(void *arg); 441 442 #ifdef HAVE_LIBNGHTTP2 443 static isc_result_t 444 listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, 445 const ns_listen_tls_params_t *tls_params, 446 isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, 447 isc_mem_t *mctx, isc_nm_proxy_type_t proxy, 448 ns_listenelt_t **target); 449 #endif 450 451 static isc_result_t 452 listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 453 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 454 isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target); 455 456 static isc_result_t 457 listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 458 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 459 isc_tlsctx_cache_t *tlsctx_cache, 460 ns_listenlist_t **target); 461 462 static isc_result_t 463 configure_forward(const cfg_obj_t *config, dns_view_t *view, 464 const dns_name_t *origin, const cfg_obj_t *forwarders, 465 const cfg_obj_t *forwardtype); 466 467 static isc_result_t 468 configure_alternates(const cfg_obj_t *config, dns_view_t *view, 469 const cfg_obj_t *alternates); 470 471 static isc_result_t 472 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 473 const cfg_obj_t *vconfig, dns_view_t *view, 474 dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, 475 dns_keystorelist_t *keystores, cfg_aclconfctx_t *aclconf, 476 bool added, bool old_rpz_ok, bool is_catz_member, bool modify); 477 478 static void 479 configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, 480 dns_view_t *view); 481 482 static isc_result_t 483 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 484 cfg_aclconfctx_t *actx); 485 486 static const cfg_obj_t * 487 find_maplist(const cfg_obj_t *config, const char *listname, const char *name); 488 489 static isc_result_t 490 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); 491 492 static void 493 newzone_cfgctx_destroy(void **cfgp); 494 495 static isc_result_t 496 putstr(isc_buffer_t **b, const char *str); 497 498 static isc_result_t 499 putmem(isc_buffer_t **b, const char *str, size_t len); 500 501 static isc_result_t 502 putuint8(isc_buffer_t **b, uint8_t val); 503 504 static isc_result_t 505 putnull(isc_buffer_t **b); 506 507 #ifdef HAVE_LMDB 508 static isc_result_t 509 nzd_writable(dns_view_t *view); 510 511 static isc_result_t 512 nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi); 513 514 static isc_result_t 515 nzd_env_reopen(dns_view_t *view); 516 517 static void 518 nzd_env_close(dns_view_t *view); 519 520 static isc_result_t 521 nzd_close(MDB_txn **txnp, bool commit); 522 #else /* ifdef HAVE_LMDB */ 523 static isc_result_t 524 nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); 525 #endif /* ifdef HAVE_LMDB */ 526 527 static isc_result_t 528 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg); 529 530 /*% 531 * Configure a single view ACL at '*aclp'. Get its configuration from 532 * 'vconfig' (for per-view configuration) and maybe from 'config' 533 */ 534 static isc_result_t 535 configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, 536 const cfg_obj_t *gconfig, const char *aclname, 537 const char *acltuplename, cfg_aclconfctx_t *actx, 538 isc_mem_t *mctx, dns_acl_t **aclp) { 539 isc_result_t result; 540 const cfg_obj_t *maps[4]; 541 const cfg_obj_t *aclobj = NULL; 542 int i = 0; 543 544 if (*aclp != NULL) { 545 dns_acl_detach(aclp); 546 } 547 if (vconfig != NULL) { 548 maps[i++] = cfg_tuple_get(vconfig, "options"); 549 } 550 if (config != NULL) { 551 const cfg_obj_t *options = NULL; 552 (void)cfg_map_get(config, "options", &options); 553 if (options != NULL) { 554 maps[i++] = options; 555 } 556 } 557 if (gconfig != NULL) { 558 const cfg_obj_t *options = NULL; 559 (void)cfg_map_get(gconfig, "options", &options); 560 if (options != NULL) { 561 maps[i++] = options; 562 } 563 } 564 maps[i] = NULL; 565 566 (void)named_config_get(maps, aclname, &aclobj); 567 if (aclobj == NULL) { 568 /* 569 * No value available. *aclp == NULL. 570 */ 571 return ISC_R_SUCCESS; 572 } 573 574 if (acltuplename != NULL) { 575 /* 576 * If the ACL is given in an optional tuple, retrieve it. 577 * The parser should have ensured that a valid object be 578 * returned. 579 */ 580 aclobj = cfg_tuple_get(aclobj, acltuplename); 581 } 582 583 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 0, 584 aclp); 585 586 return result; 587 } 588 589 /*% 590 * Configure a sortlist at '*aclp'. Essentially the same as 591 * configure_view_acl() except it calls cfg_acl_fromconfig with a 592 * nest_level value of 2. 593 */ 594 static isc_result_t 595 configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, 596 cfg_aclconfctx_t *actx, isc_mem_t *mctx, 597 dns_acl_t **aclp) { 598 isc_result_t result; 599 const cfg_obj_t *maps[3]; 600 const cfg_obj_t *aclobj = NULL; 601 int i = 0; 602 603 if (*aclp != NULL) { 604 dns_acl_detach(aclp); 605 } 606 if (vconfig != NULL) { 607 maps[i++] = cfg_tuple_get(vconfig, "options"); 608 } 609 if (config != NULL) { 610 const cfg_obj_t *options = NULL; 611 (void)cfg_map_get(config, "options", &options); 612 if (options != NULL) { 613 maps[i++] = options; 614 } 615 } 616 maps[i] = NULL; 617 618 (void)named_config_get(maps, "sortlist", &aclobj); 619 if (aclobj == NULL) { 620 return ISC_R_SUCCESS; 621 } 622 623 /* 624 * Use a nest level of 3 for the "top level" of the sortlist; 625 * this means each entry in the top three levels will be stored 626 * as lists of separate, nested ACLs, rather than merged together 627 * into IP tables as is usually done with ACLs. 628 */ 629 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 3, 630 aclp); 631 632 return result; 633 } 634 635 static isc_result_t 636 configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, 637 const char *confname, const char *conftuplename, 638 isc_mem_t *mctx, dns_nametree_t **ntp) { 639 isc_result_t result = ISC_R_SUCCESS; 640 const cfg_obj_t *maps[3]; 641 const cfg_obj_t *obj = NULL; 642 const cfg_listelt_t *element = NULL; 643 int i = 0; 644 dns_fixedname_t fixed; 645 dns_name_t *name = NULL; 646 isc_buffer_t b; 647 const char *str = NULL; 648 const cfg_obj_t *nameobj = NULL; 649 650 if (*ntp != NULL) { 651 dns_nametree_detach(ntp); 652 } 653 dns_nametree_create(mctx, DNS_NAMETREE_BOOL, confname, ntp); 654 655 if (vconfig != NULL) { 656 maps[i++] = cfg_tuple_get(vconfig, "options"); 657 } 658 if (config != NULL) { 659 const cfg_obj_t *options = NULL; 660 (void)cfg_map_get(config, "options", &options); 661 if (options != NULL) { 662 maps[i++] = options; 663 } 664 } 665 maps[i] = NULL; 666 667 (void)named_config_get(maps, confname, &obj); 668 if (obj == NULL) { 669 /* 670 * No value available. *ntp == NULL. 671 */ 672 return ISC_R_SUCCESS; 673 } 674 675 if (conftuplename != NULL) { 676 obj = cfg_tuple_get(obj, conftuplename); 677 if (cfg_obj_isvoid(obj)) { 678 return ISC_R_SUCCESS; 679 } 680 } 681 682 name = dns_fixedname_initname(&fixed); 683 for (element = cfg_list_first(obj); element != NULL; 684 element = cfg_list_next(element)) 685 { 686 nameobj = cfg_listelt_value(element); 687 str = cfg_obj_asstring(nameobj); 688 isc_buffer_constinit(&b, str, strlen(str)); 689 isc_buffer_add(&b, strlen(str)); 690 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 691 result = dns_nametree_add(*ntp, name, true); 692 if (result != ISC_R_SUCCESS) { 693 cfg_obj_log(nameobj, named_g_lctx, ISC_LOG_ERROR, 694 "failed to add %s for %s: %s", str, 695 confname, isc_result_totext(result)); 696 goto cleanup; 697 } 698 } 699 700 return ISC_R_SUCCESS; 701 702 cleanup: 703 dns_nametree_detach(ntp); 704 return result; 705 } 706 707 static isc_result_t 708 ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp, 709 unsigned char *digest, dns_rdata_ds_t *ds) { 710 isc_result_t result; 711 dns_rdata_dnskey_t keystruct; 712 dns_rdata_t rdata = DNS_RDATA_INIT; 713 uint32_t rdata1, rdata2, rdata3; 714 const char *datastr = NULL, *namestr = NULL; 715 unsigned char data[4096]; 716 isc_buffer_t databuf; 717 unsigned char rrdata[4096]; 718 isc_buffer_t rrdatabuf; 719 isc_region_t r; 720 dns_fixedname_t fname; 721 dns_name_t *name = NULL; 722 isc_buffer_t namebuf; 723 const char *atstr = NULL; 724 enum { 725 INIT_DNSKEY, 726 STATIC_DNSKEY, 727 INIT_DS, 728 STATIC_DS, 729 TRUSTED 730 } anchortype; 731 732 REQUIRE(namestrp != NULL && *namestrp == NULL); 733 REQUIRE(ds != NULL); 734 735 /* if DNSKEY, flags; if DS, key tag */ 736 rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1")); 737 738 /* if DNSKEY, protocol; if DS, algorithm */ 739 rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2")); 740 741 /* if DNSKEY, algorithm; if DS, digest type */ 742 rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3")); 743 744 namestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 745 *namestrp = namestr; 746 747 name = dns_fixedname_initname(&fname); 748 isc_buffer_constinit(&namebuf, namestr, strlen(namestr)); 749 isc_buffer_add(&namebuf, strlen(namestr)); 750 CHECK(dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL)); 751 752 if (*initialp) { 753 atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype")); 754 755 if (strcasecmp(atstr, "static-key") == 0) { 756 *initialp = false; 757 anchortype = STATIC_DNSKEY; 758 } else if (strcasecmp(atstr, "static-ds") == 0) { 759 *initialp = false; 760 anchortype = STATIC_DS; 761 } else if (strcasecmp(atstr, "initial-key") == 0) { 762 anchortype = INIT_DNSKEY; 763 } else if (strcasecmp(atstr, "initial-ds") == 0) { 764 anchortype = INIT_DS; 765 } else { 766 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 767 "key '%s': " 768 "invalid initialization method '%s'", 769 namestr, atstr); 770 result = ISC_R_FAILURE; 771 goto cleanup; 772 } 773 } else { 774 anchortype = TRUSTED; 775 } 776 777 isc_buffer_init(&databuf, data, sizeof(data)); 778 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 779 780 *ds = (dns_rdata_ds_t){ .common.rdclass = dns_rdataclass_in, 781 .common.rdtype = dns_rdatatype_ds }; 782 783 ISC_LINK_INIT(&ds->common, link); 784 785 switch (anchortype) { 786 case INIT_DNSKEY: 787 case STATIC_DNSKEY: 788 case TRUSTED: 789 /* 790 * This function should never be reached for view 791 * class other than IN 792 */ 793 keystruct.common.rdclass = dns_rdataclass_in; 794 keystruct.common.rdtype = dns_rdatatype_dnskey; 795 796 /* 797 * The key data in keystruct is not dynamically allocated. 798 */ 799 keystruct.mctx = NULL; 800 801 ISC_LINK_INIT(&keystruct.common, link); 802 803 if (rdata1 > 0xffff) { 804 CHECKM(ISC_R_RANGE, "key flags"); 805 } 806 if (rdata1 & DNS_KEYFLAG_REVOKE) { 807 CHECKM(DST_R_BADKEYTYPE, "key flags revoke bit set"); 808 } 809 if (rdata2 > 0xff) { 810 CHECKM(ISC_R_RANGE, "key protocol"); 811 } 812 if (rdata3 > 0xff) { 813 CHECKM(ISC_R_RANGE, "key algorithm"); 814 } 815 816 keystruct.flags = (uint16_t)rdata1; 817 keystruct.protocol = (uint8_t)rdata2; 818 keystruct.algorithm = (uint8_t)rdata3; 819 820 if (!dst_algorithm_supported(keystruct.algorithm)) { 821 CHECK(DST_R_UNSUPPORTEDALG); 822 } 823 824 datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); 825 CHECK(isc_base64_decodestring(datastr, &databuf)); 826 isc_buffer_usedregion(&databuf, &r); 827 keystruct.datalen = r.length; 828 keystruct.data = r.base; 829 830 CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass, 831 keystruct.common.rdtype, &keystruct, 832 &rrdatabuf)); 833 CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, 834 digest, ds)); 835 break; 836 837 case INIT_DS: 838 case STATIC_DS: 839 if (rdata1 > 0xffff) { 840 CHECKM(ISC_R_RANGE, "key tag"); 841 } 842 if (rdata2 > 0xff) { 843 CHECKM(ISC_R_RANGE, "key algorithm"); 844 } 845 if (rdata3 > 0xff) { 846 CHECKM(ISC_R_RANGE, "digest type"); 847 } 848 849 ds->key_tag = (uint16_t)rdata1; 850 ds->algorithm = (uint8_t)rdata2; 851 ds->digest_type = (uint8_t)rdata3; 852 853 datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); 854 CHECK(isc_hex_decodestring(datastr, &databuf)); 855 isc_buffer_usedregion(&databuf, &r); 856 857 switch (ds->digest_type) { 858 case DNS_DSDIGEST_SHA1: 859 if (r.length != ISC_SHA1_DIGESTLENGTH) { 860 CHECK(ISC_R_UNEXPECTEDEND); 861 } 862 break; 863 case DNS_DSDIGEST_SHA256: 864 if (r.length != ISC_SHA256_DIGESTLENGTH) { 865 CHECK(ISC_R_UNEXPECTEDEND); 866 } 867 break; 868 case DNS_DSDIGEST_SHA384: 869 if (r.length != ISC_SHA384_DIGESTLENGTH) { 870 CHECK(ISC_R_UNEXPECTEDEND); 871 } 872 break; 873 default: 874 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 875 "key '%s': " 876 "unknown ds digest type %u", 877 namestr, ds->digest_type); 878 result = ISC_R_FAILURE; 879 goto cleanup; 880 break; 881 } 882 883 ds->length = r.length; 884 ds->digest = digest; 885 memmove(ds->digest, r.base, r.length); 886 887 break; 888 889 default: 890 UNREACHABLE(); 891 } 892 893 return ISC_R_SUCCESS; 894 895 cleanup: 896 return result; 897 } 898 899 static void 900 sfd_add(const dns_name_t *name, void *arg) { 901 if (arg != NULL) { 902 dns_view_sfd_add(arg, name); 903 } 904 } 905 906 /*% 907 * Parse 'key' in the context of view configuration 'vconfig'. If successful, 908 * add the key to 'secroots' if both of the following conditions are true: 909 * 910 * - 'keyname_match' is NULL or it matches the owner name of 'key', 911 * - support for the algorithm used by 'key' is not disabled by 'resolver' 912 * for the owner name of 'key'. 913 * 914 * 'managed' is true for managed keys and false for trusted keys. 'mctx' is 915 * the memory context to use for allocating memory. 916 */ 917 static isc_result_t 918 process_key(const cfg_obj_t *key, dns_keytable_t *secroots, 919 const dns_name_t *keyname_match, dns_view_t *view, bool managed) { 920 dns_fixedname_t fkeyname; 921 dns_name_t *keyname = NULL; 922 const char *namestr = NULL; 923 dns_rdata_ds_t ds; 924 isc_result_t result; 925 bool initializing = managed; 926 unsigned char digest[ISC_MAX_MD_SIZE]; 927 isc_buffer_t b; 928 929 result = ta_fromconfig(key, &initializing, &namestr, digest, &ds); 930 931 switch (result) { 932 case ISC_R_SUCCESS: 933 /* 934 * Trust anchor was parsed correctly. 935 */ 936 isc_buffer_constinit(&b, namestr, strlen(namestr)); 937 isc_buffer_add(&b, strlen(namestr)); 938 keyname = dns_fixedname_initname(&fkeyname); 939 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); 940 if (result != ISC_R_SUCCESS) { 941 return result; 942 } 943 break; 944 case DST_R_UNSUPPORTEDALG: 945 case DST_R_BADKEYTYPE: 946 /* 947 * Key was parsed correctly, but it cannot be used; this is not 948 * a fatal error - log a warning about this key being ignored, 949 * but do not prevent any further ones from being processed. 950 */ 951 cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, 952 "ignoring %s for '%s': %s", 953 initializing ? "initial-key" : "static-key", 954 namestr, isc_result_totext(result)); 955 return ISC_R_SUCCESS; 956 case DST_R_NOCRYPTO: 957 /* 958 * Crypto support is not available. 959 */ 960 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 961 "ignoring %s for '%s': no crypto support", 962 initializing ? "initial-key" : "static-key", 963 namestr); 964 return result; 965 default: 966 /* 967 * Something unexpected happened; we have no choice but to 968 * indicate an error so that the configuration loading process 969 * is interrupted. 970 */ 971 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 972 "configuring %s for '%s': %s", 973 initializing ? "initial-key" : "static-key", 974 namestr, isc_result_totext(result)); 975 return ISC_R_FAILURE; 976 } 977 978 /* 979 * If the caller requested to only load keys for a specific name and 980 * the owner name of this key does not match the requested name, do not 981 * load it. 982 */ 983 if (keyname_match != NULL && !dns_name_equal(keyname_match, keyname)) { 984 goto done; 985 } 986 987 /* 988 * Ensure that 'resolver' allows using the algorithm of this key for 989 * its owner name. If it does not, do not load the key and log a 990 * warning, but do not prevent further keys from being processed. 991 */ 992 if (!dns_resolver_algorithm_supported(view->resolver, keyname, 993 ds.algorithm)) 994 { 995 cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, 996 "ignoring %s for '%s': algorithm is disabled", 997 initializing ? "initial-key" : "static-key", 998 namestr); 999 goto done; 1000 } 1001 1002 /* 1003 * Add the key to 'secroots'. Keys from a "trust-anchors" or 1004 * "managed-keys" statement may be either static or initializing 1005 * keys. If it's not initializing, we don't want to treat it as 1006 * managed, so we use 'initializing' twice here, for both the 1007 * 'managed' and 'initializing' arguments to dns_keytable_add(). 1008 */ 1009 result = dns_keytable_add(secroots, initializing, initializing, keyname, 1010 &ds, sfd_add, view); 1011 1012 done: 1013 return result; 1014 } 1015 1016 /* 1017 * Load keys from configuration into key table. If 'keyname' is specified, 1018 * only load keys matching that name. If 'managed' is true, load the key as 1019 * an initializing key. 1020 */ 1021 static isc_result_t 1022 load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, 1023 const dns_name_t *keyname) { 1024 const cfg_listelt_t *elt, *elt2; 1025 const cfg_obj_t *keylist; 1026 isc_result_t result; 1027 dns_keytable_t *secroots = NULL; 1028 1029 CHECK(dns_view_getsecroots(view, &secroots)); 1030 1031 for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) 1032 { 1033 keylist = cfg_listelt_value(elt); 1034 1035 for (elt2 = cfg_list_first(keylist); elt2 != NULL; 1036 elt2 = cfg_list_next(elt2)) 1037 { 1038 CHECK(process_key(cfg_listelt_value(elt2), secroots, 1039 keyname, view, managed)); 1040 } 1041 } 1042 1043 cleanup: 1044 if (secroots != NULL) { 1045 dns_keytable_detach(&secroots); 1046 } 1047 if (result == DST_R_NOCRYPTO) { 1048 result = ISC_R_SUCCESS; 1049 } 1050 return result; 1051 } 1052 1053 /*% 1054 * Check whether a key has been successfully loaded. 1055 */ 1056 static bool 1057 keyloaded(dns_view_t *view, const dns_name_t *name) { 1058 isc_result_t result; 1059 dns_keytable_t *secroots = NULL; 1060 dns_keynode_t *keynode = NULL; 1061 1062 result = dns_view_getsecroots(view, &secroots); 1063 if (result != ISC_R_SUCCESS) { 1064 return false; 1065 } 1066 1067 result = dns_keytable_find(secroots, name, &keynode); 1068 1069 if (keynode != NULL) { 1070 dns_keynode_detach(&keynode); 1071 } 1072 if (secroots != NULL) { 1073 dns_keytable_detach(&secroots); 1074 } 1075 1076 return result == ISC_R_SUCCESS; 1077 } 1078 1079 /*% 1080 * Configure DNSSEC keys for a view. 1081 * 1082 * The per-view configuration values and the server-global defaults are read 1083 * from 'vconfig' and 'config'. 1084 */ 1085 static isc_result_t 1086 configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, 1087 const cfg_obj_t *config, const cfg_obj_t *bindkeys, 1088 bool auto_root) { 1089 isc_result_t result = ISC_R_SUCCESS; 1090 const cfg_obj_t *view_keys = NULL; 1091 const cfg_obj_t *global_keys = NULL; 1092 const cfg_obj_t *view_managed_keys = NULL; 1093 const cfg_obj_t *view_trust_anchors = NULL; 1094 const cfg_obj_t *global_managed_keys = NULL; 1095 const cfg_obj_t *global_trust_anchors = NULL; 1096 const cfg_obj_t *maps[4]; 1097 const cfg_obj_t *voptions = NULL; 1098 const cfg_obj_t *options = NULL; 1099 const cfg_obj_t *obj = NULL; 1100 const char *directory; 1101 int i = 0; 1102 1103 /* We don't need trust anchors for the _bind view */ 1104 if (strcmp(view->name, "_bind") == 0 && 1105 view->rdclass == dns_rdataclass_chaos) 1106 { 1107 return ISC_R_SUCCESS; 1108 } 1109 1110 if (vconfig != NULL) { 1111 voptions = cfg_tuple_get(vconfig, "options"); 1112 if (voptions != NULL) { 1113 (void)cfg_map_get(voptions, "trusted-keys", &view_keys); 1114 1115 /* managed-keys and trust-anchors are synonyms. */ 1116 (void)cfg_map_get(voptions, "managed-keys", 1117 &view_managed_keys); 1118 (void)cfg_map_get(voptions, "trust-anchors", 1119 &view_trust_anchors); 1120 1121 maps[i++] = voptions; 1122 } 1123 } 1124 1125 if (config != NULL) { 1126 (void)cfg_map_get(config, "trusted-keys", &global_keys); 1127 1128 /* managed-keys and trust-anchors are synonyms. */ 1129 (void)cfg_map_get(config, "managed-keys", &global_managed_keys); 1130 (void)cfg_map_get(config, "trust-anchors", 1131 &global_trust_anchors); 1132 1133 (void)cfg_map_get(config, "options", &options); 1134 if (options != NULL) { 1135 maps[i++] = options; 1136 } 1137 } 1138 1139 maps[i++] = named_g_defaults; 1140 maps[i] = NULL; 1141 1142 dns_view_initsecroots(view); 1143 dns_view_initntatable(view, named_g_loopmgr); 1144 1145 if (auto_root && view->rdclass == dns_rdataclass_in) { 1146 const cfg_obj_t *builtin_keys = NULL; 1147 1148 /* 1149 * If bind.keys exists and is populated, it overrides 1150 * the trust-anchors clause hard-coded in named_g_config. 1151 */ 1152 if (bindkeys != NULL) { 1153 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1154 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1155 "obtaining root key for view %s " 1156 "from '%s'", 1157 view->name, named_g_server->bindkeysfile); 1158 1159 (void)cfg_map_get(bindkeys, "trust-anchors", 1160 &builtin_keys); 1161 1162 if (builtin_keys == NULL) { 1163 isc_log_write( 1164 named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1165 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 1166 "dnssec-validation auto: " 1167 "WARNING: root zone key " 1168 "not found"); 1169 } 1170 } 1171 1172 if (builtin_keys == NULL) { 1173 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1174 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1175 "using built-in root key for view %s", 1176 view->name); 1177 1178 (void)cfg_map_get(named_g_config, "trust-anchors", 1179 &builtin_keys); 1180 } 1181 1182 if (builtin_keys != NULL) { 1183 CHECK(load_view_keys(builtin_keys, view, true, 1184 dns_rootname)); 1185 } 1186 1187 if (!keyloaded(view, dns_rootname)) { 1188 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1189 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1190 "root key not loaded"); 1191 result = ISC_R_FAILURE; 1192 goto cleanup; 1193 } 1194 } 1195 1196 if (view->rdclass == dns_rdataclass_in) { 1197 CHECK(load_view_keys(view_keys, view, false, NULL)); 1198 CHECK(load_view_keys(view_trust_anchors, view, true, NULL)); 1199 CHECK(load_view_keys(view_managed_keys, view, true, NULL)); 1200 1201 CHECK(load_view_keys(global_keys, view, false, NULL)); 1202 CHECK(load_view_keys(global_trust_anchors, view, true, NULL)); 1203 CHECK(load_view_keys(global_managed_keys, view, true, NULL)); 1204 } 1205 1206 /* 1207 * Add key zone for managed keys. 1208 */ 1209 obj = NULL; 1210 (void)named_config_get(maps, "managed-keys-directory", &obj); 1211 directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL); 1212 if (directory != NULL) { 1213 result = isc_file_isdirectory(directory); 1214 } 1215 if (result != ISC_R_SUCCESS) { 1216 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1217 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1218 "invalid managed-keys-directory %s: %s", 1219 directory, isc_result_totext(result)); 1220 goto cleanup; 1221 } else if (directory != NULL) { 1222 if (!isc_file_isdirwritable(directory)) { 1223 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1224 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1225 "managed-keys-directory '%s' " 1226 "is not writable", 1227 directory); 1228 result = ISC_R_NOPERM; 1229 goto cleanup; 1230 } 1231 } 1232 1233 if (auto_root) { 1234 CHECK(add_keydata_zone(view, directory, named_g_mctx)); 1235 } 1236 1237 cleanup: 1238 return result; 1239 } 1240 1241 static isc_result_t 1242 mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { 1243 const cfg_listelt_t *element; 1244 const cfg_obj_t *obj; 1245 const char *str; 1246 dns_fixedname_t fixed; 1247 dns_name_t *name; 1248 bool value; 1249 isc_result_t result; 1250 isc_buffer_t b; 1251 1252 name = dns_fixedname_initname(&fixed); 1253 for (element = cfg_list_first(mbs); element != NULL; 1254 element = cfg_list_next(element)) 1255 { 1256 obj = cfg_listelt_value(element); 1257 str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 1258 isc_buffer_constinit(&b, str, strlen(str)); 1259 isc_buffer_add(&b, strlen(str)); 1260 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1261 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); 1262 CHECK(dns_resolver_setmustbesecure(resolver, name, value)); 1263 } 1264 1265 result = ISC_R_SUCCESS; 1266 1267 cleanup: 1268 return result; 1269 } 1270 1271 /*% 1272 * Get a dispatch appropriate for the resolver of a given view. 1273 */ 1274 static isc_result_t 1275 get_view_querysource_dispatch(const cfg_obj_t **maps, int af, 1276 dns_dispatch_t **dispatchp, bool is_firstview) { 1277 isc_result_t result = ISC_R_FAILURE; 1278 dns_dispatch_t *disp = NULL; 1279 isc_sockaddr_t sa; 1280 const cfg_obj_t *obj = NULL; 1281 1282 switch (af) { 1283 case AF_INET: 1284 result = named_config_get(maps, "query-source", &obj); 1285 INSIST(result == ISC_R_SUCCESS); 1286 break; 1287 case AF_INET6: 1288 result = named_config_get(maps, "query-source-v6", &obj); 1289 INSIST(result == ISC_R_SUCCESS); 1290 break; 1291 default: 1292 UNREACHABLE(); 1293 } 1294 1295 sa = *(cfg_obj_assockaddr(obj)); 1296 INSIST(isc_sockaddr_pf(&sa) == af); 1297 1298 /* 1299 * If we don't support this address family, we're done! 1300 */ 1301 switch (af) { 1302 case AF_INET: 1303 result = isc_net_probeipv4(); 1304 break; 1305 case AF_INET6: 1306 result = isc_net_probeipv6(); 1307 break; 1308 default: 1309 UNREACHABLE(); 1310 } 1311 if (result != ISC_R_SUCCESS) { 1312 return ISC_R_SUCCESS; 1313 } 1314 1315 /* 1316 * Try to find a dispatcher that we can share. 1317 */ 1318 if (isc_sockaddr_getport(&sa) != 0) { 1319 INSIST(obj != NULL); 1320 if (is_firstview) { 1321 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 1322 "using specific query-source port " 1323 "suppresses port randomization and can be " 1324 "insecure."); 1325 } 1326 } 1327 1328 result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, &disp); 1329 if (result != ISC_R_SUCCESS) { 1330 isc_sockaddr_t any; 1331 char buf[ISC_SOCKADDR_FORMATSIZE]; 1332 1333 switch (af) { 1334 case AF_INET: 1335 isc_sockaddr_any(&any); 1336 break; 1337 case AF_INET6: 1338 isc_sockaddr_any6(&any); 1339 break; 1340 } 1341 if (isc_sockaddr_equal(&sa, &any)) { 1342 return ISC_R_SUCCESS; 1343 } 1344 isc_sockaddr_format(&sa, buf, sizeof(buf)); 1345 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1346 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1347 "could not get query source dispatcher (%s): %s", 1348 buf, isc_result_totext(result)); 1349 return result; 1350 } 1351 1352 *dispatchp = disp; 1353 1354 return ISC_R_SUCCESS; 1355 } 1356 1357 static isc_result_t 1358 configure_order(dns_order_t *order, const cfg_obj_t *ent) { 1359 dns_rdataclass_t rdclass; 1360 dns_rdatatype_t rdtype; 1361 const cfg_obj_t *obj; 1362 dns_fixedname_t fixed; 1363 unsigned int mode = 0; 1364 const char *str; 1365 isc_buffer_t b; 1366 isc_result_t result; 1367 bool addroot; 1368 1369 result = named_config_getclass(cfg_tuple_get(ent, "class"), 1370 dns_rdataclass_any, &rdclass); 1371 if (result != ISC_R_SUCCESS) { 1372 return result; 1373 } 1374 1375 result = named_config_gettype(cfg_tuple_get(ent, "type"), 1376 dns_rdatatype_any, &rdtype); 1377 if (result != ISC_R_SUCCESS) { 1378 return result; 1379 } 1380 1381 obj = cfg_tuple_get(ent, "name"); 1382 if (cfg_obj_isstring(obj)) { 1383 str = cfg_obj_asstring(obj); 1384 } else { 1385 str = "*"; 1386 } 1387 addroot = (strcmp(str, "*") == 0); 1388 isc_buffer_constinit(&b, str, strlen(str)); 1389 isc_buffer_add(&b, strlen(str)); 1390 dns_fixedname_init(&fixed); 1391 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, dns_rootname, 1392 0, NULL); 1393 if (result != ISC_R_SUCCESS) { 1394 return result; 1395 } 1396 1397 obj = cfg_tuple_get(ent, "ordering"); 1398 INSIST(cfg_obj_isstring(obj)); 1399 str = cfg_obj_asstring(obj); 1400 if (!strcasecmp(str, "fixed")) { 1401 #if DNS_RDATASET_FIXED 1402 mode = DNS_RDATASETATTR_FIXEDORDER; 1403 #else /* if DNS_RDATASET_FIXED */ 1404 mode = DNS_RDATASETATTR_CYCLIC; 1405 #endif /* DNS_RDATASET_FIXED */ 1406 } else if (!strcasecmp(str, "random")) { 1407 mode = DNS_RDATASETATTR_RANDOMIZE; 1408 } else if (!strcasecmp(str, "cyclic")) { 1409 mode = DNS_RDATASETATTR_CYCLIC; 1410 } else if (!strcasecmp(str, "none")) { 1411 mode = DNS_RDATASETATTR_NONE; 1412 } else { 1413 UNREACHABLE(); 1414 } 1415 1416 /* 1417 * "*" should match everything including the root (BIND 8 compat). 1418 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a 1419 * explicit entry for "." when the name is "*". 1420 */ 1421 if (addroot) { 1422 result = dns_order_add(order, dns_rootname, rdtype, rdclass, 1423 mode); 1424 if (result != ISC_R_SUCCESS) { 1425 return result; 1426 } 1427 } 1428 1429 return dns_order_add(order, dns_fixedname_name(&fixed), rdtype, rdclass, 1430 mode); 1431 } 1432 1433 static isc_result_t 1434 configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { 1435 isc_netaddr_t na; 1436 dns_peer_t *peer; 1437 const cfg_obj_t *obj; 1438 const char *str; 1439 isc_result_t result; 1440 unsigned int prefixlen; 1441 1442 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); 1443 1444 peer = NULL; 1445 result = dns_peer_newprefix(mctx, &na, prefixlen, &peer); 1446 if (result != ISC_R_SUCCESS) { 1447 return result; 1448 } 1449 1450 obj = NULL; 1451 (void)cfg_map_get(cpeer, "bogus", &obj); 1452 if (obj != NULL) { 1453 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); 1454 } 1455 1456 obj = NULL; 1457 (void)cfg_map_get(cpeer, "provide-ixfr", &obj); 1458 if (obj != NULL) { 1459 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); 1460 } 1461 1462 obj = NULL; 1463 (void)cfg_map_get(cpeer, "request-expire", &obj); 1464 if (obj != NULL) { 1465 CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj))); 1466 } 1467 1468 obj = NULL; 1469 (void)cfg_map_get(cpeer, "request-ixfr", &obj); 1470 if (obj != NULL) { 1471 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); 1472 } 1473 1474 obj = NULL; 1475 (void)cfg_map_get(cpeer, "request-nsid", &obj); 1476 if (obj != NULL) { 1477 CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); 1478 } 1479 1480 obj = NULL; 1481 (void)cfg_map_get(cpeer, "send-cookie", &obj); 1482 if (obj != NULL) { 1483 CHECK(dns_peer_setsendcookie(peer, cfg_obj_asboolean(obj))); 1484 } 1485 1486 obj = NULL; 1487 (void)cfg_map_get(cpeer, "require-cookie", &obj); 1488 if (obj != NULL) { 1489 CHECK(dns_peer_setrequirecookie(peer, cfg_obj_asboolean(obj))); 1490 } 1491 1492 obj = NULL; 1493 (void)cfg_map_get(cpeer, "edns", &obj); 1494 if (obj != NULL) { 1495 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); 1496 } 1497 1498 obj = NULL; 1499 (void)cfg_map_get(cpeer, "edns-udp-size", &obj); 1500 if (obj != NULL) { 1501 uint32_t udpsize = cfg_obj_asuint32(obj); 1502 if (udpsize < 512U) { 1503 udpsize = 512U; 1504 } 1505 if (udpsize > 4096U) { 1506 udpsize = 4096U; 1507 } 1508 CHECK(dns_peer_setudpsize(peer, (uint16_t)udpsize)); 1509 } 1510 1511 obj = NULL; 1512 (void)cfg_map_get(cpeer, "edns-version", &obj); 1513 if (obj != NULL) { 1514 uint32_t ednsversion = cfg_obj_asuint32(obj); 1515 if (ednsversion > 255U) { 1516 ednsversion = 255U; 1517 } 1518 CHECK(dns_peer_setednsversion(peer, (uint8_t)ednsversion)); 1519 } 1520 1521 obj = NULL; 1522 (void)cfg_map_get(cpeer, "max-udp-size", &obj); 1523 if (obj != NULL) { 1524 uint32_t udpsize = cfg_obj_asuint32(obj); 1525 if (udpsize < 512U) { 1526 udpsize = 512U; 1527 } 1528 if (udpsize > 4096U) { 1529 udpsize = 4096U; 1530 } 1531 CHECK(dns_peer_setmaxudp(peer, (uint16_t)udpsize)); 1532 } 1533 1534 obj = NULL; 1535 (void)cfg_map_get(cpeer, "padding", &obj); 1536 if (obj != NULL) { 1537 uint32_t padding = cfg_obj_asuint32(obj); 1538 if (padding > 512U) { 1539 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 1540 "server padding value cannot " 1541 "exceed 512: lowering"); 1542 padding = 512U; 1543 } 1544 CHECK(dns_peer_setpadding(peer, (uint16_t)padding)); 1545 } 1546 1547 obj = NULL; 1548 (void)cfg_map_get(cpeer, "tcp-only", &obj); 1549 if (obj != NULL) { 1550 CHECK(dns_peer_setforcetcp(peer, cfg_obj_asboolean(obj))); 1551 } 1552 1553 obj = NULL; 1554 (void)cfg_map_get(cpeer, "tcp-keepalive", &obj); 1555 if (obj != NULL) { 1556 CHECK(dns_peer_settcpkeepalive(peer, cfg_obj_asboolean(obj))); 1557 } 1558 1559 obj = NULL; 1560 (void)cfg_map_get(cpeer, "transfers", &obj); 1561 if (obj != NULL) { 1562 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); 1563 } 1564 1565 obj = NULL; 1566 (void)cfg_map_get(cpeer, "transfer-format", &obj); 1567 if (obj != NULL) { 1568 str = cfg_obj_asstring(obj); 1569 if (strcasecmp(str, "many-answers") == 0) { 1570 CHECK(dns_peer_settransferformat(peer, 1571 dns_many_answers)); 1572 } else if (strcasecmp(str, "one-answer") == 0) { 1573 CHECK(dns_peer_settransferformat(peer, dns_one_answer)); 1574 } else { 1575 UNREACHABLE(); 1576 } 1577 } 1578 1579 obj = NULL; 1580 (void)cfg_map_get(cpeer, "keys", &obj); 1581 if (obj != NULL) { 1582 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); 1583 if (result != ISC_R_SUCCESS) { 1584 goto cleanup; 1585 } 1586 } 1587 1588 obj = NULL; 1589 if (na.family == AF_INET) { 1590 (void)cfg_map_get(cpeer, "transfer-source", &obj); 1591 } else { 1592 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); 1593 } 1594 if (obj != NULL) { 1595 result = dns_peer_settransfersource(peer, 1596 cfg_obj_assockaddr(obj)); 1597 if (result != ISC_R_SUCCESS) { 1598 goto cleanup; 1599 } 1600 } 1601 1602 obj = NULL; 1603 if (na.family == AF_INET) { 1604 (void)cfg_map_get(cpeer, "notify-source", &obj); 1605 } else { 1606 (void)cfg_map_get(cpeer, "notify-source-v6", &obj); 1607 } 1608 if (obj != NULL) { 1609 result = dns_peer_setnotifysource(peer, 1610 cfg_obj_assockaddr(obj)); 1611 if (result != ISC_R_SUCCESS) { 1612 goto cleanup; 1613 } 1614 } 1615 1616 obj = NULL; 1617 if (na.family == AF_INET) { 1618 (void)cfg_map_get(cpeer, "query-source", &obj); 1619 } else { 1620 (void)cfg_map_get(cpeer, "query-source-v6", &obj); 1621 } 1622 if (obj != NULL) { 1623 result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj)); 1624 if (result != ISC_R_SUCCESS) { 1625 goto cleanup; 1626 } 1627 } 1628 1629 *peerp = peer; 1630 return ISC_R_SUCCESS; 1631 1632 cleanup: 1633 dns_peer_detach(&peer); 1634 return result; 1635 } 1636 1637 static isc_result_t 1638 configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, 1639 const dns_dyndbctx_t *dctx) { 1640 isc_result_t result = ISC_R_SUCCESS; 1641 const cfg_obj_t *obj; 1642 const char *name, *library; 1643 1644 /* Get the name of the dyndb instance and the library path . */ 1645 name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name")); 1646 library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library")); 1647 1648 obj = cfg_tuple_get(dyndb, "parameters"); 1649 if (obj != NULL) { 1650 result = dns_dyndb_load(library, name, cfg_obj_asstring(obj), 1651 cfg_obj_file(obj), cfg_obj_line(obj), 1652 mctx, dctx); 1653 } 1654 1655 if (result != ISC_R_SUCCESS) { 1656 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1657 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1658 "dynamic database '%s' configuration failed: %s", 1659 name, isc_result_totext(result)); 1660 } 1661 return result; 1662 } 1663 1664 static isc_result_t 1665 disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1666 isc_result_t result; 1667 const cfg_obj_t *algorithms; 1668 const cfg_listelt_t *element; 1669 const char *str; 1670 dns_fixedname_t fixed; 1671 dns_name_t *name; 1672 isc_buffer_t b; 1673 1674 name = dns_fixedname_initname(&fixed); 1675 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1676 isc_buffer_constinit(&b, str, strlen(str)); 1677 isc_buffer_add(&b, strlen(str)); 1678 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1679 1680 algorithms = cfg_tuple_get(disabled, "algorithms"); 1681 for (element = cfg_list_first(algorithms); element != NULL; 1682 element = cfg_list_next(element)) 1683 { 1684 isc_textregion_t r; 1685 dns_secalg_t alg; 1686 1687 r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element))); 1688 r.length = strlen(r.base); 1689 1690 result = dns_secalg_fromtext(&alg, &r); 1691 if (result != ISC_R_SUCCESS) { 1692 uint8_t ui; 1693 result = isc_parse_uint8(&ui, r.base, 10); 1694 alg = ui; 1695 } 1696 if (result != ISC_R_SUCCESS) { 1697 cfg_obj_log(cfg_listelt_value(element), named_g_lctx, 1698 ISC_LOG_ERROR, "invalid algorithm"); 1699 CHECK(result); 1700 } 1701 CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); 1702 } 1703 cleanup: 1704 return result; 1705 } 1706 1707 static isc_result_t 1708 disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1709 isc_result_t result; 1710 const cfg_obj_t *digests; 1711 const cfg_listelt_t *element; 1712 const char *str; 1713 dns_fixedname_t fixed; 1714 dns_name_t *name; 1715 isc_buffer_t b; 1716 1717 name = dns_fixedname_initname(&fixed); 1718 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1719 isc_buffer_constinit(&b, str, strlen(str)); 1720 isc_buffer_add(&b, strlen(str)); 1721 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1722 1723 digests = cfg_tuple_get(disabled, "digests"); 1724 for (element = cfg_list_first(digests); element != NULL; 1725 element = cfg_list_next(element)) 1726 { 1727 isc_textregion_t r; 1728 dns_dsdigest_t digest; 1729 1730 r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element))); 1731 r.length = strlen(r.base); 1732 1733 /* disable_ds_digests handles numeric values. */ 1734 result = dns_dsdigest_fromtext(&digest, &r); 1735 if (result != ISC_R_SUCCESS) { 1736 cfg_obj_log(cfg_listelt_value(element), named_g_lctx, 1737 ISC_LOG_ERROR, "invalid algorithm"); 1738 CHECK(result); 1739 } 1740 CHECK(dns_resolver_disable_ds_digest(resolver, name, digest)); 1741 } 1742 cleanup: 1743 return result; 1744 } 1745 1746 static bool 1747 on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { 1748 const cfg_listelt_t *element; 1749 dns_fixedname_t fixed; 1750 dns_name_t *name; 1751 isc_result_t result; 1752 const cfg_obj_t *value; 1753 const char *str; 1754 isc_buffer_t b; 1755 1756 name = dns_fixedname_initname(&fixed); 1757 1758 for (element = cfg_list_first(disablelist); element != NULL; 1759 element = cfg_list_next(element)) 1760 { 1761 value = cfg_listelt_value(element); 1762 str = cfg_obj_asstring(value); 1763 isc_buffer_constinit(&b, str, strlen(str)); 1764 isc_buffer_add(&b, strlen(str)); 1765 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 1766 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1767 if (dns_name_equal(name, zonename)) { 1768 return true; 1769 } 1770 } 1771 return false; 1772 } 1773 1774 static isc_result_t 1775 check_dbtype(dns_zone_t *zone, unsigned int dbtypec, const char **dbargv, 1776 isc_mem_t *mctx) { 1777 char **argv = NULL; 1778 unsigned int i; 1779 isc_result_t result = ISC_R_SUCCESS; 1780 1781 CHECK(dns_zone_getdbtype(zone, &argv, mctx)); 1782 1783 /* 1784 * Check that all the arguments match. 1785 */ 1786 for (i = 0; i < dbtypec; i++) { 1787 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) { 1788 CHECK(ISC_R_FAILURE); 1789 } 1790 } 1791 1792 /* 1793 * Check that there are not extra arguments. 1794 */ 1795 if (i == dbtypec && argv[i] != NULL) { 1796 result = ISC_R_FAILURE; 1797 } 1798 1799 cleanup: 1800 isc_mem_free(mctx, argv); 1801 return result; 1802 } 1803 1804 static void 1805 setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) { 1806 isc_stats_t *zoneqrystats; 1807 1808 dns_zone_setstatlevel(zone, level); 1809 1810 zoneqrystats = NULL; 1811 if (level == dns_zonestat_full) { 1812 isc_stats_create(mctx, &zoneqrystats, ns_statscounter_max); 1813 } 1814 dns_zone_setrequeststats(zone, zoneqrystats); 1815 if (zoneqrystats != NULL) { 1816 isc_stats_detach(&zoneqrystats); 1817 } 1818 } 1819 1820 static named_cache_t * 1821 cachelist_find(named_cachelist_t *cachelist, const char *cachename, 1822 dns_rdataclass_t rdclass) { 1823 named_cache_t *nsc; 1824 1825 for (nsc = ISC_LIST_HEAD(*cachelist); nsc != NULL; 1826 nsc = ISC_LIST_NEXT(nsc, link)) 1827 { 1828 if (nsc->rdclass == rdclass && 1829 strcmp(dns_cache_getname(nsc->cache), cachename) == 0) 1830 { 1831 return nsc; 1832 } 1833 } 1834 1835 return NULL; 1836 } 1837 1838 static bool 1839 cache_reusable(dns_view_t *originview, dns_view_t *view, 1840 bool new_zero_no_soattl) { 1841 if (originview->rdclass != view->rdclass || 1842 originview->checknames != view->checknames || 1843 dns_resolver_getzeronosoattl(originview->resolver) != 1844 new_zero_no_soattl || 1845 originview->acceptexpired != view->acceptexpired || 1846 originview->enablevalidation != view->enablevalidation || 1847 originview->maxcachettl != view->maxcachettl || 1848 originview->maxncachettl != view->maxncachettl) 1849 { 1850 return false; 1851 } 1852 1853 return true; 1854 } 1855 1856 static bool 1857 cache_sharable(dns_view_t *originview, dns_view_t *view, 1858 bool new_zero_no_soattl, uint64_t new_max_cache_size, 1859 uint32_t new_stale_ttl, uint32_t new_stale_refresh_time) { 1860 /* 1861 * If the cache cannot even reused for the same view, it cannot be 1862 * shared with other views. 1863 */ 1864 if (!cache_reusable(originview, view, new_zero_no_soattl)) { 1865 return false; 1866 } 1867 1868 /* 1869 * Check other cache related parameters that must be consistent among 1870 * the sharing views. 1871 */ 1872 if (dns_cache_getservestalettl(originview->cache) != new_stale_ttl || 1873 dns_cache_getservestalerefresh(originview->cache) != 1874 new_stale_refresh_time || 1875 dns_cache_getcachesize(originview->cache) != new_max_cache_size) 1876 { 1877 return false; 1878 } 1879 1880 return true; 1881 } 1882 1883 /* 1884 * Callback from DLZ configure when the driver sets up a writeable zone 1885 */ 1886 static isc_result_t 1887 dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) { 1888 dns_name_t *origin = dns_zone_getorigin(zone); 1889 dns_rdataclass_t zclass = view->rdclass; 1890 isc_result_t result; 1891 1892 result = dns_zonemgr_managezone(named_g_server->zonemgr, zone); 1893 if (result != ISC_R_SUCCESS) { 1894 return result; 1895 } 1896 dns_zone_setstats(zone, named_g_server->zonestats); 1897 1898 return named_zone_configure_writeable_dlz(dlzdb, zone, zclass, origin); 1899 } 1900 1901 static isc_result_t 1902 dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, 1903 unsigned int prefixlen, const char *server, const char *contact) { 1904 char reverse[48 + sizeof("ip6.arpa.")] = { 0 }; 1905 char buf[sizeof("x.x.")]; 1906 const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." }; 1907 const char *sep = ": view "; 1908 const char *viewname = view->name; 1909 const unsigned char *s6; 1910 dns_fixedname_t fixed; 1911 dns_name_t *name; 1912 dns_zone_t *zone = NULL; 1913 int dns64_dbtypec = 4; 1914 isc_buffer_t b; 1915 isc_result_t result; 1916 1917 REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || 1918 prefixlen == 56 || prefixlen == 64 || prefixlen == 96); 1919 1920 if (!strcmp(viewname, "_default")) { 1921 sep = ""; 1922 viewname = ""; 1923 } 1924 1925 /* 1926 * Construct the reverse name of the zone. 1927 */ 1928 s6 = na->type.in6.s6_addr; 1929 while (prefixlen > 0) { 1930 prefixlen -= 8; 1931 snprintf(buf, sizeof(buf), "%x.%x.", s6[prefixlen / 8] & 0xf, 1932 (s6[prefixlen / 8] >> 4) & 0xf); 1933 strlcat(reverse, buf, sizeof(reverse)); 1934 } 1935 strlcat(reverse, "ip6.arpa.", sizeof(reverse)); 1936 1937 /* 1938 * Create the actual zone. 1939 */ 1940 if (server != NULL) { 1941 dns64_dbtype[2] = server; 1942 } 1943 if (contact != NULL) { 1944 dns64_dbtype[3] = contact; 1945 } 1946 name = dns_fixedname_initname(&fixed); 1947 isc_buffer_constinit(&b, reverse, strlen(reverse)); 1948 isc_buffer_add(&b, strlen(reverse)); 1949 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1950 dns_zone_create(&zone, mctx, 0); 1951 CHECK(dns_zone_setorigin(zone, name)); 1952 dns_zone_setview(zone, view); 1953 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 1954 dns_zone_setclass(zone, view->rdclass); 1955 dns_zone_settype(zone, dns_zone_primary); 1956 dns_zone_setstats(zone, named_g_server->zonestats); 1957 dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype); 1958 if (view->queryacl != NULL) { 1959 dns_zone_setqueryacl(zone, view->queryacl); 1960 } 1961 if (view->queryonacl != NULL) { 1962 dns_zone_setqueryonacl(zone, view->queryonacl); 1963 } 1964 dns_zone_setdialup(zone, dns_dialuptype_no); 1965 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 1966 dns_zone_setnotifytype(zone, dns_notifytype_no); 1967 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 1968 setquerystats(zone, mctx, dns_zonestat_none); 1969 CHECK(dns_view_addzone(view, zone)); 1970 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1971 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1972 "dns64 reverse zone%s%s: %s", sep, viewname, reverse); 1973 1974 cleanup: 1975 if (zone != NULL) { 1976 dns_zone_detach(&zone); 1977 } 1978 return result; 1979 } 1980 1981 #ifdef USE_DNSRPS 1982 typedef struct conf_dnsrps_ctx conf_dnsrps_ctx_t; 1983 struct conf_dnsrps_ctx { 1984 isc_result_t result; 1985 char *cstr; 1986 size_t cstr_size; 1987 isc_mem_t *mctx; 1988 }; 1989 1990 /* 1991 * Add to the DNSRPS configuration string. 1992 */ 1993 static bool 1994 conf_dnsrps_sadd(conf_dnsrps_ctx_t *ctx, const char *p, ...) { 1995 size_t new_len, cur_len, new_cstr_size; 1996 char *new_cstr; 1997 va_list args; 1998 1999 if (ctx->cstr == NULL) { 2000 ctx->cstr = isc_mem_get(ctx->mctx, 256); 2001 ctx->cstr[0] = '\0'; 2002 ctx->cstr_size = 256; 2003 } 2004 2005 cur_len = strlen(ctx->cstr); 2006 va_start(args, p); 2007 new_len = vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, 2008 args) + 2009 1; 2010 va_end(args); 2011 2012 if (cur_len + new_len <= ctx->cstr_size) { 2013 return true; 2014 } 2015 2016 new_cstr_size = ((cur_len + new_len) / 256 + 1) * 256; 2017 new_cstr = isc_mem_get(ctx->mctx, new_cstr_size); 2018 2019 memmove(new_cstr, ctx->cstr, cur_len); 2020 isc_mem_put(ctx->mctx, ctx->cstr, ctx->cstr_size); 2021 ctx->cstr_size = new_cstr_size; 2022 ctx->cstr = new_cstr; 2023 2024 /* cannot use args twice after a single va_start()on some systems */ 2025 va_start(args, p); 2026 vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, args); 2027 va_end(args); 2028 return true; 2029 } 2030 2031 /* 2032 * Get a DNSRPS configuration value using the global and view options 2033 * for the default. Return false upon failure. 2034 */ 2035 static bool 2036 conf_dnsrps_get(const cfg_obj_t **sub_obj, const cfg_obj_t **maps, 2037 const cfg_obj_t *obj, const char *name, 2038 conf_dnsrps_ctx_t *ctx) { 2039 if (ctx != NULL && ctx->result != ISC_R_SUCCESS) { 2040 *sub_obj = NULL; 2041 return false; 2042 } 2043 2044 *sub_obj = cfg_tuple_get(obj, name); 2045 if (cfg_obj_isvoid(*sub_obj)) { 2046 *sub_obj = NULL; 2047 if (maps != NULL && 2048 ISC_R_SUCCESS != named_config_get(maps, name, sub_obj)) 2049 { 2050 *sub_obj = NULL; 2051 } 2052 } 2053 return true; 2054 } 2055 2056 /* 2057 * Handle a DNSRPS boolean configuration value with the global and view 2058 * options providing the default. 2059 */ 2060 static void 2061 conf_dnsrps_yes_no(const cfg_obj_t *obj, const char *name, 2062 conf_dnsrps_ctx_t *ctx) { 2063 const cfg_obj_t *sub_obj; 2064 2065 if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { 2066 return; 2067 } 2068 if (sub_obj == NULL) { 2069 return; 2070 } 2071 if (ctx == NULL) { 2072 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 2073 "\"%s\" without \"dnsrps-enable yes\"", name); 2074 return; 2075 } 2076 2077 conf_dnsrps_sadd(ctx, " %s %s", name, 2078 cfg_obj_asboolean(sub_obj) ? "yes" : "no"); 2079 } 2080 2081 static void 2082 conf_dnsrps_num(const cfg_obj_t *obj, const char *name, 2083 conf_dnsrps_ctx_t *ctx) { 2084 const cfg_obj_t *sub_obj; 2085 2086 if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { 2087 return; 2088 } 2089 if (sub_obj == NULL) { 2090 return; 2091 } 2092 if (ctx == NULL) { 2093 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 2094 "\"%s\" without \"dnsrps-enable yes\"", name); 2095 return; 2096 } 2097 2098 if (cfg_obj_isduration(sub_obj)) { 2099 conf_dnsrps_sadd(ctx, " %s %d", name, 2100 cfg_obj_asduration(sub_obj)); 2101 } else { 2102 conf_dnsrps_sadd(ctx, " %s %d", name, 2103 cfg_obj_asuint32(sub_obj)); 2104 } 2105 } 2106 2107 /* 2108 * Convert the parsed RPZ configuration statement to a string for 2109 * dns_rpz_new_zones(). 2110 */ 2111 static isc_result_t 2112 conf_dnsrps(dns_view_t *view, const cfg_obj_t **maps, bool nsip_enabled, 2113 bool nsdname_enabled, dns_rpz_zbits_t *nsip_on, 2114 dns_rpz_zbits_t *nsdname_on, char **rps_cstr, size_t *rps_cstr_size, 2115 const cfg_obj_t *rpz_obj, const cfg_listelt_t *zone_element) { 2116 conf_dnsrps_ctx_t ctx; 2117 const cfg_obj_t *zone_obj, *obj; 2118 dns_rpz_num_t rpz_num; 2119 bool on; 2120 const char *s; 2121 2122 memset(&ctx, 0, sizeof(ctx)); 2123 ctx.result = ISC_R_SUCCESS; 2124 ctx.mctx = view->mctx; 2125 2126 for (rpz_num = 0; zone_element != NULL && ctx.result == ISC_R_SUCCESS; 2127 ++rpz_num) 2128 { 2129 zone_obj = cfg_listelt_value(zone_element); 2130 2131 s = cfg_obj_asstring(cfg_tuple_get(zone_obj, "zone name")); 2132 conf_dnsrps_sadd(&ctx, "zone \"%s\"", s); 2133 2134 obj = cfg_tuple_get(zone_obj, "policy"); 2135 if (!cfg_obj_isvoid(obj)) { 2136 s = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 2137 conf_dnsrps_sadd(&ctx, " policy %s", s); 2138 if (strcasecmp(s, "cname") == 0) { 2139 s = cfg_obj_asstring( 2140 cfg_tuple_get(obj, "cname")); 2141 conf_dnsrps_sadd(&ctx, " %s", s); 2142 } 2143 } 2144 2145 conf_dnsrps_yes_no(zone_obj, "recursive-only", &ctx); 2146 conf_dnsrps_yes_no(zone_obj, "log", &ctx); 2147 conf_dnsrps_num(zone_obj, "max-policy-ttl", &ctx); 2148 obj = cfg_tuple_get(rpz_obj, "nsip-enable"); 2149 if (!cfg_obj_isvoid(obj)) { 2150 if (cfg_obj_asboolean(obj)) { 2151 *nsip_on |= DNS_RPZ_ZBIT(rpz_num); 2152 } else { 2153 *nsip_on &= ~DNS_RPZ_ZBIT(rpz_num); 2154 } 2155 } 2156 on = ((*nsip_on & DNS_RPZ_ZBIT(rpz_num)) != 0); 2157 if (nsip_enabled != on) { 2158 conf_dnsrps_sadd(&ctx, on ? " nsip-enable yes " 2159 : " nsip-enable no "); 2160 } 2161 obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); 2162 if (!cfg_obj_isvoid(obj)) { 2163 if (cfg_obj_asboolean(obj)) { 2164 *nsdname_on |= DNS_RPZ_ZBIT(rpz_num); 2165 } else { 2166 *nsdname_on &= ~DNS_RPZ_ZBIT(rpz_num); 2167 } 2168 } 2169 on = ((*nsdname_on & DNS_RPZ_ZBIT(rpz_num)) != 0); 2170 if (nsdname_enabled != on) { 2171 conf_dnsrps_sadd(&ctx, on ? " nsdname-enable yes " 2172 : " nsdname-enable no "); 2173 } 2174 conf_dnsrps_sadd(&ctx, ";\n"); 2175 zone_element = cfg_list_next(zone_element); 2176 } 2177 2178 conf_dnsrps_yes_no(rpz_obj, "recursive-only", &ctx); 2179 conf_dnsrps_num(rpz_obj, "max-policy-ttl", &ctx); 2180 conf_dnsrps_num(rpz_obj, "min-ns-dots", &ctx); 2181 conf_dnsrps_yes_no(rpz_obj, "qname-wait-recurse", &ctx); 2182 conf_dnsrps_yes_no(rpz_obj, "break-dnssec", &ctx); 2183 if (!nsip_enabled) { 2184 conf_dnsrps_sadd(&ctx, " nsip-enable no "); 2185 } 2186 if (!nsdname_enabled) { 2187 conf_dnsrps_sadd(&ctx, " nsdname-enable no "); 2188 } 2189 2190 /* 2191 * Get the general dnsrpzd parameters from the response-policy 2192 * statement in the view and the general options. 2193 */ 2194 if (conf_dnsrps_get(&obj, maps, rpz_obj, "dnsrps-options", &ctx) && 2195 obj != NULL) 2196 { 2197 conf_dnsrps_sadd(&ctx, " %s\n", cfg_obj_asstring(obj)); 2198 } 2199 2200 if (ctx.result == ISC_R_SUCCESS) { 2201 *rps_cstr = ctx.cstr; 2202 *rps_cstr_size = ctx.cstr_size; 2203 } else { 2204 if (ctx.cstr != NULL) { 2205 isc_mem_put(ctx.mctx, ctx.cstr, ctx.cstr_size); 2206 } 2207 *rps_cstr = NULL; 2208 *rps_cstr_size = 0; 2209 } 2210 return ctx.result; 2211 } 2212 #endif /* ifdef USE_DNSRPS */ 2213 2214 static isc_result_t 2215 configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 2216 const char *str, const char *msg) { 2217 isc_result_t result; 2218 2219 result = dns_name_fromstring(name, str, dns_rootname, DNS_NAME_DOWNCASE, 2220 view->mctx); 2221 if (result != ISC_R_SUCCESS) { 2222 cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2223 "invalid %s '%s'", msg, str); 2224 } 2225 return result; 2226 } 2227 2228 static isc_result_t 2229 configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 2230 const char *str, const dns_name_t *origin) { 2231 isc_result_t result; 2232 2233 result = dns_name_fromstring(name, str, origin, DNS_NAME_DOWNCASE, 2234 view->mctx); 2235 if (result != ISC_R_SUCCESS) { 2236 cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2237 "invalid zone '%s'", str); 2238 } 2239 return result; 2240 } 2241 2242 static isc_result_t 2243 configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, 2244 bool recursive_only_default, bool add_soa_default, 2245 dns_ttl_t ttl_default, uint32_t minupdateinterval_default, 2246 const dns_rpz_zone_t *old, bool *old_rpz_okp) { 2247 const cfg_obj_t *rpz_obj, *obj; 2248 const char *str; 2249 dns_rpz_zone_t *zone = NULL; 2250 isc_result_t result; 2251 dns_rpz_num_t rpz_num; 2252 2253 REQUIRE(old != NULL || !*old_rpz_okp); 2254 2255 rpz_obj = cfg_listelt_value(element); 2256 2257 if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) { 2258 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2259 "limit of %d response policy zones exceeded", 2260 DNS_RPZ_MAX_ZONES); 2261 return ISC_R_FAILURE; 2262 } 2263 2264 result = dns_rpz_new_zone(view->rpzs, &zone); 2265 if (result != ISC_R_SUCCESS) { 2266 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2267 "Error creating new RPZ zone : %s", 2268 isc_result_totext(result)); 2269 return result; 2270 } 2271 2272 obj = cfg_tuple_get(rpz_obj, "recursive-only"); 2273 if (cfg_obj_isvoid(obj) ? recursive_only_default 2274 : cfg_obj_asboolean(obj)) 2275 { 2276 view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(zone->num); 2277 } else { 2278 view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(zone->num); 2279 } 2280 2281 obj = cfg_tuple_get(rpz_obj, "log"); 2282 if (!cfg_obj_isvoid(obj) && !cfg_obj_asboolean(obj)) { 2283 view->rpzs->p.no_log |= DNS_RPZ_ZBIT(zone->num); 2284 } else { 2285 view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(zone->num); 2286 } 2287 2288 obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 2289 if (cfg_obj_isduration(obj)) { 2290 zone->max_policy_ttl = cfg_obj_asduration(obj); 2291 } else { 2292 zone->max_policy_ttl = ttl_default; 2293 } 2294 if (*old_rpz_okp && zone->max_policy_ttl != old->max_policy_ttl) { 2295 *old_rpz_okp = false; 2296 } 2297 2298 obj = cfg_tuple_get(rpz_obj, "min-update-interval"); 2299 if (cfg_obj_isduration(obj)) { 2300 zone->min_update_interval = cfg_obj_asduration(obj); 2301 } else { 2302 zone->min_update_interval = minupdateinterval_default; 2303 } 2304 if (*old_rpz_okp && 2305 zone->min_update_interval != old->min_update_interval) 2306 { 2307 *old_rpz_okp = false; 2308 } 2309 2310 str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); 2311 result = configure_rpz_name(view, rpz_obj, &zone->origin, str, "zone"); 2312 if (result != ISC_R_SUCCESS) { 2313 return result; 2314 } 2315 if (dns_name_equal(&zone->origin, dns_rootname)) { 2316 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2317 "invalid zone name '%s'", str); 2318 return DNS_R_EMPTYLABEL; 2319 } 2320 if (!view->rpzs->p.dnsrps_enabled) { 2321 for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones - 1; 2322 ++rpz_num) 2323 { 2324 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, 2325 &zone->origin)) 2326 { 2327 cfg_obj_log(rpz_obj, named_g_lctx, 2328 DNS_RPZ_ERROR_LEVEL, 2329 "duplicate '%s'", str); 2330 result = DNS_R_DUPLICATE; 2331 return result; 2332 } 2333 } 2334 } 2335 if (*old_rpz_okp && !dns_name_equal(&old->origin, &zone->origin)) { 2336 *old_rpz_okp = false; 2337 } 2338 2339 result = configure_rpz_name2(view, rpz_obj, &zone->client_ip, 2340 DNS_RPZ_CLIENT_IP_ZONE, &zone->origin); 2341 if (result != ISC_R_SUCCESS) { 2342 return result; 2343 } 2344 2345 result = configure_rpz_name2(view, rpz_obj, &zone->ip, DNS_RPZ_IP_ZONE, 2346 &zone->origin); 2347 if (result != ISC_R_SUCCESS) { 2348 return result; 2349 } 2350 2351 result = configure_rpz_name2(view, rpz_obj, &zone->nsdname, 2352 DNS_RPZ_NSDNAME_ZONE, &zone->origin); 2353 if (result != ISC_R_SUCCESS) { 2354 return result; 2355 } 2356 2357 result = configure_rpz_name2(view, rpz_obj, &zone->nsip, 2358 DNS_RPZ_NSIP_ZONE, &zone->origin); 2359 if (result != ISC_R_SUCCESS) { 2360 return result; 2361 } 2362 2363 result = configure_rpz_name(view, rpz_obj, &zone->passthru, 2364 DNS_RPZ_PASSTHRU_NAME, "name"); 2365 if (result != ISC_R_SUCCESS) { 2366 return result; 2367 } 2368 2369 result = configure_rpz_name(view, rpz_obj, &zone->drop, 2370 DNS_RPZ_DROP_NAME, "name"); 2371 if (result != ISC_R_SUCCESS) { 2372 return result; 2373 } 2374 2375 result = configure_rpz_name(view, rpz_obj, &zone->tcp_only, 2376 DNS_RPZ_TCP_ONLY_NAME, "name"); 2377 if (result != ISC_R_SUCCESS) { 2378 return result; 2379 } 2380 2381 obj = cfg_tuple_get(rpz_obj, "policy"); 2382 if (cfg_obj_isvoid(obj)) { 2383 zone->policy = DNS_RPZ_POLICY_GIVEN; 2384 } else { 2385 str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 2386 zone->policy = dns_rpz_str2policy(str); 2387 INSIST(zone->policy != DNS_RPZ_POLICY_ERROR); 2388 if (zone->policy == DNS_RPZ_POLICY_CNAME) { 2389 str = cfg_obj_asstring(cfg_tuple_get(obj, "cname")); 2390 result = configure_rpz_name(view, rpz_obj, &zone->cname, 2391 str, "cname"); 2392 if (result != ISC_R_SUCCESS) { 2393 return result; 2394 } 2395 } 2396 } 2397 if (*old_rpz_okp && (zone->policy != old->policy || 2398 !dns_name_equal(&old->cname, &zone->cname))) 2399 { 2400 *old_rpz_okp = false; 2401 } 2402 2403 obj = cfg_tuple_get(rpz_obj, "ede"); 2404 if (!cfg_obj_isstring(obj)) { 2405 zone->ede = 0; 2406 } else { 2407 str = cfg_obj_asstring(obj); 2408 zone->ede = dns_rpz_str2ede(str); 2409 INSIST(zone->ede != UINT16_MAX); 2410 } 2411 if (*old_rpz_okp && zone->ede != old->ede) { 2412 *old_rpz_okp = false; 2413 } 2414 2415 obj = cfg_tuple_get(rpz_obj, "add-soa"); 2416 if (cfg_obj_isvoid(obj)) { 2417 zone->addsoa = add_soa_default; 2418 } else { 2419 zone->addsoa = cfg_obj_asboolean(obj); 2420 } 2421 if (*old_rpz_okp && zone->addsoa != old->addsoa) { 2422 *old_rpz_okp = false; 2423 } 2424 2425 return ISC_R_SUCCESS; 2426 } 2427 2428 static isc_result_t 2429 configure_rpz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t **maps, 2430 const cfg_obj_t *rpz_obj, bool *old_rpz_okp) { 2431 bool dnsrps_enabled; 2432 const cfg_listelt_t *zone_element; 2433 char *rps_cstr; 2434 size_t rps_cstr_size; 2435 const cfg_obj_t *sub_obj; 2436 bool recursive_only_default, add_soa_default; 2437 bool nsip_enabled, nsdname_enabled; 2438 dns_rpz_zbits_t nsip_on, nsdname_on; 2439 dns_ttl_t ttl_default; 2440 uint32_t minupdateinterval_default; 2441 dns_rpz_zones_t *zones; 2442 const dns_rpz_zones_t *old; 2443 bool pview_must_detach = false; 2444 const dns_rpz_zone_t *old_zone; 2445 isc_result_t result; 2446 int i; 2447 2448 *old_rpz_okp = false; 2449 2450 zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list")); 2451 if (zone_element == NULL) { 2452 return ISC_R_SUCCESS; 2453 } 2454 2455 nsip_enabled = true; 2456 sub_obj = cfg_tuple_get(rpz_obj, "nsip-enable"); 2457 if (!cfg_obj_isvoid(sub_obj)) { 2458 nsip_enabled = cfg_obj_asboolean(sub_obj); 2459 } 2460 nsip_on = nsip_enabled ? DNS_RPZ_ALL_ZBITS : 0; 2461 2462 nsdname_enabled = true; 2463 sub_obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); 2464 if (!cfg_obj_isvoid(sub_obj)) { 2465 nsdname_enabled = cfg_obj_asboolean(sub_obj); 2466 } 2467 nsdname_on = nsdname_enabled ? DNS_RPZ_ALL_ZBITS : 0; 2468 2469 /* 2470 * "dnsrps-enable yes|no" can be either a global or response-policy 2471 * clause. 2472 */ 2473 dnsrps_enabled = false; 2474 rps_cstr = NULL; 2475 rps_cstr_size = 0; 2476 sub_obj = NULL; 2477 (void)named_config_get(maps, "dnsrps-enable", &sub_obj); 2478 if (sub_obj != NULL) { 2479 dnsrps_enabled = cfg_obj_asboolean(sub_obj); 2480 } 2481 sub_obj = cfg_tuple_get(rpz_obj, "dnsrps-enable"); 2482 if (!cfg_obj_isvoid(sub_obj)) { 2483 dnsrps_enabled = cfg_obj_asboolean(sub_obj); 2484 } 2485 #ifndef USE_DNSRPS 2486 if (dnsrps_enabled) { 2487 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2488 "\"dnsrps-enable yes\" but" 2489 " without `./configure --enable-dnsrps`"); 2490 return ISC_R_FAILURE; 2491 } 2492 #else /* ifndef USE_DNSRPS */ 2493 if (dnsrps_enabled) { 2494 if (librpz == NULL) { 2495 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2496 "\"dnsrps-enable yes\" but %s", 2497 librpz_lib_open_emsg.c); 2498 return ISC_R_FAILURE; 2499 } 2500 2501 /* 2502 * Generate the DNS Response Policy Service 2503 * configuration string. 2504 */ 2505 result = conf_dnsrps(view, maps, nsip_enabled, nsdname_enabled, 2506 &nsip_on, &nsdname_on, &rps_cstr, 2507 &rps_cstr_size, rpz_obj, zone_element); 2508 if (result != ISC_R_SUCCESS) { 2509 return result; 2510 } 2511 } 2512 #endif /* ifndef USE_DNSRPS */ 2513 2514 result = dns_rpz_new_zones(view, named_g_loopmgr, rps_cstr, 2515 rps_cstr_size, &view->rpzs); 2516 if (result != ISC_R_SUCCESS) { 2517 return result; 2518 } 2519 2520 zones = view->rpzs; 2521 2522 zones->p.nsip_on = nsip_on; 2523 zones->p.nsdname_on = nsdname_on; 2524 2525 sub_obj = cfg_tuple_get(rpz_obj, "recursive-only"); 2526 if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { 2527 recursive_only_default = false; 2528 } else { 2529 recursive_only_default = true; 2530 } 2531 2532 sub_obj = cfg_tuple_get(rpz_obj, "add-soa"); 2533 if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { 2534 add_soa_default = false; 2535 } else { 2536 add_soa_default = true; 2537 } 2538 2539 sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec"); 2540 if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) { 2541 zones->p.break_dnssec = true; 2542 } else { 2543 zones->p.break_dnssec = false; 2544 } 2545 2546 sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 2547 if (cfg_obj_isduration(sub_obj)) { 2548 ttl_default = cfg_obj_asduration(sub_obj); 2549 } else { 2550 ttl_default = DNS_RPZ_MAX_TTL_DEFAULT; 2551 } 2552 2553 sub_obj = cfg_tuple_get(rpz_obj, "min-update-interval"); 2554 if (cfg_obj_isduration(sub_obj)) { 2555 minupdateinterval_default = cfg_obj_asduration(sub_obj); 2556 } else { 2557 minupdateinterval_default = DNS_RPZ_MINUPDATEINTERVAL_DEFAULT; 2558 } 2559 2560 sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots"); 2561 if (cfg_obj_isuint32(sub_obj)) { 2562 zones->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1; 2563 } else { 2564 zones->p.min_ns_labels = 2; 2565 } 2566 2567 sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse"); 2568 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2569 zones->p.qname_wait_recurse = true; 2570 } else { 2571 zones->p.qname_wait_recurse = false; 2572 } 2573 2574 sub_obj = cfg_tuple_get(rpz_obj, "nsdname-wait-recurse"); 2575 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2576 zones->p.nsdname_wait_recurse = true; 2577 } else { 2578 zones->p.nsdname_wait_recurse = false; 2579 } 2580 2581 sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse"); 2582 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2583 zones->p.nsip_wait_recurse = true; 2584 } else { 2585 zones->p.nsip_wait_recurse = false; 2586 } 2587 2588 if (pview != NULL) { 2589 old = pview->rpzs; 2590 } else { 2591 result = dns_viewlist_find(&named_g_server->viewlist, 2592 view->name, view->rdclass, &pview); 2593 if (result == ISC_R_SUCCESS) { 2594 pview_must_detach = true; 2595 old = pview->rpzs; 2596 } else { 2597 old = NULL; 2598 } 2599 } 2600 2601 if (old == NULL) { 2602 *old_rpz_okp = false; 2603 } else { 2604 *old_rpz_okp = true; 2605 } 2606 2607 for (i = 0; zone_element != NULL; 2608 ++i, zone_element = cfg_list_next(zone_element)) 2609 { 2610 INSIST(!*old_rpz_okp || old != NULL); 2611 if (*old_rpz_okp && i < old->p.num_zones) { 2612 old_zone = old->zones[i]; 2613 } else { 2614 *old_rpz_okp = false; 2615 old_zone = NULL; 2616 } 2617 result = configure_rpz_zone( 2618 view, zone_element, recursive_only_default, 2619 add_soa_default, ttl_default, minupdateinterval_default, 2620 old_zone, old_rpz_okp); 2621 if (result != ISC_R_SUCCESS) { 2622 if (pview_must_detach) { 2623 dns_view_detach(&pview); 2624 } 2625 return result; 2626 } 2627 } 2628 2629 /* 2630 * If this is a reloading and the parameters and list of policy 2631 * zones are unchanged, then use the same policy data. 2632 * Data for individual zones that must be reloaded will be merged. 2633 */ 2634 if (*old_rpz_okp) { 2635 if (old != NULL && 2636 memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0) 2637 { 2638 *old_rpz_okp = false; 2639 } else if ((old == NULL || old->rps_cstr == NULL) != 2640 (zones->rps_cstr == NULL)) 2641 { 2642 *old_rpz_okp = false; 2643 } else if (old != NULL && zones->rps_cstr != NULL && 2644 strcmp(old->rps_cstr, zones->rps_cstr) != 0) 2645 { 2646 *old_rpz_okp = false; 2647 } 2648 } 2649 2650 if (*old_rpz_okp) { 2651 dns_rpz_zones_shutdown(view->rpzs); 2652 dns_rpz_zones_detach(&view->rpzs); 2653 dns_rpz_zones_attach(pview->rpzs, &view->rpzs); 2654 dns_rpz_zones_detach(&pview->rpzs); 2655 } else if (old != NULL && pview != NULL) { 2656 ++pview->rpzs->rpz_ver; 2657 view->rpzs->rpz_ver = pview->rpzs->rpz_ver; 2658 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_DEBUG_LEVEL1, 2659 "updated RPZ policy: version %d", 2660 view->rpzs->rpz_ver); 2661 } 2662 2663 if (pview_must_detach) { 2664 dns_view_detach(&pview); 2665 } 2666 2667 return ISC_R_SUCCESS; 2668 } 2669 2670 static void 2671 catz_addmodzone_cb(void *arg) { 2672 catz_chgzone_t *cz = (catz_chgzone_t *)arg; 2673 isc_result_t result; 2674 dns_forwarders_t *dnsforwarders = NULL; 2675 dns_name_t *name = NULL; 2676 isc_buffer_t namebuf; 2677 isc_buffer_t *confbuf = NULL; 2678 char nameb[DNS_NAME_FORMATSIZE]; 2679 const cfg_obj_t *zlist = NULL; 2680 cfg_obj_t *zoneconf = NULL; 2681 cfg_obj_t *zoneobj = NULL; 2682 ns_cfgctx_t *cfg = NULL; 2683 dns_zone_t *zone = NULL; 2684 2685 if (isc_loop_shuttingdown(isc_loop_get(named_g_loopmgr, isc_tid()))) { 2686 goto cleanup; 2687 } 2688 2689 /* 2690 * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' 2691 * is true, so this is expected to be non-NULL. 2692 */ 2693 cfg = (ns_cfgctx_t *)cz->view->new_zone_config; 2694 if (cfg == NULL) { 2695 CHECK(ISC_R_FAILURE); 2696 } 2697 2698 name = dns_catz_entry_getname(cz->entry); 2699 2700 isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); 2701 dns_name_totext(name, DNS_NAME_OMITFINALDOT, &namebuf); 2702 isc_buffer_putuint8(&namebuf, 0); 2703 2704 result = dns_fwdtable_find(cz->view->fwdtable, name, &dnsforwarders); 2705 if (result == ISC_R_SUCCESS && 2706 dnsforwarders->fwdpolicy == dns_fwdpolicy_only) 2707 { 2708 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2709 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2710 "catz: catz_addmodzone_cb: " 2711 "zone '%s' will not be processed because of the " 2712 "explicitly configured forwarding for that zone", 2713 nameb); 2714 goto cleanup; 2715 } 2716 2717 result = dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone); 2718 2719 if (cz->mod) { 2720 dns_catz_zone_t *parentcatz; 2721 2722 if (result != ISC_R_SUCCESS) { 2723 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2724 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2725 "catz: error \"%s\" while trying to " 2726 "modify zone '%s'", 2727 isc_result_totext(result), nameb); 2728 goto cleanup; 2729 } 2730 2731 if (!dns_zone_getadded(zone)) { 2732 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2733 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2734 "catz: catz_addmodzone_cb: " 2735 "zone '%s' is not a dynamically " 2736 "added zone", 2737 nameb); 2738 goto cleanup; 2739 } 2740 2741 parentcatz = dns_zone_get_parentcatz(zone); 2742 2743 if (parentcatz == NULL) { 2744 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2745 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2746 "catz: catz_addmodzone_cb: " 2747 "zone '%s' exists and is not added by " 2748 "a catalog zone, so won't be modified", 2749 nameb); 2750 goto cleanup; 2751 } 2752 if (parentcatz != cz->origin) { 2753 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2754 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2755 "catz: catz_addmodzone_cb: " 2756 "zone '%s' exists in multiple " 2757 "catalog zones", 2758 nameb); 2759 goto cleanup; 2760 } 2761 2762 dns_zone_detach(&zone); 2763 } else { 2764 /* Zone shouldn't already exist when adding */ 2765 if (result == ISC_R_SUCCESS) { 2766 if (dns_zone_get_parentcatz(zone) == NULL) { 2767 isc_log_write( 2768 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2769 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2770 "catz: " 2771 "catz_addmodzone_cb: " 2772 "zone '%s' will not be added " 2773 "because it is an explicitly " 2774 "configured zone", 2775 nameb); 2776 } else { 2777 isc_log_write( 2778 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2779 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2780 "catz: " 2781 "catz_addmodzone_cb: " 2782 "zone '%s' will not be added " 2783 "because another catalog zone " 2784 "already contains an entry with " 2785 "that zone", 2786 nameb); 2787 } 2788 goto cleanup; 2789 } else { 2790 RUNTIME_CHECK(result == ISC_R_NOTFOUND); 2791 } 2792 } 2793 RUNTIME_CHECK(zone == NULL); 2794 /* Create a config for new zone */ 2795 confbuf = NULL; 2796 result = dns_catz_generate_zonecfg(cz->origin, cz->entry, &confbuf); 2797 if (result == ISC_R_SUCCESS) { 2798 cfg_parser_reset(cfg->add_parser); 2799 result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, 2800 &cfg_type_addzoneconf, 0, &zoneconf); 2801 isc_buffer_free(&confbuf); 2802 } 2803 /* 2804 * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() 2805 * failed. 2806 */ 2807 if (result != ISC_R_SUCCESS) { 2808 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2809 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 2810 "catz: error \"%s\" while trying to generate " 2811 "config for zone '%s'", 2812 isc_result_totext(result), nameb); 2813 goto cleanup; 2814 } 2815 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 2816 if (!cfg_obj_islist(zlist)) { 2817 CHECK(ISC_R_FAILURE); 2818 } 2819 2820 /* For now we only support adding one zone at a time */ 2821 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 2822 2823 /* Mark view unfrozen so that zone can be added */ 2824 isc_loopmgr_pause(named_g_loopmgr); 2825 dns_view_thaw(cz->view); 2826 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, cz->view, 2827 &cz->cbd->server->viewlist, 2828 &cz->cbd->server->kasplist, 2829 &cz->cbd->server->keystorelist, cfg->actx, true, 2830 false, true, cz->mod); 2831 dns_view_freeze(cz->view); 2832 isc_loopmgr_resume(named_g_loopmgr); 2833 2834 if (result != ISC_R_SUCCESS) { 2835 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2836 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2837 "catz: failed to configure zone '%s' - %d", nameb, 2838 result); 2839 goto cleanup; 2840 } 2841 2842 /* Is it there yet? */ 2843 CHECK(dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone)); 2844 2845 /* 2846 * Load the zone from the master file. If this fails, we'll 2847 * need to undo the configuration we've done already. 2848 */ 2849 result = dns_zone_load(zone, true); 2850 if (result != ISC_R_SUCCESS) { 2851 dns_db_t *dbp = NULL; 2852 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2853 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 2854 "catz: dns_zone_load() failed " 2855 "with %s; reverting.", 2856 isc_result_totext(result)); 2857 2858 /* If the zone loaded partially, unload it */ 2859 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 2860 dns_db_detach(&dbp); 2861 dns_zone_unload(zone); 2862 } 2863 2864 /* Remove the zone from the zone table */ 2865 dns_view_delzone(cz->view, zone); 2866 goto cleanup; 2867 } 2868 2869 /* Flag the zone as having been added at runtime */ 2870 dns_zone_setadded(zone, true); 2871 dns_zone_set_parentcatz(zone, cz->origin); 2872 2873 cleanup: 2874 if (zone != NULL) { 2875 dns_zone_detach(&zone); 2876 } 2877 if (zoneconf != NULL) { 2878 cfg_obj_destroy(cfg->add_parser, &zoneconf); 2879 } 2880 if (dnsforwarders != NULL) { 2881 dns_forwarders_detach(&dnsforwarders); 2882 } 2883 dns_catz_entry_detach(cz->origin, &cz->entry); 2884 dns_catz_zone_detach(&cz->origin); 2885 dns_view_weakdetach(&cz->view); 2886 isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); 2887 } 2888 2889 static void 2890 catz_delzone_cb(void *arg) { 2891 catz_chgzone_t *cz = (catz_chgzone_t *)arg; 2892 isc_result_t result; 2893 dns_zone_t *zone = NULL; 2894 dns_db_t *dbp = NULL; 2895 char cname[DNS_NAME_FORMATSIZE]; 2896 const char *file = NULL; 2897 2898 if (isc_loop_shuttingdown(isc_loop_get(named_g_loopmgr, isc_tid()))) { 2899 goto cleanup; 2900 } 2901 2902 isc_loopmgr_pause(named_g_loopmgr); 2903 2904 dns_name_format(dns_catz_entry_getname(cz->entry), cname, 2905 DNS_NAME_FORMATSIZE); 2906 result = dns_view_findzone(cz->view, dns_catz_entry_getname(cz->entry), 2907 DNS_ZTFIND_EXACT, &zone); 2908 if (result != ISC_R_SUCCESS) { 2909 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2910 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2911 "catz: catz_delzone_cb: " 2912 "zone '%s' not found", 2913 cname); 2914 goto resume; 2915 } 2916 2917 if (!dns_zone_getadded(zone)) { 2918 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2919 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2920 "catz: catz_delzone_cb: " 2921 "zone '%s' is not a dynamically added zone", 2922 cname); 2923 goto resume; 2924 } 2925 2926 if (dns_zone_get_parentcatz(zone) != cz->origin) { 2927 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2928 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2929 "catz: catz_delzone_cb: zone " 2930 "'%s' exists in multiple catalog zones", 2931 cname); 2932 goto resume; 2933 } 2934 2935 /* Stop answering for this zone */ 2936 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 2937 dns_db_detach(&dbp); 2938 dns_zone_unload(zone); 2939 } 2940 2941 if (dns_view_delzone(cz->view, zone) != ISC_R_SUCCESS) { 2942 goto resume; 2943 } 2944 file = dns_zone_getfile(zone); 2945 if (file != NULL) { 2946 isc_file_remove(file); 2947 file = dns_zone_getjournal(zone); 2948 if (file != NULL) { 2949 isc_file_remove(file); 2950 } 2951 } 2952 2953 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2954 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2955 "catz: catz_delzone_cb: " 2956 "zone '%s' deleted", 2957 cname); 2958 resume: 2959 isc_loopmgr_resume(named_g_loopmgr); 2960 cleanup: 2961 if (zone != NULL) { 2962 dns_zone_detach(&zone); 2963 } 2964 dns_catz_entry_detach(cz->origin, &cz->entry); 2965 dns_catz_zone_detach(&cz->origin); 2966 dns_view_weakdetach(&cz->view); 2967 isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); 2968 } 2969 2970 static isc_result_t 2971 catz_run(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 2972 void *udata, catz_type_t type) { 2973 catz_chgzone_t *cz = NULL; 2974 isc_job_cb action = NULL; 2975 2976 switch (type) { 2977 case CATZ_ADDZONE: 2978 case CATZ_MODZONE: 2979 action = catz_addmodzone_cb; 2980 break; 2981 case CATZ_DELZONE: 2982 action = catz_delzone_cb; 2983 break; 2984 default: 2985 REQUIRE(0); 2986 UNREACHABLE(); 2987 } 2988 2989 cz = isc_mem_get(view->mctx, sizeof(*cz)); 2990 *cz = (catz_chgzone_t){ 2991 .cbd = (catz_cb_data_t *)udata, 2992 .mod = (type == CATZ_MODZONE), 2993 }; 2994 isc_mem_attach(view->mctx, &cz->mctx); 2995 2996 dns_catz_entry_attach(entry, &cz->entry); 2997 dns_catz_zone_attach(origin, &cz->origin); 2998 dns_view_weakattach(view, &cz->view); 2999 3000 isc_async_run(named_g_mainloop, action, cz); 3001 3002 return ISC_R_SUCCESS; 3003 } 3004 3005 static isc_result_t 3006 catz_addzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3007 void *udata) { 3008 return catz_run(entry, origin, view, udata, CATZ_ADDZONE); 3009 } 3010 3011 static isc_result_t 3012 catz_delzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3013 void *udata) { 3014 return catz_run(entry, origin, view, udata, CATZ_DELZONE); 3015 } 3016 3017 static isc_result_t 3018 catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3019 void *udata) { 3020 return catz_run(entry, origin, view, udata, CATZ_MODZONE); 3021 } 3022 3023 static void 3024 catz_changeview(dns_catz_entry_t *entry, void *arg1, void *arg2) { 3025 dns_view_t *pview = arg1; 3026 dns_view_t *view = arg2; 3027 3028 dns_zone_t *zone = NULL; 3029 isc_result_t result = dns_view_findzone( 3030 pview, dns_catz_entry_getname(entry), DNS_ZTFIND_EXACT, &zone); 3031 3032 if (result != ISC_R_SUCCESS) { 3033 return; 3034 } 3035 3036 dns_zone_setview(zone, view); 3037 dns_view_addzone(view, zone); 3038 3039 dns_zone_detach(&zone); 3040 } 3041 3042 static void 3043 catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { 3044 dns_view_t *view = arg1; 3045 catz_reconfig_data_t *data = arg2; 3046 isc_buffer_t namebuf; 3047 isc_buffer_t *confbuf = NULL; 3048 const cfg_obj_t *zlist = NULL; 3049 char nameb[DNS_NAME_FORMATSIZE]; 3050 cfg_obj_t *zoneconf = NULL; 3051 cfg_obj_t *zoneobj = NULL; 3052 ns_cfgctx_t *cfg = NULL; 3053 dns_zone_t *zone = NULL; 3054 isc_result_t result; 3055 3056 isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); 3057 dns_name_totext(dns_catz_entry_getname(entry), DNS_NAME_OMITFINALDOT, 3058 &namebuf); 3059 isc_buffer_putuint8(&namebuf, 0); 3060 3061 result = dns_view_findzone(view, dns_catz_entry_getname(entry), 3062 DNS_ZTFIND_EXACT, &zone); 3063 if (result != ISC_R_SUCCESS) { 3064 return; 3065 } 3066 3067 /* 3068 * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' 3069 * is true, so this is expected to be non-NULL. 3070 */ 3071 cfg = (ns_cfgctx_t *)view->new_zone_config; 3072 if (cfg == NULL) { 3073 CHECK(ISC_R_FAILURE); 3074 } 3075 3076 result = dns_catz_generate_zonecfg(data->catz, entry, &confbuf); 3077 if (result == ISC_R_SUCCESS) { 3078 cfg_parser_reset(cfg->add_parser); 3079 result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, 3080 &cfg_type_addzoneconf, 0, &zoneconf); 3081 isc_buffer_free(&confbuf); 3082 } 3083 /* 3084 * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() 3085 * failed. 3086 */ 3087 if (result != ISC_R_SUCCESS) { 3088 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3089 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 3090 "catz_reconfigure: error \"%s\" while trying to " 3091 "generate config for member zone '%s'", 3092 isc_result_totext(result), nameb); 3093 goto cleanup; 3094 } 3095 3096 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 3097 if (!cfg_obj_islist(zlist)) { 3098 CHECK(ISC_R_FAILURE); 3099 } 3100 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 3101 3102 result = configure_zone(data->config, zoneobj, cfg->vconfig, view, 3103 &data->cbd->server->viewlist, 3104 &data->cbd->server->kasplist, 3105 &data->cbd->server->keystorelist, cfg->actx, 3106 true, false, true, true); 3107 if (result != ISC_R_SUCCESS) { 3108 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3109 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 3110 "catz_reconfigure : error \"%s\" while trying to " 3111 "reconfigure member zone '%s'", 3112 isc_result_totext(result), nameb); 3113 goto cleanup; 3114 } 3115 3116 cleanup: 3117 if (zoneconf != NULL) { 3118 cfg_obj_destroy(cfg->add_parser, &zoneconf); 3119 } 3120 3121 dns_zone_detach(&zone); 3122 } 3123 3124 static isc_result_t 3125 configure_catz_zone(dns_view_t *view, dns_view_t *pview, 3126 const cfg_obj_t *config, const cfg_listelt_t *element) { 3127 const cfg_obj_t *catz_obj, *obj; 3128 dns_catz_zone_t *zone = NULL; 3129 const char *str; 3130 isc_result_t result; 3131 dns_name_t origin; 3132 dns_catz_options_t *opts; 3133 3134 dns_name_init(&origin, NULL); 3135 catz_obj = cfg_listelt_value(element); 3136 3137 str = cfg_obj_asstring(cfg_tuple_get(catz_obj, "zone name")); 3138 3139 result = dns_name_fromstring(&origin, str, dns_rootname, 3140 DNS_NAME_DOWNCASE, view->mctx); 3141 if (result == ISC_R_SUCCESS && dns_name_equal(&origin, dns_rootname)) { 3142 result = DNS_R_EMPTYLABEL; 3143 } 3144 3145 if (result != ISC_R_SUCCESS) { 3146 cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3147 "catz: invalid zone name '%s'", str); 3148 goto cleanup; 3149 } 3150 3151 result = dns_catz_zone_add(view->catzs, &origin, &zone); 3152 if (result == ISC_R_EXISTS) { 3153 catz_reconfig_data_t data = { 3154 .catz = zone, 3155 .config = config, 3156 .cbd = (catz_cb_data_t *)dns_catz_zones_get_udata( 3157 view->catzs), 3158 }; 3159 3160 /* 3161 * We have to walk through all the member zones, re-attach 3162 * them to the current view and reconfigure 3163 */ 3164 dns_catz_zone_for_each_entry2(zone, catz_changeview, pview, 3165 view); 3166 dns_catz_zone_for_each_entry2(zone, catz_reconfigure, view, 3167 &data); 3168 } 3169 3170 dns_catz_zone_resetdefoptions(zone); 3171 opts = dns_catz_zone_getdefoptions(zone); 3172 3173 obj = cfg_tuple_get(catz_obj, "default-masters"); 3174 if (obj == NULL || !cfg_obj_istuple(obj)) { 3175 obj = cfg_tuple_get(catz_obj, "default-primaries"); 3176 } 3177 if (obj != NULL && cfg_obj_istuple(obj)) { 3178 result = named_config_getipandkeylist( 3179 config, "primaries", obj, view->mctx, &opts->masters); 3180 } 3181 3182 obj = cfg_tuple_get(catz_obj, "in-memory"); 3183 if (obj != NULL && cfg_obj_isboolean(obj)) { 3184 opts->in_memory = cfg_obj_asboolean(obj); 3185 } 3186 3187 obj = cfg_tuple_get(catz_obj, "zone-directory"); 3188 if (!opts->in_memory && obj != NULL && cfg_obj_isstring(obj)) { 3189 opts->zonedir = isc_mem_strdup(view->mctx, 3190 cfg_obj_asstring(obj)); 3191 if (isc_file_isdirectory(opts->zonedir) != ISC_R_SUCCESS) { 3192 cfg_obj_log(obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3193 "catz: zone-directory '%s' " 3194 "not found; zone files will not be " 3195 "saved", 3196 opts->zonedir); 3197 opts->in_memory = true; 3198 } 3199 } 3200 3201 obj = cfg_tuple_get(catz_obj, "min-update-interval"); 3202 if (obj != NULL && cfg_obj_isduration(obj)) { 3203 opts->min_update_interval = cfg_obj_asduration(obj); 3204 } 3205 3206 cleanup: 3207 dns_name_free(&origin, view->mctx); 3208 3209 return result; 3210 } 3211 3212 static catz_cb_data_t ns_catz_cbdata; 3213 static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = { 3214 catz_addzone, catz_modzone, catz_delzone, &ns_catz_cbdata 3215 }; 3216 3217 static isc_result_t 3218 configure_catz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t *config, 3219 const cfg_obj_t *catz_obj) { 3220 const cfg_listelt_t *zone_element = NULL; 3221 const dns_catz_zones_t *old = NULL; 3222 bool pview_must_detach = false; 3223 isc_result_t result; 3224 3225 /* xxxwpk TODO do it cleaner, once, somewhere */ 3226 ns_catz_cbdata.server = named_g_server; 3227 3228 zone_element = cfg_list_first(cfg_tuple_get(catz_obj, "zone list")); 3229 if (zone_element == NULL) { 3230 return ISC_R_SUCCESS; 3231 } 3232 3233 if (pview != NULL) { 3234 old = pview->catzs; 3235 } else { 3236 result = dns_viewlist_find(&named_g_server->viewlist, 3237 view->name, view->rdclass, &pview); 3238 if (result == ISC_R_SUCCESS) { 3239 pview_must_detach = true; 3240 old = pview->catzs; 3241 } 3242 } 3243 3244 if (old != NULL) { 3245 dns_catz_zones_attach(pview->catzs, &view->catzs); 3246 dns_catz_zones_detach(&pview->catzs); 3247 dns_catz_prereconfig(view->catzs); 3248 } else { 3249 view->catzs = dns_catz_zones_new(view->mctx, named_g_loopmgr, 3250 &ns_catz_zonemodmethods); 3251 } 3252 3253 while (zone_element != NULL) { 3254 CHECK(configure_catz_zone(view, pview, config, zone_element)); 3255 zone_element = cfg_list_next(zone_element); 3256 } 3257 3258 if (old != NULL) { 3259 dns_catz_postreconfig(view->catzs); 3260 } 3261 3262 result = ISC_R_SUCCESS; 3263 3264 cleanup: 3265 if (pview_must_detach) { 3266 dns_view_detach(&pview); 3267 } 3268 3269 return result; 3270 } 3271 3272 #define CHECK_RRL(cond, pat, val1, val2) \ 3273 do { \ 3274 if (!(cond)) { \ 3275 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, pat, \ 3276 val1, val2); \ 3277 result = ISC_R_RANGE; \ 3278 goto cleanup; \ 3279 } \ 3280 } while (0) 3281 3282 #define CHECK_RRL_RATE(rate, def, max_rate, name) \ 3283 do { \ 3284 obj = NULL; \ 3285 rrl->rate.str = name; \ 3286 result = cfg_map_get(map, name, &obj); \ 3287 if (result == ISC_R_SUCCESS) { \ 3288 rrl->rate.r = cfg_obj_asuint32(obj); \ 3289 CHECK_RRL(rrl->rate.r <= max_rate, name " %d > %d", \ 3290 rrl->rate.r, max_rate); \ 3291 } else { \ 3292 rrl->rate.r = def; \ 3293 } \ 3294 rrl->rate.scaled = rrl->rate.r; \ 3295 } while (0) 3296 3297 static isc_result_t 3298 configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) { 3299 const cfg_obj_t *obj; 3300 dns_rrl_t *rrl; 3301 isc_result_t result; 3302 int min_entries, i, j; 3303 3304 /* 3305 * Most DNS servers have few clients, but intentinally open 3306 * recursive and authoritative servers often have many. 3307 * So start with a small number of entries unless told otherwise 3308 * to reduce cold-start costs. 3309 */ 3310 min_entries = 500; 3311 obj = NULL; 3312 result = cfg_map_get(map, "min-table-size", &obj); 3313 if (result == ISC_R_SUCCESS) { 3314 min_entries = cfg_obj_asuint32(obj); 3315 if (min_entries < 1) { 3316 min_entries = 1; 3317 } 3318 } 3319 result = dns_rrl_init(&rrl, view, min_entries); 3320 if (result != ISC_R_SUCCESS) { 3321 return result; 3322 } 3323 3324 i = ISC_MAX(20000, min_entries); 3325 obj = NULL; 3326 result = cfg_map_get(map, "max-table-size", &obj); 3327 if (result == ISC_R_SUCCESS) { 3328 i = cfg_obj_asuint32(obj); 3329 CHECK_RRL(i >= min_entries, 3330 "max-table-size %d < min-table-size %d", i, 3331 min_entries); 3332 } 3333 rrl->max_entries = i; 3334 3335 CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE, 3336 "responses-per-second"); 3337 CHECK_RRL_RATE(referrals_per_second, rrl->responses_per_second.r, 3338 DNS_RRL_MAX_RATE, "referrals-per-second"); 3339 CHECK_RRL_RATE(nodata_per_second, rrl->responses_per_second.r, 3340 DNS_RRL_MAX_RATE, "nodata-per-second"); 3341 CHECK_RRL_RATE(nxdomains_per_second, rrl->responses_per_second.r, 3342 DNS_RRL_MAX_RATE, "nxdomains-per-second"); 3343 CHECK_RRL_RATE(errors_per_second, rrl->responses_per_second.r, 3344 DNS_RRL_MAX_RATE, "errors-per-second"); 3345 3346 CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, "all-per-second"); 3347 3348 CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, "slip"); 3349 3350 i = 15; 3351 obj = NULL; 3352 result = cfg_map_get(map, "window", &obj); 3353 if (result == ISC_R_SUCCESS) { 3354 i = cfg_obj_asuint32(obj); 3355 CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW, 3356 "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW); 3357 } 3358 rrl->window = i; 3359 3360 i = 0; 3361 obj = NULL; 3362 result = cfg_map_get(map, "qps-scale", &obj); 3363 if (result == ISC_R_SUCCESS) { 3364 i = cfg_obj_asuint32(obj); 3365 CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, ""); 3366 } 3367 rrl->qps_scale = i; 3368 rrl->qps = 1.0; 3369 3370 i = 24; 3371 obj = NULL; 3372 result = cfg_map_get(map, "ipv4-prefix-length", &obj); 3373 if (result == ISC_R_SUCCESS) { 3374 i = cfg_obj_asuint32(obj); 3375 CHECK_RRL(i >= 8 && i <= 32, 3376 "invalid 'ipv4-prefix-length %d'%s", i, ""); 3377 } 3378 rrl->ipv4_prefixlen = i; 3379 if (i == 32) { 3380 rrl->ipv4_mask = 0xffffffff; 3381 } else { 3382 rrl->ipv4_mask = htonl(0xffffffff << (32 - i)); 3383 } 3384 3385 i = 56; 3386 obj = NULL; 3387 result = cfg_map_get(map, "ipv6-prefix-length", &obj); 3388 if (result == ISC_R_SUCCESS) { 3389 i = cfg_obj_asuint32(obj); 3390 CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX, 3391 "ipv6-prefix-length %d < 16 or > %d", i, 3392 DNS_RRL_MAX_PREFIX); 3393 } 3394 rrl->ipv6_prefixlen = i; 3395 for (j = 0; j < 4; ++j) { 3396 if (i <= 0) { 3397 rrl->ipv6_mask[j] = 0; 3398 } else if (i < 32) { 3399 rrl->ipv6_mask[j] = htonl(0xffffffff << (32 - i)); 3400 } else { 3401 rrl->ipv6_mask[j] = 0xffffffff; 3402 } 3403 i -= 32; 3404 } 3405 3406 obj = NULL; 3407 result = cfg_map_get(map, "exempt-clients", &obj); 3408 if (result == ISC_R_SUCCESS) { 3409 result = cfg_acl_fromconfig(obj, config, named_g_lctx, 3410 named_g_aclconfctx, named_g_mctx, 0, 3411 &rrl->exempt); 3412 CHECK_RRL(result == ISC_R_SUCCESS, "invalid %s%s", 3413 "address match list", ""); 3414 } 3415 3416 obj = NULL; 3417 result = cfg_map_get(map, "log-only", &obj); 3418 if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj)) { 3419 rrl->log_only = true; 3420 } else { 3421 rrl->log_only = false; 3422 } 3423 3424 return ISC_R_SUCCESS; 3425 3426 cleanup: 3427 dns_rrl_view_destroy(view); 3428 return result; 3429 } 3430 3431 static isc_result_t 3432 add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 3433 const dns_name_t *origin, const dns_name_t *contact) { 3434 dns_dbnode_t *node = NULL; 3435 dns_rdata_t rdata = DNS_RDATA_INIT; 3436 dns_rdatalist_t rdatalist; 3437 dns_rdataset_t rdataset; 3438 isc_result_t result; 3439 unsigned char buf[DNS_SOA_BUFFERSIZE]; 3440 3441 CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800, 3442 7200, 604800, 86400, buf, &rdata)); 3443 3444 dns_rdatalist_init(&rdatalist); 3445 rdatalist.type = rdata.type; 3446 rdatalist.rdclass = rdata.rdclass; 3447 rdatalist.ttl = 86400; 3448 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 3449 3450 dns_rdataset_init(&rdataset); 3451 dns_rdatalist_tordataset(&rdatalist, &rdataset); 3452 CHECK(dns_db_findnode(db, name, true, &node)); 3453 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 3454 3455 cleanup: 3456 if (node != NULL) { 3457 dns_db_detachnode(db, &node); 3458 } 3459 return result; 3460 } 3461 3462 static isc_result_t 3463 add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 3464 const dns_name_t *nsname) { 3465 dns_dbnode_t *node = NULL; 3466 dns_rdata_ns_t ns; 3467 dns_rdata_t rdata = DNS_RDATA_INIT; 3468 dns_rdatalist_t rdatalist; 3469 dns_rdataset_t rdataset; 3470 isc_result_t result; 3471 isc_buffer_t b; 3472 unsigned char buf[DNS_NAME_MAXWIRE]; 3473 3474 isc_buffer_init(&b, buf, sizeof(buf)); 3475 3476 ns.common.rdtype = dns_rdatatype_ns; 3477 ns.common.rdclass = dns_db_class(db); 3478 ns.mctx = NULL; 3479 dns_name_init(&ns.name, NULL); 3480 dns_name_clone(nsname, &ns.name); 3481 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, 3482 &ns, &b)); 3483 3484 dns_rdatalist_init(&rdatalist); 3485 rdatalist.type = rdata.type; 3486 rdatalist.rdclass = rdata.rdclass; 3487 rdatalist.ttl = 86400; 3488 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 3489 3490 dns_rdataset_init(&rdataset); 3491 dns_rdatalist_tordataset(&rdatalist, &rdataset); 3492 CHECK(dns_db_findnode(db, name, true, &node)); 3493 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 3494 3495 cleanup: 3496 if (node != NULL) { 3497 dns_db_detachnode(db, &node); 3498 } 3499 return result; 3500 } 3501 3502 static isc_result_t 3503 create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view, 3504 const cfg_obj_t *zonelist, const char **empty_dbtype, 3505 int empty_dbtypec, dns_zonestat_level_t statlevel) { 3506 char namebuf[DNS_NAME_FORMATSIZE]; 3507 const cfg_listelt_t *element; 3508 const cfg_obj_t *obj; 3509 const cfg_obj_t *zconfig; 3510 const cfg_obj_t *zoptions; 3511 const char *default_dbtype[4] = { ZONEDB_DEFAULT }; 3512 const char *sep = ": view "; 3513 const char *str; 3514 const char *viewname = view->name; 3515 dns_db_t *db = NULL; 3516 dns_dbversion_t *version = NULL; 3517 dns_fixedname_t cfixed; 3518 dns_fixedname_t fixed; 3519 dns_fixedname_t nsfixed; 3520 dns_name_t *contact; 3521 dns_name_t *ns; 3522 dns_name_t *zname; 3523 dns_zone_t *zone = NULL; 3524 int default_dbtypec = 1; 3525 isc_result_t result; 3526 dns_namereln_t namereln; 3527 int order; 3528 unsigned int nlabels; 3529 3530 zname = dns_fixedname_initname(&fixed); 3531 ns = dns_fixedname_initname(&nsfixed); 3532 contact = dns_fixedname_initname(&cfixed); 3533 3534 /* 3535 * Look for forward "zones" beneath this empty zone and if so 3536 * create a custom db for the empty zone. 3537 */ 3538 for (element = cfg_list_first(zonelist); element != NULL; 3539 element = cfg_list_next(element)) 3540 { 3541 zconfig = cfg_listelt_value(element); 3542 str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 3543 CHECK(dns_name_fromstring(zname, str, dns_rootname, 0, NULL)); 3544 namereln = dns_name_fullcompare(zname, name, &order, &nlabels); 3545 if (namereln != dns_namereln_subdomain) { 3546 continue; 3547 } 3548 3549 zoptions = cfg_tuple_get(zconfig, "options"); 3550 3551 obj = NULL; 3552 (void)cfg_map_get(zoptions, "type", &obj); 3553 if (obj != NULL && 3554 strcasecmp(cfg_obj_asstring(obj), "forward") == 0) 3555 { 3556 obj = NULL; 3557 (void)cfg_map_get(zoptions, "forward", &obj); 3558 if (obj == NULL) { 3559 continue; 3560 } 3561 if (strcasecmp(cfg_obj_asstring(obj), "only") != 0) { 3562 continue; 3563 } 3564 } 3565 if (db == NULL) { 3566 CHECK(dns_db_create(view->mctx, ZONEDB_DEFAULT, name, 3567 dns_dbtype_zone, view->rdclass, 0, 3568 NULL, &db)); 3569 CHECK(dns_db_newversion(db, &version)); 3570 if (strcmp(empty_dbtype[2], "@") == 0) { 3571 dns_name_clone(name, ns); 3572 } else { 3573 CHECK(dns_name_fromstring(ns, empty_dbtype[2], 3574 dns_rootname, 0, 3575 NULL)); 3576 } 3577 CHECK(dns_name_fromstring(contact, empty_dbtype[3], 3578 dns_rootname, 0, NULL)); 3579 CHECK(add_soa(db, version, name, ns, contact)); 3580 CHECK(add_ns(db, version, name, ns)); 3581 } 3582 CHECK(add_ns(db, version, zname, dns_rootname)); 3583 } 3584 3585 /* 3586 * Is the existing zone ok to use? 3587 */ 3588 if (pzone != NULL) { 3589 unsigned int typec; 3590 const char **dbargv = NULL; 3591 3592 if (db != NULL) { 3593 typec = default_dbtypec; 3594 dbargv = default_dbtype; 3595 } else { 3596 typec = empty_dbtypec; 3597 dbargv = empty_dbtype; 3598 } 3599 3600 result = check_dbtype(pzone, typec, dbargv, view->mctx); 3601 if (result != ISC_R_SUCCESS) { 3602 pzone = NULL; 3603 } 3604 3605 if (pzone != NULL && 3606 dns_zone_gettype(pzone) != dns_zone_primary) 3607 { 3608 pzone = NULL; 3609 } 3610 if (pzone != NULL && dns_zone_getfile(pzone) != NULL) { 3611 pzone = NULL; 3612 } 3613 if (pzone != NULL) { 3614 dns_zone_getraw(pzone, &zone); 3615 if (zone != NULL) { 3616 dns_zone_detach(&zone); 3617 pzone = NULL; 3618 } 3619 } 3620 } 3621 3622 if (pzone == NULL) { 3623 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 3624 CHECK(dns_zone_setorigin(zone, name)); 3625 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 3626 if (db == NULL) { 3627 dns_zone_setdbtype(zone, empty_dbtypec, empty_dbtype); 3628 } 3629 dns_zone_setclass(zone, view->rdclass); 3630 dns_zone_settype(zone, dns_zone_primary); 3631 dns_zone_setstats(zone, named_g_server->zonestats); 3632 } else { 3633 dns_zone_attach(pzone, &zone); 3634 } 3635 3636 dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, false); 3637 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 3638 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 3639 dns_zone_setnotifytype(zone, dns_notifytype_no); 3640 dns_zone_setdialup(zone, dns_dialuptype_no); 3641 dns_zone_setautomatic(zone, true); 3642 if (view->queryacl != NULL) { 3643 dns_zone_setqueryacl(zone, view->queryacl); 3644 } else { 3645 dns_zone_clearqueryacl(zone); 3646 } 3647 if (view->queryonacl != NULL) { 3648 dns_zone_setqueryonacl(zone, view->queryonacl); 3649 } else { 3650 dns_zone_clearqueryonacl(zone); 3651 } 3652 dns_zone_clearupdateacl(zone); 3653 if (view->transferacl != NULL) { 3654 dns_zone_setxfracl(zone, view->transferacl); 3655 } else { 3656 dns_zone_clearxfracl(zone); 3657 } 3658 3659 setquerystats(zone, view->mctx, statlevel); 3660 if (db != NULL) { 3661 dns_db_closeversion(db, &version, true); 3662 CHECK(dns_zone_replacedb(zone, db, false)); 3663 } 3664 dns_zone_setoption(zone, DNS_ZONEOPT_AUTOEMPTY, true); 3665 dns_zone_setview(zone, view); 3666 CHECK(dns_view_addzone(view, zone)); 3667 3668 if (!strcmp(viewname, "_default")) { 3669 sep = ""; 3670 viewname = ""; 3671 } 3672 dns_name_format(name, namebuf, sizeof(namebuf)); 3673 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_ZONELOAD, 3674 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 3675 "automatic empty zone%s%s: %s", sep, viewname, namebuf); 3676 3677 cleanup: 3678 if (zone != NULL) { 3679 dns_zone_detach(&zone); 3680 } 3681 if (version != NULL) { 3682 dns_db_closeversion(db, &version, false); 3683 } 3684 if (db != NULL) { 3685 dns_db_detach(&db); 3686 } 3687 3688 INSIST(version == NULL); 3689 3690 return result; 3691 } 3692 3693 static isc_result_t 3694 create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view, 3695 const dns_name_t *name, const char *type, isc_mem_t *mctx, 3696 const char *server, const char *contact) { 3697 char namebuf[DNS_NAME_FORMATSIZE]; 3698 const char *dbtype[4] = { "_builtin", NULL, "@", "." }; 3699 const char *sep = ": view "; 3700 const char *viewname = view->name; 3701 dns_zone_t *zone = NULL; 3702 int dbtypec = 4; 3703 isc_result_t result; 3704 3705 REQUIRE(type != NULL); 3706 3707 if (!strcmp(viewname, "_default")) { 3708 sep = ""; 3709 viewname = ""; 3710 } 3711 3712 dbtype[1] = type; 3713 if (server != NULL) { 3714 dbtype[2] = server; 3715 } 3716 if (contact != NULL) { 3717 dbtype[3] = contact; 3718 } 3719 3720 if (pzone != NULL) { 3721 result = check_dbtype(pzone, dbtypec, dbtype, view->mctx); 3722 if (result != ISC_R_SUCCESS) { 3723 pzone = NULL; 3724 } 3725 } 3726 3727 if (pzone == NULL) { 3728 /* 3729 * Create the actual zone. 3730 */ 3731 dns_zone_create(&zone, mctx, 0); 3732 CHECK(dns_zone_setorigin(zone, name)); 3733 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 3734 dns_zone_setclass(zone, view->rdclass); 3735 dns_zone_settype(zone, dns_zone_primary); 3736 dns_zone_setstats(zone, named_g_server->zonestats); 3737 dns_zone_setdbtype(zone, dbtypec, dbtype); 3738 dns_zone_setdialup(zone, dns_dialuptype_no); 3739 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 3740 dns_zone_setnotifytype(zone, dns_notifytype_no); 3741 dns_zone_setautomatic(zone, true); 3742 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 3743 } else { 3744 dns_zone_attach(pzone, &zone); 3745 } 3746 if (view->queryacl != NULL) { 3747 dns_zone_setqueryacl(zone, view->queryacl); 3748 } else { 3749 dns_zone_clearqueryacl(zone); 3750 } 3751 if (view->queryonacl != NULL) { 3752 dns_zone_setqueryonacl(zone, view->queryonacl); 3753 } else { 3754 dns_zone_clearqueryonacl(zone); 3755 } 3756 dns_zone_setview(zone, view); 3757 CHECK(dns_view_addzone(view, zone)); 3758 3759 dns_name_format(name, namebuf, sizeof(namebuf)); 3760 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3761 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 3762 "automatic ipv4only zone%s%s: %s", sep, viewname, 3763 namebuf); 3764 3765 cleanup: 3766 if (zone != NULL) { 3767 dns_zone_detach(&zone); 3768 } 3769 return result; 3770 } 3771 3772 #ifdef HAVE_DNSTAP 3773 static isc_result_t 3774 configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) { 3775 isc_result_t result; 3776 const cfg_obj_t *obj, *obj2; 3777 const cfg_listelt_t *element; 3778 const char *dpath; 3779 const cfg_obj_t *dlist = NULL; 3780 dns_dtmsgtype_t dttypes = 0; 3781 unsigned int i; 3782 struct fstrm_iothr_options *fopt = NULL; 3783 3784 result = named_config_get(maps, "dnstap", &dlist); 3785 if (result != ISC_R_SUCCESS) { 3786 return ISC_R_SUCCESS; 3787 } 3788 3789 for (element = cfg_list_first(dlist); element != NULL; 3790 element = cfg_list_next(element)) 3791 { 3792 const char *str; 3793 dns_dtmsgtype_t dt = 0; 3794 3795 obj = cfg_listelt_value(element); 3796 obj2 = cfg_tuple_get(obj, "type"); 3797 str = cfg_obj_asstring(obj2); 3798 if (strcasecmp(str, "client") == 0) { 3799 dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR; 3800 } else if (strcasecmp(str, "auth") == 0) { 3801 dt |= DNS_DTTYPE_AQ | DNS_DTTYPE_AR; 3802 } else if (strcasecmp(str, "resolver") == 0) { 3803 dt |= DNS_DTTYPE_RQ | DNS_DTTYPE_RR; 3804 } else if (strcasecmp(str, "forwarder") == 0) { 3805 dt |= DNS_DTTYPE_FQ | DNS_DTTYPE_FR; 3806 } else if (strcasecmp(str, "update") == 0) { 3807 dt |= DNS_DTTYPE_UQ | DNS_DTTYPE_UR; 3808 } else if (strcasecmp(str, "all") == 0) { 3809 dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR | DNS_DTTYPE_AQ | 3810 DNS_DTTYPE_AR | DNS_DTTYPE_RQ | DNS_DTTYPE_RR | 3811 DNS_DTTYPE_FQ | DNS_DTTYPE_FR | DNS_DTTYPE_UQ | 3812 DNS_DTTYPE_UR; 3813 } 3814 3815 obj2 = cfg_tuple_get(obj, "mode"); 3816 if (obj2 == NULL || cfg_obj_isvoid(obj2)) { 3817 dttypes |= dt; 3818 continue; 3819 } 3820 3821 str = cfg_obj_asstring(obj2); 3822 if (strcasecmp(str, "query") == 0) { 3823 dt &= ~DNS_DTTYPE_RESPONSE; 3824 } else if (strcasecmp(str, "response") == 0) { 3825 dt &= ~DNS_DTTYPE_QUERY; 3826 } 3827 3828 dttypes |= dt; 3829 } 3830 3831 if (named_g_server->dtenv == NULL && dttypes != 0) { 3832 dns_dtmode_t dmode; 3833 uint64_t max_size = 0; 3834 uint32_t rolls = 0; 3835 isc_log_rollsuffix_t suffix = isc_log_rollsuffix_increment; 3836 3837 obj = NULL; 3838 CHECKM(named_config_get(maps, "dnstap-output", &obj), 3839 "'dnstap-output' must be set if 'dnstap' is set"); 3840 3841 obj2 = cfg_tuple_get(obj, "mode"); 3842 if (obj2 == NULL) { 3843 CHECKM(ISC_R_FAILURE, "dnstap-output mode not found"); 3844 } 3845 if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0) { 3846 dmode = dns_dtmode_file; 3847 } else { 3848 dmode = dns_dtmode_unix; 3849 } 3850 3851 obj2 = cfg_tuple_get(obj, "path"); 3852 if (obj2 == NULL) { 3853 CHECKM(ISC_R_FAILURE, "dnstap-output path not found"); 3854 } 3855 3856 dpath = cfg_obj_asstring(obj2); 3857 3858 obj2 = cfg_tuple_get(obj, "size"); 3859 if (obj2 != NULL && cfg_obj_isuint64(obj2)) { 3860 max_size = cfg_obj_asuint64(obj2); 3861 if (max_size > SIZE_MAX) { 3862 cfg_obj_log(obj2, named_g_lctx, ISC_LOG_WARNING, 3863 "'dnstap-output size " 3864 "%" PRIu64 "' " 3865 "is too large for this " 3866 "system; reducing to %lu", 3867 max_size, (unsigned long)SIZE_MAX); 3868 max_size = SIZE_MAX; 3869 } 3870 } 3871 3872 obj2 = cfg_tuple_get(obj, "versions"); 3873 if (obj2 != NULL && cfg_obj_isuint32(obj2)) { 3874 rolls = cfg_obj_asuint32(obj2); 3875 } else { 3876 rolls = ISC_LOG_ROLLINFINITE; 3877 } 3878 3879 obj2 = cfg_tuple_get(obj, "suffix"); 3880 if (obj2 != NULL && cfg_obj_isstring(obj2) && 3881 strcasecmp(cfg_obj_asstring(obj2), "timestamp") == 0) 3882 { 3883 suffix = isc_log_rollsuffix_timestamp; 3884 } 3885 3886 fopt = fstrm_iothr_options_init(); 3887 /* 3888 * Both network threads and worker threads may log dnstap data. 3889 */ 3890 fstrm_iothr_options_set_num_input_queues(fopt, 3891 2 * named_g_cpus); 3892 fstrm_iothr_options_set_queue_model( 3893 fopt, FSTRM_IOTHR_QUEUE_MODEL_MPSC); 3894 3895 obj = NULL; 3896 result = named_config_get(maps, "fstrm-set-buffer-hint", &obj); 3897 if (result == ISC_R_SUCCESS) { 3898 i = cfg_obj_asuint32(obj); 3899 fstrm_iothr_options_set_buffer_hint(fopt, i); 3900 } 3901 3902 obj = NULL; 3903 result = named_config_get(maps, "fstrm-set-flush-timeout", 3904 &obj); 3905 if (result == ISC_R_SUCCESS) { 3906 i = cfg_obj_asuint32(obj); 3907 fstrm_iothr_options_set_flush_timeout(fopt, i); 3908 } 3909 3910 obj = NULL; 3911 result = named_config_get(maps, "fstrm-set-input-queue-size", 3912 &obj); 3913 if (result == ISC_R_SUCCESS) { 3914 i = cfg_obj_asuint32(obj); 3915 fstrm_iothr_options_set_input_queue_size(fopt, i); 3916 } 3917 3918 obj = NULL; 3919 result = named_config_get( 3920 maps, "fstrm-set-output-notify-threshold", &obj); 3921 if (result == ISC_R_SUCCESS) { 3922 i = cfg_obj_asuint32(obj); 3923 fstrm_iothr_options_set_queue_notify_threshold(fopt, i); 3924 } 3925 3926 obj = NULL; 3927 result = named_config_get(maps, "fstrm-set-output-queue-model", 3928 &obj); 3929 if (result == ISC_R_SUCCESS) { 3930 if (strcasecmp(cfg_obj_asstring(obj), "spsc") == 0) { 3931 i = FSTRM_IOTHR_QUEUE_MODEL_SPSC; 3932 } else { 3933 i = FSTRM_IOTHR_QUEUE_MODEL_MPSC; 3934 } 3935 fstrm_iothr_options_set_queue_model(fopt, i); 3936 } 3937 3938 obj = NULL; 3939 result = named_config_get(maps, "fstrm-set-output-queue-size", 3940 &obj); 3941 if (result == ISC_R_SUCCESS) { 3942 i = cfg_obj_asuint32(obj); 3943 fstrm_iothr_options_set_output_queue_size(fopt, i); 3944 } 3945 3946 obj = NULL; 3947 result = named_config_get(maps, "fstrm-set-reopen-interval", 3948 &obj); 3949 if (result == ISC_R_SUCCESS) { 3950 i = cfg_obj_asduration(obj); 3951 fstrm_iothr_options_set_reopen_interval(fopt, i); 3952 } 3953 3954 CHECKM(dns_dt_create(named_g_mctx, dmode, dpath, &fopt, 3955 named_g_mainloop, &named_g_server->dtenv), 3956 "unable to create dnstap environment"); 3957 3958 CHECKM(dns_dt_setupfile(named_g_server->dtenv, max_size, rolls, 3959 suffix), 3960 "unable to set up dnstap logfile"); 3961 } 3962 3963 if (named_g_server->dtenv == NULL) { 3964 return ISC_R_SUCCESS; 3965 } 3966 3967 obj = NULL; 3968 result = named_config_get(maps, "dnstap-version", &obj); 3969 if (result != ISC_R_SUCCESS) { 3970 /* not specified; use the product and version */ 3971 dns_dt_setversion(named_g_server->dtenv, PACKAGE_STRING); 3972 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 3973 /* Quoted string */ 3974 dns_dt_setversion(named_g_server->dtenv, cfg_obj_asstring(obj)); 3975 } 3976 3977 obj = NULL; 3978 result = named_config_get(maps, "dnstap-identity", &obj); 3979 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 3980 /* "hostname" is interpreted as boolean true */ 3981 char buf[256]; 3982 if (gethostname(buf, sizeof(buf)) == 0) { 3983 dns_dt_setidentity(named_g_server->dtenv, buf); 3984 } 3985 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 3986 /* Quoted string */ 3987 dns_dt_setidentity(named_g_server->dtenv, 3988 cfg_obj_asstring(obj)); 3989 } 3990 3991 dns_dt_attach(named_g_server->dtenv, &view->dtenv); 3992 view->dttypes = dttypes; 3993 3994 result = ISC_R_SUCCESS; 3995 3996 cleanup: 3997 if (fopt != NULL) { 3998 fstrm_iothr_options_destroy(&fopt); 3999 } 4000 4001 return result; 4002 } 4003 #endif /* HAVE_DNSTAP */ 4004 4005 static isc_result_t 4006 create_mapped_acl(void) { 4007 isc_result_t result; 4008 dns_acl_t *acl = NULL; 4009 struct in6_addr in6 = IN6ADDR_V4MAPPED_INIT; 4010 isc_netaddr_t addr; 4011 4012 isc_netaddr_fromin6(&addr, &in6); 4013 4014 dns_acl_create(named_g_mctx, 1, &acl); 4015 4016 result = dns_iptable_addprefix(acl->iptable, &addr, 96, true); 4017 if (result == ISC_R_SUCCESS) { 4018 dns_acl_attach(acl, &named_g_mapped); 4019 } 4020 dns_acl_detach(&acl); 4021 return result; 4022 } 4023 4024 /*% 4025 * A callback for the cfg_pluginlist_foreach() call in configure_view() below. 4026 * If registering any plugin fails, registering subsequent ones is not 4027 * attempted. 4028 */ 4029 static isc_result_t 4030 register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj, 4031 const char *plugin_path, const char *parameters, 4032 void *callback_data) { 4033 dns_view_t *view = callback_data; 4034 char full_path[PATH_MAX]; 4035 isc_result_t result; 4036 4037 result = ns_plugin_expandpath(plugin_path, full_path, 4038 sizeof(full_path)); 4039 if (result != ISC_R_SUCCESS) { 4040 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4041 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4042 "%s: plugin configuration failed: " 4043 "unable to get full plugin path: %s", 4044 plugin_path, isc_result_totext(result)); 4045 return result; 4046 } 4047 4048 result = ns_plugin_register(full_path, parameters, config, 4049 cfg_obj_file(obj), cfg_obj_line(obj), 4050 named_g_mctx, named_g_lctx, 4051 named_g_aclconfctx, view); 4052 if (result != ISC_R_SUCCESS) { 4053 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4054 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4055 "%s: plugin configuration failed: %s", full_path, 4056 isc_result_totext(result)); 4057 } 4058 4059 return result; 4060 } 4061 4062 /* 4063 * Determine if a minimal-sized cache can be used for a given view, according 4064 * to 'maps' (implicit defaults, global options, view options) and 'optionmaps' 4065 * (global options, view options). This is only allowed for views which have 4066 * recursion disabled and do not have "max-cache-size" set explicitly. Using 4067 * minimal-sized caches prevents a situation in which all explicitly configured 4068 * and built-in views inherit the default "max-cache-size 90%;" setting, which 4069 * could lead to memory exhaustion with multiple views configured. 4070 */ 4071 static bool 4072 minimal_cache_allowed(const cfg_obj_t *maps[4], 4073 const cfg_obj_t *optionmaps[3]) { 4074 const cfg_obj_t *obj; 4075 4076 /* 4077 * Do not use a minimal-sized cache for a view with recursion enabled. 4078 */ 4079 obj = NULL; 4080 (void)named_config_get(maps, "recursion", &obj); 4081 INSIST(obj != NULL); 4082 if (cfg_obj_asboolean(obj)) { 4083 return false; 4084 } 4085 4086 /* 4087 * Do not use a minimal-sized cache if a specific size was requested. 4088 */ 4089 obj = NULL; 4090 (void)named_config_get(optionmaps, "max-cache-size", &obj); 4091 if (obj != NULL) { 4092 return false; 4093 } 4094 4095 return true; 4096 } 4097 4098 static const char *const response_synonyms[] = { "response", NULL }; 4099 4100 /* 4101 * Configure 'view' according to 'vconfig', taking defaults from 4102 * 'config' where values are missing in 'vconfig'. 4103 * 4104 * When configuring the default view, 'vconfig' will be NULL and the 4105 * global defaults in 'config' used exclusively. 4106 */ 4107 static isc_result_t 4108 configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, 4109 cfg_obj_t *vconfig, named_cachelist_t *cachelist, 4110 dns_kasplist_t *kasplist, dns_keystorelist_t *keystores, 4111 const cfg_obj_t *bindkeys, isc_mem_t *mctx, 4112 cfg_aclconfctx_t *actx, bool need_hints) { 4113 const cfg_obj_t *maps[4]; 4114 const cfg_obj_t *cfgmaps[3]; 4115 const cfg_obj_t *optionmaps[3]; 4116 const cfg_obj_t *options = NULL; 4117 const cfg_obj_t *voptions = NULL; 4118 const cfg_obj_t *forwardtype; 4119 const cfg_obj_t *forwarders; 4120 const cfg_obj_t *alternates; 4121 const cfg_obj_t *zonelist; 4122 const cfg_obj_t *dlzlist; 4123 const cfg_obj_t *dlz; 4124 const cfg_obj_t *prefetch_trigger; 4125 const cfg_obj_t *prefetch_eligible; 4126 unsigned int dlzargc; 4127 char **dlzargv; 4128 const cfg_obj_t *dyndb_list, *plugin_list; 4129 const cfg_obj_t *disabled; 4130 const cfg_obj_t *obj, *obj2; 4131 const cfg_listelt_t *element = NULL; 4132 const cfg_listelt_t *zone_element_latest = NULL; 4133 in_port_t port; 4134 dns_cache_t *cache = NULL; 4135 isc_result_t result; 4136 size_t max_cache_size; 4137 uint32_t max_cache_size_percent = 0; 4138 size_t max_adb_size; 4139 uint32_t lame_ttl, fail_ttl; 4140 uint32_t max_stale_ttl = 0; 4141 uint32_t stale_refresh_time = 0; 4142 dns_tsigkeyring_t *ring = NULL; 4143 dns_transport_list_t *transports = NULL; 4144 dns_view_t *pview = NULL; /* Production view */ 4145 dns_dispatch_t *dispatch4 = NULL; 4146 dns_dispatch_t *dispatch6 = NULL; 4147 bool rpz_configured = false; 4148 bool catz_configured = false; 4149 bool shared_cache = false; 4150 int i = 0, j = 0, k = 0; 4151 const char *str; 4152 const char *cachename = NULL; 4153 dns_order_t *order = NULL; 4154 uint32_t udpsize; 4155 uint32_t maxbits; 4156 unsigned int resopts = 0; 4157 dns_zone_t *zone = NULL; 4158 uint32_t max_clients_per_query; 4159 bool empty_zones_enable; 4160 const cfg_obj_t *disablelist = NULL; 4161 isc_stats_t *resstats = NULL; 4162 dns_stats_t *resquerystats = NULL; 4163 bool auto_root = false; 4164 named_cache_t *nsc; 4165 bool zero_no_soattl; 4166 dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; 4167 unsigned int query_timeout; 4168 bool old_rpz_ok = false; 4169 dns_dyndbctx_t *dctx = NULL; 4170 dns_ntatable_t *ntatable = NULL; 4171 const char *qminmode = NULL; 4172 dns_adb_t *adb = NULL; 4173 4174 REQUIRE(DNS_VIEW_VALID(view)); 4175 4176 if (config != NULL) { 4177 (void)cfg_map_get(config, "options", &options); 4178 } 4179 4180 /* 4181 * maps: view options, options, defaults 4182 * cfgmaps: view options, config 4183 * optionmaps: view options, options 4184 */ 4185 if (vconfig != NULL) { 4186 voptions = cfg_tuple_get(vconfig, "options"); 4187 maps[i++] = voptions; 4188 optionmaps[j++] = voptions; 4189 cfgmaps[k++] = voptions; 4190 } 4191 if (options != NULL) { 4192 maps[i++] = options; 4193 optionmaps[j++] = options; 4194 } 4195 4196 maps[i++] = named_g_defaults; 4197 maps[i] = NULL; 4198 optionmaps[j] = NULL; 4199 if (config != NULL) { 4200 cfgmaps[k++] = config; 4201 } 4202 cfgmaps[k] = NULL; 4203 4204 /* 4205 * Set the view's port number for outgoing queries. 4206 */ 4207 CHECKM(named_config_getport(config, "port", &port), "port"); 4208 dns_view_setdstport(view, port); 4209 4210 /* 4211 * Make the list of response policy zone names for a view that 4212 * is used for real lookups and so cares about hints. 4213 */ 4214 obj = NULL; 4215 if (view->rdclass == dns_rdataclass_in && need_hints && 4216 named_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) 4217 { 4218 CHECK(configure_rpz(view, NULL, maps, obj, &old_rpz_ok)); 4219 rpz_configured = true; 4220 } 4221 4222 obj = NULL; 4223 if (view->rdclass != dns_rdataclass_in && need_hints && 4224 named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) 4225 { 4226 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4227 "'catalog-zones' option is only supported " 4228 "for views with class IN"); 4229 } 4230 4231 obj = NULL; 4232 if (view->rdclass == dns_rdataclass_in && need_hints && 4233 named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) 4234 { 4235 CHECK(configure_catz(view, NULL, config, obj)); 4236 catz_configured = true; 4237 } 4238 4239 /* 4240 * Configure the zones. 4241 */ 4242 zonelist = NULL; 4243 if (voptions != NULL) { 4244 (void)cfg_map_get(voptions, "zone", &zonelist); 4245 } else { 4246 (void)cfg_map_get(config, "zone", &zonelist); 4247 } 4248 4249 /* 4250 * Load zone configuration 4251 */ 4252 for (element = cfg_list_first(zonelist); element != NULL; 4253 element = cfg_list_next(element)) 4254 { 4255 const cfg_obj_t *zconfig = cfg_listelt_value(element); 4256 CHECK(configure_zone(config, zconfig, vconfig, view, viewlist, 4257 kasplist, keystores, actx, false, 4258 old_rpz_ok, false, false)); 4259 zone_element_latest = element; 4260 } 4261 4262 /* 4263 * Check that a primary or secondary zone was found for each 4264 * zone named in the response policy statement, unless we are 4265 * using RPZ service interface. 4266 */ 4267 if (view->rpzs != NULL && !view->rpzs->p.dnsrps_enabled) { 4268 dns_rpz_num_t n; 4269 4270 for (n = 0; n < view->rpzs->p.num_zones; ++n) { 4271 if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) { 4272 char namebuf[DNS_NAME_FORMATSIZE]; 4273 4274 dns_name_format(&view->rpzs->zones[n]->origin, 4275 namebuf, sizeof(namebuf)); 4276 isc_log_write(named_g_lctx, 4277 NAMED_LOGCATEGORY_GENERAL, 4278 NAMED_LOGMODULE_SERVER, 4279 DNS_RPZ_ERROR_LEVEL, 4280 "rpz '%s' is not a primary or a " 4281 "secondary zone", 4282 namebuf); 4283 result = ISC_R_NOTFOUND; 4284 goto cleanup; 4285 } 4286 } 4287 } 4288 4289 /* 4290 * If we're allowing added zones, then load zone configuration 4291 * from the newzone file for zones that were added during previous 4292 * runs. 4293 */ 4294 CHECK(configure_newzones(view, config, vconfig, actx)); 4295 4296 /* 4297 * Create Dynamically Loadable Zone driver. 4298 */ 4299 dlzlist = NULL; 4300 if (voptions != NULL) { 4301 (void)cfg_map_get(voptions, "dlz", &dlzlist); 4302 } else { 4303 (void)cfg_map_get(config, "dlz", &dlzlist); 4304 } 4305 4306 for (element = cfg_list_first(dlzlist); element != NULL; 4307 element = cfg_list_next(element)) 4308 { 4309 dlz = cfg_listelt_value(element); 4310 4311 obj = NULL; 4312 (void)cfg_map_get(dlz, "database", &obj); 4313 if (obj != NULL) { 4314 dns_dlzdb_t *dlzdb = NULL; 4315 const cfg_obj_t *name, *search = NULL; 4316 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 4317 4318 if (s == NULL) { 4319 result = ISC_R_NOMEMORY; 4320 goto cleanup; 4321 } 4322 4323 result = isc_commandline_strtoargv(mctx, s, &dlzargc, 4324 &dlzargv, 0); 4325 if (result != ISC_R_SUCCESS) { 4326 isc_mem_free(mctx, s); 4327 goto cleanup; 4328 } 4329 4330 name = cfg_map_getname(dlz); 4331 result = dns_dlzcreate(mctx, cfg_obj_asstring(name), 4332 dlzargv[0], dlzargc, dlzargv, 4333 &dlzdb); 4334 isc_mem_free(mctx, s); 4335 isc_mem_cput(mctx, dlzargv, dlzargc, sizeof(*dlzargv)); 4336 if (result != ISC_R_SUCCESS) { 4337 goto cleanup; 4338 } 4339 4340 /* 4341 * If the DLZ backend supports configuration, 4342 * and is searchable, then call its configure 4343 * method now. If not searchable, we'll take 4344 * care of it when we process the zone statement. 4345 */ 4346 (void)cfg_map_get(dlz, "search", &search); 4347 if (search == NULL || cfg_obj_asboolean(search)) { 4348 dlzdb->search = true; 4349 result = dns_dlzconfigure( 4350 view, dlzdb, dlzconfigure_callback); 4351 if (result != ISC_R_SUCCESS) { 4352 goto cleanup; 4353 } 4354 ISC_LIST_APPEND(view->dlz_searched, dlzdb, 4355 link); 4356 } else { 4357 dlzdb->search = false; 4358 ISC_LIST_APPEND(view->dlz_unsearched, dlzdb, 4359 link); 4360 } 4361 } 4362 } 4363 4364 /* 4365 * Obtain configuration parameters that affect the decision of whether 4366 * we can reuse/share an existing cache. 4367 */ 4368 obj = NULL; 4369 result = named_config_get(maps, "max-cache-size", &obj); 4370 INSIST(result == ISC_R_SUCCESS); 4371 /* 4372 * If "-T maxcachesize=..." is in effect, it overrides any other 4373 * "max-cache-size" setting found in configuration, either implicit or 4374 * explicit. For simplicity, the value passed to that command line 4375 * option is always treated as the number of bytes to set 4376 * "max-cache-size" to. 4377 */ 4378 if (named_g_maxcachesize != 0) { 4379 max_cache_size = named_g_maxcachesize; 4380 } else if (minimal_cache_allowed(maps, optionmaps)) { 4381 /* 4382 * dns_cache_setcachesize() will adjust this to the smallest 4383 * allowed value. 4384 */ 4385 max_cache_size = 1; 4386 } else if (cfg_obj_isstring(obj)) { 4387 str = cfg_obj_asstring(obj); 4388 INSIST(strcasecmp(str, "unlimited") == 0); 4389 max_cache_size = 0; 4390 } else if (cfg_obj_ispercentage(obj)) { 4391 max_cache_size = SIZE_AS_PERCENT; 4392 max_cache_size_percent = cfg_obj_aspercentage(obj); 4393 } else { 4394 uint64_t value = cfg_obj_asuint64(obj); 4395 if (value > SIZE_MAX) { 4396 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4397 "'max-cache-size " 4398 "%" PRIu64 "' " 4399 "is too large for this " 4400 "system; reducing to %lu", 4401 value, (unsigned long)SIZE_MAX); 4402 value = SIZE_MAX; 4403 } 4404 max_cache_size = (size_t)value; 4405 } 4406 4407 if (max_cache_size == SIZE_AS_PERCENT) { 4408 uint64_t totalphys = isc_meminfo_totalphys(); 4409 4410 max_cache_size = 4411 (size_t)(totalphys * max_cache_size_percent / 100); 4412 if (totalphys == 0) { 4413 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4414 "Unable to determine amount of physical " 4415 "memory, setting 'max-cache-size' to " 4416 "unlimited"); 4417 } else { 4418 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 4419 "'max-cache-size %d%%' " 4420 "- setting to %" PRIu64 "MB " 4421 "(out of %" PRIu64 "MB)", 4422 max_cache_size_percent, 4423 (uint64_t)(max_cache_size / (1024 * 1024)), 4424 totalphys / (1024 * 1024)); 4425 } 4426 } 4427 4428 /* Check-names. */ 4429 obj = NULL; 4430 result = named_checknames_get(maps, response_synonyms, &obj); 4431 INSIST(result == ISC_R_SUCCESS); 4432 4433 str = cfg_obj_asstring(obj); 4434 if (strcasecmp(str, "fail") == 0) { 4435 resopts |= DNS_RESOLVER_CHECKNAMES | 4436 DNS_RESOLVER_CHECKNAMESFAIL; 4437 view->checknames = true; 4438 } else if (strcasecmp(str, "warn") == 0) { 4439 resopts |= DNS_RESOLVER_CHECKNAMES; 4440 view->checknames = false; 4441 } else if (strcasecmp(str, "ignore") == 0) { 4442 view->checknames = false; 4443 } else { 4444 UNREACHABLE(); 4445 } 4446 4447 obj = NULL; 4448 result = named_config_get(maps, "zero-no-soa-ttl-cache", &obj); 4449 INSIST(result == ISC_R_SUCCESS); 4450 zero_no_soattl = cfg_obj_asboolean(obj); 4451 4452 obj = NULL; 4453 result = named_config_get(maps, "resolver-use-dns64", &obj); 4454 INSIST(result == ISC_R_SUCCESS); 4455 view->usedns64 = cfg_obj_asboolean(obj); 4456 4457 obj = NULL; 4458 result = named_config_get(maps, "dns64", &obj); 4459 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && 4460 strcmp(view->name, "_meta")) 4461 { 4462 isc_netaddr_t na, suffix, *sp; 4463 unsigned int prefixlen; 4464 const char *server, *contact; 4465 const cfg_obj_t *myobj; 4466 4467 myobj = NULL; 4468 result = named_config_get(maps, "dns64-server", &myobj); 4469 if (result == ISC_R_SUCCESS) { 4470 server = cfg_obj_asstring(myobj); 4471 } else { 4472 server = NULL; 4473 } 4474 4475 myobj = NULL; 4476 result = named_config_get(maps, "dns64-contact", &myobj); 4477 if (result == ISC_R_SUCCESS) { 4478 contact = cfg_obj_asstring(myobj); 4479 } else { 4480 contact = NULL; 4481 } 4482 4483 for (element = cfg_list_first(obj); element != NULL; 4484 element = cfg_list_next(element)) 4485 { 4486 const cfg_obj_t *map = cfg_listelt_value(element); 4487 dns_dns64_t *dns64 = NULL; 4488 unsigned int dns64options = 0; 4489 4490 cfg_obj_asnetprefix(cfg_map_getname(map), &na, 4491 &prefixlen); 4492 4493 obj = NULL; 4494 (void)cfg_map_get(map, "suffix", &obj); 4495 if (obj != NULL) { 4496 sp = &suffix; 4497 isc_netaddr_fromsockaddr( 4498 sp, cfg_obj_assockaddr(obj)); 4499 } else { 4500 sp = NULL; 4501 } 4502 4503 clients = mapped = excluded = NULL; 4504 obj = NULL; 4505 (void)cfg_map_get(map, "clients", &obj); 4506 if (obj != NULL) { 4507 result = cfg_acl_fromconfig(obj, config, 4508 named_g_lctx, actx, 4509 mctx, 0, &clients); 4510 if (result != ISC_R_SUCCESS) { 4511 goto cleanup; 4512 } 4513 } 4514 obj = NULL; 4515 (void)cfg_map_get(map, "mapped", &obj); 4516 if (obj != NULL) { 4517 result = cfg_acl_fromconfig(obj, config, 4518 named_g_lctx, actx, 4519 mctx, 0, &mapped); 4520 if (result != ISC_R_SUCCESS) { 4521 goto cleanup; 4522 } 4523 } 4524 obj = NULL; 4525 (void)cfg_map_get(map, "exclude", &obj); 4526 if (obj != NULL) { 4527 result = cfg_acl_fromconfig(obj, config, 4528 named_g_lctx, actx, 4529 mctx, 0, &excluded); 4530 if (result != ISC_R_SUCCESS) { 4531 goto cleanup; 4532 } 4533 } else { 4534 if (named_g_mapped == NULL) { 4535 result = create_mapped_acl(); 4536 if (result != ISC_R_SUCCESS) { 4537 goto cleanup; 4538 } 4539 } 4540 dns_acl_attach(named_g_mapped, &excluded); 4541 } 4542 4543 obj = NULL; 4544 (void)cfg_map_get(map, "recursive-only", &obj); 4545 if (obj != NULL && cfg_obj_asboolean(obj)) { 4546 dns64options |= DNS_DNS64_RECURSIVE_ONLY; 4547 } 4548 4549 obj = NULL; 4550 (void)cfg_map_get(map, "break-dnssec", &obj); 4551 if (obj != NULL && cfg_obj_asboolean(obj)) { 4552 dns64options |= DNS_DNS64_BREAK_DNSSEC; 4553 } 4554 4555 result = dns_dns64_create(mctx, &na, prefixlen, sp, 4556 clients, mapped, excluded, 4557 dns64options, &dns64); 4558 if (result != ISC_R_SUCCESS) { 4559 goto cleanup; 4560 } 4561 dns_dns64_append(&view->dns64, dns64); 4562 view->dns64cnt++; 4563 result = dns64_reverse(view, mctx, &na, prefixlen, 4564 server, contact); 4565 if (result != ISC_R_SUCCESS) { 4566 goto cleanup; 4567 } 4568 if (clients != NULL) { 4569 dns_acl_detach(&clients); 4570 } 4571 if (mapped != NULL) { 4572 dns_acl_detach(&mapped); 4573 } 4574 if (excluded != NULL) { 4575 dns_acl_detach(&excluded); 4576 } 4577 } 4578 } 4579 4580 obj = NULL; 4581 result = named_config_get(maps, "dnssec-accept-expired", &obj); 4582 INSIST(result == ISC_R_SUCCESS); 4583 view->acceptexpired = cfg_obj_asboolean(obj); 4584 4585 obj = NULL; 4586 /* 'optionmaps', not 'maps': don't check named_g_defaults yet */ 4587 (void)named_config_get(optionmaps, "dnssec-validation", &obj); 4588 if (obj == NULL) { 4589 /* 4590 * Default to VALIDATION_DEFAULT as set in config.c. 4591 */ 4592 (void)cfg_map_get(named_g_defaults, "dnssec-validation", &obj); 4593 INSIST(obj != NULL); 4594 } 4595 if (obj != NULL) { 4596 if (cfg_obj_isboolean(obj)) { 4597 view->enablevalidation = cfg_obj_asboolean(obj); 4598 } else { 4599 /* 4600 * If dnssec-validation is set but not boolean, 4601 * then it must be "auto" 4602 */ 4603 view->enablevalidation = true; 4604 auto_root = true; 4605 } 4606 } 4607 4608 obj = NULL; 4609 result = named_config_get(maps, "max-cache-ttl", &obj); 4610 INSIST(result == ISC_R_SUCCESS); 4611 view->maxcachettl = cfg_obj_asduration(obj); 4612 4613 obj = NULL; 4614 result = named_config_get(maps, "max-ncache-ttl", &obj); 4615 INSIST(result == ISC_R_SUCCESS); 4616 view->maxncachettl = cfg_obj_asduration(obj); 4617 4618 obj = NULL; 4619 result = named_config_get(maps, "min-cache-ttl", &obj); 4620 INSIST(result == ISC_R_SUCCESS); 4621 view->mincachettl = cfg_obj_asduration(obj); 4622 4623 obj = NULL; 4624 result = named_config_get(maps, "min-ncache-ttl", &obj); 4625 INSIST(result == ISC_R_SUCCESS); 4626 view->minncachettl = cfg_obj_asduration(obj); 4627 4628 obj = NULL; 4629 result = named_config_get(maps, "synth-from-dnssec", &obj); 4630 INSIST(result == ISC_R_SUCCESS); 4631 view->synthfromdnssec = cfg_obj_asboolean(obj); 4632 4633 obj = NULL; 4634 result = named_config_get(maps, "stale-cache-enable", &obj); 4635 INSIST(result == ISC_R_SUCCESS); 4636 if (cfg_obj_asboolean(obj)) { 4637 obj = NULL; 4638 result = named_config_get(maps, "max-stale-ttl", &obj); 4639 INSIST(result == ISC_R_SUCCESS); 4640 max_stale_ttl = ISC_MAX(cfg_obj_asduration(obj), 1); 4641 } 4642 /* 4643 * If 'stale-cache-enable' is false, max_stale_ttl is set to 0, 4644 * meaning keeping stale RRsets in cache is disabled. 4645 */ 4646 4647 obj = NULL; 4648 result = named_config_get(maps, "stale-answer-enable", &obj); 4649 INSIST(result == ISC_R_SUCCESS); 4650 view->staleanswersenable = cfg_obj_asboolean(obj); 4651 4652 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 4653 view->rdclass, &pview); 4654 if (result == ISC_R_SUCCESS) { 4655 view->staleanswersok = pview->staleanswersok; 4656 dns_view_detach(&pview); 4657 } else { 4658 view->staleanswersok = dns_stale_answer_conf; 4659 } 4660 4661 obj = NULL; 4662 result = named_config_get(maps, "stale-answer-client-timeout", &obj); 4663 INSIST(result == ISC_R_SUCCESS); 4664 if (cfg_obj_isstring(obj)) { 4665 /* 4666 * The only string values available for this option 4667 * are "disabled" and "off". 4668 * We use (uint32_t) -1 to represent disabled since 4669 * a value of zero means that stale data can be used 4670 * to promptly answer the query, while an attempt to 4671 * refresh the RRset will still be made in background. 4672 */ 4673 view->staleanswerclienttimeout = (uint32_t)-1; 4674 } else { 4675 view->staleanswerclienttimeout = cfg_obj_asuint32(obj); 4676 4677 /* 4678 * BIND 9 no longer supports non-zero values of 4679 * stale-answer-client-timeout. 4680 */ 4681 if (view->staleanswerclienttimeout != 0) { 4682 view->staleanswerclienttimeout = 0; 4683 isc_log_write( 4684 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4685 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 4686 "BIND 9 no longer supports non-zero values of " 4687 "stale-answer-client-timeout, adjusted to 0"); 4688 } 4689 } 4690 4691 obj = NULL; 4692 result = named_config_get(maps, "stale-refresh-time", &obj); 4693 INSIST(result == ISC_R_SUCCESS); 4694 stale_refresh_time = cfg_obj_asduration(obj); 4695 4696 /* 4697 * Configure the view's cache. 4698 * 4699 * First, check to see if there are any attach-cache options. If yes, 4700 * attempt to lookup an existing cache at attach it to the view. If 4701 * there is not one, then try to reuse an existing cache if possible; 4702 * otherwise create a new cache. 4703 * 4704 * Note that the ADB is not preserved or shared in either case. 4705 * 4706 * When a matching view is found, the associated statistics are also 4707 * retrieved and reused. 4708 * 4709 * XXX Determining when it is safe to reuse or share a cache is tricky. 4710 * When the view's configuration changes, the cached data may become 4711 * invalid because it reflects our old view of the world. We check 4712 * some of the configuration parameters that could invalidate the cache 4713 * or otherwise make it unshareable, but there are other configuration 4714 * options that should be checked. For example, if a view uses a 4715 * forwarder, changes in the forwarder configuration may invalidate 4716 * the cache. At the moment, it's the administrator's responsibility to 4717 * ensure these configuration options don't invalidate reusing/sharing. 4718 */ 4719 obj = NULL; 4720 result = named_config_get(maps, "attach-cache", &obj); 4721 if (result == ISC_R_SUCCESS) { 4722 cachename = cfg_obj_asstring(obj); 4723 } else { 4724 cachename = view->name; 4725 } 4726 cache = NULL; 4727 nsc = cachelist_find(cachelist, cachename, view->rdclass); 4728 if (nsc != NULL) { 4729 if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, 4730 max_cache_size, max_stale_ttl, 4731 stale_refresh_time)) 4732 { 4733 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4734 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4735 "views %s and %s can't share the cache " 4736 "due to configuration parameter mismatch", 4737 nsc->primaryview->name, view->name); 4738 result = ISC_R_FAILURE; 4739 goto cleanup; 4740 } 4741 dns_cache_attach(nsc->cache, &cache); 4742 shared_cache = true; 4743 } else { 4744 if (strcmp(cachename, view->name) == 0) { 4745 result = dns_viewlist_find(&named_g_server->viewlist, 4746 cachename, view->rdclass, 4747 &pview); 4748 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 4749 { 4750 goto cleanup; 4751 } 4752 if (pview != NULL) { 4753 if (!cache_reusable(pview, view, 4754 zero_no_soattl)) 4755 { 4756 isc_log_write(named_g_lctx, 4757 NAMED_LOGCATEGORY_GENERAL, 4758 NAMED_LOGMODULE_SERVER, 4759 ISC_LOG_DEBUG(1), 4760 "cache cannot be reused " 4761 "for view %s due to " 4762 "configuration parameter " 4763 "mismatch", 4764 view->name); 4765 } else { 4766 INSIST(pview->cache != NULL); 4767 isc_log_write(named_g_lctx, 4768 NAMED_LOGCATEGORY_GENERAL, 4769 NAMED_LOGMODULE_SERVER, 4770 ISC_LOG_DEBUG(3), 4771 "reusing existing cache"); 4772 dns_cache_attach(pview->cache, &cache); 4773 } 4774 dns_resolver_getstats(pview->resolver, 4775 &resstats); 4776 dns_resolver_getquerystats(pview->resolver, 4777 &resquerystats); 4778 dns_view_detach(&pview); 4779 } 4780 } 4781 if (cache == NULL) { 4782 /* 4783 * Create a cache with the desired name. This normally 4784 * equals the view name, but may also be a forward 4785 * reference to a view that share the cache with this 4786 * view but is not yet configured. If it is not the 4787 * view name but not a forward reference either, then it 4788 * is simply a named cache that is not shared. 4789 */ 4790 CHECK(dns_cache_create(named_g_loopmgr, view->rdclass, 4791 cachename, mctx, &cache)); 4792 } 4793 nsc = isc_mem_get(mctx, sizeof(*nsc)); 4794 nsc->cache = NULL; 4795 dns_cache_attach(cache, &nsc->cache); 4796 nsc->primaryview = view; 4797 nsc->needflush = false; 4798 nsc->adbsizeadjusted = false; 4799 nsc->rdclass = view->rdclass; 4800 ISC_LINK_INIT(nsc, link); 4801 ISC_LIST_APPEND(*cachelist, nsc, link); 4802 } 4803 dns_view_setcache(view, cache, shared_cache); 4804 4805 dns_cache_setcachesize(cache, max_cache_size); 4806 dns_cache_setservestalettl(cache, max_stale_ttl); 4807 dns_cache_setservestalerefresh(cache, stale_refresh_time); 4808 4809 dns_cache_detach(&cache); 4810 4811 obj = NULL; 4812 result = named_config_get(maps, "stale-answer-ttl", &obj); 4813 INSIST(result == ISC_R_SUCCESS); 4814 view->staleanswerttl = ISC_MAX(cfg_obj_asduration(obj), 1); 4815 4816 /* 4817 * Resolver. 4818 */ 4819 CHECK(get_view_querysource_dispatch( 4820 maps, AF_INET, &dispatch4, 4821 (ISC_LIST_PREV(view, link) == NULL))); 4822 CHECK(get_view_querysource_dispatch( 4823 maps, AF_INET6, &dispatch6, 4824 (ISC_LIST_PREV(view, link) == NULL))); 4825 if (dispatch4 == NULL && dispatch6 == NULL) { 4826 UNEXPECTED_ERROR("unable to obtain either an IPv4 or" 4827 " an IPv6 dispatch"); 4828 result = ISC_R_UNEXPECTED; 4829 goto cleanup; 4830 } 4831 4832 CHECK(dns_view_createresolver(view, named_g_netmgr, resopts, 4833 named_g_server->tlsctx_client_cache, 4834 dispatch4, dispatch6)); 4835 4836 if (resstats == NULL) { 4837 isc_stats_create(mctx, &resstats, dns_resstatscounter_max); 4838 } 4839 dns_resolver_setstats(view->resolver, resstats); 4840 if (resquerystats == NULL) { 4841 dns_rdatatypestats_create(mctx, &resquerystats); 4842 } 4843 dns_resolver_setquerystats(view->resolver, resquerystats); 4844 4845 /* 4846 * Set the ADB cache size to 1/8th of the max-cache-size or 4847 * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. 4848 */ 4849 max_adb_size = 0; 4850 if (max_cache_size != 0U) { 4851 max_adb_size = max_cache_size / 8; 4852 if (max_adb_size == 0U) { 4853 max_adb_size = 1; /* Force minimum. */ 4854 } 4855 if (view != nsc->primaryview && 4856 max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) 4857 { 4858 max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; 4859 if (!nsc->adbsizeadjusted) { 4860 dns_view_getadb(nsc->primaryview, &adb); 4861 if (adb != NULL) { 4862 dns_adb_setadbsize( 4863 adb, 4864 MAX_ADB_SIZE_FOR_CACHESHARE); 4865 nsc->adbsizeadjusted = true; 4866 dns_adb_detach(&adb); 4867 } 4868 } 4869 } 4870 } 4871 dns_view_getadb(view, &adb); 4872 if (adb != NULL) { 4873 dns_adb_setadbsize(adb, max_adb_size); 4874 dns_adb_detach(&adb); 4875 } 4876 4877 /* 4878 * Set up ADB quotas 4879 */ 4880 { 4881 uint32_t fps, freq; 4882 double low, high, discount; 4883 4884 obj = NULL; 4885 result = named_config_get(maps, "fetches-per-server", &obj); 4886 INSIST(result == ISC_R_SUCCESS); 4887 obj2 = cfg_tuple_get(obj, "fetches"); 4888 fps = cfg_obj_asuint32(obj2); 4889 obj2 = cfg_tuple_get(obj, "response"); 4890 if (!cfg_obj_isvoid(obj2)) { 4891 const char *resp = cfg_obj_asstring(obj2); 4892 isc_result_t r = DNS_R_SERVFAIL; 4893 4894 if (strcasecmp(resp, "drop") == 0) { 4895 r = DNS_R_DROP; 4896 } else if (strcasecmp(resp, "fail") == 0) { 4897 r = DNS_R_SERVFAIL; 4898 } else { 4899 UNREACHABLE(); 4900 } 4901 4902 dns_resolver_setquotaresponse(view->resolver, 4903 dns_quotatype_server, r); 4904 } 4905 4906 obj = NULL; 4907 result = named_config_get(maps, "fetch-quota-params", &obj); 4908 INSIST(result == ISC_R_SUCCESS); 4909 4910 obj2 = cfg_tuple_get(obj, "frequency"); 4911 freq = cfg_obj_asuint32(obj2); 4912 4913 obj2 = cfg_tuple_get(obj, "low"); 4914 low = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 4915 4916 obj2 = cfg_tuple_get(obj, "high"); 4917 high = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 4918 4919 obj2 = cfg_tuple_get(obj, "discount"); 4920 discount = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 4921 4922 dns_view_getadb(view, &adb); 4923 if (adb != NULL) { 4924 dns_adb_setquota(adb, fps, freq, low, high, discount); 4925 dns_adb_detach(&adb); 4926 } 4927 } 4928 4929 /* 4930 * Set resolver's lame-ttl. 4931 */ 4932 obj = NULL; 4933 result = named_config_get(maps, "lame-ttl", &obj); 4934 INSIST(result == ISC_R_SUCCESS); 4935 lame_ttl = cfg_obj_asduration(obj); 4936 if (lame_ttl > 0) { 4937 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4938 "disabling lame cache despite lame-ttl > 0 as it " 4939 "may cause performance issues"); 4940 } 4941 4942 /* 4943 * Set the resolver's query timeout. 4944 */ 4945 obj = NULL; 4946 result = named_config_get(maps, "resolver-query-timeout", &obj); 4947 INSIST(result == ISC_R_SUCCESS); 4948 query_timeout = cfg_obj_asuint32(obj); 4949 dns_resolver_settimeout(view->resolver, query_timeout); 4950 4951 /* Specify whether to use 0-TTL for negative response for SOA query */ 4952 dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); 4953 4954 /* 4955 * Set the resolver's EDNS UDP size. 4956 */ 4957 obj = NULL; 4958 result = named_config_get(maps, "edns-udp-size", &obj); 4959 INSIST(result == ISC_R_SUCCESS); 4960 udpsize = cfg_obj_asuint32(obj); 4961 if (udpsize < 512) { 4962 udpsize = 512; 4963 } 4964 if (udpsize > 4096) { 4965 udpsize = 4096; 4966 } 4967 dns_view_setudpsize(view, (uint16_t)udpsize); 4968 4969 /* 4970 * Set the maximum UDP response size. 4971 */ 4972 obj = NULL; 4973 result = named_config_get(maps, "max-udp-size", &obj); 4974 INSIST(result == ISC_R_SUCCESS); 4975 udpsize = cfg_obj_asuint32(obj); 4976 if (udpsize < 512) { 4977 udpsize = 512; 4978 } 4979 if (udpsize > 4096) { 4980 udpsize = 4096; 4981 } 4982 view->maxudp = udpsize; 4983 4984 /* 4985 * Set the maximum UDP when a COOKIE is not provided. 4986 */ 4987 obj = NULL; 4988 result = named_config_get(maps, "nocookie-udp-size", &obj); 4989 INSIST(result == ISC_R_SUCCESS); 4990 udpsize = cfg_obj_asuint32(obj); 4991 if (udpsize < 128) { 4992 udpsize = 128; 4993 } 4994 if (udpsize > view->maxudp) { 4995 udpsize = view->maxudp; 4996 } 4997 view->nocookieudp = udpsize; 4998 4999 /* 5000 * Set the maximum rsa exponent bits. 5001 */ 5002 obj = NULL; 5003 result = named_config_get(maps, "max-rsa-exponent-size", &obj); 5004 INSIST(result == ISC_R_SUCCESS); 5005 maxbits = cfg_obj_asuint32(obj); 5006 if (maxbits != 0 && maxbits < 35) { 5007 maxbits = 35; 5008 } 5009 if (maxbits > 4096) { 5010 maxbits = 4096; 5011 } 5012 view->maxbits = maxbits; 5013 5014 /* 5015 * Set supported DNSSEC algorithms. 5016 */ 5017 disabled = NULL; 5018 (void)named_config_get(maps, "disable-algorithms", &disabled); 5019 if (disabled != NULL) { 5020 for (element = cfg_list_first(disabled); element != NULL; 5021 element = cfg_list_next(element)) 5022 { 5023 CHECK(disable_algorithms(cfg_listelt_value(element), 5024 view->resolver)); 5025 } 5026 } 5027 5028 /* 5029 * Set supported DS digest types. 5030 */ 5031 disabled = NULL; 5032 (void)named_config_get(maps, "disable-ds-digests", &disabled); 5033 if (disabled != NULL) { 5034 for (element = cfg_list_first(disabled); element != NULL; 5035 element = cfg_list_next(element)) 5036 { 5037 CHECK(disable_ds_digests(cfg_listelt_value(element), 5038 view->resolver)); 5039 } 5040 } 5041 5042 /* 5043 * A global or view "forwarders" option, if present, 5044 * creates an entry for "." in the forwarding table. 5045 */ 5046 forwardtype = NULL; 5047 forwarders = NULL; 5048 (void)named_config_get(maps, "forward", &forwardtype); 5049 (void)named_config_get(maps, "forwarders", &forwarders); 5050 if (forwarders != NULL) { 5051 CHECK(configure_forward(config, view, dns_rootname, forwarders, 5052 forwardtype)); 5053 } 5054 5055 /* 5056 * Dual Stack Servers. 5057 */ 5058 alternates = NULL; 5059 (void)named_config_get(maps, "dual-stack-servers", &alternates); 5060 if (alternates != NULL) { 5061 CHECK(configure_alternates(config, view, alternates)); 5062 } 5063 5064 /* 5065 * We have default hints for class IN if we need them. 5066 */ 5067 if (view->rdclass == dns_rdataclass_in && view->hints == NULL) { 5068 dns_view_sethints(view, named_g_server->in_roothints); 5069 } 5070 5071 /* 5072 * If we still have no hints, this is a non-IN view with no 5073 * "hints zone" configured. Issue a warning, except if this 5074 * is a root server. Root servers never need to consult 5075 * their hints, so it's no point requiring users to configure 5076 * them. 5077 */ 5078 if (view->hints == NULL) { 5079 dns_zone_t *rootzone = NULL; 5080 (void)dns_view_findzone(view, dns_rootname, DNS_ZTFIND_EXACT, 5081 &rootzone); 5082 if (rootzone != NULL) { 5083 dns_zone_detach(&rootzone); 5084 need_hints = false; 5085 } 5086 if (need_hints) { 5087 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 5088 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 5089 "no root hints for view '%s'", 5090 view->name); 5091 } 5092 } 5093 5094 /* 5095 * Configure the view's transports (DoT/DoH) 5096 */ 5097 CHECK(named_transports_fromconfig(config, vconfig, view->mctx, 5098 &transports)); 5099 dns_view_settransports(view, transports); 5100 dns_transport_list_detach(&transports); 5101 5102 /* 5103 * Configure the view's TSIG keys. 5104 */ 5105 CHECK(named_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); 5106 if (named_g_server->sessionkey != NULL) { 5107 dns_tsigkey_t *tsigkey = NULL; 5108 result = dns_tsigkey_createfromkey( 5109 named_g_server->session_keyname, 5110 named_g_server->session_keyalg, 5111 named_g_server->sessionkey, false, false, NULL, 0, 0, 5112 mctx, &tsigkey); 5113 if (result == ISC_R_SUCCESS) { 5114 result = dns_tsigkeyring_add(ring, tsigkey); 5115 dns_tsigkey_detach(&tsigkey); 5116 } 5117 CHECK(result); 5118 } 5119 dns_view_setkeyring(view, ring); 5120 dns_tsigkeyring_detach(&ring); 5121 5122 /* 5123 * See if we can re-use a dynamic key ring. 5124 */ 5125 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 5126 view->rdclass, &pview); 5127 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 5128 goto cleanup; 5129 } 5130 if (pview != NULL) { 5131 dns_view_getdynamickeyring(pview, &ring); 5132 if (ring != NULL) { 5133 dns_view_setdynamickeyring(view, ring); 5134 } 5135 dns_tsigkeyring_detach(&ring); 5136 dns_view_detach(&pview); 5137 } else { 5138 dns_view_restorekeyring(view); 5139 } 5140 5141 /* 5142 * Configure the view's peer list. 5143 */ 5144 { 5145 const cfg_obj_t *peers = NULL; 5146 dns_peerlist_t *newpeers = NULL; 5147 5148 (void)named_config_get(cfgmaps, "server", &peers); 5149 CHECK(dns_peerlist_new(mctx, &newpeers)); 5150 for (element = cfg_list_first(peers); element != NULL; 5151 element = cfg_list_next(element)) 5152 { 5153 const cfg_obj_t *cpeer = cfg_listelt_value(element); 5154 dns_peer_t *peer; 5155 5156 CHECK(configure_peer(cpeer, mctx, &peer)); 5157 dns_peerlist_addpeer(newpeers, peer); 5158 dns_peer_detach(&peer); 5159 } 5160 dns_peerlist_detach(&view->peers); 5161 view->peers = newpeers; /* Transfer ownership. */ 5162 } 5163 5164 /* 5165 * Configure the views rrset-order. 5166 */ 5167 { 5168 const cfg_obj_t *rrsetorder = NULL; 5169 5170 (void)named_config_get(maps, "rrset-order", &rrsetorder); 5171 CHECK(dns_order_create(mctx, &order)); 5172 for (element = cfg_list_first(rrsetorder); element != NULL; 5173 element = cfg_list_next(element)) 5174 { 5175 const cfg_obj_t *ent = cfg_listelt_value(element); 5176 5177 CHECK(configure_order(order, ent)); 5178 } 5179 if (view->order != NULL) { 5180 dns_order_detach(&view->order); 5181 } 5182 dns_order_attach(order, &view->order); 5183 dns_order_detach(&order); 5184 } 5185 /* 5186 * Copy the aclenv object. 5187 */ 5188 dns_aclenv_copy(view->aclenv, ns_interfacemgr_getaclenv( 5189 named_g_server->interfacemgr)); 5190 5191 /* 5192 * Configure the "match-clients" and "match-destinations" ACL. 5193 * (These are only meaningful at the view level, but 'config' 5194 * must be passed so that named ACLs defined at the global level 5195 * can be retrieved.) 5196 */ 5197 CHECK(configure_view_acl(vconfig, config, NULL, "match-clients", NULL, 5198 actx, named_g_mctx, &view->matchclients)); 5199 CHECK(configure_view_acl(vconfig, config, NULL, "match-destinations", 5200 NULL, actx, named_g_mctx, 5201 &view->matchdestinations)); 5202 5203 /* 5204 * Configure the "match-recursive-only" option. 5205 */ 5206 obj = NULL; 5207 (void)named_config_get(maps, "match-recursive-only", &obj); 5208 if (obj != NULL && cfg_obj_asboolean(obj)) { 5209 view->matchrecursiveonly = true; 5210 } else { 5211 view->matchrecursiveonly = false; 5212 } 5213 5214 /* 5215 * Configure other configurable data. 5216 */ 5217 obj = NULL; 5218 result = named_config_get(maps, "recursion", &obj); 5219 INSIST(result == ISC_R_SUCCESS); 5220 view->recursion = cfg_obj_asboolean(obj); 5221 5222 obj = NULL; 5223 result = named_config_get(maps, "qname-minimization", &obj); 5224 INSIST(result == ISC_R_SUCCESS); 5225 qminmode = cfg_obj_asstring(obj); 5226 INSIST(qminmode != NULL); 5227 if (!strcmp(qminmode, "strict")) { 5228 view->qminimization = true; 5229 view->qmin_strict = true; 5230 } else if (!strcmp(qminmode, "relaxed")) { 5231 view->qminimization = true; 5232 view->qmin_strict = false; 5233 } else { /* "disabled" or "off" */ 5234 view->qminimization = false; 5235 view->qmin_strict = false; 5236 } 5237 5238 obj = NULL; 5239 result = named_config_get(maps, "auth-nxdomain", &obj); 5240 INSIST(result == ISC_R_SUCCESS); 5241 view->auth_nxdomain = cfg_obj_asboolean(obj); 5242 5243 obj = NULL; 5244 result = named_config_get(maps, "minimal-any", &obj); 5245 INSIST(result == ISC_R_SUCCESS); 5246 view->minimal_any = cfg_obj_asboolean(obj); 5247 5248 obj = NULL; 5249 result = named_config_get(maps, "minimal-responses", &obj); 5250 INSIST(result == ISC_R_SUCCESS); 5251 if (cfg_obj_isboolean(obj)) { 5252 if (cfg_obj_asboolean(obj)) { 5253 view->minimalresponses = dns_minimal_yes; 5254 } else { 5255 view->minimalresponses = dns_minimal_no; 5256 } 5257 } else { 5258 str = cfg_obj_asstring(obj); 5259 if (strcasecmp(str, "no-auth") == 0) { 5260 view->minimalresponses = dns_minimal_noauth; 5261 } else if (strcasecmp(str, "no-auth-recursive") == 0) { 5262 view->minimalresponses = dns_minimal_noauthrec; 5263 } else { 5264 UNREACHABLE(); 5265 } 5266 } 5267 5268 obj = NULL; 5269 result = named_config_get(maps, "transfer-format", &obj); 5270 INSIST(result == ISC_R_SUCCESS); 5271 str = cfg_obj_asstring(obj); 5272 if (strcasecmp(str, "many-answers") == 0) { 5273 view->transfer_format = dns_many_answers; 5274 } else if (strcasecmp(str, "one-answer") == 0) { 5275 view->transfer_format = dns_one_answer; 5276 } else { 5277 UNREACHABLE(); 5278 } 5279 5280 obj = NULL; 5281 result = named_config_get(maps, "trust-anchor-telemetry", &obj); 5282 INSIST(result == ISC_R_SUCCESS); 5283 view->trust_anchor_telemetry = cfg_obj_asboolean(obj); 5284 5285 obj = NULL; 5286 result = named_config_get(maps, "root-key-sentinel", &obj); 5287 INSIST(result == ISC_R_SUCCESS); 5288 view->root_key_sentinel = cfg_obj_asboolean(obj); 5289 5290 /* 5291 * Set the "allow-query", "allow-query-cache", "allow-recursion", 5292 * "allow-recursion-on" and "allow-query-cache-on" ACLs if 5293 * configured in named.conf, but NOT from the global defaults. 5294 * This is done by leaving the third argument to configure_view_acl() 5295 * NULL. 5296 * 5297 * We ignore the global defaults here because these ACLs 5298 * can inherit from each other. If any are still unset after 5299 * applying the inheritance rules, we'll look up the defaults at 5300 * that time. 5301 */ 5302 5303 /* named.conf only */ 5304 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query", NULL, 5305 actx, named_g_mctx, &view->queryacl)); 5306 5307 /* named.conf only */ 5308 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache", 5309 NULL, actx, named_g_mctx, &view->cacheacl)); 5310 /* named.conf only */ 5311 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on", 5312 NULL, actx, named_g_mctx, &view->cacheonacl)); 5313 5314 CHECK(configure_view_acl(vconfig, config, named_g_config, "allow-proxy", 5315 NULL, actx, named_g_mctx, &view->proxyacl)); 5316 5317 CHECK(configure_view_acl(vconfig, config, named_g_config, 5318 "allow-proxy-on", NULL, actx, named_g_mctx, 5319 &view->proxyonacl)); 5320 5321 if (strcmp(view->name, "_bind") != 0 && 5322 view->rdclass != dns_rdataclass_chaos) 5323 { 5324 /* named.conf only */ 5325 CHECK(configure_view_acl(vconfig, config, NULL, 5326 "allow-recursion", NULL, actx, 5327 named_g_mctx, &view->recursionacl)); 5328 /* named.conf only */ 5329 CHECK(configure_view_acl(vconfig, config, NULL, 5330 "allow-recursion-on", NULL, actx, 5331 named_g_mctx, &view->recursiononacl)); 5332 } 5333 5334 if (view->recursion) { 5335 /* 5336 * "allow-query-cache" inherits from "allow-recursion" if set, 5337 * otherwise from "allow-query" if set. 5338 */ 5339 if (view->cacheacl == NULL) { 5340 if (view->recursionacl != NULL) { 5341 dns_acl_attach(view->recursionacl, 5342 &view->cacheacl); 5343 } else if (view->queryacl != NULL) { 5344 dns_acl_attach(view->queryacl, &view->cacheacl); 5345 } 5346 } 5347 5348 /* 5349 * "allow-recursion" inherits from "allow-query-cache" if set, 5350 * otherwise from "allow-query" if set. 5351 */ 5352 if (view->recursionacl == NULL) { 5353 if (view->cacheacl != NULL) { 5354 dns_acl_attach(view->cacheacl, 5355 &view->recursionacl); 5356 } else if (view->queryacl != NULL) { 5357 dns_acl_attach(view->queryacl, 5358 &view->recursionacl); 5359 } 5360 } 5361 5362 /* 5363 * "allow-query-cache-on" inherits from "allow-recursion-on" 5364 * if set. 5365 */ 5366 if (view->cacheonacl == NULL) { 5367 if (view->recursiononacl != NULL) { 5368 dns_acl_attach(view->recursiononacl, 5369 &view->cacheonacl); 5370 } 5371 } 5372 5373 /* 5374 * "allow-recursion-on" inherits from "allow-query-cache-on" 5375 * if set. 5376 */ 5377 if (view->recursiononacl == NULL) { 5378 if (view->cacheonacl != NULL) { 5379 dns_acl_attach(view->cacheonacl, 5380 &view->recursiononacl); 5381 } 5382 } 5383 5384 /* 5385 * If any are still unset at this point, we now get default 5386 * values for from the global config. 5387 */ 5388 5389 if (view->recursionacl == NULL) { 5390 /* global default only */ 5391 CHECK(configure_view_acl( 5392 NULL, NULL, named_g_config, "allow-recursion", 5393 NULL, actx, named_g_mctx, &view->recursionacl)); 5394 } 5395 if (view->recursiononacl == NULL) { 5396 /* global default only */ 5397 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5398 "allow-recursion-on", NULL, 5399 actx, named_g_mctx, 5400 &view->recursiononacl)); 5401 } 5402 if (view->cacheacl == NULL) { 5403 /* global default only */ 5404 CHECK(configure_view_acl( 5405 NULL, NULL, named_g_config, "allow-query-cache", 5406 NULL, actx, named_g_mctx, &view->cacheacl)); 5407 } 5408 if (view->cacheonacl == NULL) { 5409 /* global default only */ 5410 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5411 "allow-query-cache-on", NULL, 5412 actx, named_g_mctx, 5413 &view->cacheonacl)); 5414 } 5415 } else { 5416 /* 5417 * We're not recursive; if the query-cache ACLs haven't 5418 * been set at the options/view level, set them to none. 5419 */ 5420 if (view->cacheacl == NULL) { 5421 CHECK(dns_acl_none(mctx, &view->cacheacl)); 5422 } 5423 if (view->cacheonacl == NULL) { 5424 CHECK(dns_acl_none(mctx, &view->cacheonacl)); 5425 } 5426 } 5427 5428 /* 5429 * Finished setting recursion and query-cache ACLs, so now we 5430 * can get the allow-query default if it wasn't set in named.conf 5431 */ 5432 if (view->queryacl == NULL) { 5433 /* global default only */ 5434 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5435 "allow-query", NULL, actx, 5436 named_g_mctx, &view->queryacl)); 5437 } 5438 5439 /* 5440 * Ignore case when compressing responses to the specified 5441 * clients. This causes case not always to be preserved, 5442 * and is needed by some broken clients. 5443 */ 5444 CHECK(configure_view_acl(vconfig, config, named_g_config, 5445 "no-case-compress", NULL, actx, named_g_mctx, 5446 &view->nocasecompress)); 5447 5448 /* 5449 * Disable name compression completely, this is a tradeoff 5450 * between CPU and network usage. 5451 */ 5452 obj = NULL; 5453 result = named_config_get(maps, "message-compression", &obj); 5454 INSIST(result == ISC_R_SUCCESS); 5455 view->msgcompression = cfg_obj_asboolean(obj); 5456 5457 /* 5458 * Filter setting on addresses in the answer section. 5459 */ 5460 CHECK(configure_view_acl(vconfig, config, named_g_config, 5461 "deny-answer-addresses", "acl", actx, 5462 named_g_mctx, &view->denyansweracl)); 5463 CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", 5464 "except-from", named_g_mctx, 5465 &view->answeracl_exclude)); 5466 5467 /* 5468 * Filter setting on names (CNAME/DNAME targets) in the answer section. 5469 */ 5470 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 5471 "name", named_g_mctx, 5472 &view->denyanswernames)); 5473 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 5474 "except-from", named_g_mctx, 5475 &view->answernames_exclude)); 5476 5477 /* 5478 * Configure sortlist, if set 5479 */ 5480 CHECK(configure_view_sortlist(vconfig, config, actx, named_g_mctx, 5481 &view->sortlist)); 5482 5483 /* 5484 * Configure default allow-update and allow-update-forwarding ACLs, 5485 * so they can be inherited by zones. (XXX: These are not 5486 * read from the options/view level here. However, they may be 5487 * read from there in zoneconf.c:configure_zone_acl() later.) 5488 */ 5489 if (view->updateacl == NULL) { 5490 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5491 "allow-update", NULL, actx, 5492 named_g_mctx, &view->updateacl)); 5493 } 5494 if (view->upfwdacl == NULL) { 5495 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5496 "allow-update-forwarding", NULL, actx, 5497 named_g_mctx, &view->upfwdacl)); 5498 } 5499 5500 /* 5501 * Configure default allow-transfer and allow-notify ACLs so they 5502 * can be inherited by zones. 5503 */ 5504 if (view->transferacl == NULL) { 5505 CHECK(configure_view_acl(vconfig, config, named_g_config, 5506 "allow-transfer", NULL, actx, 5507 named_g_mctx, &view->transferacl)); 5508 } 5509 if (view->notifyacl == NULL) { 5510 CHECK(configure_view_acl(vconfig, config, named_g_config, 5511 "allow-notify", NULL, actx, 5512 named_g_mctx, &view->notifyacl)); 5513 } 5514 5515 obj = NULL; 5516 result = named_config_get(maps, "provide-ixfr", &obj); 5517 INSIST(result == ISC_R_SUCCESS); 5518 view->provideixfr = cfg_obj_asboolean(obj); 5519 5520 obj = NULL; 5521 result = named_config_get(maps, "request-nsid", &obj); 5522 INSIST(result == ISC_R_SUCCESS); 5523 view->requestnsid = cfg_obj_asboolean(obj); 5524 5525 obj = NULL; 5526 result = named_config_get(maps, "send-cookie", &obj); 5527 INSIST(result == ISC_R_SUCCESS); 5528 view->sendcookie = cfg_obj_asboolean(obj); 5529 5530 obj = NULL; 5531 if (view->pad_acl != NULL) { 5532 dns_acl_detach(&view->pad_acl); 5533 } 5534 result = named_config_get(optionmaps, "response-padding", &obj); 5535 if (result == ISC_R_SUCCESS) { 5536 const cfg_obj_t *padobj = cfg_tuple_get(obj, "block-size"); 5537 const cfg_obj_t *aclobj = cfg_tuple_get(obj, "acl"); 5538 uint32_t padding = cfg_obj_asuint32(padobj); 5539 5540 if (padding > 512U) { 5541 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 5542 "response-padding block-size cannot " 5543 "exceed 512: lowering"); 5544 padding = 512U; 5545 } 5546 view->padding = (uint16_t)padding; 5547 CHECK(cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, 5548 named_g_mctx, 0, &view->pad_acl)); 5549 } 5550 5551 obj = NULL; 5552 result = named_config_get(maps, "require-server-cookie", &obj); 5553 INSIST(result == ISC_R_SUCCESS); 5554 view->requireservercookie = cfg_obj_asboolean(obj); 5555 5556 obj = NULL; 5557 result = named_config_get(maps, "v6-bias", &obj); 5558 INSIST(result == ISC_R_SUCCESS); 5559 view->v6bias = cfg_obj_asuint32(obj) * 1000; 5560 5561 obj = NULL; 5562 result = named_config_get(maps, "max-clients-per-query", &obj); 5563 INSIST(result == ISC_R_SUCCESS); 5564 max_clients_per_query = cfg_obj_asuint32(obj); 5565 5566 obj = NULL; 5567 result = named_config_get(maps, "clients-per-query", &obj); 5568 INSIST(result == ISC_R_SUCCESS); 5569 dns_resolver_setclientsperquery(view->resolver, cfg_obj_asuint32(obj), 5570 max_clients_per_query); 5571 5572 /* 5573 * This is used for the cache and also as a default value 5574 * for zone databases. 5575 */ 5576 obj = NULL; 5577 result = named_config_get(maps, "max-records-per-type", &obj); 5578 INSIST(result == ISC_R_SUCCESS); 5579 dns_view_setmaxrrperset(view, cfg_obj_asuint32(obj)); 5580 5581 /* 5582 * This is used for the cache and also as a default value 5583 * for zone databases. 5584 */ 5585 obj = NULL; 5586 result = named_config_get(maps, "max-types-per-name", &obj); 5587 INSIST(result == ISC_R_SUCCESS); 5588 dns_view_setmaxtypepername(view, cfg_obj_asuint32(obj)); 5589 5590 obj = NULL; 5591 result = named_config_get(maps, "max-recursion-depth", &obj); 5592 INSIST(result == ISC_R_SUCCESS); 5593 dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); 5594 5595 obj = NULL; 5596 result = named_config_get(maps, "max-recursion-queries", &obj); 5597 INSIST(result == ISC_R_SUCCESS); 5598 dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); 5599 5600 obj = NULL; 5601 result = named_config_get(maps, "max-query-restarts", &obj); 5602 INSIST(result == ISC_R_SUCCESS); 5603 dns_view_setmaxrestarts(view, cfg_obj_asuint32(obj)); 5604 5605 obj = NULL; 5606 result = named_config_get(maps, "max-validations-per-fetch", &obj); 5607 if (result == ISC_R_SUCCESS) { 5608 dns_resolver_setmaxvalidations(view->resolver, 5609 cfg_obj_asuint32(obj)); 5610 } 5611 5612 obj = NULL; 5613 result = named_config_get(maps, "max-validation-failures-per-fetch", 5614 &obj); 5615 if (result == ISC_R_SUCCESS) { 5616 dns_resolver_setmaxvalidationfails(view->resolver, 5617 cfg_obj_asuint32(obj)); 5618 } 5619 5620 obj = NULL; 5621 result = named_config_get(maps, "fetches-per-zone", &obj); 5622 INSIST(result == ISC_R_SUCCESS); 5623 obj2 = cfg_tuple_get(obj, "fetches"); 5624 dns_resolver_setfetchesperzone(view->resolver, cfg_obj_asuint32(obj2)); 5625 obj2 = cfg_tuple_get(obj, "response"); 5626 if (!cfg_obj_isvoid(obj2)) { 5627 const char *resp = cfg_obj_asstring(obj2); 5628 isc_result_t r = DNS_R_SERVFAIL; 5629 5630 if (strcasecmp(resp, "drop") == 0) { 5631 r = DNS_R_DROP; 5632 } else if (strcasecmp(resp, "fail") == 0) { 5633 r = DNS_R_SERVFAIL; 5634 } else { 5635 UNREACHABLE(); 5636 } 5637 5638 dns_resolver_setquotaresponse(view->resolver, 5639 dns_quotatype_zone, r); 5640 } 5641 5642 obj = NULL; 5643 result = named_config_get(maps, "prefetch", &obj); 5644 INSIST(result == ISC_R_SUCCESS); 5645 prefetch_trigger = cfg_tuple_get(obj, "trigger"); 5646 view->prefetch_trigger = cfg_obj_asuint32(prefetch_trigger); 5647 if (view->prefetch_trigger > 10) { 5648 view->prefetch_trigger = 10; 5649 } 5650 prefetch_eligible = cfg_tuple_get(obj, "eligible"); 5651 if (cfg_obj_isvoid(prefetch_eligible)) { 5652 int m; 5653 for (m = 1; maps[m] != NULL; m++) { 5654 obj = NULL; 5655 result = named_config_get(&maps[m], "prefetch", &obj); 5656 INSIST(result == ISC_R_SUCCESS); 5657 prefetch_eligible = cfg_tuple_get(obj, "eligible"); 5658 if (cfg_obj_isuint32(prefetch_eligible)) { 5659 break; 5660 } 5661 } 5662 INSIST(cfg_obj_isuint32(prefetch_eligible)); 5663 } 5664 view->prefetch_eligible = cfg_obj_asuint32(prefetch_eligible); 5665 if (view->prefetch_eligible < view->prefetch_trigger + 6) { 5666 view->prefetch_eligible = view->prefetch_trigger + 6; 5667 } 5668 5669 /* 5670 * For now, there is only one kind of trusted keys, the 5671 * "security roots". 5672 */ 5673 CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, 5674 auto_root)); 5675 5676 obj = NULL; 5677 result = named_config_get(maps, "dnssec-must-be-secure", &obj); 5678 if (result == ISC_R_SUCCESS) { 5679 CHECK(mustbesecure(obj, view->resolver)); 5680 } 5681 5682 obj = NULL; 5683 result = named_config_get(maps, "nta-recheck", &obj); 5684 INSIST(result == ISC_R_SUCCESS); 5685 view->nta_recheck = cfg_obj_asduration(obj); 5686 5687 obj = NULL; 5688 result = named_config_get(maps, "nta-lifetime", &obj); 5689 INSIST(result == ISC_R_SUCCESS); 5690 view->nta_lifetime = cfg_obj_asduration(obj); 5691 5692 obj = NULL; 5693 result = named_config_get(maps, "preferred-glue", &obj); 5694 if (result == ISC_R_SUCCESS) { 5695 str = cfg_obj_asstring(obj); 5696 if (strcasecmp(str, "a") == 0) { 5697 view->preferred_glue = dns_rdatatype_a; 5698 } else if (strcasecmp(str, "aaaa") == 0) { 5699 view->preferred_glue = dns_rdatatype_aaaa; 5700 } else { 5701 view->preferred_glue = 0; 5702 } 5703 } else { 5704 view->preferred_glue = 0; 5705 } 5706 5707 /* 5708 * Load DynDB modules. 5709 */ 5710 dyndb_list = NULL; 5711 if (voptions != NULL) { 5712 (void)cfg_map_get(voptions, "dyndb", &dyndb_list); 5713 } else { 5714 (void)cfg_map_get(config, "dyndb", &dyndb_list); 5715 } 5716 5717 for (element = cfg_list_first(dyndb_list); element != NULL; 5718 element = cfg_list_next(element)) 5719 { 5720 const cfg_obj_t *dyndb = cfg_listelt_value(element); 5721 5722 if (dctx == NULL) { 5723 const void *hashinit = isc_hash_get_initializer(); 5724 CHECK(dns_dyndb_createctx(mctx, hashinit, named_g_lctx, 5725 view, named_g_server->zonemgr, 5726 named_g_loopmgr, &dctx)); 5727 } 5728 5729 CHECK(configure_dyndb(dyndb, mctx, dctx)); 5730 } 5731 5732 /* 5733 * Load plugins. 5734 */ 5735 plugin_list = NULL; 5736 if (voptions != NULL) { 5737 (void)cfg_map_get(voptions, "plugin", &plugin_list); 5738 } else { 5739 (void)cfg_map_get(config, "plugin", &plugin_list); 5740 } 5741 5742 if (plugin_list != NULL) { 5743 INSIST(view->hooktable == NULL); 5744 CHECK(ns_hooktable_create(view->mctx, 5745 (ns_hooktable_t **)&view->hooktable)); 5746 view->hooktable_free = ns_hooktable_free; 5747 5748 ns_plugins_create(view->mctx, (ns_plugins_t **)&view->plugins); 5749 view->plugins_free = ns_plugins_free; 5750 5751 CHECK(cfg_pluginlist_foreach(config, plugin_list, named_g_lctx, 5752 register_one_plugin, view)); 5753 } 5754 5755 /* 5756 * Setup automatic empty zones. If recursion is off then 5757 * they are disabled by default. 5758 */ 5759 obj = NULL; 5760 (void)named_config_get(maps, "empty-zones-enable", &obj); 5761 (void)named_config_get(maps, "disable-empty-zone", &disablelist); 5762 if (obj == NULL && disablelist == NULL && 5763 view->rdclass == dns_rdataclass_in) 5764 { 5765 empty_zones_enable = view->recursion; 5766 } else if (view->rdclass == dns_rdataclass_in) { 5767 if (obj != NULL) { 5768 empty_zones_enable = cfg_obj_asboolean(obj); 5769 } else { 5770 empty_zones_enable = view->recursion; 5771 } 5772 } else { 5773 empty_zones_enable = false; 5774 } 5775 5776 if (empty_zones_enable) { 5777 const char *empty; 5778 int empty_zone = 0; 5779 dns_fixedname_t fixed; 5780 dns_name_t *name; 5781 isc_buffer_t buffer; 5782 char server[DNS_NAME_FORMATSIZE + 1]; 5783 char contact[DNS_NAME_FORMATSIZE + 1]; 5784 const char *empty_dbtype[4] = { "_builtin", "empty", NULL, 5785 NULL }; 5786 int empty_dbtypec = 4; 5787 dns_zonestat_level_t statlevel = dns_zonestat_none; 5788 5789 name = dns_fixedname_initname(&fixed); 5790 5791 obj = NULL; 5792 result = named_config_get(maps, "empty-server", &obj); 5793 if (result == ISC_R_SUCCESS) { 5794 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 5795 dns_rootname, 0, NULL)); 5796 isc_buffer_init(&buffer, server, sizeof(server) - 1); 5797 CHECK(dns_name_totext(name, 0, &buffer)); 5798 server[isc_buffer_usedlength(&buffer)] = 0; 5799 empty_dbtype[2] = server; 5800 } else { 5801 empty_dbtype[2] = "@"; 5802 } 5803 5804 obj = NULL; 5805 result = named_config_get(maps, "empty-contact", &obj); 5806 if (result == ISC_R_SUCCESS) { 5807 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 5808 dns_rootname, 0, NULL)); 5809 isc_buffer_init(&buffer, contact, sizeof(contact) - 1); 5810 CHECK(dns_name_totext(name, 0, &buffer)); 5811 contact[isc_buffer_usedlength(&buffer)] = 0; 5812 empty_dbtype[3] = contact; 5813 } else { 5814 empty_dbtype[3] = "."; 5815 } 5816 5817 obj = NULL; 5818 result = named_config_get(maps, "zone-statistics", &obj); 5819 INSIST(result == ISC_R_SUCCESS); 5820 if (cfg_obj_isboolean(obj)) { 5821 if (cfg_obj_asboolean(obj)) { 5822 statlevel = dns_zonestat_full; 5823 } else { 5824 statlevel = dns_zonestat_none; 5825 } 5826 } else { 5827 const char *levelstr = cfg_obj_asstring(obj); 5828 if (strcasecmp(levelstr, "full") == 0) { 5829 statlevel = dns_zonestat_full; 5830 } else if (strcasecmp(levelstr, "terse") == 0) { 5831 statlevel = dns_zonestat_terse; 5832 } else if (strcasecmp(levelstr, "none") == 0) { 5833 statlevel = dns_zonestat_none; 5834 } else { 5835 UNREACHABLE(); 5836 } 5837 } 5838 5839 for (empty = empty_zones[empty_zone]; empty != NULL; 5840 empty = empty_zones[++empty_zone]) 5841 { 5842 dns_forwarders_t *dnsforwarders = NULL; 5843 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 5844 5845 /* 5846 * Look for zone on drop list. 5847 */ 5848 CHECK(dns_name_fromstring(name, empty, dns_rootname, 0, 5849 NULL)); 5850 if (disablelist != NULL && 5851 on_disable_list(disablelist, name)) 5852 { 5853 continue; 5854 } 5855 5856 /* 5857 * This zone already exists. 5858 */ 5859 (void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 5860 &zone); 5861 if (zone != NULL) { 5862 dns_zone_detach(&zone); 5863 continue; 5864 } 5865 5866 /* 5867 * If we would forward this name don't add a 5868 * empty zone for it. 5869 */ 5870 result = dns_fwdtable_find(view->fwdtable, name, 5871 &dnsforwarders); 5872 if (result == ISC_R_SUCCESS || 5873 result == DNS_R_PARTIALMATCH) 5874 { 5875 fwdpolicy = dnsforwarders->fwdpolicy; 5876 dns_forwarders_detach(&dnsforwarders); 5877 } 5878 if (fwdpolicy == dns_fwdpolicy_only) { 5879 continue; 5880 } 5881 5882 /* 5883 * See if we can re-use a existing zone. 5884 */ 5885 result = dns_viewlist_find(&named_g_server->viewlist, 5886 view->name, view->rdclass, 5887 &pview); 5888 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 5889 { 5890 goto cleanup; 5891 } 5892 5893 if (pview != NULL) { 5894 (void)dns_view_findzone( 5895 pview, name, DNS_ZTFIND_EXACT, &zone); 5896 dns_view_detach(&pview); 5897 } 5898 5899 CHECK(create_empty_zone(zone, name, view, zonelist, 5900 empty_dbtype, empty_dbtypec, 5901 statlevel)); 5902 if (zone != NULL) { 5903 dns_zone_detach(&zone); 5904 } 5905 } 5906 } 5907 5908 obj = NULL; 5909 if (view->rdclass == dns_rdataclass_in) { 5910 (void)named_config_get(maps, "ipv4only-enable", &obj); 5911 } 5912 if (view->rdclass == dns_rdataclass_in && (obj != NULL) 5913 ? cfg_obj_asboolean(obj) 5914 : !ISC_LIST_EMPTY(view->dns64)) 5915 { 5916 const char *server, *contact; 5917 dns_fixedname_t fixed; 5918 dns_name_t *name; 5919 struct { 5920 const char *name; 5921 const char *type; 5922 } zones[] = { 5923 { "ipv4only.arpa", "ipv4only" }, 5924 { "170.0.0.192.in-addr.arpa", "ipv4reverse" }, 5925 { "171.0.0.192.in-addr.arpa", "ipv4reverse" }, 5926 }; 5927 size_t ipv4only_zone; 5928 5929 obj = NULL; 5930 result = named_config_get(maps, "ipv4only-server", &obj); 5931 if (result == ISC_R_SUCCESS) { 5932 server = cfg_obj_asstring(obj); 5933 } else { 5934 server = NULL; 5935 } 5936 5937 obj = NULL; 5938 result = named_config_get(maps, "ipv4only-contact", &obj); 5939 if (result == ISC_R_SUCCESS) { 5940 contact = cfg_obj_asstring(obj); 5941 } else { 5942 contact = NULL; 5943 } 5944 5945 name = dns_fixedname_initname(&fixed); 5946 for (ipv4only_zone = 0; ipv4only_zone < ARRAY_SIZE(zones); 5947 ipv4only_zone++) 5948 { 5949 dns_forwarders_t *dnsforwarders = NULL; 5950 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 5951 5952 CHECK(dns_name_fromstring(name, 5953 zones[ipv4only_zone].name, 5954 dns_rootname, 0, NULL)); 5955 5956 (void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 5957 &zone); 5958 if (zone != NULL) { 5959 dns_zone_detach(&zone); 5960 continue; 5961 } 5962 5963 /* 5964 * If we would forward this name don't add it. 5965 */ 5966 result = dns_fwdtable_find(view->fwdtable, name, 5967 &dnsforwarders); 5968 if (result == ISC_R_SUCCESS || 5969 result == DNS_R_PARTIALMATCH) 5970 { 5971 fwdpolicy = dnsforwarders->fwdpolicy; 5972 dns_forwarders_detach(&dnsforwarders); 5973 } 5974 if (fwdpolicy == dns_fwdpolicy_only) { 5975 continue; 5976 } 5977 5978 /* 5979 * See if we can re-use a existing zone. 5980 */ 5981 result = dns_viewlist_find(&named_g_server->viewlist, 5982 view->name, view->rdclass, 5983 &pview); 5984 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 5985 { 5986 goto cleanup; 5987 } 5988 5989 if (pview != NULL) { 5990 (void)dns_view_findzone( 5991 pview, name, DNS_ZTFIND_EXACT, &zone); 5992 dns_view_detach(&pview); 5993 } 5994 5995 CHECK(create_ipv4only_zone(zone, view, name, 5996 zones[ipv4only_zone].type, 5997 mctx, server, contact)); 5998 if (zone != NULL) { 5999 dns_zone_detach(&zone); 6000 } 6001 } 6002 } 6003 6004 obj = NULL; 6005 result = named_config_get(maps, "rate-limit", &obj); 6006 if (result == ISC_R_SUCCESS) { 6007 result = configure_rrl(view, config, obj); 6008 if (result != ISC_R_SUCCESS) { 6009 goto cleanup; 6010 } 6011 } 6012 6013 /* 6014 * Set the servfail-ttl. 6015 */ 6016 obj = NULL; 6017 result = named_config_get(maps, "servfail-ttl", &obj); 6018 INSIST(result == ISC_R_SUCCESS); 6019 fail_ttl = cfg_obj_asduration(obj); 6020 if (fail_ttl > 30) { 6021 fail_ttl = 30; 6022 } 6023 dns_view_setfailttl(view, fail_ttl); 6024 6025 /* 6026 * Name space to look up redirect information in. 6027 */ 6028 obj = NULL; 6029 result = named_config_get(maps, "nxdomain-redirect", &obj); 6030 if (result == ISC_R_SUCCESS) { 6031 dns_name_t *name = dns_fixedname_name(&view->redirectfixed); 6032 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 6033 dns_rootname, 0, NULL)); 6034 view->redirectzone = name; 6035 } else { 6036 view->redirectzone = NULL; 6037 } 6038 6039 /* 6040 * Exceptions to DNSSEC validation. 6041 */ 6042 obj = NULL; 6043 result = named_config_get(maps, "validate-except", &obj); 6044 if (result == ISC_R_SUCCESS) { 6045 result = dns_view_getntatable(view, &ntatable); 6046 } 6047 if (result == ISC_R_SUCCESS) { 6048 for (element = cfg_list_first(obj); element != NULL; 6049 element = cfg_list_next(element)) 6050 { 6051 dns_fixedname_t fntaname; 6052 dns_name_t *ntaname; 6053 6054 ntaname = dns_fixedname_initname(&fntaname); 6055 obj = cfg_listelt_value(element); 6056 CHECK(dns_name_fromstring(ntaname, 6057 cfg_obj_asstring(obj), 6058 dns_rootname, 0, NULL)); 6059 CHECK(dns_ntatable_add(ntatable, ntaname, true, 0, 6060 0xffffffffU)); 6061 } 6062 } 6063 6064 #ifdef HAVE_DNSTAP 6065 /* 6066 * Set up the dnstap environment and configure message 6067 * types to log. 6068 */ 6069 CHECK(configure_dnstap(maps, view)); 6070 #endif /* HAVE_DNSTAP */ 6071 6072 result = ISC_R_SUCCESS; 6073 6074 cleanup: 6075 /* 6076 * Revert to the old view if there was an error. 6077 */ 6078 if (result != ISC_R_SUCCESS) { 6079 isc_result_t result2; 6080 6081 result2 = dns_viewlist_find(&named_g_server->viewlist, 6082 view->name, view->rdclass, &pview); 6083 if (result2 == ISC_R_SUCCESS) { 6084 dns_view_thaw(pview); 6085 6086 obj = NULL; 6087 if (rpz_configured && 6088 pview->rdclass == dns_rdataclass_in && need_hints && 6089 named_config_get(maps, "response-policy", &obj) == 6090 ISC_R_SUCCESS) 6091 { 6092 /* 6093 * We are swapping the places of the `view` and 6094 * `pview` in the function's parameters list 6095 * because we are reverting the same operation 6096 * done previously in the "correct" order. 6097 */ 6098 result2 = configure_rpz(pview, view, maps, obj, 6099 &old_rpz_ok); 6100 if (result2 != ISC_R_SUCCESS) { 6101 isc_log_write(named_g_lctx, 6102 NAMED_LOGCATEGORY_GENERAL, 6103 NAMED_LOGMODULE_SERVER, 6104 ISC_LOG_ERROR, 6105 "rpz configuration " 6106 "revert failed for view " 6107 "'%s'", 6108 pview->name); 6109 } 6110 } 6111 6112 obj = NULL; 6113 if (catz_configured && 6114 pview->rdclass == dns_rdataclass_in && need_hints && 6115 named_config_get(maps, "catalog-zones", &obj) == 6116 ISC_R_SUCCESS) 6117 { 6118 /* 6119 * We are swapping the places of the `view` and 6120 * `pview` in the function's parameters list 6121 * because we are reverting the same operation 6122 * done previously in the "correct" order. 6123 */ 6124 result2 = configure_catz(pview, view, config, 6125 obj); 6126 if (result2 != ISC_R_SUCCESS) { 6127 isc_log_write(named_g_lctx, 6128 NAMED_LOGCATEGORY_GENERAL, 6129 NAMED_LOGMODULE_SERVER, 6130 ISC_LOG_ERROR, 6131 "catz configuration " 6132 "revert failed for view " 6133 "'%s'", 6134 pview->name); 6135 } 6136 } 6137 6138 dns_view_freeze(pview); 6139 } 6140 6141 if (pview != NULL) { 6142 dns_view_detach(&pview); 6143 } 6144 6145 if (zone_element_latest != NULL) { 6146 for (element = cfg_list_first(zonelist); 6147 element != NULL; element = cfg_list_next(element)) 6148 { 6149 const cfg_obj_t *zconfig = 6150 cfg_listelt_value(element); 6151 configure_zone_setviewcommit(result, zconfig, 6152 view); 6153 if (element == zone_element_latest) { 6154 /* 6155 * This was the latest element that was 6156 * successfully configured earlier. 6157 */ 6158 break; 6159 } 6160 } 6161 } 6162 } 6163 6164 if (ntatable != NULL) { 6165 dns_ntatable_detach(&ntatable); 6166 } 6167 if (clients != NULL) { 6168 dns_acl_detach(&clients); 6169 } 6170 if (mapped != NULL) { 6171 dns_acl_detach(&mapped); 6172 } 6173 if (excluded != NULL) { 6174 dns_acl_detach(&excluded); 6175 } 6176 if (ring != NULL) { 6177 dns_tsigkeyring_detach(&ring); 6178 } 6179 if (zone != NULL) { 6180 dns_zone_detach(&zone); 6181 } 6182 if (dispatch4 != NULL) { 6183 dns_dispatch_detach(&dispatch4); 6184 } 6185 if (dispatch6 != NULL) { 6186 dns_dispatch_detach(&dispatch6); 6187 } 6188 if (resstats != NULL) { 6189 isc_stats_detach(&resstats); 6190 } 6191 if (resquerystats != NULL) { 6192 dns_stats_detach(&resquerystats); 6193 } 6194 if (order != NULL) { 6195 dns_order_detach(&order); 6196 } 6197 if (cache != NULL) { 6198 dns_cache_detach(&cache); 6199 } 6200 if (dctx != NULL) { 6201 dns_dyndb_destroyctx(&dctx); 6202 } 6203 6204 return result; 6205 } 6206 6207 static isc_result_t 6208 configure_hints(dns_view_t *view, const char *filename) { 6209 isc_result_t result; 6210 dns_db_t *db; 6211 6212 db = NULL; 6213 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); 6214 if (result == ISC_R_SUCCESS) { 6215 dns_view_sethints(view, db); 6216 dns_db_detach(&db); 6217 } 6218 6219 return result; 6220 } 6221 6222 static isc_result_t 6223 configure_alternates(const cfg_obj_t *config, dns_view_t *view, 6224 const cfg_obj_t *alternates) { 6225 const cfg_obj_t *portobj; 6226 const cfg_obj_t *addresses; 6227 const cfg_listelt_t *element; 6228 isc_result_t result = ISC_R_SUCCESS; 6229 in_port_t port; 6230 6231 /* 6232 * Determine which port to send requests to. 6233 */ 6234 CHECKM(named_config_getport(config, "port", &port), "port"); 6235 6236 if (alternates != NULL) { 6237 portobj = cfg_tuple_get(alternates, "port"); 6238 if (cfg_obj_isuint32(portobj)) { 6239 uint32_t val = cfg_obj_asuint32(portobj); 6240 if (val > UINT16_MAX) { 6241 cfg_obj_log(portobj, named_g_lctx, 6242 ISC_LOG_ERROR, 6243 "port '%u' out of range", val); 6244 return ISC_R_RANGE; 6245 } 6246 port = (in_port_t)val; 6247 } 6248 } 6249 6250 addresses = NULL; 6251 if (alternates != NULL) { 6252 addresses = cfg_tuple_get(alternates, "addresses"); 6253 } 6254 6255 for (element = cfg_list_first(addresses); element != NULL; 6256 element = cfg_list_next(element)) 6257 { 6258 const cfg_obj_t *alternate = cfg_listelt_value(element); 6259 isc_sockaddr_t sa; 6260 6261 if (!cfg_obj_issockaddr(alternate)) { 6262 dns_fixedname_t fixed; 6263 dns_name_t *name; 6264 const char *str = cfg_obj_asstring( 6265 cfg_tuple_get(alternate, "name")); 6266 isc_buffer_t buffer; 6267 in_port_t myport = port; 6268 6269 isc_buffer_constinit(&buffer, str, strlen(str)); 6270 isc_buffer_add(&buffer, strlen(str)); 6271 name = dns_fixedname_initname(&fixed); 6272 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, 6273 NULL)); 6274 6275 portobj = cfg_tuple_get(alternate, "port"); 6276 if (cfg_obj_isuint32(portobj)) { 6277 uint32_t val = cfg_obj_asuint32(portobj); 6278 if (val > UINT16_MAX) { 6279 cfg_obj_log(portobj, named_g_lctx, 6280 ISC_LOG_ERROR, 6281 "port '%u' out of range", 6282 val); 6283 return ISC_R_RANGE; 6284 } 6285 myport = (in_port_t)val; 6286 } 6287 dns_resolver_addalternate(view->resolver, NULL, name, 6288 myport); 6289 continue; 6290 } 6291 6292 sa = *cfg_obj_assockaddr(alternate); 6293 if (isc_sockaddr_getport(&sa) == 0) { 6294 isc_sockaddr_setport(&sa, port); 6295 } 6296 dns_resolver_addalternate(view->resolver, &sa, NULL, 0); 6297 } 6298 6299 cleanup: 6300 return result; 6301 } 6302 6303 static isc_result_t 6304 validate_tls(const cfg_obj_t *config, dns_view_t *view, const cfg_obj_t *obj, 6305 isc_log_t *logctx, const char *str, dns_name_t **name) { 6306 dns_fixedname_t fname; 6307 dns_name_t *nm = dns_fixedname_initname(&fname); 6308 isc_result_t result = dns_name_fromstring(nm, str, dns_rootname, 0, 6309 NULL); 6310 6311 if (result != ISC_R_SUCCESS) { 6312 cfg_obj_log(obj, logctx, ISC_LOG_ERROR, 6313 "'%s' is not a valid name", str); 6314 return result; 6315 } 6316 6317 if (strcasecmp(str, "ephemeral") != 0) { 6318 const cfg_obj_t *tlsmap = find_maplist(config, "tls", str); 6319 6320 if (tlsmap == NULL) { 6321 cfg_obj_log(obj, logctx, ISC_LOG_ERROR, 6322 "tls '%s' is not defined", str); 6323 return ISC_R_FAILURE; 6324 } 6325 } 6326 6327 if (name != NULL && *name == NULL) { 6328 *name = isc_mem_get(view->mctx, sizeof(dns_name_t)); 6329 dns_name_init(*name, NULL); 6330 dns_name_dup(nm, view->mctx, *name); 6331 } 6332 6333 return ISC_R_SUCCESS; 6334 } 6335 6336 static isc_result_t 6337 configure_forward(const cfg_obj_t *config, dns_view_t *view, 6338 const dns_name_t *origin, const cfg_obj_t *forwarders, 6339 const cfg_obj_t *forwardtype) { 6340 const cfg_obj_t *portobj = NULL; 6341 const cfg_obj_t *tlspobj = NULL; 6342 const cfg_obj_t *faddresses = NULL; 6343 const cfg_listelt_t *element = NULL; 6344 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 6345 dns_forwarderlist_t fwdlist; 6346 dns_forwarder_t *fwd = NULL; 6347 isc_result_t result; 6348 in_port_t port; 6349 in_port_t tls_port; 6350 const char *tls = NULL; 6351 6352 ISC_LIST_INIT(fwdlist); 6353 6354 /* 6355 * Determine which port to send forwarded requests to. 6356 */ 6357 CHECKM(named_config_getport(config, "port", &port), "port"); 6358 CHECKM(named_config_getport(config, "tls-port", &tls_port), "tls-port"); 6359 6360 if (forwarders != NULL) { 6361 portobj = cfg_tuple_get(forwarders, "port"); 6362 if (cfg_obj_isuint32(portobj)) { 6363 uint32_t val = cfg_obj_asuint32(portobj); 6364 if (val > UINT16_MAX) { 6365 cfg_obj_log(portobj, named_g_lctx, 6366 ISC_LOG_ERROR, 6367 "port '%u' out of range", val); 6368 return ISC_R_RANGE; 6369 } 6370 port = tls_port = (in_port_t)val; 6371 } 6372 } 6373 6374 /* 6375 * TLS value for forwarded requests. 6376 */ 6377 if (forwarders != NULL) { 6378 tlspobj = cfg_tuple_get(forwarders, "tls"); 6379 if (cfg_obj_isstring(tlspobj)) { 6380 tls = cfg_obj_asstring(tlspobj); 6381 if (tls != NULL) { 6382 result = validate_tls(config, view, tlspobj, 6383 named_g_lctx, tls, NULL); 6384 if (result != ISC_R_SUCCESS) { 6385 return result; 6386 } 6387 } 6388 } 6389 } 6390 6391 faddresses = NULL; 6392 if (forwarders != NULL) { 6393 faddresses = cfg_tuple_get(forwarders, "addresses"); 6394 } 6395 6396 for (element = cfg_list_first(faddresses); element != NULL; 6397 element = cfg_list_next(element)) 6398 { 6399 const cfg_obj_t *forwarder = cfg_listelt_value(element); 6400 const char *cur_tls = NULL; 6401 6402 fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t)); 6403 fwd->tlsname = NULL; 6404 cur_tls = cfg_obj_getsockaddrtls(forwarder); 6405 if (cur_tls == NULL) { 6406 cur_tls = tls; 6407 } 6408 if (cur_tls != NULL) { 6409 result = validate_tls(config, view, faddresses, 6410 named_g_lctx, cur_tls, 6411 &fwd->tlsname); 6412 if (result != ISC_R_SUCCESS) { 6413 isc_mem_put(view->mctx, fwd, 6414 sizeof(dns_forwarder_t)); 6415 goto cleanup; 6416 } 6417 } 6418 fwd->addr = *cfg_obj_assockaddr(forwarder); 6419 if (isc_sockaddr_getport(&fwd->addr) == 0) { 6420 isc_sockaddr_setport(&fwd->addr, 6421 cur_tls != NULL ? tls_port : port); 6422 } 6423 ISC_LINK_INIT(fwd, link); 6424 ISC_LIST_APPEND(fwdlist, fwd, link); 6425 } 6426 6427 if (ISC_LIST_EMPTY(fwdlist)) { 6428 if (forwardtype != NULL) { 6429 cfg_obj_log(forwardtype, named_g_lctx, ISC_LOG_WARNING, 6430 "no forwarders seen; disabling " 6431 "forwarding"); 6432 } 6433 fwdpolicy = dns_fwdpolicy_none; 6434 } else { 6435 if (forwardtype == NULL) { 6436 fwdpolicy = dns_fwdpolicy_first; 6437 } else { 6438 const char *forwardstr = cfg_obj_asstring(forwardtype); 6439 if (strcasecmp(forwardstr, "first") == 0) { 6440 fwdpolicy = dns_fwdpolicy_first; 6441 } else if (strcasecmp(forwardstr, "only") == 0) { 6442 fwdpolicy = dns_fwdpolicy_only; 6443 } else { 6444 UNREACHABLE(); 6445 } 6446 } 6447 } 6448 6449 result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist, 6450 fwdpolicy); 6451 if (result != ISC_R_SUCCESS) { 6452 char namebuf[DNS_NAME_FORMATSIZE]; 6453 dns_name_format(origin, namebuf, sizeof(namebuf)); 6454 cfg_obj_log(forwarders, named_g_lctx, ISC_LOG_WARNING, 6455 "could not set up forwarding for domain '%s': %s", 6456 namebuf, isc_result_totext(result)); 6457 goto cleanup; 6458 } 6459 6460 if (fwdpolicy == dns_fwdpolicy_only) { 6461 dns_view_sfd_add(view, origin); 6462 } 6463 6464 result = ISC_R_SUCCESS; 6465 6466 cleanup: 6467 6468 while (!ISC_LIST_EMPTY(fwdlist)) { 6469 fwd = ISC_LIST_HEAD(fwdlist); 6470 ISC_LIST_UNLINK(fwdlist, fwd, link); 6471 if (fwd->tlsname != NULL) { 6472 dns_name_free(fwd->tlsname, view->mctx); 6473 isc_mem_put(view->mctx, fwd->tlsname, 6474 sizeof(dns_name_t)); 6475 } 6476 isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t)); 6477 } 6478 6479 return result; 6480 } 6481 6482 static isc_result_t 6483 get_viewinfo(const cfg_obj_t *vconfig, const char **namep, 6484 dns_rdataclass_t *classp) { 6485 isc_result_t result = ISC_R_SUCCESS; 6486 const char *viewname; 6487 dns_rdataclass_t viewclass; 6488 6489 REQUIRE(namep != NULL && *namep == NULL); 6490 REQUIRE(classp != NULL); 6491 6492 if (vconfig != NULL) { 6493 const cfg_obj_t *classobj = NULL; 6494 6495 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 6496 classobj = cfg_tuple_get(vconfig, "class"); 6497 CHECK(named_config_getclass(classobj, dns_rdataclass_in, 6498 &viewclass)); 6499 if (dns_rdataclass_ismeta(viewclass)) { 6500 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6501 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6502 "view '%s': class must not be meta", 6503 viewname); 6504 CHECK(ISC_R_FAILURE); 6505 } 6506 } else { 6507 viewname = "_default"; 6508 viewclass = dns_rdataclass_in; 6509 } 6510 6511 *namep = viewname; 6512 *classp = viewclass; 6513 6514 cleanup: 6515 return result; 6516 } 6517 6518 /* 6519 * Find a view based on its configuration info and attach to it. 6520 * 6521 * If 'vconfig' is NULL, attach to the default view. 6522 */ 6523 static isc_result_t 6524 find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 6525 dns_view_t **viewp) { 6526 isc_result_t result; 6527 const char *viewname = NULL; 6528 dns_rdataclass_t viewclass; 6529 dns_view_t *view = NULL; 6530 6531 result = get_viewinfo(vconfig, &viewname, &viewclass); 6532 if (result != ISC_R_SUCCESS) { 6533 return result; 6534 } 6535 6536 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 6537 if (result != ISC_R_SUCCESS) { 6538 return result; 6539 } 6540 6541 *viewp = view; 6542 return ISC_R_SUCCESS; 6543 } 6544 6545 /* 6546 * Create a new view and add it to the list. 6547 * 6548 * If 'vconfig' is NULL, create the default view. 6549 * 6550 * The view created is attached to '*viewp'. 6551 */ 6552 static isc_result_t 6553 create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 6554 dns_view_t **viewp) { 6555 isc_result_t result; 6556 const char *viewname = NULL; 6557 dns_rdataclass_t viewclass; 6558 dns_view_t *view = NULL; 6559 6560 result = get_viewinfo(vconfig, &viewname, &viewclass); 6561 if (result != ISC_R_SUCCESS) { 6562 return result; 6563 } 6564 6565 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 6566 if (result == ISC_R_SUCCESS) { 6567 return ISC_R_EXISTS; 6568 } 6569 if (result != ISC_R_NOTFOUND) { 6570 return result; 6571 } 6572 INSIST(view == NULL); 6573 6574 result = dns_view_create(named_g_mctx, named_g_loopmgr, 6575 named_g_dispatchmgr, viewclass, viewname, 6576 &view); 6577 if (result != ISC_R_SUCCESS) { 6578 return result; 6579 } 6580 6581 isc_nonce_buf(view->secret, sizeof(view->secret)); 6582 6583 ISC_LIST_APPEND(*viewlist, view, link); 6584 dns_view_attach(view, viewp); 6585 return ISC_R_SUCCESS; 6586 } 6587 6588 /* 6589 * Configure or reconfigure a zone. 6590 */ 6591 static isc_result_t 6592 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 6593 const cfg_obj_t *vconfig, dns_view_t *view, 6594 dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, 6595 dns_keystorelist_t *keystores, cfg_aclconfctx_t *aclconf, 6596 bool added, bool old_rpz_ok, bool is_catz_member, bool modify) { 6597 dns_view_t *pview = NULL; /* Production view */ 6598 dns_zone_t *zone = NULL; /* New or reused zone */ 6599 dns_zone_t *raw = NULL; /* New or reused raw zone */ 6600 dns_zone_t *dupzone = NULL; 6601 const cfg_obj_t *options = NULL; 6602 const cfg_obj_t *zoptions = NULL; 6603 const cfg_obj_t *typeobj = NULL; 6604 const cfg_obj_t *forwarders = NULL; 6605 const cfg_obj_t *forwardtype = NULL; 6606 const cfg_obj_t *ixfrfromdiffs = NULL; 6607 const cfg_obj_t *viewobj = NULL; 6608 isc_result_t result = ISC_R_SUCCESS; 6609 isc_result_t tresult; 6610 isc_buffer_t buffer; 6611 dns_fixedname_t fixorigin; 6612 dns_name_t *origin; 6613 const char *zname; 6614 dns_rdataclass_t zclass; 6615 const char *ztypestr; 6616 dns_rpz_num_t rpz_num; 6617 bool zone_is_catz = false; 6618 bool zone_maybe_inline = false; 6619 bool inline_signing = false; 6620 bool fullsign = false; 6621 6622 options = NULL; 6623 (void)cfg_map_get(config, "options", &options); 6624 6625 zoptions = cfg_tuple_get(zconfig, "options"); 6626 6627 /* 6628 * Get the zone origin as a dns_name_t. 6629 */ 6630 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 6631 isc_buffer_constinit(&buffer, zname, strlen(zname)); 6632 isc_buffer_add(&buffer, strlen(zname)); 6633 dns_fixedname_init(&fixorigin); 6634 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, 6635 dns_rootname, 0, NULL)); 6636 origin = dns_fixedname_name(&fixorigin); 6637 6638 CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"), 6639 view->rdclass, &zclass)); 6640 if (zclass != view->rdclass) { 6641 const char *vname = NULL; 6642 if (vconfig != NULL) { 6643 vname = cfg_obj_asstring( 6644 cfg_tuple_get(vconfig, "name")); 6645 } else { 6646 vname = "<default view>"; 6647 } 6648 6649 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6650 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6651 "zone '%s': wrong class for view '%s'", zname, 6652 vname); 6653 result = ISC_R_FAILURE; 6654 goto cleanup; 6655 } 6656 6657 (void)cfg_map_get(zoptions, "in-view", &viewobj); 6658 if (viewobj != NULL) { 6659 const char *inview = cfg_obj_asstring(viewobj); 6660 dns_view_t *otherview = NULL; 6661 6662 if (viewlist == NULL) { 6663 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6664 "'in-view' option is not permitted in " 6665 "dynamically added zones"); 6666 result = ISC_R_FAILURE; 6667 goto cleanup; 6668 } 6669 6670 result = dns_viewlist_find(viewlist, inview, view->rdclass, 6671 &otherview); 6672 if (result != ISC_R_SUCCESS) { 6673 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6674 "view '%s' is not yet defined.", inview); 6675 result = ISC_R_FAILURE; 6676 goto cleanup; 6677 } 6678 6679 result = dns_view_findzone(otherview, origin, DNS_ZTFIND_EXACT, 6680 &zone); 6681 dns_view_detach(&otherview); 6682 if (result != ISC_R_SUCCESS) { 6683 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6684 "zone '%s' not defined in view '%s'", zname, 6685 inview); 6686 result = ISC_R_FAILURE; 6687 goto cleanup; 6688 } 6689 6690 CHECK(dns_view_addzone(view, zone)); 6691 dns_zone_detach(&zone); 6692 6693 /* 6694 * If the zone contains a 'forwarders' statement, configure 6695 * selective forwarding. Note: this is not inherited from the 6696 * other view. 6697 */ 6698 forwarders = NULL; 6699 result = cfg_map_get(zoptions, "forwarders", &forwarders); 6700 if (result == ISC_R_SUCCESS) { 6701 forwardtype = NULL; 6702 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6703 CHECK(configure_forward(config, view, origin, 6704 forwarders, forwardtype)); 6705 } 6706 result = ISC_R_SUCCESS; 6707 goto cleanup; 6708 } 6709 6710 (void)cfg_map_get(zoptions, "type", &typeobj); 6711 if (typeobj == NULL) { 6712 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6713 "zone '%s' 'type' not specified", zname); 6714 result = ISC_R_FAILURE; 6715 goto cleanup; 6716 } 6717 ztypestr = cfg_obj_asstring(typeobj); 6718 6719 /* 6720 * "hints zones" aren't zones. If we've got one, 6721 * configure it and return. 6722 */ 6723 if (strcasecmp(ztypestr, "hint") == 0) { 6724 const cfg_obj_t *fileobj = NULL; 6725 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { 6726 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6727 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6728 "zone '%s': 'file' not specified", zname); 6729 result = ISC_R_FAILURE; 6730 goto cleanup; 6731 } 6732 if (dns_name_equal(origin, dns_rootname)) { 6733 const char *hintsfile = cfg_obj_asstring(fileobj); 6734 6735 CHECK(configure_hints(view, hintsfile)); 6736 } else { 6737 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6738 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 6739 "ignoring non-root hint zone '%s'", 6740 zname); 6741 result = ISC_R_SUCCESS; 6742 } 6743 /* Skip ordinary zone processing. */ 6744 goto cleanup; 6745 } 6746 6747 /* 6748 * "forward zones" aren't zones either. Translate this syntax into 6749 * the appropriate selective forwarding configuration and return. 6750 */ 6751 if (strcasecmp(ztypestr, "forward") == 0) { 6752 forwardtype = NULL; 6753 forwarders = NULL; 6754 6755 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6756 (void)cfg_map_get(zoptions, "forwarders", &forwarders); 6757 CHECK(configure_forward(config, view, origin, forwarders, 6758 forwardtype)); 6759 goto cleanup; 6760 } 6761 6762 /* 6763 * Redirect zones only require minimal configuration. 6764 */ 6765 if (strcasecmp(ztypestr, "redirect") == 0) { 6766 if (view->redirect != NULL) { 6767 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6768 "redirect zone already exists"); 6769 result = ISC_R_EXISTS; 6770 goto cleanup; 6771 } 6772 result = dns_viewlist_find(viewlist, view->name, view->rdclass, 6773 &pview); 6774 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6775 goto cleanup; 6776 } 6777 if (pview != NULL && pview->redirect != NULL) { 6778 dns_zone_attach(pview->redirect, &zone); 6779 dns_zone_setview(zone, view); 6780 } else { 6781 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, 6782 &zone)); 6783 CHECK(dns_zone_setorigin(zone, origin)); 6784 dns_zone_setview(zone, view); 6785 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, 6786 zone)); 6787 dns_zone_setstats(zone, named_g_server->zonestats); 6788 } 6789 CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, 6790 kasplist, keystores, zone, NULL)); 6791 dns_zone_attach(zone, &view->redirect); 6792 goto cleanup; 6793 } 6794 6795 if (!modify) { 6796 /* 6797 * Check for duplicates in the new zone table. 6798 */ 6799 result = dns_view_findzone(view, origin, DNS_ZTFIND_EXACT, 6800 &dupzone); 6801 if (result == ISC_R_SUCCESS) { 6802 /* 6803 * We already have this zone! 6804 */ 6805 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6806 "zone '%s' already exists", zname); 6807 dns_zone_detach(&dupzone); 6808 result = ISC_R_EXISTS; 6809 goto cleanup; 6810 } 6811 INSIST(dupzone == NULL); 6812 } 6813 6814 /* 6815 * Note whether this is a response policy zone and which one if so, 6816 * unless we are using RPZ service interface. In that case, the 6817 * BIND zone database has nothing to do with rpz and so we don't care. 6818 */ 6819 for (rpz_num = 0;; ++rpz_num) { 6820 if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones || 6821 view->rpzs->p.dnsrps_enabled) 6822 { 6823 rpz_num = DNS_RPZ_INVALID_NUM; 6824 break; 6825 } 6826 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin)) 6827 { 6828 break; 6829 } 6830 } 6831 6832 if (!is_catz_member && view->catzs != NULL && 6833 dns_catz_zone_get(view->catzs, origin) != NULL) 6834 { 6835 zone_is_catz = true; 6836 } 6837 6838 /* 6839 * See if we can reuse an existing zone. This is 6840 * only possible if all of these are true: 6841 * - The zone's view exists 6842 * - A zone with the right name exists in the view 6843 * - The zone is compatible with the config 6844 * options (e.g., an existing primary zone cannot 6845 * be reused if the options specify a secondary zone) 6846 * - The zone was not and is still not a response policy zone 6847 * or the zone is a policy zone with an unchanged number 6848 * and we are using the old policy zone summary data. 6849 */ 6850 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 6851 view->rdclass, &pview); 6852 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6853 goto cleanup; 6854 } 6855 if (pview != NULL) { 6856 result = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, 6857 &zone); 6858 } 6859 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6860 goto cleanup; 6861 } 6862 6863 if (zone != NULL && 6864 !named_zone_reusable(zone, zconfig, vconfig, config, kasplist)) 6865 { 6866 dns_zone_detach(&zone); 6867 fullsign = true; 6868 } 6869 6870 if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) || 6871 (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok))) 6872 { 6873 dns_zone_detach(&zone); 6874 } 6875 6876 if (zone != NULL) { 6877 /* 6878 * We found a reusable zone. Make it use the 6879 * new view. 6880 */ 6881 dns_zone_setview(zone, view); 6882 } else { 6883 /* 6884 * We cannot reuse an existing zone, we have 6885 * to create a new one. 6886 */ 6887 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 6888 CHECK(dns_zone_setorigin(zone, origin)); 6889 dns_zone_setview(zone, view); 6890 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 6891 dns_zone_setstats(zone, named_g_server->zonestats); 6892 } 6893 if (rpz_num != DNS_RPZ_INVALID_NUM) { 6894 result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num); 6895 if (result != ISC_R_SUCCESS) { 6896 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6897 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6898 "zone '%s': incompatible" 6899 " masterfile-format or database" 6900 " for a response policy zone", 6901 zname); 6902 goto cleanup; 6903 } 6904 } 6905 6906 if (zone_is_catz) { 6907 dns_zone_catz_enable(zone, view->catzs); 6908 } else if (dns_zone_catz_is_enabled(zone)) { 6909 dns_zone_catz_disable(zone); 6910 } 6911 6912 /* 6913 * If the zone contains a 'forwarders' statement, configure 6914 * selective forwarding. 6915 */ 6916 forwarders = NULL; 6917 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) { 6918 forwardtype = NULL; 6919 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6920 CHECK(configure_forward(config, view, origin, forwarders, 6921 forwardtype)); 6922 } 6923 6924 /* 6925 * Mark whether the zone was originally added at runtime or not 6926 */ 6927 dns_zone_setadded(zone, added); 6928 6929 /* 6930 * Determine if we need to set up inline signing. 6931 */ 6932 zone_maybe_inline = (strcasecmp(ztypestr, "primary") == 0 || 6933 strcasecmp(ztypestr, "master") == 0 || 6934 strcasecmp(ztypestr, "secondary") == 0 || 6935 strcasecmp(ztypestr, "slave") == 0); 6936 6937 if (zone_maybe_inline) { 6938 inline_signing = named_zone_inlinesigning(zconfig, vconfig, 6939 config, kasplist); 6940 } 6941 if (inline_signing) { 6942 dns_zone_getraw(zone, &raw); 6943 if (raw == NULL) { 6944 dns_zone_create(&raw, dns_zone_getmem(zone), 6945 dns_zone_gettid(zone)); 6946 CHECK(dns_zone_setorigin(raw, origin)); 6947 dns_zone_setview(raw, view); 6948 dns_zone_setstats(raw, named_g_server->zonestats); 6949 CHECK(dns_zone_link(zone, raw)); 6950 } 6951 if (cfg_map_get(zoptions, "ixfr-from-differences", 6952 &ixfrfromdiffs) == ISC_R_SUCCESS) 6953 { 6954 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6955 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 6956 "zone '%s': 'ixfr-from-differences' is " 6957 "ignored for inline-signed zones", 6958 zname); 6959 } 6960 } 6961 6962 /* 6963 * Configure the zone. 6964 */ 6965 CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, kasplist, 6966 keystores, zone, raw)); 6967 6968 /* 6969 * Add the zone to its view in the new view list. 6970 */ 6971 if (!modify) { 6972 CHECK(dns_view_addzone(view, zone)); 6973 } 6974 6975 if (zone_is_catz) { 6976 /* 6977 * force catz reload if the zone is loaded; 6978 * if it's not it'll get reloaded on zone load 6979 */ 6980 dns_db_t *db = NULL; 6981 6982 tresult = dns_zone_getdb(zone, &db); 6983 if (tresult == ISC_R_SUCCESS) { 6984 dns_catz_dbupdate_callback(db, view->catzs); 6985 dns_db_detach(&db); 6986 } 6987 } 6988 6989 /* 6990 * Ensure that zone keys are reloaded on reconfig 6991 */ 6992 if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0) { 6993 dns_zone_rekey(zone, fullsign); 6994 } 6995 6996 cleanup: 6997 if (zone != NULL) { 6998 dns_zone_detach(&zone); 6999 } 7000 if (raw != NULL) { 7001 dns_zone_detach(&raw); 7002 } 7003 if (pview != NULL) { 7004 dns_view_detach(&pview); 7005 } 7006 7007 return result; 7008 } 7009 7010 /* 7011 * Configure built-in zone for storing managed-key data. 7012 */ 7013 static isc_result_t 7014 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { 7015 isc_result_t result; 7016 dns_view_t *pview = NULL; 7017 dns_zone_t *zone = NULL; 7018 dns_acl_t *none = NULL; 7019 char filename[PATH_MAX]; 7020 bool defaultview; 7021 7022 REQUIRE(view != NULL); 7023 7024 /* See if we can re-use an existing keydata zone. */ 7025 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 7026 view->rdclass, &pview); 7027 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 7028 return result; 7029 } 7030 7031 if (pview != NULL) { 7032 if (pview->managed_keys != NULL) { 7033 dns_zone_attach(pview->managed_keys, 7034 &view->managed_keys); 7035 dns_zone_setview(pview->managed_keys, view); 7036 dns_zone_setviewcommit(pview->managed_keys); 7037 dns_view_detach(&pview); 7038 dns_zone_synckeyzone(view->managed_keys); 7039 return ISC_R_SUCCESS; 7040 } 7041 7042 dns_view_detach(&pview); 7043 } 7044 7045 /* No existing keydata zone was found; create one */ 7046 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 7047 CHECK(dns_zone_setorigin(zone, dns_rootname)); 7048 7049 defaultview = (strcmp(view->name, "_default") == 0); 7050 CHECK(isc_file_sanitize( 7051 directory, defaultview ? "managed-keys" : view->name, 7052 defaultview ? "bind" : "mkeys", filename, sizeof(filename))); 7053 CHECK(dns_zone_setfile(zone, filename, dns_masterformat_text, 7054 &dns_master_style_default)); 7055 7056 dns_zone_setview(zone, view); 7057 dns_zone_settype(zone, dns_zone_key); 7058 dns_zone_setclass(zone, view->rdclass); 7059 7060 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 7061 7062 CHECK(dns_acl_none(mctx, &none)); 7063 dns_zone_setqueryacl(zone, none); 7064 dns_zone_setqueryonacl(zone, none); 7065 dns_acl_detach(&none); 7066 7067 dns_zone_setdialup(zone, dns_dialuptype_no); 7068 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 7069 dns_zone_setnotifytype(zone, dns_notifytype_no); 7070 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 7071 dns_zone_setjournalsize(zone, 0); 7072 7073 dns_zone_setstats(zone, named_g_server->zonestats); 7074 setquerystats(zone, mctx, dns_zonestat_none); 7075 7076 if (view->managed_keys != NULL) { 7077 dns_zone_detach(&view->managed_keys); 7078 } 7079 dns_zone_attach(zone, &view->managed_keys); 7080 7081 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7082 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7083 "set up managed keys zone for view %s, file '%s'", 7084 view->name, filename); 7085 7086 cleanup: 7087 if (zone != NULL) { 7088 dns_zone_detach(&zone); 7089 } 7090 if (none != NULL) { 7091 dns_acl_detach(&none); 7092 } 7093 7094 return result; 7095 } 7096 7097 /* 7098 * Configure a single server quota. 7099 */ 7100 static void 7101 configure_server_quota(const cfg_obj_t **maps, const char *name, 7102 isc_quota_t *quota) { 7103 const cfg_obj_t *obj = NULL; 7104 isc_result_t result; 7105 7106 result = named_config_get(maps, name, &obj); 7107 INSIST(result == ISC_R_SUCCESS); 7108 isc_quota_max(quota, cfg_obj_asuint32(obj)); 7109 } 7110 7111 /* 7112 * This function is called as soon as the 'directory' statement has been 7113 * parsed. This can be extended to support other options if necessary. 7114 */ 7115 static isc_result_t 7116 directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { 7117 isc_result_t result; 7118 const char *directory; 7119 7120 REQUIRE(strcasecmp("directory", clausename) == 0); 7121 7122 UNUSED(arg); 7123 UNUSED(clausename); 7124 7125 /* 7126 * Change directory. 7127 */ 7128 directory = cfg_obj_asstring(obj); 7129 7130 if (!isc_file_ischdiridempotent(directory)) { 7131 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 7132 "option 'directory' contains relative path '%s'", 7133 directory); 7134 } 7135 7136 if (!isc_file_isdirwritable(directory)) { 7137 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7138 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7139 "directory '%s' is not writable", directory); 7140 return ISC_R_NOPERM; 7141 } 7142 7143 result = isc_dir_chdir(directory); 7144 if (result != ISC_R_SUCCESS) { 7145 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7146 "change directory to '%s' failed: %s", directory, 7147 isc_result_totext(result)); 7148 return result; 7149 } 7150 7151 char cwd[PATH_MAX]; 7152 if (getcwd(cwd, sizeof(cwd)) == cwd) { 7153 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7154 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7155 "the working directory is now '%s'", cwd); 7156 } 7157 7158 return ISC_R_SUCCESS; 7159 } 7160 7161 /* 7162 * This event callback is invoked to do periodic network interface 7163 * scanning. 7164 */ 7165 7166 static void 7167 interface_timer_tick(void *arg) { 7168 named_server_t *server = (named_server_t *)arg; 7169 7170 (void)ns_interfacemgr_scan(server->interfacemgr, false, false); 7171 } 7172 7173 static void 7174 heartbeat_timer_tick(void *arg) { 7175 named_server_t *server = (named_server_t *)arg; 7176 dns_view_t *view = NULL; 7177 7178 view = ISC_LIST_HEAD(server->viewlist); 7179 while (view != NULL) { 7180 dns_view_dialup(view); 7181 view = ISC_LIST_NEXT(view, link); 7182 } 7183 } 7184 7185 typedef struct { 7186 isc_mem_t *mctx; 7187 isc_loop_t *loop; 7188 dns_fetch_t *fetch; 7189 dns_view_t *view; 7190 dns_fixedname_t tatname; 7191 dns_fixedname_t keyname; 7192 dns_rdataset_t rdataset; 7193 dns_rdataset_t sigrdataset; 7194 } ns_tat_t; 7195 7196 static int 7197 cid(const void *a, const void *b) { 7198 const uint16_t ida = *(const uint16_t *)a; 7199 const uint16_t idb = *(const uint16_t *)b; 7200 if (ida < idb) { 7201 return -1; 7202 } else if (ida > idb) { 7203 return 1; 7204 } else { 7205 return 0; 7206 } 7207 } 7208 7209 static void 7210 tat_done(void *arg) { 7211 dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg; 7212 ns_tat_t *tat = NULL; 7213 7214 INSIST(resp != NULL); 7215 7216 tat = resp->arg; 7217 7218 INSIST(tat != NULL); 7219 7220 /* Free resources which are not of interest */ 7221 if (resp->node != NULL) { 7222 dns_db_detachnode(resp->db, &resp->node); 7223 } 7224 if (resp->db != NULL) { 7225 dns_db_detach(&resp->db); 7226 } 7227 isc_mem_putanddetach(&resp->mctx, resp, sizeof(*resp)); 7228 dns_resolver_destroyfetch(&tat->fetch); 7229 if (dns_rdataset_isassociated(&tat->rdataset)) { 7230 dns_rdataset_disassociate(&tat->rdataset); 7231 } 7232 if (dns_rdataset_isassociated(&tat->sigrdataset)) { 7233 dns_rdataset_disassociate(&tat->sigrdataset); 7234 } 7235 dns_view_detach(&tat->view); 7236 isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); 7237 } 7238 7239 struct dotat_arg { 7240 dns_view_t *view; 7241 isc_loop_t *loop; 7242 }; 7243 7244 /*% 7245 * Prepare the QNAME for the TAT query to be sent by processing the trust 7246 * anchors present at 'keynode' of 'keytable'. Store the result in 'dst' and 7247 * the domain name which 'keynode' is associated with in 'origin'. 7248 * 7249 * A maximum of 12 key IDs can be reported in a single TAT query due to the 7250 * 63-octet length limit for any single label in a domain name. If there are 7251 * more than 12 keys configured at 'keynode', only the first 12 will be 7252 * reported in the TAT query. 7253 */ 7254 static isc_result_t 7255 get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) { 7256 dns_rdataset_t dsset; 7257 unsigned int i, n = 0; 7258 uint16_t ids[12]; 7259 isc_textregion_t r; 7260 char label[64]; 7261 int m; 7262 7263 dns_rdataset_init(&dsset); 7264 if (dns_keynode_dsset(keynode, &dsset)) { 7265 isc_result_t result; 7266 7267 for (result = dns_rdataset_first(&dsset); 7268 result == ISC_R_SUCCESS; 7269 result = dns_rdataset_next(&dsset)) 7270 { 7271 dns_rdata_t rdata = DNS_RDATA_INIT; 7272 dns_rdata_ds_t ds; 7273 7274 dns_rdata_reset(&rdata); 7275 dns_rdataset_current(&dsset, &rdata); 7276 result = dns_rdata_tostruct(&rdata, &ds, NULL); 7277 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7278 if (n < (sizeof(ids) / sizeof(ids[0]))) { 7279 ids[n] = ds.key_tag; 7280 n++; 7281 } 7282 } 7283 dns_rdataset_disassociate(&dsset); 7284 } 7285 7286 if (n == 0) { 7287 return DNS_R_EMPTYNAME; 7288 } 7289 7290 if (n > 1) { 7291 qsort(ids, n, sizeof(ids[0]), cid); 7292 } 7293 7294 /* 7295 * Encoded as "_ta-xxxx\(-xxxx\)*" where xxxx is the hex version of 7296 * of the keyid. 7297 */ 7298 label[0] = 0; 7299 r.base = label; 7300 r.length = sizeof(label); 7301 m = snprintf(r.base, r.length, "_ta"); 7302 if (m < 0 || (unsigned int)m > r.length) { 7303 return ISC_R_FAILURE; 7304 } 7305 isc_textregion_consume(&r, m); 7306 for (i = 0; i < n; i++) { 7307 m = snprintf(r.base, r.length, "-%04x", ids[i]); 7308 if (m < 0 || (unsigned int)m > r.length) { 7309 return ISC_R_FAILURE; 7310 } 7311 isc_textregion_consume(&r, m); 7312 } 7313 7314 return dns_name_fromstring(target, label, keyname, 0, NULL); 7315 } 7316 7317 static void 7318 tat_send(void *arg) { 7319 ns_tat_t *tat = (ns_tat_t *)arg; 7320 char namebuf[DNS_NAME_FORMATSIZE]; 7321 dns_fixedname_t fdomain; 7322 dns_name_t *domain = NULL; 7323 dns_rdataset_t nameservers; 7324 isc_result_t result; 7325 dns_name_t *keyname = NULL; 7326 dns_name_t *tatname = NULL; 7327 7328 keyname = dns_fixedname_name(&tat->keyname); 7329 tatname = dns_fixedname_name(&tat->tatname); 7330 7331 dns_name_format(tatname, namebuf, sizeof(namebuf)); 7332 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7333 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7334 "%s: sending trust-anchor-telemetry query '%s/NULL'", 7335 tat->view->name, namebuf); 7336 7337 /* 7338 * TAT queries should be sent to the authoritative servers for a given 7339 * zone. If this function is called for a keytable node corresponding 7340 * to a locally served zone, calling dns_resolver_createfetch() with 7341 * NULL 'domain' and 'nameservers' arguments will cause 'tatname' to be 7342 * resolved locally, without sending any TAT queries upstream. 7343 * 7344 * Work around this issue by calling dns_view_findzonecut() first. If 7345 * the zone is served locally, the NS RRset for the given domain name 7346 * will be retrieved from local data; if it is not, the deepest zone 7347 * cut we have for it will be retrieved from cache. In either case, 7348 * passing the results to dns_resolver_createfetch() will prevent it 7349 * from returning NXDOMAIN for 'tatname' while still allowing it to 7350 * chase down any potential delegations returned by upstream servers in 7351 * order to eventually find the destination host to send the TAT query 7352 * to. 7353 * 7354 * After the dns_view_findzonecut() call, 'domain' will hold the 7355 * deepest zone cut we can find for 'keyname' while 'nameservers' will 7356 * hold the NS RRset at that zone cut. 7357 */ 7358 domain = dns_fixedname_initname(&fdomain); 7359 dns_rdataset_init(&nameservers); 7360 result = dns_view_findzonecut(tat->view, keyname, domain, NULL, 0, 0, 7361 true, true, &nameservers, NULL); 7362 if (result == ISC_R_SUCCESS) { 7363 result = dns_resolver_createfetch( 7364 tat->view->resolver, tatname, dns_rdatatype_null, 7365 domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, 7366 tat->loop, tat_done, tat, &tat->rdataset, 7367 &tat->sigrdataset, &tat->fetch); 7368 } 7369 7370 /* 7371 * 'domain' holds the dns_name_t pointer inside a dst_key_t structure. 7372 * dns_resolver_createfetch() creates its own copy of 'domain' if it 7373 * succeeds. Thus, 'domain' is not freed here. 7374 * 7375 * Even if dns_view_findzonecut() returned something else than 7376 * ISC_R_SUCCESS, it still could have associated 'nameservers'. 7377 * dns_resolver_createfetch() creates its own copy of 'nameservers' if 7378 * it succeeds. Thus, we need to check whether 'nameservers' is 7379 * associated and release it if it is. 7380 */ 7381 if (dns_rdataset_isassociated(&nameservers)) { 7382 dns_rdataset_disassociate(&nameservers); 7383 } 7384 7385 if (result != ISC_R_SUCCESS) { 7386 dns_view_detach(&tat->view); 7387 isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); 7388 } 7389 } 7390 7391 static void 7392 dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, dns_name_t *keyname, 7393 void *arg) { 7394 struct dotat_arg *dotat_arg = (struct dotat_arg *)arg; 7395 isc_result_t result; 7396 dns_view_t *view = NULL; 7397 ns_tat_t *tat = NULL; 7398 7399 REQUIRE(keytable != NULL); 7400 REQUIRE(keynode != NULL); 7401 REQUIRE(dotat_arg != NULL); 7402 7403 view = dotat_arg->view; 7404 7405 tat = isc_mem_get(view->mctx, sizeof(*tat)); 7406 *tat = (ns_tat_t){ 0 }; 7407 7408 dns_rdataset_init(&tat->rdataset); 7409 dns_rdataset_init(&tat->sigrdataset); 7410 dns_name_copy(keyname, dns_fixedname_initname(&tat->keyname)); 7411 result = get_tat_qname(dns_fixedname_initname(&tat->tatname), keyname, 7412 keynode); 7413 if (result != ISC_R_SUCCESS) { 7414 isc_mem_put(view->mctx, tat, sizeof(*tat)); 7415 return; 7416 } 7417 isc_mem_attach(view->mctx, &tat->mctx); 7418 tat->loop = dotat_arg->loop; 7419 dns_view_attach(view, &tat->view); 7420 7421 /* 7422 * We don't want to be holding the keytable lock when calling 7423 * dns_view_findzonecut() as it creates a lock order loop so 7424 * call dns_view_findzonecut() in a event handler. 7425 * 7426 * zone->lock (dns_zone_setviewcommit) while holding view->lock 7427 * (dns_view_setviewcommit) 7428 * 7429 * keytable->lock (dns_keytable_find) while holding zone->lock 7430 * (zone_asyncload) 7431 * 7432 * view->lock (dns_view_findzonecut) while holding keytable->lock 7433 * (dns_keytable_forall) 7434 */ 7435 isc_async_run(named_g_mainloop, tat_send, tat); 7436 } 7437 7438 static void 7439 tat_timer_tick(void *arg) { 7440 isc_result_t result; 7441 named_server_t *server = (named_server_t *)arg; 7442 struct dotat_arg dotat_arg = { 0 }; 7443 dns_view_t *view = NULL; 7444 dns_keytable_t *secroots = NULL; 7445 7446 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 7447 view = ISC_LIST_NEXT(view, link)) 7448 { 7449 if (!view->trust_anchor_telemetry || !view->enablevalidation) { 7450 continue; 7451 } 7452 7453 result = dns_view_getsecroots(view, &secroots); 7454 if (result != ISC_R_SUCCESS) { 7455 continue; 7456 } 7457 7458 dotat_arg.view = view; 7459 dotat_arg.loop = named_g_mainloop; 7460 dns_keytable_forall(secroots, dotat, &dotat_arg); 7461 dns_keytable_detach(&secroots); 7462 } 7463 } 7464 7465 static void 7466 pps_timer_tick(void *arg) { 7467 static unsigned int oldrequests = 0; 7468 unsigned int requests = atomic_load_relaxed(&ns_client_requests); 7469 7470 UNUSED(arg); 7471 7472 /* 7473 * Don't worry about wrapping as the overflow result will be right. 7474 */ 7475 dns_pps = (requests - oldrequests) / 1200; 7476 oldrequests = requests; 7477 } 7478 7479 /* 7480 * Replace the current value of '*field', a dynamically allocated 7481 * string or NULL, with a dynamically allocated copy of the 7482 * null-terminated string pointed to by 'value', or NULL. 7483 */ 7484 static void 7485 setstring(named_server_t *server, char **field, const char *value) { 7486 char *copy; 7487 7488 if (value != NULL) { 7489 copy = isc_mem_strdup(server->mctx, value); 7490 } else { 7491 copy = NULL; 7492 } 7493 7494 if (*field != NULL) { 7495 isc_mem_free(server->mctx, *field); 7496 } 7497 7498 *field = copy; 7499 } 7500 7501 /* 7502 * Replace the current value of '*field', a dynamically allocated 7503 * string or NULL, with another dynamically allocated string 7504 * or NULL if whether 'obj' is a string or void value, respectively. 7505 */ 7506 static void 7507 setoptstring(named_server_t *server, char **field, const cfg_obj_t *obj) { 7508 if (cfg_obj_isvoid(obj)) { 7509 setstring(server, field, NULL); 7510 } else { 7511 setstring(server, field, cfg_obj_asstring(obj)); 7512 } 7513 } 7514 7515 static void 7516 portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports, 7517 bool positive) { 7518 const cfg_listelt_t *element; 7519 7520 for (element = cfg_list_first(ports); element != NULL; 7521 element = cfg_list_next(element)) 7522 { 7523 const cfg_obj_t *obj = cfg_listelt_value(element); 7524 7525 if (cfg_obj_isuint32(obj)) { 7526 in_port_t port = (in_port_t)cfg_obj_asuint32(obj); 7527 7528 if (positive) { 7529 isc_portset_add(portset, port); 7530 } else { 7531 isc_portset_remove(portset, port); 7532 } 7533 } else { 7534 const cfg_obj_t *obj_loport, *obj_hiport; 7535 in_port_t loport, hiport; 7536 7537 obj_loport = cfg_tuple_get(obj, "loport"); 7538 loport = (in_port_t)cfg_obj_asuint32(obj_loport); 7539 obj_hiport = cfg_tuple_get(obj, "hiport"); 7540 hiport = (in_port_t)cfg_obj_asuint32(obj_hiport); 7541 7542 if (positive) { 7543 isc_portset_addrange(portset, loport, hiport); 7544 } else { 7545 isc_portset_removerange(portset, loport, 7546 hiport); 7547 } 7548 } 7549 } 7550 } 7551 7552 static isc_result_t 7553 removed(dns_zone_t *zone, void *uap) { 7554 if (dns_zone_getview(zone) != uap) { 7555 return ISC_R_SUCCESS; 7556 } 7557 7558 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", 7559 dns_zonetype_name(dns_zone_gettype(zone))); 7560 return ISC_R_SUCCESS; 7561 } 7562 7563 static void 7564 cleanup_session_key(named_server_t *server, isc_mem_t *mctx) { 7565 if (server->session_keyfile != NULL) { 7566 isc_file_remove(server->session_keyfile); 7567 isc_mem_free(mctx, server->session_keyfile); 7568 server->session_keyfile = NULL; 7569 } 7570 7571 if (server->session_keyname != NULL) { 7572 if (dns_name_dynamic(server->session_keyname)) { 7573 dns_name_free(server->session_keyname, mctx); 7574 } 7575 isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); 7576 server->session_keyname = NULL; 7577 } 7578 7579 if (server->sessionkey != NULL) { 7580 dst_key_free(&server->sessionkey); 7581 } 7582 7583 server->session_keyalg = DST_ALG_UNKNOWN; 7584 server->session_keybits = 0; 7585 } 7586 7587 static isc_result_t 7588 generate_session_key(const char *filename, const char *keynamestr, 7589 const dns_name_t *keyname, dst_algorithm_t alg, 7590 uint16_t bits, isc_mem_t *mctx, bool first_time, 7591 dst_key_t **keyp) { 7592 isc_result_t result = ISC_R_SUCCESS; 7593 dst_key_t *key = NULL; 7594 isc_buffer_t key_txtbuffer; 7595 isc_buffer_t key_rawbuffer; 7596 char key_txtsecret[256]; 7597 char key_rawsecret[64]; 7598 isc_region_t key_rawregion; 7599 FILE *fp = NULL; 7600 7601 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7602 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7603 "generating session key for dynamic DNS"); 7604 7605 /* generate key */ 7606 result = dst_key_generate(keyname, alg, bits, 1, 0, DNS_KEYPROTO_ANY, 7607 dns_rdataclass_in, NULL, mctx, &key, NULL); 7608 if (result != ISC_R_SUCCESS) { 7609 return result; 7610 } 7611 7612 /* 7613 * Dump the key to the buffer for later use. 7614 */ 7615 isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); 7616 CHECK(dst_key_tobuffer(key, &key_rawbuffer)); 7617 7618 isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); 7619 isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); 7620 CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); 7621 7622 /* Dump the key to the key file. */ 7623 fp = named_os_openfile(filename, S_IRUSR | S_IWUSR, first_time); 7624 if (fp == NULL) { 7625 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7626 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7627 "could not create %s", filename); 7628 result = ISC_R_NOPERM; 7629 goto cleanup; 7630 } 7631 7632 fprintf(fp, 7633 "key \"%s\" {\n" 7634 "\talgorithm %s;\n" 7635 "\tsecret \"%.*s\";\n};\n", 7636 keynamestr, dst_hmac_algorithm_totext(alg), 7637 (int)isc_buffer_usedlength(&key_txtbuffer), 7638 (char *)isc_buffer_base(&key_txtbuffer)); 7639 7640 CHECK(isc_stdio_flush(fp)); 7641 result = isc_stdio_close(fp); 7642 if (result != ISC_R_SUCCESS) { 7643 goto cleanup; 7644 } 7645 7646 *keyp = key; 7647 return ISC_R_SUCCESS; 7648 7649 cleanup: 7650 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7651 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7652 "failed to generate session key " 7653 "for dynamic DNS: %s", 7654 isc_result_totext(result)); 7655 if (fp != NULL) { 7656 (void)isc_stdio_close(fp); 7657 (void)isc_file_remove(filename); 7658 } 7659 if (key != NULL) { 7660 dst_key_free(&key); 7661 } 7662 7663 return result; 7664 } 7665 7666 static isc_result_t 7667 configure_session_key(const cfg_obj_t **maps, named_server_t *server, 7668 isc_mem_t *mctx, bool first_time) { 7669 const char *keyfile = NULL, *keynamestr = NULL, *algstr = NULL; 7670 unsigned int algtype; 7671 dns_fixedname_t fname; 7672 dns_name_t *keyname = NULL; 7673 isc_buffer_t buffer; 7674 uint16_t bits; 7675 const cfg_obj_t *obj = NULL; 7676 bool need_deleteold = false; 7677 bool need_createnew = false; 7678 isc_result_t result; 7679 7680 obj = NULL; 7681 result = named_config_get(maps, "session-keyfile", &obj); 7682 if (result == ISC_R_SUCCESS) { 7683 if (cfg_obj_isvoid(obj)) { 7684 keyfile = NULL; /* disable it */ 7685 } else { 7686 keyfile = cfg_obj_asstring(obj); 7687 } 7688 } else { 7689 keyfile = named_g_defaultsessionkeyfile; 7690 } 7691 7692 obj = NULL; 7693 result = named_config_get(maps, "session-keyname", &obj); 7694 INSIST(result == ISC_R_SUCCESS); 7695 keynamestr = cfg_obj_asstring(obj); 7696 isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr)); 7697 isc_buffer_add(&buffer, strlen(keynamestr)); 7698 keyname = dns_fixedname_initname(&fname); 7699 result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); 7700 if (result != ISC_R_SUCCESS) { 7701 return result; 7702 } 7703 7704 obj = NULL; 7705 result = named_config_get(maps, "session-keyalg", &obj); 7706 INSIST(result == ISC_R_SUCCESS); 7707 algstr = cfg_obj_asstring(obj); 7708 result = named_config_getkeyalgorithm(algstr, &algtype, &bits); 7709 if (result != ISC_R_SUCCESS) { 7710 const char *s = " (keeping current key)"; 7711 7712 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7713 "session-keyalg: " 7714 "unsupported or unknown algorithm '%s'%s", 7715 algstr, server->session_keyfile != NULL ? s : ""); 7716 return result; 7717 } 7718 7719 /* See if we need to (re)generate a new key. */ 7720 if (keyfile == NULL) { 7721 if (server->session_keyfile != NULL) { 7722 need_deleteold = true; 7723 } 7724 } else if (server->session_keyfile == NULL) { 7725 need_createnew = true; 7726 } else if (strcmp(keyfile, server->session_keyfile) != 0 || 7727 !dns_name_equal(server->session_keyname, keyname) || 7728 server->session_keyalg != algtype || 7729 server->session_keybits != bits) 7730 { 7731 need_deleteold = true; 7732 need_createnew = true; 7733 } 7734 7735 if (need_deleteold) { 7736 INSIST(server->session_keyfile != NULL); 7737 INSIST(server->session_keyname != NULL); 7738 INSIST(server->sessionkey != NULL); 7739 7740 cleanup_session_key(server, mctx); 7741 } 7742 7743 if (need_createnew) { 7744 INSIST(server->sessionkey == NULL); 7745 INSIST(server->session_keyfile == NULL); 7746 INSIST(server->session_keyname == NULL); 7747 INSIST(server->session_keyalg == DST_ALG_UNKNOWN); 7748 INSIST(server->session_keybits == 0); 7749 7750 server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); 7751 dns_name_init(server->session_keyname, NULL); 7752 dns_name_dup(keyname, mctx, server->session_keyname); 7753 7754 server->session_keyfile = isc_mem_strdup(mctx, keyfile); 7755 7756 server->session_keyalg = algtype; 7757 server->session_keybits = bits; 7758 7759 CHECK(generate_session_key(keyfile, keynamestr, keyname, 7760 algtype, bits, mctx, first_time, 7761 &server->sessionkey)); 7762 } 7763 7764 return result; 7765 7766 cleanup: 7767 cleanup_session_key(server, mctx); 7768 return result; 7769 } 7770 7771 static isc_result_t 7772 setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 7773 cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx) { 7774 isc_result_t result = ISC_R_SUCCESS; 7775 bool allow = false; 7776 ns_cfgctx_t *nzcfg = NULL; 7777 const cfg_obj_t *maps[4]; 7778 const cfg_obj_t *options = NULL, *voptions = NULL; 7779 const cfg_obj_t *nz = NULL; 7780 const cfg_obj_t *nzdir = NULL; 7781 const char *dir = NULL; 7782 const cfg_obj_t *obj = NULL; 7783 int i = 0; 7784 uint64_t mapsize = 0ULL; 7785 7786 REQUIRE(config != NULL); 7787 7788 if (vconfig != NULL) { 7789 voptions = cfg_tuple_get(vconfig, "options"); 7790 } 7791 if (voptions != NULL) { 7792 maps[i++] = voptions; 7793 } 7794 result = cfg_map_get(config, "options", &options); 7795 if (result == ISC_R_SUCCESS) { 7796 maps[i++] = options; 7797 } 7798 maps[i++] = named_g_defaults; 7799 maps[i] = NULL; 7800 7801 result = named_config_get(maps, "allow-new-zones", &nz); 7802 if (result == ISC_R_SUCCESS) { 7803 allow = cfg_obj_asboolean(nz); 7804 } 7805 result = named_config_get(maps, "new-zones-directory", &nzdir); 7806 if (result == ISC_R_SUCCESS) { 7807 dir = cfg_obj_asstring(nzdir); 7808 result = isc_file_isdirectory(dir); 7809 if (result != ISC_R_SUCCESS) { 7810 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 7811 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7812 "invalid new-zones-directory %s: %s", dir, 7813 isc_result_totext(result)); 7814 return result; 7815 } 7816 if (!isc_file_isdirwritable(dir)) { 7817 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7818 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7819 "new-zones-directory '%s' " 7820 "is not writable", 7821 dir); 7822 return ISC_R_NOPERM; 7823 } 7824 7825 dns_view_setnewzonedir(view, dir); 7826 } 7827 7828 #ifdef HAVE_LMDB 7829 result = named_config_get(maps, "lmdb-mapsize", &obj); 7830 if (result == ISC_R_SUCCESS && obj != NULL) { 7831 mapsize = cfg_obj_asuint64(obj); 7832 if (mapsize < (1ULL << 20)) { /* 1 megabyte */ 7833 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7834 "'lmdb-mapsize " 7835 "%" PRId64 "' " 7836 "is too small", 7837 mapsize); 7838 return ISC_R_FAILURE; 7839 } else if (mapsize > (1ULL << 40)) { /* 1 terabyte */ 7840 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7841 "'lmdb-mapsize " 7842 "%" PRId64 "' " 7843 "is too large", 7844 mapsize); 7845 return ISC_R_FAILURE; 7846 } 7847 } 7848 #else /* ifdef HAVE_LMDB */ 7849 UNUSED(obj); 7850 #endif /* HAVE_LMDB */ 7851 7852 /* 7853 * A non-empty catalog-zones statement implies allow-new-zones 7854 */ 7855 if (!allow) { 7856 const cfg_obj_t *cz = NULL; 7857 result = named_config_get(maps, "catalog-zones", &cz); 7858 if (result == ISC_R_SUCCESS) { 7859 const cfg_listelt_t *e = 7860 cfg_list_first(cfg_tuple_get(cz, "zone list")); 7861 if (e != NULL) { 7862 allow = true; 7863 } 7864 } 7865 } 7866 7867 if (!allow) { 7868 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 7869 return ISC_R_SUCCESS; 7870 } 7871 7872 nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg)); 7873 *nzcfg = (ns_cfgctx_t){ 0 }; 7874 7875 /* 7876 * We attach the parser that was used for config as well 7877 * as the one that will be used for added zones, to avoid 7878 * a shutdown race later. 7879 */ 7880 isc_mem_attach(view->mctx, &nzcfg->mctx); 7881 cfg_parser_attach(conf_parser, &nzcfg->conf_parser); 7882 cfg_parser_attach(named_g_addparser, &nzcfg->add_parser); 7883 cfg_aclconfctx_attach(actx, &nzcfg->actx); 7884 7885 result = dns_view_setnewzones(view, true, nzcfg, newzone_cfgctx_destroy, 7886 mapsize); 7887 if (result != ISC_R_SUCCESS) { 7888 cfg_aclconfctx_detach(&nzcfg->actx); 7889 cfg_parser_destroy(&nzcfg->add_parser); 7890 cfg_parser_destroy(&nzcfg->conf_parser); 7891 isc_mem_putanddetach(&nzcfg->mctx, nzcfg, sizeof(*nzcfg)); 7892 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 7893 return result; 7894 } 7895 7896 cfg_obj_attach(config, &nzcfg->config); 7897 if (vconfig != NULL) { 7898 cfg_obj_attach(vconfig, &nzcfg->vconfig); 7899 } 7900 7901 result = load_nzf(view, nzcfg); 7902 return result; 7903 } 7904 7905 static void 7906 configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, 7907 dns_view_t *view) { 7908 const char *zname; 7909 dns_fixedname_t fixorigin; 7910 dns_name_t *origin; 7911 isc_result_t result2; 7912 dns_view_t *pview = NULL; 7913 dns_zone_t *zone = NULL; 7914 7915 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 7916 origin = dns_fixedname_initname(&fixorigin); 7917 7918 result2 = dns_name_fromstring(origin, zname, dns_rootname, 0, NULL); 7919 if (result2 != ISC_R_SUCCESS) { 7920 return; 7921 } 7922 7923 result2 = dns_viewlist_find(&named_g_server->viewlist, view->name, 7924 view->rdclass, &pview); 7925 if (result2 != ISC_R_SUCCESS) { 7926 return; 7927 } 7928 7929 result2 = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, &zone); 7930 if (result2 != ISC_R_SUCCESS) { 7931 dns_view_detach(&pview); 7932 return; 7933 } 7934 7935 if (result == ISC_R_SUCCESS) { 7936 dns_zone_setviewcommit(zone); 7937 } else { 7938 dns_zone_setviewrevert(zone); 7939 } 7940 7941 dns_zone_detach(&zone); 7942 dns_view_detach(&pview); 7943 } 7944 7945 #ifndef HAVE_LMDB 7946 7947 static isc_result_t 7948 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 7949 cfg_aclconfctx_t *actx) { 7950 isc_result_t result; 7951 ns_cfgctx_t *nzctx; 7952 const cfg_obj_t *zonelist; 7953 const cfg_listelt_t *element; 7954 7955 nzctx = view->new_zone_config; 7956 if (nzctx == NULL || nzctx->nzf_config == NULL) { 7957 return ISC_R_SUCCESS; 7958 } 7959 7960 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7961 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7962 "loading additional zones for view '%s'", view->name); 7963 7964 zonelist = NULL; 7965 cfg_map_get(nzctx->nzf_config, "zone", &zonelist); 7966 7967 for (element = cfg_list_first(zonelist); element != NULL; 7968 element = cfg_list_next(element)) 7969 { 7970 const cfg_obj_t *zconfig = cfg_listelt_value(element); 7971 CHECK(configure_zone(config, zconfig, vconfig, view, 7972 &named_g_server->viewlist, 7973 &named_g_server->kasplist, 7974 &named_g_server->keystorelist, actx, true, 7975 false, false, false)); 7976 } 7977 7978 result = ISC_R_SUCCESS; 7979 7980 cleanup: 7981 for (element = cfg_list_first(zonelist); element != NULL; 7982 element = cfg_list_next(element)) 7983 { 7984 const cfg_obj_t *zconfig = cfg_listelt_value(element); 7985 configure_zone_setviewcommit(result, zconfig, view); 7986 } 7987 7988 return result; 7989 } 7990 7991 #else /* HAVE_LMDB */ 7992 7993 static isc_result_t 7994 data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, 7995 cfg_obj_t **zoneconfig) { 7996 isc_result_t result; 7997 const char *zone_name; 7998 size_t zone_name_len; 7999 const char *zone_config; 8000 size_t zone_config_len; 8001 cfg_obj_t *zoneconf = NULL; 8002 char bufname[DNS_NAME_FORMATSIZE]; 8003 8004 REQUIRE(view != NULL); 8005 REQUIRE(key != NULL); 8006 REQUIRE(data != NULL); 8007 REQUIRE(text != NULL); 8008 REQUIRE(zoneconfig != NULL && *zoneconfig == NULL); 8009 8010 if (*text == NULL) { 8011 isc_buffer_allocate(view->mctx, text, 256); 8012 } else { 8013 isc_buffer_clear(*text); 8014 } 8015 8016 zone_name = (const char *)key->mv_data; 8017 zone_name_len = key->mv_size; 8018 INSIST(zone_name != NULL && zone_name_len > 0); 8019 8020 zone_config = (const char *)data->mv_data; 8021 zone_config_len = data->mv_size; 8022 INSIST(zone_config != NULL && zone_config_len > 0); 8023 8024 /* zone zonename { config; }; */ 8025 result = isc_buffer_reserve(*text, 6 + zone_name_len + 2 + 8026 zone_config_len + 2); 8027 if (result != ISC_R_SUCCESS) { 8028 goto cleanup; 8029 } 8030 8031 CHECK(putstr(text, "zone \"")); 8032 CHECK(putmem(text, (const void *)zone_name, zone_name_len)); 8033 CHECK(putstr(text, "\" ")); 8034 CHECK(putmem(text, (const void *)zone_config, zone_config_len)); 8035 CHECK(putstr(text, ";\n")); 8036 8037 snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len, 8038 zone_name); 8039 8040 cfg_parser_reset(named_g_addparser); 8041 result = cfg_parse_buffer(named_g_addparser, *text, bufname, 0, 8042 &cfg_type_addzoneconf, 0, &zoneconf); 8043 if (result != ISC_R_SUCCESS) { 8044 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8045 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8046 "parsing config for zone '%.*s' in " 8047 "NZD database '%s' failed", 8048 (int)zone_name_len, zone_name, view->new_zone_db); 8049 goto cleanup; 8050 } 8051 8052 *zoneconfig = zoneconf; 8053 zoneconf = NULL; 8054 result = ISC_R_SUCCESS; 8055 8056 cleanup: 8057 if (zoneconf != NULL) { 8058 cfg_obj_destroy(named_g_addparser, &zoneconf); 8059 } 8060 8061 return result; 8062 } 8063 8064 /*% 8065 * Prototype for a callback which can be used with for_all_newzone_cfgs(). 8066 */ 8067 typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig, 8068 cfg_obj_t *config, cfg_obj_t *vconfig, 8069 dns_view_t *view, 8070 cfg_aclconfctx_t *actx); 8071 8072 /*% 8073 * For each zone found in a NZD opened by the caller, create an object 8074 * representing its configuration and invoke "callback" with the created 8075 * object, "config", "vconfig", "mctx", "view" and "actx" as arguments (all 8076 * these are non-global variables required to invoke configure_zone()). 8077 * Immediately interrupt processing if an error is encountered while 8078 * transforming NZD data into a zone configuration object or if "callback" 8079 * returns an error. 8080 * 8081 * Caller must hold 'view->new_zone_lock'. 8082 */ 8083 static isc_result_t 8084 for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config, 8085 cfg_obj_t *vconfig, dns_view_t *view, 8086 cfg_aclconfctx_t *actx, MDB_txn *txn, MDB_dbi dbi) { 8087 const cfg_obj_t *zconfig, *zlist; 8088 isc_result_t result = ISC_R_SUCCESS; 8089 cfg_obj_t *zconfigobj = NULL; 8090 isc_buffer_t *text = NULL; 8091 MDB_cursor *cursor = NULL; 8092 MDB_val data, key; 8093 int status; 8094 8095 status = mdb_cursor_open(txn, dbi, &cursor); 8096 if (status != MDB_SUCCESS) { 8097 return ISC_R_FAILURE; 8098 } 8099 8100 for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); 8101 status == MDB_SUCCESS; 8102 status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) 8103 { 8104 /* 8105 * Create a configuration object from data fetched from NZD. 8106 */ 8107 result = data_to_cfg(view, &key, &data, &text, &zconfigobj); 8108 if (result != ISC_R_SUCCESS) { 8109 break; 8110 } 8111 8112 /* 8113 * Extract zone configuration from configuration object. 8114 */ 8115 zlist = NULL; 8116 result = cfg_map_get(zconfigobj, "zone", &zlist); 8117 if (result != ISC_R_SUCCESS) { 8118 break; 8119 } else if (!cfg_obj_islist(zlist)) { 8120 result = ISC_R_FAILURE; 8121 break; 8122 } 8123 zconfig = cfg_listelt_value(cfg_list_first(zlist)); 8124 8125 /* 8126 * Invoke callback. 8127 */ 8128 result = callback(zconfig, config, vconfig, view, actx); 8129 if (result != ISC_R_SUCCESS) { 8130 break; 8131 } 8132 8133 /* 8134 * Destroy the configuration object created in this iteration. 8135 */ 8136 cfg_obj_destroy(named_g_addparser, &zconfigobj); 8137 } 8138 8139 if (text != NULL) { 8140 isc_buffer_free(&text); 8141 } 8142 if (zconfigobj != NULL) { 8143 cfg_obj_destroy(named_g_addparser, &zconfigobj); 8144 } 8145 mdb_cursor_close(cursor); 8146 8147 return result; 8148 } 8149 8150 /*% 8151 * Attempt to configure a zone found in NZD and return the result. 8152 */ 8153 static isc_result_t 8154 configure_newzone(const cfg_obj_t *zconfig, cfg_obj_t *config, 8155 cfg_obj_t *vconfig, dns_view_t *view, 8156 cfg_aclconfctx_t *actx) { 8157 return configure_zone( 8158 config, zconfig, vconfig, view, &named_g_server->viewlist, 8159 &named_g_server->kasplist, &named_g_server->keystorelist, actx, 8160 true, false, false, false); 8161 } 8162 8163 /*% 8164 * Revert new view assignment for a zone found in NZD. 8165 */ 8166 static isc_result_t 8167 configure_newzone_revert(const cfg_obj_t *zconfig, cfg_obj_t *config, 8168 cfg_obj_t *vconfig, dns_view_t *view, 8169 cfg_aclconfctx_t *actx) { 8170 UNUSED(config); 8171 UNUSED(vconfig); 8172 UNUSED(actx); 8173 8174 configure_zone_setviewcommit(ISC_R_FAILURE, zconfig, view); 8175 8176 return ISC_R_SUCCESS; 8177 } 8178 8179 static isc_result_t 8180 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 8181 cfg_aclconfctx_t *actx) { 8182 isc_result_t result; 8183 MDB_txn *txn = NULL; 8184 MDB_dbi dbi; 8185 8186 if (view->new_zone_config == NULL) { 8187 return ISC_R_SUCCESS; 8188 } 8189 8190 LOCK(&view->new_zone_lock); 8191 8192 result = nzd_open(view, MDB_RDONLY, &txn, &dbi); 8193 if (result != ISC_R_SUCCESS) { 8194 UNLOCK(&view->new_zone_lock); 8195 return ISC_R_SUCCESS; 8196 } 8197 8198 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8199 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8200 "loading NZD configs from '%s' " 8201 "for view '%s'", 8202 view->new_zone_db, view->name); 8203 8204 result = for_all_newzone_cfgs(configure_newzone, config, vconfig, view, 8205 actx, txn, dbi); 8206 if (result != ISC_R_SUCCESS) { 8207 /* 8208 * An error was encountered while attempting to configure zones 8209 * found in NZD. As this error may have been caused by a 8210 * configure_zone() failure, try restoring a sane configuration 8211 * by reattaching all zones found in NZD to the old view. If 8212 * this also fails, too bad, there is nothing more we can do in 8213 * terms of trying to make things right. 8214 */ 8215 (void)for_all_newzone_cfgs(configure_newzone_revert, config, 8216 vconfig, view, actx, txn, dbi); 8217 } 8218 8219 (void)nzd_close(&txn, false); 8220 8221 UNLOCK(&view->new_zone_lock); 8222 8223 return result; 8224 } 8225 8226 static isc_result_t 8227 get_newzone_config(dns_view_t *view, const char *zonename, 8228 cfg_obj_t **zoneconfig) { 8229 isc_result_t result; 8230 int status; 8231 cfg_obj_t *zoneconf = NULL; 8232 isc_buffer_t *text = NULL; 8233 MDB_txn *txn = NULL; 8234 MDB_dbi dbi; 8235 MDB_val key, data; 8236 char zname[DNS_NAME_FORMATSIZE]; 8237 dns_fixedname_t fname; 8238 dns_name_t *name; 8239 isc_buffer_t b; 8240 8241 INSIST(zoneconfig != NULL && *zoneconfig == NULL); 8242 8243 LOCK(&view->new_zone_lock); 8244 8245 CHECK(nzd_open(view, MDB_RDONLY, &txn, &dbi)); 8246 8247 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8248 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8249 "loading NZD config from '%s' " 8250 "for zone '%s'", 8251 view->new_zone_db, zonename); 8252 8253 /* Normalize zone name */ 8254 isc_buffer_constinit(&b, zonename, strlen(zonename)); 8255 isc_buffer_add(&b, strlen(zonename)); 8256 name = dns_fixedname_initname(&fname); 8257 CHECK(dns_name_fromtext(name, &b, dns_rootname, DNS_NAME_DOWNCASE, 8258 NULL)); 8259 dns_name_format(name, zname, sizeof(zname)); 8260 8261 key.mv_data = zname; 8262 key.mv_size = strlen(zname); 8263 8264 status = mdb_get(txn, dbi, &key, &data); 8265 if (status != MDB_SUCCESS) { 8266 CHECK(ISC_R_FAILURE); 8267 } 8268 8269 CHECK(data_to_cfg(view, &key, &data, &text, &zoneconf)); 8270 8271 *zoneconfig = zoneconf; 8272 zoneconf = NULL; 8273 result = ISC_R_SUCCESS; 8274 8275 cleanup: 8276 (void)nzd_close(&txn, false); 8277 8278 UNLOCK(&view->new_zone_lock); 8279 8280 if (zoneconf != NULL) { 8281 cfg_obj_destroy(named_g_addparser, &zoneconf); 8282 } 8283 if (text != NULL) { 8284 isc_buffer_free(&text); 8285 } 8286 8287 return result; 8288 } 8289 8290 #endif /* HAVE_LMDB */ 8291 8292 static isc_result_t 8293 load_configuration(const char *filename, named_server_t *server, 8294 bool first_time) { 8295 cfg_obj_t *config = NULL, *bindkeys = NULL; 8296 cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; 8297 const cfg_listelt_t *element; 8298 const cfg_obj_t *builtin_views; 8299 const cfg_obj_t *maps[3]; 8300 const cfg_obj_t *obj; 8301 const cfg_obj_t *options; 8302 const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; 8303 const cfg_obj_t *kasps; 8304 const cfg_obj_t *keystores; 8305 dns_kasp_t *kasp = NULL; 8306 dns_kasp_t *kasp_next = NULL; 8307 dns_kasp_t *default_kasp = NULL; 8308 dns_kasplist_t tmpkasplist, kasplist; 8309 dns_keystore_t *keystore = NULL; 8310 dns_keystore_t *keystore_next = NULL; 8311 dns_keystorelist_t tmpkeystorelist, keystorelist; 8312 const cfg_obj_t *views; 8313 8314 dns_view_t *view_next = NULL; 8315 dns_viewlist_t tmpviewlist; 8316 dns_viewlist_t viewlist, builtin_viewlist; 8317 in_port_t listen_port, udpport_low, udpport_high; 8318 int i, backlog; 8319 isc_interval_t interval; 8320 isc_logconfig_t *logc = NULL; 8321 isc_portset_t *v4portset = NULL; 8322 isc_portset_t *v6portset = NULL; 8323 isc_result_t result; 8324 uint32_t heartbeat_interval; 8325 uint32_t interface_interval; 8326 uint32_t udpsize; 8327 uint32_t transfer_message_size; 8328 uint32_t recv_tcp_buffer_size; 8329 uint32_t send_tcp_buffer_size; 8330 uint32_t recv_udp_buffer_size; 8331 uint32_t send_udp_buffer_size; 8332 named_cache_t *nsc; 8333 named_cachelist_t cachelist, tmpcachelist; 8334 ns_altsecret_t *altsecret; 8335 ns_altsecretlist_t altsecrets, tmpaltsecrets; 8336 uint32_t softquota = 0; 8337 uint32_t max; 8338 uint64_t initial, idle, keepalive, advertised; 8339 bool loadbalancesockets; 8340 bool exclusive = true; 8341 dns_aclenv_t *env = 8342 ns_interfacemgr_getaclenv(named_g_server->interfacemgr); 8343 8344 /* 8345 * Require the reconfiguration to happen always on the main loop 8346 */ 8347 REQUIRE(isc_loop() == named_g_mainloop); 8348 8349 ISC_LIST_INIT(kasplist); 8350 ISC_LIST_INIT(keystorelist); 8351 ISC_LIST_INIT(viewlist); 8352 ISC_LIST_INIT(builtin_viewlist); 8353 ISC_LIST_INIT(cachelist); 8354 ISC_LIST_INIT(altsecrets); 8355 8356 /* Ensure exclusive access to configuration data. */ 8357 isc_loopmgr_pause(named_g_loopmgr); 8358 8359 /* Create the ACL configuration context */ 8360 if (named_g_aclconfctx != NULL) { 8361 cfg_aclconfctx_detach(&named_g_aclconfctx); 8362 } 8363 result = cfg_aclconfctx_create(named_g_mctx, &named_g_aclconfctx); 8364 if (result != ISC_R_SUCCESS) { 8365 goto cleanup_exclusive; 8366 } 8367 8368 /* 8369 * Shut down all dyndb instances. 8370 */ 8371 dns_dyndb_cleanup(false); 8372 8373 /* 8374 * Parse the global default pseudo-config file. 8375 */ 8376 if (first_time) { 8377 result = named_config_parsedefaults(named_g_parser, 8378 &named_g_config); 8379 if (result != ISC_R_SUCCESS) { 8380 named_main_earlyfatal("unable to load " 8381 "internal defaults: %s", 8382 isc_result_totext(result)); 8383 } 8384 RUNTIME_CHECK(cfg_map_get(named_g_config, "options", 8385 &named_g_defaults) == ISC_R_SUCCESS); 8386 } 8387 8388 /* 8389 * Log the current working directory. 8390 */ 8391 if (first_time) { 8392 char cwd[PATH_MAX]; 8393 if (getcwd(cwd, sizeof(cwd)) == cwd) { 8394 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8395 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8396 "the initial working directory is '%s'", 8397 cwd); 8398 } 8399 } 8400 8401 /* 8402 * Parse the configuration file using the new config code. 8403 */ 8404 config = NULL; 8405 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8406 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8407 "loading configuration from '%s'", filename); 8408 result = cfg_parser_create(named_g_mctx, named_g_lctx, &conf_parser); 8409 if (result != ISC_R_SUCCESS) { 8410 goto cleanup_exclusive; 8411 } 8412 8413 cfg_parser_setcallback(conf_parser, directory_callback, NULL); 8414 result = cfg_parse_file(conf_parser, filename, &cfg_type_namedconf, 8415 &config); 8416 if (result != ISC_R_SUCCESS) { 8417 goto cleanup_conf_parser; 8418 } 8419 8420 /* 8421 * Check the validity of the configuration. 8422 * 8423 * (Ignore plugin parameters for now; they will be 8424 * checked later when the modules are actually loaded and 8425 * registered.) 8426 */ 8427 result = isccfg_check_namedconf(config, BIND_CHECK_ALGORITHMS, 8428 named_g_lctx, named_g_mctx); 8429 if (result != ISC_R_SUCCESS) { 8430 goto cleanup_config; 8431 } 8432 8433 /* Let's recreate the TLS context cache */ 8434 if (server->tlsctx_server_cache != NULL) { 8435 isc_tlsctx_cache_detach(&server->tlsctx_server_cache); 8436 } 8437 8438 isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_server_cache); 8439 8440 if (server->tlsctx_client_cache != NULL) { 8441 isc_tlsctx_cache_detach(&server->tlsctx_client_cache); 8442 } 8443 8444 isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_client_cache); 8445 8446 dns_zonemgr_set_tlsctx_cache(server->zonemgr, 8447 server->tlsctx_client_cache); 8448 8449 /* 8450 * Fill in the maps array, used for resolving defaults. 8451 */ 8452 i = 0; 8453 options = NULL; 8454 result = cfg_map_get(config, "options", &options); 8455 if (result == ISC_R_SUCCESS) { 8456 maps[i++] = options; 8457 } 8458 maps[i++] = named_g_defaults; 8459 maps[i] = NULL; 8460 8461 #if HAVE_LIBNGHTTP2 8462 obj = NULL; 8463 result = named_config_get(maps, "http-port", &obj); 8464 INSIST(result == ISC_R_SUCCESS); 8465 named_g_httpport = (in_port_t)cfg_obj_asuint32(obj); 8466 8467 obj = NULL; 8468 result = named_config_get(maps, "https-port", &obj); 8469 INSIST(result == ISC_R_SUCCESS); 8470 named_g_httpsport = (in_port_t)cfg_obj_asuint32(obj); 8471 8472 obj = NULL; 8473 result = named_config_get(maps, "http-listener-clients", &obj); 8474 INSIST(result == ISC_R_SUCCESS); 8475 named_g_http_listener_clients = cfg_obj_asuint32(obj); 8476 8477 obj = NULL; 8478 result = named_config_get(maps, "http-streams-per-connection", &obj); 8479 INSIST(result == ISC_R_SUCCESS); 8480 named_g_http_streams_per_conn = cfg_obj_asuint32(obj); 8481 #endif 8482 8483 /* 8484 * If "dnssec-validation auto" is turned on, the root key 8485 * will be used as a default trust anchor. The root key 8486 * is built in, but if bindkeys-file is set, then it will 8487 * be overridden with the key in that file. 8488 */ 8489 obj = NULL; 8490 (void)named_config_get(maps, "bindkeys-file", &obj); 8491 if (obj != NULL) { 8492 setstring(server, &server->bindkeysfile, cfg_obj_asstring(obj)); 8493 INSIST(server->bindkeysfile != NULL); 8494 if (access(server->bindkeysfile, R_OK) != 0) { 8495 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8496 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8497 "unable to open '%s'; using built-in " 8498 "keys instead", 8499 server->bindkeysfile); 8500 } else { 8501 result = cfg_parser_create(named_g_mctx, named_g_lctx, 8502 &bindkeys_parser); 8503 if (result != ISC_R_SUCCESS) { 8504 goto cleanup_config; 8505 } 8506 8507 result = cfg_parse_file(bindkeys_parser, 8508 server->bindkeysfile, 8509 &cfg_type_bindkeys, &bindkeys); 8510 if (result != ISC_R_SUCCESS) { 8511 isc_log_write( 8512 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8513 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8514 "unable to parse '%s' " 8515 "error '%s'; using " 8516 "built-in keys instead", 8517 server->bindkeysfile, 8518 isc_result_totext(result)); 8519 } 8520 } 8521 } else { 8522 setstring(server, &server->bindkeysfile, NULL); 8523 } 8524 8525 #if defined(HAVE_GEOIP2) 8526 /* 8527 * Release any previously opened GeoIP2 databases. 8528 */ 8529 named_geoip_unload(); 8530 8531 /* 8532 * Initialize GeoIP databases from the configured location. 8533 * This should happen before configuring any ACLs, so that we 8534 * know what databases are available and can reject any GeoIP 8535 * ACLs that can't work. 8536 */ 8537 obj = NULL; 8538 result = named_config_get(maps, "geoip-directory", &obj); 8539 INSIST(result == ISC_R_SUCCESS); 8540 if (cfg_obj_isstring(obj)) { 8541 char *dir = UNCONST(cfg_obj_asstring(obj)); 8542 named_geoip_load(dir); 8543 } 8544 named_g_aclconfctx->geoip = named_g_geoip; 8545 #endif /* HAVE_GEOIP2 */ 8546 8547 /* 8548 * Configure various server options. 8549 */ 8550 configure_server_quota(maps, "transfers-out", 8551 &server->sctx->xfroutquota); 8552 configure_server_quota(maps, "tcp-clients", &server->sctx->tcpquota); 8553 configure_server_quota(maps, "recursive-clients", 8554 &server->sctx->recursionquota); 8555 configure_server_quota(maps, "update-quota", &server->sctx->updquota); 8556 configure_server_quota(maps, "sig0checks-quota", 8557 &server->sctx->sig0checksquota); 8558 8559 max = isc_quota_getmax(&server->sctx->recursionquota); 8560 if (max > 1000) { 8561 unsigned int margin = ISC_MAX(100, named_g_cpus + 1); 8562 if (margin + 100 > max) { 8563 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8564 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8565 "'recursive-clients %d' too low when " 8566 "running with %d worker threads", 8567 max, named_g_cpus); 8568 result = ISC_R_RANGE; 8569 8570 goto cleanup_bindkeys_parser; 8571 } 8572 softquota = max - margin; 8573 } else { 8574 softquota = (max * 90) / 100; 8575 } 8576 isc_quota_soft(&server->sctx->recursionquota, softquota); 8577 8578 obj = NULL; 8579 result = named_config_get(maps, "sig0checks-quota-exempt", &obj); 8580 if (result == ISC_R_SUCCESS) { 8581 result = cfg_acl_fromconfig( 8582 obj, config, named_g_lctx, named_g_aclconfctx, 8583 named_g_mctx, 0, &server->sctx->sig0checksquota_exempt); 8584 INSIST(result == ISC_R_SUCCESS); 8585 } 8586 8587 /* 8588 * Set "blackhole". Only legal at options level; there is 8589 * no default. 8590 */ 8591 result = configure_view_acl(NULL, config, NULL, "blackhole", NULL, 8592 named_g_aclconfctx, named_g_mctx, 8593 &server->sctx->blackholeacl); 8594 if (result != ISC_R_SUCCESS) { 8595 goto cleanup_bindkeys_parser; 8596 } 8597 8598 if (server->sctx->blackholeacl != NULL) { 8599 dns_dispatchmgr_setblackhole(named_g_dispatchmgr, 8600 server->sctx->blackholeacl); 8601 } 8602 8603 obj = NULL; 8604 result = named_config_get(maps, "match-mapped-addresses", &obj); 8605 INSIST(result == ISC_R_SUCCESS); 8606 env->match_mapped = cfg_obj_asboolean(obj); 8607 8608 /* 8609 * Configure the network manager 8610 */ 8611 obj = NULL; 8612 result = named_config_get(maps, "tcp-initial-timeout", &obj); 8613 INSIST(result == ISC_R_SUCCESS); 8614 initial = cfg_obj_asuint32(obj) * 100; 8615 if (initial > MAX_INITIAL_TIMEOUT) { 8616 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8617 "tcp-initial-timeout value is out of range: " 8618 "lowering to %" PRIu32, 8619 MAX_INITIAL_TIMEOUT / 100); 8620 initial = MAX_INITIAL_TIMEOUT; 8621 } else if (initial < MIN_INITIAL_TIMEOUT) { 8622 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8623 "tcp-initial-timeout value is out of range: " 8624 "raising to %" PRIu32, 8625 MIN_INITIAL_TIMEOUT / 100); 8626 initial = MIN_INITIAL_TIMEOUT; 8627 } 8628 8629 obj = NULL; 8630 result = named_config_get(maps, "tcp-idle-timeout", &obj); 8631 INSIST(result == ISC_R_SUCCESS); 8632 idle = cfg_obj_asuint32(obj) * 100; 8633 if (idle > MAX_IDLE_TIMEOUT) { 8634 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8635 "tcp-idle-timeout value is out of range: " 8636 "lowering to %" PRIu32, 8637 MAX_IDLE_TIMEOUT / 100); 8638 idle = MAX_IDLE_TIMEOUT; 8639 } else if (idle < MIN_IDLE_TIMEOUT) { 8640 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8641 "tcp-idle-timeout value is out of range: " 8642 "raising to %" PRIu32, 8643 MIN_IDLE_TIMEOUT / 100); 8644 idle = MIN_IDLE_TIMEOUT; 8645 } 8646 8647 obj = NULL; 8648 result = named_config_get(maps, "tcp-keepalive-timeout", &obj); 8649 INSIST(result == ISC_R_SUCCESS); 8650 keepalive = cfg_obj_asuint32(obj) * 100; 8651 if (keepalive > MAX_KEEPALIVE_TIMEOUT) { 8652 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8653 "tcp-keepalive-timeout value is out of range: " 8654 "lowering to %" PRIu32, 8655 MAX_KEEPALIVE_TIMEOUT / 100); 8656 keepalive = MAX_KEEPALIVE_TIMEOUT; 8657 } else if (keepalive < MIN_KEEPALIVE_TIMEOUT) { 8658 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8659 "tcp-keepalive-timeout value is out of range: " 8660 "raising to %" PRIu32, 8661 MIN_KEEPALIVE_TIMEOUT / 100); 8662 keepalive = MIN_KEEPALIVE_TIMEOUT; 8663 } 8664 8665 obj = NULL; 8666 result = named_config_get(maps, "tcp-advertised-timeout", &obj); 8667 INSIST(result == ISC_R_SUCCESS); 8668 advertised = cfg_obj_asuint32(obj) * 100; 8669 if (advertised > MAX_ADVERTISED_TIMEOUT) { 8670 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8671 "tcp-advertized-timeout value is out of range: " 8672 "lowering to %" PRIu32, 8673 MAX_ADVERTISED_TIMEOUT / 100); 8674 advertised = MAX_ADVERTISED_TIMEOUT; 8675 } 8676 8677 isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, 8678 advertised); 8679 8680 #define CAP_IF_NOT_ZERO(v, min, max) \ 8681 if (v > 0 && v < min) { \ 8682 v = min; \ 8683 } else if (v > max) { \ 8684 v = max; \ 8685 } 8686 8687 /* Set the kernel send and receive buffer sizes */ 8688 obj = NULL; 8689 result = named_config_get(maps, "tcp-receive-buffer", &obj); 8690 INSIST(result == ISC_R_SUCCESS); 8691 recv_tcp_buffer_size = cfg_obj_asuint32(obj); 8692 CAP_IF_NOT_ZERO(recv_tcp_buffer_size, 4096, INT32_MAX); 8693 8694 obj = NULL; 8695 result = named_config_get(maps, "tcp-send-buffer", &obj); 8696 INSIST(result == ISC_R_SUCCESS); 8697 send_tcp_buffer_size = cfg_obj_asuint32(obj); 8698 CAP_IF_NOT_ZERO(send_tcp_buffer_size, 4096, INT32_MAX); 8699 8700 obj = NULL; 8701 result = named_config_get(maps, "udp-receive-buffer", &obj); 8702 INSIST(result == ISC_R_SUCCESS); 8703 recv_udp_buffer_size = cfg_obj_asuint32(obj); 8704 CAP_IF_NOT_ZERO(recv_udp_buffer_size, 4096, INT32_MAX); 8705 8706 obj = NULL; 8707 result = named_config_get(maps, "udp-send-buffer", &obj); 8708 INSIST(result == ISC_R_SUCCESS); 8709 send_udp_buffer_size = cfg_obj_asuint32(obj); 8710 CAP_IF_NOT_ZERO(send_udp_buffer_size, 4096, INT32_MAX); 8711 8712 isc_nm_setnetbuffers(named_g_netmgr, recv_tcp_buffer_size, 8713 send_tcp_buffer_size, recv_udp_buffer_size, 8714 send_udp_buffer_size); 8715 8716 #undef CAP_IF_NOT_ZERO 8717 8718 /* 8719 * Configure sets of UDP query source ports. 8720 */ 8721 result = isc_portset_create(named_g_mctx, &v4portset); 8722 if (result != ISC_R_SUCCESS) { 8723 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8724 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8725 "creating UDP/IPv4 port set: %s", 8726 isc_result_totext(result)); 8727 goto cleanup_bindkeys_parser; 8728 } 8729 result = isc_portset_create(named_g_mctx, &v6portset); 8730 if (result != ISC_R_SUCCESS) { 8731 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8732 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8733 "creating UDP/IPv6 port set: %s", 8734 isc_result_totext(result)); 8735 goto cleanup_v4portset; 8736 } 8737 8738 usev4ports = NULL; 8739 usev6ports = NULL; 8740 avoidv4ports = NULL; 8741 avoidv6ports = NULL; 8742 8743 (void)named_config_get(maps, "use-v4-udp-ports", &usev4ports); 8744 if (usev4ports != NULL) { 8745 portset_fromconf(v4portset, usev4ports, true); 8746 } else { 8747 result = isc_net_getudpportrange(AF_INET, &udpport_low, 8748 &udpport_high); 8749 if (result != ISC_R_SUCCESS) { 8750 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8751 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8752 "get the default UDP/IPv4 port range: %s", 8753 isc_result_totext(result)); 8754 goto cleanup_v6portset; 8755 } 8756 8757 if (udpport_low == udpport_high) { 8758 isc_portset_add(v4portset, udpport_low); 8759 } else { 8760 isc_portset_addrange(v4portset, udpport_low, 8761 udpport_high); 8762 } 8763 if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE4)) { 8764 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8765 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8766 "using default UDP/IPv4 port range: " 8767 "[%d, %d]", 8768 udpport_low, udpport_high); 8769 } 8770 } 8771 (void)named_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports); 8772 if (avoidv4ports != NULL) { 8773 portset_fromconf(v4portset, avoidv4ports, false); 8774 } 8775 8776 (void)named_config_get(maps, "use-v6-udp-ports", &usev6ports); 8777 if (usev6ports != NULL) { 8778 portset_fromconf(v6portset, usev6ports, true); 8779 } else { 8780 result = isc_net_getudpportrange(AF_INET6, &udpport_low, 8781 &udpport_high); 8782 if (result != ISC_R_SUCCESS) { 8783 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8784 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8785 "get the default UDP/IPv6 port range: %s", 8786 isc_result_totext(result)); 8787 goto cleanup_v6portset; 8788 } 8789 if (udpport_low == udpport_high) { 8790 isc_portset_add(v6portset, udpport_low); 8791 } else { 8792 isc_portset_addrange(v6portset, udpport_low, 8793 udpport_high); 8794 } 8795 if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE6)) { 8796 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8797 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8798 "using default UDP/IPv6 port range: " 8799 "[%d, %d]", 8800 udpport_low, udpport_high); 8801 } 8802 } 8803 (void)named_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports); 8804 if (avoidv6ports != NULL) { 8805 portset_fromconf(v6portset, avoidv6ports, false); 8806 } 8807 8808 dns_dispatchmgr_setavailports(named_g_dispatchmgr, v4portset, 8809 v6portset); 8810 8811 /* 8812 * Set the EDNS UDP size when we don't match a view. 8813 */ 8814 obj = NULL; 8815 result = named_config_get(maps, "edns-udp-size", &obj); 8816 INSIST(result == ISC_R_SUCCESS); 8817 udpsize = cfg_obj_asuint32(obj); 8818 if (udpsize < 512) { 8819 udpsize = 512; 8820 } 8821 if (udpsize > 4096) { 8822 udpsize = 4096; 8823 } 8824 server->sctx->udpsize = (uint16_t)udpsize; 8825 8826 /* Set the transfer message size for TCP */ 8827 obj = NULL; 8828 result = named_config_get(maps, "transfer-message-size", &obj); 8829 INSIST(result == ISC_R_SUCCESS); 8830 transfer_message_size = cfg_obj_asuint32(obj); 8831 if (transfer_message_size < 512) { 8832 transfer_message_size = 512; 8833 } else if (transfer_message_size > 65535) { 8834 transfer_message_size = 65535; 8835 } 8836 server->sctx->transfer_tcp_message_size = 8837 (uint16_t)transfer_message_size; 8838 8839 /* 8840 * Configure the zone manager. 8841 */ 8842 obj = NULL; 8843 result = named_config_get(maps, "transfers-in", &obj); 8844 INSIST(result == ISC_R_SUCCESS); 8845 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); 8846 8847 obj = NULL; 8848 result = named_config_get(maps, "transfers-per-ns", &obj); 8849 INSIST(result == ISC_R_SUCCESS); 8850 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); 8851 8852 obj = NULL; 8853 result = named_config_get(maps, "notify-rate", &obj); 8854 INSIST(result == ISC_R_SUCCESS); 8855 dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj)); 8856 8857 obj = NULL; 8858 result = named_config_get(maps, "startup-notify-rate", &obj); 8859 INSIST(result == ISC_R_SUCCESS); 8860 dns_zonemgr_setstartupnotifyrate(server->zonemgr, 8861 cfg_obj_asuint32(obj)); 8862 8863 obj = NULL; 8864 result = named_config_get(maps, "serial-query-rate", &obj); 8865 INSIST(result == ISC_R_SUCCESS); 8866 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); 8867 8868 /* 8869 * Determine which port to use for listening for incoming connections. 8870 */ 8871 if (named_g_port != 0) { 8872 listen_port = named_g_port; 8873 } else { 8874 result = named_config_getport(config, "port", &listen_port); 8875 if (result != ISC_R_SUCCESS) { 8876 goto cleanup_v6portset; 8877 } 8878 } 8879 8880 /* 8881 * Find the listen queue depth. 8882 */ 8883 obj = NULL; 8884 result = named_config_get(maps, "tcp-listen-queue", &obj); 8885 INSIST(result == ISC_R_SUCCESS); 8886 backlog = cfg_obj_asuint32(obj); 8887 if ((backlog > 0) && (backlog < 10)) { 8888 backlog = 10; 8889 } 8890 ns_interfacemgr_setbacklog(server->interfacemgr, backlog); 8891 8892 obj = NULL; 8893 result = named_config_get(maps, "reuseport", &obj); 8894 INSIST(result == ISC_R_SUCCESS); 8895 loadbalancesockets = cfg_obj_asboolean(obj); 8896 #if HAVE_SO_REUSEPORT_LB 8897 if (first_time) { 8898 isc_nm_setloadbalancesockets(named_g_netmgr, 8899 cfg_obj_asboolean(obj)); 8900 } else if (loadbalancesockets != 8901 isc_nm_getloadbalancesockets(named_g_netmgr)) 8902 { 8903 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8904 "changing reuseport value requires server restart"); 8905 } 8906 #else 8907 if (loadbalancesockets) { 8908 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8909 "reuseport has no effect on this system"); 8910 } 8911 #endif 8912 8913 /* 8914 * Configure the interface manager according to the "listen-on" 8915 * statement. 8916 */ 8917 { 8918 const cfg_obj_t *clistenon = NULL; 8919 ns_listenlist_t *listenon = NULL; 8920 8921 /* 8922 * Even though listen-on is present in the default 8923 * configuration, this way is easier. 8924 */ 8925 if (options != NULL) { 8926 (void)cfg_map_get(options, "listen-on", &clistenon); 8927 } 8928 if (clistenon != NULL) { 8929 result = listenlist_fromconfig( 8930 clistenon, config, named_g_aclconfctx, 8931 named_g_mctx, AF_INET, 8932 server->tlsctx_server_cache, &listenon); 8933 } else { 8934 /* 8935 * Not specified, use default. 8936 */ 8937 result = ns_listenlist_default(named_g_mctx, 8938 listen_port, true, 8939 AF_INET, &listenon); 8940 } 8941 if (result != ISC_R_SUCCESS) { 8942 goto cleanup_v6portset; 8943 } 8944 8945 if (listenon != NULL) { 8946 ns_interfacemgr_setlistenon4(server->interfacemgr, 8947 listenon); 8948 ns_listenlist_detach(&listenon); 8949 } 8950 } 8951 8952 /* 8953 * Ditto for IPv6. 8954 */ 8955 { 8956 const cfg_obj_t *clistenon = NULL; 8957 ns_listenlist_t *listenon = NULL; 8958 8959 if (options != NULL) { 8960 (void)cfg_map_get(options, "listen-on-v6", &clistenon); 8961 } 8962 if (clistenon != NULL) { 8963 result = listenlist_fromconfig( 8964 clistenon, config, named_g_aclconfctx, 8965 named_g_mctx, AF_INET6, 8966 server->tlsctx_server_cache, &listenon); 8967 } else { 8968 /* 8969 * Not specified, use default. 8970 */ 8971 result = ns_listenlist_default(named_g_mctx, 8972 listen_port, true, 8973 AF_INET6, &listenon); 8974 } 8975 if (result != ISC_R_SUCCESS) { 8976 goto cleanup_v6portset; 8977 } 8978 if (listenon != NULL) { 8979 ns_interfacemgr_setlistenon6(server->interfacemgr, 8980 listenon); 8981 ns_listenlist_detach(&listenon); 8982 } 8983 } 8984 8985 if (first_time) { 8986 /* 8987 * Rescan the interface list to pick up changes in the 8988 * listen-on option. This requires the loopmgr to be 8989 * temporarily resumed. 8990 */ 8991 isc_loopmgr_resume(named_g_loopmgr); 8992 result = ns_interfacemgr_scan(server->interfacemgr, true, true); 8993 isc_loopmgr_pause(named_g_loopmgr); 8994 8995 /* 8996 * Check that named is able to TCP listen on at least one 8997 * interface. Otherwise, another named process could be running 8998 * and we should fail. 8999 */ 9000 if (result == ISC_R_ADDRINUSE) { 9001 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9002 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9003 "unable to listen on any configured " 9004 "interfaces"); 9005 result = ISC_R_FAILURE; 9006 goto cleanup_v6portset; 9007 } 9008 } 9009 9010 /* 9011 * Arrange for further interface scanning to occur periodically 9012 * as specified by the "interface-interval" option. 9013 */ 9014 obj = NULL; 9015 result = named_config_get(maps, "interface-interval", &obj); 9016 INSIST(result == ISC_R_SUCCESS); 9017 interface_interval = cfg_obj_asduration(obj); 9018 server->interface_interval = interface_interval; 9019 9020 /* 9021 * Enable automatic interface scans. 9022 */ 9023 obj = NULL; 9024 result = named_config_get(maps, "automatic-interface-scan", &obj); 9025 INSIST(result == ISC_R_SUCCESS); 9026 server->sctx->interface_auto = cfg_obj_asboolean(obj); 9027 9028 if (server->sctx->interface_auto) { 9029 if (ns_interfacemgr_dynamic_updates_are_reliable() && 9030 server->interface_interval != 0) 9031 { 9032 /* 9033 * In some cases the user might expect a certain 9034 * behaviour from the rescan timer, let's try to deduce 9035 * that from the configuration options. 9036 */ 9037 isc_log_write( 9038 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9039 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9040 "Disabling periodic interface re-scans timer"); 9041 server->interface_interval = 0; 9042 } 9043 9044 ns_interfacemgr_routeconnect(server->interfacemgr); 9045 } else { 9046 ns_interfacemgr_routedisconnect(server->interfacemgr); 9047 } 9048 9049 if (server->interface_interval == 0) { 9050 isc_timer_stop(server->interface_timer); 9051 } else { 9052 isc_interval_set(&interval, interface_interval, 0); 9053 isc_timer_start(server->interface_timer, isc_timertype_ticker, 9054 &interval); 9055 } 9056 9057 /* 9058 * Configure the dialup heartbeat timer. 9059 */ 9060 obj = NULL; 9061 result = named_config_get(maps, "heartbeat-interval", &obj); 9062 INSIST(result == ISC_R_SUCCESS); 9063 heartbeat_interval = cfg_obj_asuint32(obj) * 60; 9064 if (heartbeat_interval == 0) { 9065 isc_timer_stop(server->heartbeat_timer); 9066 } else if (server->heartbeat_interval != heartbeat_interval) { 9067 isc_interval_set(&interval, heartbeat_interval, 0); 9068 isc_timer_start(server->heartbeat_timer, isc_timertype_ticker, 9069 &interval); 9070 } 9071 server->heartbeat_interval = heartbeat_interval; 9072 9073 isc_interval_set(&interval, 1200, 0); 9074 isc_timer_start(server->pps_timer, isc_timertype_ticker, &interval); 9075 9076 isc_interval_set(&interval, named_g_tat_interval, 0); 9077 isc_timer_start(server->tat_timer, isc_timertype_ticker, &interval); 9078 9079 /* 9080 * Write the PID file. 9081 */ 9082 obj = NULL; 9083 if (named_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) { 9084 if (cfg_obj_isvoid(obj)) { 9085 named_os_writepidfile(NULL, first_time); 9086 } else { 9087 named_os_writepidfile(cfg_obj_asstring(obj), 9088 first_time); 9089 } 9090 } else { 9091 named_os_writepidfile(named_g_defaultpidfile, first_time); 9092 } 9093 9094 /* 9095 * Configure the server-wide session key. This must be done before 9096 * configure views because zone configuration may need to know 9097 * session-keyname. 9098 * 9099 * Failure of session key generation isn't fatal at this time; if it 9100 * turns out that a session key is really needed but doesn't exist, 9101 * we'll treat it as a fatal error then. 9102 */ 9103 (void)configure_session_key(maps, server, named_g_mctx, first_time); 9104 9105 /* 9106 * Create the built-in key store ("key-directory"). 9107 */ 9108 result = cfg_keystore_fromconfig(NULL, named_g_mctx, named_g_lctx, 9109 named_g_engine, &keystorelist, NULL); 9110 if (result != ISC_R_SUCCESS) { 9111 goto cleanup_keystorelist; 9112 } 9113 9114 /* 9115 * Create the DNSSEC key stores. 9116 */ 9117 keystores = NULL; 9118 (void)cfg_map_get(config, "key-store", &keystores); 9119 for (element = cfg_list_first(keystores); element != NULL; 9120 element = cfg_list_next(element)) 9121 { 9122 cfg_obj_t *kconfig = cfg_listelt_value(element); 9123 keystore = NULL; 9124 result = cfg_keystore_fromconfig(kconfig, named_g_mctx, 9125 named_g_lctx, named_g_engine, 9126 &keystorelist, NULL); 9127 if (result != ISC_R_SUCCESS) { 9128 goto cleanup_keystorelist; 9129 } 9130 } 9131 9132 /* 9133 * Create the built-in kasp policies ("default", "insecure"). 9134 */ 9135 kasps = NULL; 9136 (void)cfg_map_get(named_g_config, "dnssec-policy", &kasps); 9137 for (element = cfg_list_first(kasps); element != NULL; 9138 element = cfg_list_next(element)) 9139 { 9140 cfg_obj_t *kconfig = cfg_listelt_value(element); 9141 9142 kasp = NULL; 9143 result = cfg_kasp_fromconfig(kconfig, default_kasp, true, 9144 named_g_mctx, named_g_lctx, 9145 &keystorelist, &kasplist, &kasp); 9146 if (result != ISC_R_SUCCESS) { 9147 goto cleanup_kasplist; 9148 } 9149 INSIST(kasp != NULL); 9150 dns_kasp_freeze(kasp); 9151 9152 /* Insist that the first built-in policy is the default one. */ 9153 if (default_kasp == NULL) { 9154 INSIST(strcmp(dns_kasp_getname(kasp), "default") == 0); 9155 dns_kasp_attach(kasp, &default_kasp); 9156 } 9157 9158 dns_kasp_detach(&kasp); 9159 } 9160 INSIST(default_kasp != NULL); 9161 9162 /* 9163 * Create the DNSSEC key and signing policies (KASP). 9164 */ 9165 kasps = NULL; 9166 (void)cfg_map_get(config, "dnssec-policy", &kasps); 9167 for (element = cfg_list_first(kasps); element != NULL; 9168 element = cfg_list_next(element)) 9169 { 9170 cfg_obj_t *kconfig = cfg_listelt_value(element); 9171 kasp = NULL; 9172 result = cfg_kasp_fromconfig(kconfig, default_kasp, true, 9173 named_g_mctx, named_g_lctx, 9174 &keystorelist, &kasplist, &kasp); 9175 if (result != ISC_R_SUCCESS) { 9176 goto cleanup_kasplist; 9177 } 9178 INSIST(kasp != NULL); 9179 dns_kasp_freeze(kasp); 9180 dns_kasp_detach(&kasp); 9181 } 9182 dns_kasp_detach(&default_kasp); 9183 9184 /* 9185 * Save keystore list and kasp list. 9186 */ 9187 tmpkeystorelist = server->keystorelist; 9188 server->keystorelist = keystorelist; 9189 keystorelist = tmpkeystorelist; 9190 9191 tmpkasplist = server->kasplist; 9192 server->kasplist = kasplist; 9193 kasplist = tmpkasplist; 9194 9195 #ifdef USE_DNSRPS 9196 /* 9197 * Find the path to the DNSRPS implementation library. 9198 */ 9199 obj = NULL; 9200 if (named_config_get(maps, "dnsrps-library", &obj) == ISC_R_SUCCESS) { 9201 if (server->dnsrpslib != NULL) { 9202 dns_dnsrps_server_destroy(); 9203 isc_mem_free(server->mctx, server->dnsrpslib); 9204 server->dnsrpslib = NULL; 9205 } 9206 setstring(server, &server->dnsrpslib, cfg_obj_asstring(obj)); 9207 result = dns_dnsrps_server_create(server->dnsrpslib); 9208 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9209 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9210 "initializing DNSRPS RPZ provider '%s': %s", 9211 server->dnsrpslib, isc_result_totext(result)); 9212 /* 9213 * It's okay if librpz isn't available. We'll complain 9214 * later if it turns out to be needed for a view with 9215 * "dnsrps-enable yes". 9216 */ 9217 if (result == ISC_R_FILENOTFOUND) { 9218 result = ISC_R_SUCCESS; 9219 } 9220 CHECKFATAL(result, "initializing RPZ service interface"); 9221 } 9222 #endif /* ifdef USE_DNSRPS */ 9223 9224 /* 9225 * Configure the views. 9226 */ 9227 views = NULL; 9228 (void)cfg_map_get(config, "view", &views); 9229 9230 /* 9231 * Create the views. 9232 */ 9233 for (element = cfg_list_first(views); element != NULL; 9234 element = cfg_list_next(element)) 9235 { 9236 cfg_obj_t *vconfig = cfg_listelt_value(element); 9237 dns_view_t *view = NULL; 9238 9239 result = create_view(vconfig, &viewlist, &view); 9240 if (result != ISC_R_SUCCESS) { 9241 goto cleanup_viewlist; 9242 } 9243 INSIST(view != NULL); 9244 9245 result = setup_newzones(view, config, vconfig, conf_parser, 9246 named_g_aclconfctx); 9247 dns_view_detach(&view); 9248 9249 if (result != ISC_R_SUCCESS) { 9250 goto cleanup_viewlist; 9251 } 9252 } 9253 9254 /* 9255 * If there were no explicit views then we do the default 9256 * view here. 9257 */ 9258 if (views == NULL) { 9259 dns_view_t *view = NULL; 9260 9261 result = create_view(NULL, &viewlist, &view); 9262 if (result != ISC_R_SUCCESS) { 9263 goto cleanup_viewlist; 9264 } 9265 INSIST(view != NULL); 9266 9267 result = setup_newzones(view, config, NULL, conf_parser, 9268 named_g_aclconfctx); 9269 9270 dns_view_detach(&view); 9271 if (result != ISC_R_SUCCESS) { 9272 goto cleanup_viewlist; 9273 } 9274 } 9275 9276 /* 9277 * Configure and freeze all explicit views. Explicit 9278 * views that have zones were already created at parsing 9279 * time, but views with no zones must be created here. 9280 */ 9281 for (element = cfg_list_first(views); element != NULL; 9282 element = cfg_list_next(element)) 9283 { 9284 cfg_obj_t *vconfig = cfg_listelt_value(element); 9285 dns_view_t *view = NULL; 9286 9287 view = NULL; 9288 result = find_view(vconfig, &viewlist, &view); 9289 if (result != ISC_R_SUCCESS) { 9290 goto cleanup_cachelist; 9291 } 9292 9293 result = configure_view(view, &viewlist, config, vconfig, 9294 &cachelist, &server->kasplist, 9295 &server->keystorelist, bindkeys, 9296 named_g_mctx, named_g_aclconfctx, true); 9297 if (result != ISC_R_SUCCESS) { 9298 dns_view_detach(&view); 9299 goto cleanup_cachelist; 9300 } 9301 dns_view_freeze(view); 9302 dns_view_detach(&view); 9303 } 9304 9305 /* 9306 * Make sure we have a default view if and only if there 9307 * were no explicit views. 9308 */ 9309 if (views == NULL) { 9310 dns_view_t *view = NULL; 9311 result = find_view(NULL, &viewlist, &view); 9312 if (result != ISC_R_SUCCESS) { 9313 goto cleanup_cachelist; 9314 } 9315 result = configure_view(view, &viewlist, config, NULL, 9316 &cachelist, &server->kasplist, 9317 &server->keystorelist, bindkeys, 9318 named_g_mctx, named_g_aclconfctx, true); 9319 if (result != ISC_R_SUCCESS) { 9320 dns_view_detach(&view); 9321 goto cleanup_cachelist; 9322 } 9323 dns_view_freeze(view); 9324 dns_view_detach(&view); 9325 } 9326 9327 /* 9328 * Create (or recreate) the built-in views. 9329 */ 9330 builtin_views = NULL; 9331 RUNTIME_CHECK(cfg_map_get(named_g_config, "view", &builtin_views) == 9332 ISC_R_SUCCESS); 9333 for (element = cfg_list_first(builtin_views); element != NULL; 9334 element = cfg_list_next(element)) 9335 { 9336 cfg_obj_t *vconfig = cfg_listelt_value(element); 9337 dns_view_t *view = NULL; 9338 9339 result = create_view(vconfig, &builtin_viewlist, &view); 9340 if (result != ISC_R_SUCCESS) { 9341 goto cleanup_cachelist; 9342 } 9343 9344 result = configure_view( 9345 view, &viewlist, config, vconfig, &cachelist, 9346 &server->kasplist, &server->keystorelist, bindkeys, 9347 named_g_mctx, named_g_aclconfctx, false); 9348 if (result != ISC_R_SUCCESS) { 9349 dns_view_detach(&view); 9350 goto cleanup_cachelist; 9351 } 9352 dns_view_freeze(view); 9353 dns_view_detach(&view); 9354 } 9355 9356 /* Now combine the two viewlists into one */ 9357 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 9358 9359 /* 9360 * Commit any dns_zone_setview() calls on all zones in the new 9361 * view. 9362 */ 9363 for (dns_view_t *view = ISC_LIST_HEAD(viewlist); view != NULL; 9364 view = ISC_LIST_NEXT(view, link)) 9365 { 9366 dns_view_setviewcommit(view); 9367 } 9368 9369 /* Swap our new view list with the production one. */ 9370 tmpviewlist = server->viewlist; 9371 server->viewlist = viewlist; 9372 viewlist = tmpviewlist; 9373 9374 /* Make the view list available to each of the views */ 9375 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9376 view = ISC_LIST_NEXT(view, link)) 9377 { 9378 view->viewlist = &server->viewlist; 9379 } 9380 9381 /* Swap our new cache list with the production one. */ 9382 tmpcachelist = server->cachelist; 9383 server->cachelist = cachelist; 9384 cachelist = tmpcachelist; 9385 9386 /* Load the TKEY information from the configuration. */ 9387 if (options != NULL) { 9388 dns_tkeyctx_t *tkeyctx = NULL; 9389 9390 result = named_tkeyctx_fromconfig(options, named_g_mctx, 9391 &tkeyctx); 9392 if (result != ISC_R_SUCCESS) { 9393 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9394 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9395 "configuring TKEY: %s", 9396 isc_result_totext(result)); 9397 goto cleanup_cachelist; 9398 } 9399 if (server->sctx->tkeyctx != NULL) { 9400 dns_tkeyctx_destroy(&server->sctx->tkeyctx); 9401 } 9402 server->sctx->tkeyctx = tkeyctx; 9403 } 9404 9405 #ifdef HAVE_LMDB 9406 /* 9407 * If we're using LMDB, we may have created newzones databases 9408 * as root, making it impossible to reopen them later after 9409 * switching to a new userid. We close them now, and reopen 9410 * after relinquishing privileges them. 9411 */ 9412 if (first_time) { 9413 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); 9414 view != NULL; view = ISC_LIST_NEXT(view, link)) 9415 { 9416 nzd_env_close(view); 9417 } 9418 } 9419 #endif /* HAVE_LMDB */ 9420 9421 /* 9422 * Switch to the effective UID for setting up files. 9423 * Later, after configuring all the listening ports, 9424 * we'll relinquish root privileges permanently. 9425 */ 9426 if (first_time) { 9427 named_os_changeuser(false); 9428 } 9429 9430 /* 9431 * Check that the working directory is writable. 9432 */ 9433 if (!isc_file_isdirwritable(".")) { 9434 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9435 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9436 "the working directory is not writable"); 9437 result = ISC_R_NOPERM; 9438 goto cleanup_cachelist; 9439 } 9440 9441 #ifdef HAVE_LMDB 9442 /* 9443 * Reopen NZD databases. 9444 */ 9445 if (first_time) { 9446 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); 9447 view != NULL; view = ISC_LIST_NEXT(view, link)) 9448 { 9449 nzd_env_reopen(view); 9450 } 9451 } 9452 #endif /* HAVE_LMDB */ 9453 9454 /* 9455 * Configure the logging system. 9456 * 9457 * Do this after changing UID to make sure that any log 9458 * files specified in named.conf get created by the 9459 * unprivileged user, not root. 9460 */ 9461 if (named_g_logstderr) { 9462 const cfg_obj_t *logobj = NULL; 9463 9464 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9465 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9466 "not using config file logging " 9467 "statement for logging due to " 9468 "-g option"); 9469 9470 (void)cfg_map_get(config, "logging", &logobj); 9471 if (logobj != NULL) { 9472 result = named_logconfig(NULL, logobj); 9473 if (result != ISC_R_SUCCESS) { 9474 isc_log_write( 9475 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9476 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9477 "checking logging configuration " 9478 "failed: %s", 9479 isc_result_totext(result)); 9480 goto cleanup_cachelist; 9481 } 9482 } 9483 } else { 9484 const cfg_obj_t *logobj = NULL; 9485 9486 isc_logconfig_create(named_g_lctx, &logc); 9487 9488 logobj = NULL; 9489 (void)cfg_map_get(config, "logging", &logobj); 9490 if (logobj != NULL) { 9491 result = named_logconfig(logc, logobj); 9492 if (result != ISC_R_SUCCESS) { 9493 isc_log_write( 9494 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9495 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9496 "configuring logging: %s", 9497 isc_result_totext(result)); 9498 goto cleanup_logc; 9499 } 9500 } else { 9501 named_log_setdefaultchannels(logc); 9502 named_log_setdefaultsslkeylogfile(logc); 9503 result = named_log_setunmatchedcategory(logc); 9504 if (result != ISC_R_SUCCESS) { 9505 isc_log_write( 9506 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9507 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9508 "setting up default 'category " 9509 "unmatched': %s", 9510 isc_result_totext(result)); 9511 goto cleanup_logc; 9512 } 9513 result = named_log_setdefaultcategory(logc); 9514 if (result != ISC_R_SUCCESS) { 9515 isc_log_write( 9516 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9517 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9518 "setting up default 'category " 9519 "default': %s", 9520 isc_result_totext(result)); 9521 goto cleanup_logc; 9522 } 9523 } 9524 9525 isc_logconfig_use(named_g_lctx, logc); 9526 logc = NULL; 9527 9528 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9529 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9530 "now using logging configuration from " 9531 "config file"); 9532 } 9533 9534 /* 9535 * Set the default value of the query logging flag depending 9536 * whether a "queries" category has been defined. This is 9537 * a disgusting hack, but we need to do this for BIND 8 9538 * compatibility. 9539 */ 9540 if (first_time) { 9541 const cfg_obj_t *logobj = NULL; 9542 const cfg_obj_t *categories = NULL; 9543 9544 obj = NULL; 9545 if (named_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { 9546 ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES, 9547 cfg_obj_asboolean(obj)); 9548 } else { 9549 (void)cfg_map_get(config, "logging", &logobj); 9550 if (logobj != NULL) { 9551 (void)cfg_map_get(logobj, "category", 9552 &categories); 9553 } 9554 if (categories != NULL) { 9555 for (element = cfg_list_first(categories); 9556 element != NULL; 9557 element = cfg_list_next(element)) 9558 { 9559 const cfg_obj_t *catobj; 9560 const char *str; 9561 9562 obj = cfg_listelt_value(element); 9563 catobj = cfg_tuple_get(obj, "name"); 9564 str = cfg_obj_asstring(catobj); 9565 if (strcasecmp(str, "queries") == 0) { 9566 ns_server_setoption( 9567 server->sctx, 9568 NS_SERVER_LOGQUERIES, 9569 true); 9570 } 9571 } 9572 } 9573 } 9574 obj = NULL; 9575 result = named_config_get(maps, "responselog", &obj); 9576 if (result == ISC_R_SUCCESS) { 9577 ns_server_setoption(server->sctx, 9578 NS_SERVER_LOGRESPONSES, 9579 cfg_obj_asboolean(obj)); 9580 } 9581 } 9582 9583 obj = NULL; 9584 if (options != NULL && 9585 cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS) 9586 { 9587 named_g_memstatistics = cfg_obj_asboolean(obj); 9588 } else { 9589 named_g_memstatistics = 9590 ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0); 9591 } 9592 9593 obj = NULL; 9594 if (named_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS) 9595 { 9596 named_main_setmemstats(cfg_obj_asstring(obj)); 9597 } else if (named_g_memstatistics) { 9598 named_main_setmemstats("named.memstats"); 9599 } else { 9600 named_main_setmemstats(NULL); 9601 } 9602 9603 obj = NULL; 9604 result = named_config_get(maps, "statistics-file", &obj); 9605 INSIST(result == ISC_R_SUCCESS); 9606 setstring(server, &server->statsfile, cfg_obj_asstring(obj)); 9607 9608 obj = NULL; 9609 result = named_config_get(maps, "dump-file", &obj); 9610 INSIST(result == ISC_R_SUCCESS); 9611 setstring(server, &server->dumpfile, cfg_obj_asstring(obj)); 9612 9613 obj = NULL; 9614 result = named_config_get(maps, "secroots-file", &obj); 9615 INSIST(result == ISC_R_SUCCESS); 9616 setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)); 9617 9618 obj = NULL; 9619 result = named_config_get(maps, "recursing-file", &obj); 9620 INSIST(result == ISC_R_SUCCESS); 9621 setstring(server, &server->recfile, cfg_obj_asstring(obj)); 9622 9623 obj = NULL; 9624 result = named_config_get(maps, "version", &obj); 9625 if (result == ISC_R_SUCCESS) { 9626 setoptstring(server, &server->version, obj); 9627 server->version_set = true; 9628 } else { 9629 server->version_set = false; 9630 } 9631 9632 obj = NULL; 9633 result = named_config_get(maps, "hostname", &obj); 9634 if (result == ISC_R_SUCCESS) { 9635 setoptstring(server, &server->hostname, obj); 9636 server->hostname_set = true; 9637 } else { 9638 server->hostname_set = false; 9639 } 9640 9641 obj = NULL; 9642 result = named_config_get(maps, "server-id", &obj); 9643 server->sctx->usehostname = false; 9644 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 9645 /* The parser translates "hostname" to true */ 9646 server->sctx->usehostname = true; 9647 result = ns_server_setserverid(server->sctx, NULL); 9648 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 9649 /* Found a quoted string */ 9650 result = ns_server_setserverid(server->sctx, 9651 cfg_obj_asstring(obj)); 9652 } else { 9653 result = ns_server_setserverid(server->sctx, NULL); 9654 } 9655 RUNTIME_CHECK(result == ISC_R_SUCCESS); 9656 9657 obj = NULL; 9658 result = named_config_get(maps, "flush-zones-on-shutdown", &obj); 9659 if (result == ISC_R_SUCCESS) { 9660 server->flushonshutdown = cfg_obj_asboolean(obj); 9661 } else { 9662 server->flushonshutdown = false; 9663 } 9664 9665 obj = NULL; 9666 result = named_config_get(maps, "answer-cookie", &obj); 9667 INSIST(result == ISC_R_SUCCESS); 9668 server->sctx->answercookie = cfg_obj_asboolean(obj); 9669 9670 obj = NULL; 9671 result = named_config_get(maps, "cookie-algorithm", &obj); 9672 INSIST(result == ISC_R_SUCCESS); 9673 if (strcasecmp(cfg_obj_asstring(obj), "siphash24") == 0) { 9674 server->sctx->cookiealg = ns_cookiealg_siphash24; 9675 } else { 9676 UNREACHABLE(); 9677 } 9678 9679 obj = NULL; 9680 result = named_config_get(maps, "cookie-secret", &obj); 9681 if (result == ISC_R_SUCCESS) { 9682 const char *str; 9683 bool first = true; 9684 isc_buffer_t b; 9685 unsigned int usedlength; 9686 unsigned int expectedlength; 9687 9688 for (element = cfg_list_first(obj); element != NULL; 9689 element = cfg_list_next(element)) 9690 { 9691 obj = cfg_listelt_value(element); 9692 str = cfg_obj_asstring(obj); 9693 9694 if (first) { 9695 memset(server->sctx->secret, 0, 9696 sizeof(server->sctx->secret)); 9697 isc_buffer_init(&b, server->sctx->secret, 9698 sizeof(server->sctx->secret)); 9699 result = isc_hex_decodestring(str, &b); 9700 if (result != ISC_R_SUCCESS && 9701 result != ISC_R_NOSPACE) 9702 { 9703 goto cleanup_altsecrets; 9704 } 9705 first = false; 9706 } else { 9707 altsecret = isc_mem_get(server->sctx->mctx, 9708 sizeof(*altsecret)); 9709 isc_buffer_init(&b, altsecret->secret, 9710 sizeof(altsecret->secret)); 9711 result = isc_hex_decodestring(str, &b); 9712 if (result != ISC_R_SUCCESS && 9713 result != ISC_R_NOSPACE) 9714 { 9715 isc_mem_put(server->sctx->mctx, 9716 altsecret, 9717 sizeof(*altsecret)); 9718 goto cleanup_altsecrets; 9719 } 9720 ISC_LIST_INITANDAPPEND(altsecrets, altsecret, 9721 link); 9722 } 9723 9724 usedlength = isc_buffer_usedlength(&b); 9725 switch (server->sctx->cookiealg) { 9726 case ns_cookiealg_siphash24: 9727 expectedlength = ISC_SIPHASH24_KEY_LENGTH; 9728 if (usedlength != expectedlength) { 9729 result = ISC_R_RANGE; 9730 isc_log_write( 9731 named_g_lctx, 9732 NAMED_LOGCATEGORY_GENERAL, 9733 NAMED_LOGMODULE_SERVER, 9734 ISC_LOG_ERROR, 9735 "SipHash-2-4 cookie-secret " 9736 "must be 128 bits: %s", 9737 isc_result_totext(result)); 9738 goto cleanup_altsecrets; 9739 } 9740 break; 9741 } 9742 } 9743 } else { 9744 isc_nonce_buf(server->sctx->secret, 9745 sizeof(server->sctx->secret)); 9746 } 9747 9748 /* 9749 * Swap altsecrets lists. 9750 */ 9751 tmpaltsecrets = server->sctx->altsecrets; 9752 server->sctx->altsecrets = altsecrets; 9753 altsecrets = tmpaltsecrets; 9754 9755 (void)named_server_loadnta(server); 9756 9757 #ifdef USE_DNSRPS 9758 /* 9759 * Start and connect to the DNS Response Policy Service 9760 * daemon, dnsrpzd, for each view that uses DNSRPS. 9761 */ 9762 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9763 view = ISC_LIST_NEXT(view, link)) 9764 { 9765 result = dns_dnsrps_connect(view->rpzs); 9766 if (result != ISC_R_SUCCESS) { 9767 view = NULL; 9768 goto cleanup_altsecrets; 9769 } 9770 } 9771 #endif /* ifdef USE_DNSRPS */ 9772 9773 /* 9774 * Record the time of most recent configuration 9775 */ 9776 named_g_configtime = isc_time_now(); 9777 9778 isc_loopmgr_resume(named_g_loopmgr); 9779 exclusive = false; 9780 9781 /* Take back root privileges temporarily */ 9782 if (first_time) { 9783 named_os_restoreuser(); 9784 } 9785 9786 /* Configure the statistics channel(s) */ 9787 result = named_statschannels_configure(named_g_server, config, 9788 named_g_aclconfctx); 9789 if (result != ISC_R_SUCCESS) { 9790 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9791 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9792 "configuring statistics server(s): %s", 9793 isc_result_totext(result)); 9794 goto cleanup_altsecrets; 9795 } 9796 9797 /* 9798 * Bind the control port(s). 9799 */ 9800 result = named_controls_configure(named_g_server->controls, config, 9801 named_g_aclconfctx); 9802 if (result != ISC_R_SUCCESS) { 9803 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9804 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9805 "binding control channel(s): %s", 9806 isc_result_totext(result)); 9807 goto cleanup_altsecrets; 9808 } 9809 9810 (void)ns_interfacemgr_scan(server->interfacemgr, true, true); 9811 9812 /* 9813 * Permanently drop root privileges now. 9814 */ 9815 if (first_time) { 9816 named_os_changeuser(true); 9817 } 9818 9819 /* 9820 * These cleans up either the old production view list 9821 * or our temporary list depending on whether they 9822 * were swapped above or not. 9823 */ 9824 cleanup_altsecrets: 9825 while ((altsecret = ISC_LIST_HEAD(altsecrets)) != NULL) { 9826 ISC_LIST_UNLINK(altsecrets, altsecret, link); 9827 isc_mem_put(server->sctx->mctx, altsecret, sizeof(*altsecret)); 9828 } 9829 9830 cleanup_logc: 9831 if (logc != NULL) { 9832 isc_logconfig_destroy(&logc); 9833 } 9834 9835 cleanup_cachelist: 9836 while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { 9837 ISC_LIST_UNLINK(cachelist, nsc, link); 9838 dns_cache_detach(&nsc->cache); 9839 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 9840 } 9841 9842 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 9843 9844 cleanup_viewlist: 9845 for (dns_view_t *view = ISC_LIST_HEAD(viewlist); view != NULL; 9846 view = view_next) 9847 { 9848 view_next = ISC_LIST_NEXT(view, link); 9849 ISC_LIST_UNLINK(viewlist, view, link); 9850 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) 9851 { 9852 dns_view_setviewrevert(view); 9853 (void)dns_view_apply(view, false, NULL, removed, view); 9854 } 9855 dns_view_detach(&view); 9856 } 9857 9858 cleanup_kasplist: 9859 for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) { 9860 kasp_next = ISC_LIST_NEXT(kasp, link); 9861 ISC_LIST_UNLINK(kasplist, kasp, link); 9862 dns_kasp_detach(&kasp); 9863 } 9864 9865 cleanup_keystorelist: 9866 for (keystore = ISC_LIST_HEAD(keystorelist); keystore != NULL; 9867 keystore = keystore_next) 9868 { 9869 keystore_next = ISC_LIST_NEXT(keystore, link); 9870 ISC_LIST_UNLINK(keystorelist, keystore, link); 9871 dns_keystore_detach(&keystore); 9872 } 9873 9874 cleanup_v6portset: 9875 isc_portset_destroy(named_g_mctx, &v6portset); 9876 9877 cleanup_v4portset: 9878 isc_portset_destroy(named_g_mctx, &v4portset); 9879 9880 cleanup_bindkeys_parser: 9881 9882 if (bindkeys_parser != NULL) { 9883 if (bindkeys != NULL) { 9884 cfg_obj_destroy(bindkeys_parser, &bindkeys); 9885 } 9886 cfg_parser_destroy(&bindkeys_parser); 9887 } 9888 9889 cleanup_config: 9890 cfg_obj_destroy(conf_parser, &config); 9891 9892 cleanup_conf_parser: 9893 cfg_parser_destroy(&conf_parser); 9894 9895 cleanup_exclusive: 9896 if (exclusive) { 9897 isc_loopmgr_resume(named_g_loopmgr); 9898 } 9899 9900 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9901 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9902 "load_configuration: %s", isc_result_totext(result)); 9903 9904 return result; 9905 } 9906 9907 static isc_result_t 9908 view_loaded(void *arg) { 9909 isc_result_t result; 9910 ns_zoneload_t *zl = (ns_zoneload_t *)arg; 9911 9912 /* 9913 * Force zone maintenance. Do this after loading 9914 * so that we know when we need to force AXFR of 9915 * secondary zones whose master files are missing. 9916 * 9917 * We use the zoneload reference counter to let us 9918 * know when all views are finished. 9919 */ 9920 if (isc_refcount_decrement(&zl->refs) == 1) { 9921 named_server_t *server = zl->server; 9922 bool reconfig = zl->reconfig; 9923 dns_view_t *view = NULL; 9924 9925 isc_refcount_destroy(&zl->refs); 9926 isc_mem_put(server->mctx, zl, sizeof(*zl)); 9927 9928 /* 9929 * To maintain compatibility with log parsing tools that might 9930 * be looking for this string after "rndc reconfig", we keep it 9931 * as it is 9932 */ 9933 if (reconfig) { 9934 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9935 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9936 "any newly configured zones are now " 9937 "loaded"); 9938 } else { 9939 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9940 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 9941 "all zones loaded"); 9942 } 9943 9944 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9945 view = ISC_LIST_NEXT(view, link)) 9946 { 9947 if (view->managed_keys != NULL) { 9948 result = dns_zone_synckeyzone( 9949 view->managed_keys); 9950 if (result != ISC_R_SUCCESS) { 9951 isc_log_write( 9952 named_g_lctx, 9953 DNS_LOGCATEGORY_DNSSEC, 9954 DNS_LOGMODULE_DNSSEC, 9955 ISC_LOG_ERROR, 9956 "failed to initialize " 9957 "managed-keys for view %s " 9958 "(%s): DNSSEC validation is " 9959 "at risk", 9960 view->name, 9961 isc_result_totext(result)); 9962 } 9963 } 9964 } 9965 9966 CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr), 9967 "forcing zone maintenance"); 9968 9969 named_os_started(); 9970 9971 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9972 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 9973 "FIPS mode is %s", 9974 isc_fips_mode() ? "enabled" : "disabled"); 9975 9976 #if HAVE_LIBSYSTEMD 9977 sd_notifyf(0, 9978 "READY=1\n" 9979 "STATUS=running\n" 9980 "MAINPID=%" PRId64 "\n", 9981 (int64_t)getpid()); 9982 #endif /* HAVE_LIBSYSTEMD */ 9983 9984 atomic_store(&server->reload_status, NAMED_RELOAD_DONE); 9985 9986 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9987 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 9988 "running"); 9989 } 9990 9991 return ISC_R_SUCCESS; 9992 } 9993 9994 static isc_result_t 9995 load_zones(named_server_t *server, bool reconfig) { 9996 isc_result_t result = ISC_R_SUCCESS; 9997 ns_zoneload_t *zl = NULL; 9998 dns_view_t *view = NULL; 9999 10000 zl = isc_mem_get(server->mctx, sizeof(*zl)); 10001 zl->server = server; 10002 zl->reconfig = reconfig; 10003 10004 isc_loopmgr_pause(named_g_loopmgr); 10005 10006 isc_refcount_init(&zl->refs, 1); 10007 10008 /* 10009 * Schedule zones to be loaded from disk. 10010 */ 10011 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10012 view = ISC_LIST_NEXT(view, link)) 10013 { 10014 if (view->managed_keys != NULL) { 10015 result = dns_zone_load(view->managed_keys, false); 10016 if (result != ISC_R_SUCCESS && 10017 result != DNS_R_UPTODATE && 10018 result != DNS_R_CONTINUE) 10019 { 10020 goto cleanup; 10021 } 10022 } 10023 if (view->redirect != NULL) { 10024 result = dns_zone_load(view->redirect, false); 10025 if (result != ISC_R_SUCCESS && 10026 result != DNS_R_UPTODATE && 10027 result != DNS_R_CONTINUE) 10028 { 10029 goto cleanup; 10030 } 10031 } 10032 10033 /* 10034 * 'dns_view_asyncload' calls view_loaded if there are no 10035 * zones. 10036 */ 10037 isc_refcount_increment(&zl->refs); 10038 result = dns_view_asyncload(view, reconfig, view_loaded, zl); 10039 if (result != ISC_R_SUCCESS) { 10040 isc_refcount_decrement1(&zl->refs); 10041 goto cleanup; 10042 } 10043 } 10044 10045 cleanup: 10046 if (isc_refcount_decrement(&zl->refs) == 1) { 10047 isc_refcount_destroy(&zl->refs); 10048 isc_mem_put(server->mctx, zl, sizeof(*zl)); 10049 } 10050 10051 isc_loopmgr_resume(named_g_loopmgr); 10052 10053 return result; 10054 } 10055 10056 static void 10057 run_server(void *arg) { 10058 isc_result_t result; 10059 named_server_t *server = (named_server_t *)arg; 10060 dns_geoip_databases_t *geoip = NULL; 10061 10062 dns_zonemgr_create(named_g_mctx, named_g_netmgr, &server->zonemgr); 10063 10064 CHECKFATAL(dns_dispatchmgr_create(named_g_mctx, named_g_loopmgr, 10065 named_g_netmgr, &named_g_dispatchmgr), 10066 "creating dispatch manager"); 10067 10068 dns_dispatchmgr_setstats(named_g_dispatchmgr, server->resolverstats); 10069 10070 #if defined(HAVE_GEOIP2) 10071 geoip = named_g_geoip; 10072 #else /* if defined(HAVE_GEOIP2) */ 10073 geoip = NULL; 10074 #endif /* if defined(HAVE_GEOIP2) */ 10075 10076 CHECKFATAL(ns_interfacemgr_create(named_g_mctx, server->sctx, 10077 named_g_loopmgr, named_g_netmgr, 10078 named_g_dispatchmgr, geoip, 10079 &server->interfacemgr), 10080 "creating interface manager"); 10081 10082 isc_timer_create(named_g_mainloop, interface_timer_tick, server, 10083 &server->interface_timer); 10084 10085 isc_timer_create(named_g_mainloop, heartbeat_timer_tick, server, 10086 &server->heartbeat_timer); 10087 10088 isc_timer_create(named_g_mainloop, tat_timer_tick, server, 10089 &server->tat_timer); 10090 10091 isc_timer_create(named_g_mainloop, pps_timer_tick, server, 10092 &server->pps_timer); 10093 10094 CHECKFATAL( 10095 cfg_parser_create(named_g_mctx, named_g_lctx, &named_g_parser), 10096 "creating default configuration parser"); 10097 10098 CHECKFATAL(cfg_parser_create(named_g_mctx, named_g_lctx, 10099 &named_g_addparser), 10100 "creating additional configuration parser"); 10101 10102 CHECKFATAL(load_configuration(named_g_conffile, server, true), 10103 "loading configuration"); 10104 10105 CHECKFATAL(load_zones(server, false), "loading zones"); 10106 #ifdef ENABLE_AFL 10107 named_g_run_done = true; 10108 #endif /* ifdef ENABLE_AFL */ 10109 } 10110 10111 void 10112 named_server_flushonshutdown(named_server_t *server, bool flush) { 10113 REQUIRE(NAMED_SERVER_VALID(server)); 10114 10115 server->flushonshutdown = flush; 10116 } 10117 10118 static void 10119 shutdown_server(void *arg) { 10120 named_server_t *server = (named_server_t *)arg; 10121 dns_view_t *view = NULL, *view_next = NULL; 10122 dns_kasp_t *kasp = NULL, *kasp_next = NULL; 10123 dns_keystore_t *keystore = NULL, *keystore_next = NULL; 10124 bool flush = server->flushonshutdown; 10125 named_cache_t *nsc = NULL; 10126 10127 #if HAVE_LIBSYSTEMD 10128 sd_notify(0, "STOPPING=1\n"); 10129 #endif /* HAVE_LIBSYSTEMD */ 10130 10131 isc_signal_stop(server->sighup); 10132 isc_signal_destroy(&server->sighup); 10133 10134 /* 10135 * We need to shutdown the interface before going 10136 * exclusive (which would pause the netmgr). 10137 */ 10138 ns_interfacemgr_shutdown(server->interfacemgr); 10139 10140 named_controls_shutdown(server->controls); 10141 10142 named_statschannels_shutdown(server); 10143 10144 isc_loopmgr_pause(named_g_loopmgr); 10145 10146 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10147 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "shutting down%s", 10148 flush ? ": flushing changes" : ""); 10149 10150 cleanup_session_key(server, server->mctx); 10151 10152 if (named_g_aclconfctx != NULL) { 10153 cfg_aclconfctx_detach(&named_g_aclconfctx); 10154 } 10155 10156 cfg_obj_destroy(named_g_parser, &named_g_config); 10157 cfg_parser_destroy(&named_g_parser); 10158 cfg_parser_destroy(&named_g_addparser); 10159 10160 (void)named_server_saventa(server); 10161 10162 for (kasp = ISC_LIST_HEAD(server->kasplist); kasp != NULL; 10163 kasp = kasp_next) 10164 { 10165 kasp_next = ISC_LIST_NEXT(kasp, link); 10166 ISC_LIST_UNLINK(server->kasplist, kasp, link); 10167 dns_kasp_detach(&kasp); 10168 } 10169 10170 for (keystore = ISC_LIST_HEAD(server->keystorelist); keystore != NULL; 10171 keystore = keystore_next) 10172 { 10173 keystore_next = ISC_LIST_NEXT(keystore, link); 10174 ISC_LIST_UNLINK(server->keystorelist, keystore, link); 10175 dns_keystore_detach(&keystore); 10176 } 10177 10178 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10179 view = view_next) 10180 { 10181 view_next = ISC_LIST_NEXT(view, link); 10182 ISC_LIST_UNLINK(server->viewlist, view, link); 10183 dns_view_flushonshutdown(view, flush); 10184 dns_view_detach(&view); 10185 } 10186 10187 /* 10188 * Shut down all dyndb instances. 10189 */ 10190 dns_dyndb_cleanup(true); 10191 10192 while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { 10193 ISC_LIST_UNLINK(server->cachelist, nsc, link); 10194 dns_cache_detach(&nsc->cache); 10195 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 10196 } 10197 10198 isc_timer_destroy(&server->interface_timer); 10199 isc_timer_destroy(&server->heartbeat_timer); 10200 isc_timer_destroy(&server->pps_timer); 10201 isc_timer_destroy(&server->tat_timer); 10202 10203 ns_interfacemgr_detach(&server->interfacemgr); 10204 10205 dns_dispatchmgr_detach(&named_g_dispatchmgr); 10206 10207 dns_zonemgr_shutdown(server->zonemgr); 10208 10209 #if defined(HAVE_GEOIP2) 10210 named_geoip_shutdown(); 10211 #endif /* HAVE_GEOIP2 */ 10212 10213 dns_db_detach(&server->in_roothints); 10214 10215 isc_loopmgr_resume(named_g_loopmgr); 10216 } 10217 10218 static isc_result_t 10219 get_matching_view_sync(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, 10220 dns_message_t *message, dns_aclenv_t *env, 10221 isc_result_t *sigresult, dns_view_t **viewp) { 10222 dns_view_t *view; 10223 10224 /* 10225 * We should not be running synchronous view matching if signature 10226 * checking involves SIG(0). TSIG has priority of SIG(0), so if TSIG 10227 * is set then we proceed anyway. 10228 */ 10229 INSIST(message->tsigkey != NULL || message->tsig != NULL || 10230 message->sig0 == NULL); 10231 10232 for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL; 10233 view = ISC_LIST_NEXT(view, link)) 10234 { 10235 if (message->rdclass == view->rdclass || 10236 message->rdclass == dns_rdataclass_any) 10237 { 10238 const dns_name_t *tsig = NULL; 10239 10240 dns_message_resetsig(message); 10241 *sigresult = dns_message_checksig(message, view); 10242 if (*sigresult == ISC_R_SUCCESS) { 10243 tsig = dns_tsigkey_identity(message->tsigkey); 10244 } 10245 10246 if (dns_acl_allowed(srcaddr, tsig, view->matchclients, 10247 env) && 10248 dns_acl_allowed(destaddr, tsig, 10249 view->matchdestinations, env) && 10250 !(view->matchrecursiveonly && 10251 (message->flags & DNS_MESSAGEFLAG_RD) == 0)) 10252 { 10253 dns_view_attach(view, viewp); 10254 return ISC_R_SUCCESS; 10255 } 10256 } 10257 } 10258 10259 return ISC_R_NOTFOUND; 10260 } 10261 10262 static void 10263 get_matching_view_done(void *cbarg) { 10264 matching_view_ctx_t *mvctx = cbarg; 10265 dns_message_t *message = mvctx->message; 10266 10267 if (*mvctx->viewmatchresult == ISC_R_SUCCESS) { 10268 INSIST(mvctx->view != NULL); 10269 dns_view_attach(mvctx->view, mvctx->viewp); 10270 } 10271 10272 mvctx->cb(mvctx->cbarg); 10273 10274 if (mvctx->quota_result == ISC_R_SUCCESS) { 10275 isc_quota_release(&mvctx->sctx->sig0checksquota); 10276 } 10277 if (mvctx->view != NULL) { 10278 dns_view_detach(&mvctx->view); 10279 } 10280 isc_loop_detach(&mvctx->loop); 10281 ns_server_detach(&mvctx->sctx); 10282 isc_mem_put(message->mctx, mvctx, sizeof(*mvctx)); 10283 dns_message_detach(&message); 10284 } 10285 10286 static dns_view_t * 10287 get_matching_view_next(dns_view_t *view, dns_rdataclass_t rdclass) { 10288 if (view == NULL) { 10289 view = ISC_LIST_HEAD(named_g_server->viewlist); 10290 } else { 10291 view = ISC_LIST_NEXT(view, link); 10292 } 10293 while (true) { 10294 if (view == NULL || rdclass == view->rdclass || 10295 rdclass == dns_rdataclass_any) 10296 { 10297 return view; 10298 } 10299 view = ISC_LIST_NEXT(view, link); 10300 }; 10301 } 10302 10303 static void 10304 get_matching_view_continue(void *cbarg, isc_result_t result) { 10305 matching_view_ctx_t *mvctx = cbarg; 10306 dns_view_t *view = NULL; 10307 const dns_name_t *tsig = NULL; 10308 10309 *mvctx->sigresult = result; 10310 10311 if (result == ISC_R_SUCCESS) { 10312 tsig = dns_tsigkey_identity(mvctx->message->tsigkey); 10313 } 10314 10315 if (dns_acl_allowed(mvctx->srcaddr, tsig, mvctx->view->matchclients, 10316 mvctx->env) && 10317 dns_acl_allowed(mvctx->destaddr, tsig, 10318 mvctx->view->matchdestinations, mvctx->env) && 10319 !(mvctx->view->matchrecursiveonly && 10320 (mvctx->message->flags & DNS_MESSAGEFLAG_RD) == 0)) 10321 { 10322 /* 10323 * A matching view is found. 10324 */ 10325 *mvctx->viewmatchresult = ISC_R_SUCCESS; 10326 get_matching_view_done(cbarg); 10327 return; 10328 } 10329 10330 dns_message_resetsig(mvctx->message); 10331 10332 view = get_matching_view_next(mvctx->view, mvctx->message->rdclass); 10333 dns_view_detach(&mvctx->view); 10334 if (view != NULL) { 10335 /* 10336 * Try the next view. 10337 */ 10338 dns_view_attach(view, &mvctx->view); 10339 result = dns_message_checksig_async( 10340 mvctx->message, view, mvctx->loop, 10341 get_matching_view_continue, mvctx); 10342 INSIST(result == DNS_R_WAIT); 10343 return; 10344 } 10345 10346 /* 10347 * No matching view is found. 10348 */ 10349 *mvctx->viewmatchresult = ISC_R_NOTFOUND; 10350 get_matching_view_done(cbarg); 10351 } 10352 10353 /*% 10354 * Find a view that matches the source and destination addresses of a query. 10355 */ 10356 static isc_result_t 10357 get_matching_view(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, 10358 dns_message_t *message, dns_aclenv_t *env, ns_server_t *sctx, 10359 isc_loop_t *loop, isc_job_cb cb, void *cbarg, 10360 isc_result_t *sigresult, isc_result_t *viewmatchresult, 10361 dns_view_t **viewp) { 10362 dns_view_t *view = NULL; 10363 isc_result_t result; 10364 10365 REQUIRE(message != NULL); 10366 REQUIRE(sctx != NULL); 10367 REQUIRE(loop == NULL || cb != NULL); 10368 REQUIRE(sigresult != NULL); 10369 REQUIRE(viewmatchresult != NULL); 10370 REQUIRE(viewp != NULL && *viewp == NULL); 10371 10372 /* No offloading is requested if the loop is unset. */ 10373 if (loop == NULL) { 10374 *viewmatchresult = get_matching_view_sync( 10375 srcaddr, destaddr, message, env, sigresult, viewp); 10376 return *viewmatchresult; 10377 } 10378 10379 /* Also no offloading when there is no view at all to match against. */ 10380 view = get_matching_view_next(NULL, message->rdclass); 10381 if (view == NULL) { 10382 *viewmatchresult = ISC_R_NOTFOUND; 10383 return *viewmatchresult; 10384 } 10385 10386 dns_message_resetsig(message); 10387 10388 matching_view_ctx_t *mvctx = isc_mem_get(message->mctx, sizeof(*mvctx)); 10389 *mvctx = (matching_view_ctx_t){ 10390 .srcaddr = srcaddr, 10391 .destaddr = destaddr, 10392 .env = env, 10393 .cb = cb, 10394 .cbarg = cbarg, 10395 .sigresult = sigresult, 10396 .viewmatchresult = viewmatchresult, 10397 .quota_result = ISC_R_UNSET, 10398 .viewp = viewp, 10399 }; 10400 ns_server_attach(sctx, &mvctx->sctx); 10401 isc_loop_attach(loop, &mvctx->loop); 10402 dns_message_attach(message, &mvctx->message); 10403 10404 /* 10405 * If the message has a SIG0 signature which we are going to 10406 * check, and the client is not exempt from the SIG(0) quota, 10407 * then acquire a quota. TSIG has priority over SIG(0), so if 10408 * TSIG is set then we don't care. 10409 */ 10410 if (message->tsigkey == NULL && message->tsig == NULL && 10411 message->sig0 != NULL) 10412 { 10413 if (sctx->sig0checksquota_exempt != NULL) { 10414 int exempt_match; 10415 10416 result = dns_acl_match(srcaddr, NULL, 10417 sctx->sig0checksquota_exempt, 10418 env, &exempt_match, NULL); 10419 if (result == ISC_R_SUCCESS && exempt_match > 0) { 10420 mvctx->quota_result = ISC_R_EXISTS; 10421 } 10422 } 10423 if (mvctx->quota_result == ISC_R_UNSET) { 10424 mvctx->quota_result = 10425 isc_quota_acquire(&sctx->sig0checksquota); 10426 } 10427 if (mvctx->quota_result == ISC_R_SOFTQUOTA) { 10428 isc_quota_release(&sctx->sig0checksquota); 10429 } 10430 if (mvctx->quota_result != ISC_R_SUCCESS && 10431 mvctx->quota_result != ISC_R_EXISTS) 10432 { 10433 *mvctx->viewmatchresult = ISC_R_QUOTA; 10434 isc_async_run(loop, get_matching_view_done, mvctx); 10435 return DNS_R_WAIT; 10436 } 10437 } 10438 10439 dns_view_attach(view, &mvctx->view); 10440 result = dns_message_checksig_async(message, view, loop, 10441 get_matching_view_continue, mvctx); 10442 INSIST(result == DNS_R_WAIT); 10443 10444 return DNS_R_WAIT; 10445 } 10446 10447 void 10448 named_server_create(isc_mem_t *mctx, named_server_t **serverp) { 10449 isc_result_t result; 10450 named_server_t *server = isc_mem_get(mctx, sizeof(*server)); 10451 10452 *server = (named_server_t){ 10453 .mctx = mctx, 10454 .statsfile = isc_mem_strdup(mctx, "named.stats"), 10455 .dumpfile = isc_mem_strdup(mctx, "named_dump.db"), 10456 .secrootsfile = isc_mem_strdup(mctx, "named.secroots"), 10457 .recfile = isc_mem_strdup(mctx, "named.recursing"), 10458 }; 10459 10460 /* Initialize server data structures. */ 10461 ISC_LIST_INIT(server->kasplist); 10462 ISC_LIST_INIT(server->keystorelist); 10463 ISC_LIST_INIT(server->viewlist); 10464 10465 /* Must be first. */ 10466 CHECKFATAL(dst_lib_init(named_g_mctx, named_g_engine), 10467 "initializing DST"); 10468 10469 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, 10470 &server->in_roothints), 10471 "setting up root hints"); 10472 10473 atomic_init(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 10474 10475 ns_server_create(mctx, get_matching_view, &server->sctx); 10476 10477 #if defined(HAVE_GEOIP2) 10478 /* 10479 * GeoIP must be initialized before the interface 10480 * manager (which includes the ACL environment) 10481 * is created. 10482 */ 10483 named_geoip_init(); 10484 #endif /* HAVE_GEOIP2 */ 10485 10486 #ifdef ENABLE_AFL 10487 server->sctx->fuzztype = named_g_fuzz_type; 10488 server->sctx->fuzznotify = named_fuzz_notify; 10489 #endif /* ifdef ENABLE_AFL */ 10490 10491 named_g_mainloop = isc_loop_main(named_g_loopmgr); 10492 10493 isc_loop_setup(named_g_mainloop, run_server, server); 10494 isc_loop_teardown(named_g_mainloop, shutdown_server, server); 10495 10496 /* Add SIGHUP reload handler */ 10497 server->sighup = isc_signal_new( 10498 named_g_loopmgr, named_server_reloadwanted, server, SIGHUP); 10499 10500 isc_stats_create(server->mctx, &server->sockstats, 10501 isc_sockstatscounter_max); 10502 isc_nm_setstats(named_g_netmgr, server->sockstats); 10503 10504 isc_stats_create(named_g_mctx, &server->zonestats, 10505 dns_zonestatscounter_max); 10506 10507 isc_stats_create(named_g_mctx, &server->resolverstats, 10508 dns_resstatscounter_max); 10509 10510 CHECKFATAL(named_controls_create(server, &server->controls), 10511 "named_controls_create"); 10512 10513 ISC_LIST_INIT(server->statschannels); 10514 10515 ISC_LIST_INIT(server->cachelist); 10516 10517 server->magic = NAMED_SERVER_MAGIC; 10518 10519 *serverp = server; 10520 } 10521 10522 void 10523 named_server_destroy(named_server_t **serverp) { 10524 named_server_t *server = *serverp; 10525 REQUIRE(NAMED_SERVER_VALID(server)); 10526 10527 #ifdef HAVE_DNSTAP 10528 if (server->dtenv != NULL) { 10529 dns_dt_detach(&server->dtenv); 10530 } 10531 #endif /* HAVE_DNSTAP */ 10532 10533 #ifdef USE_DNSRPS 10534 dns_dnsrps_server_destroy(); 10535 isc_mem_free(server->mctx, server->dnsrpslib); 10536 #endif /* ifdef USE_DNSRPS */ 10537 10538 named_controls_destroy(&server->controls); 10539 10540 isc_stats_detach(&server->zonestats); 10541 isc_stats_detach(&server->sockstats); 10542 isc_stats_detach(&server->resolverstats); 10543 10544 if (server->sctx != NULL) { 10545 ns_server_detach(&server->sctx); 10546 } 10547 10548 isc_mem_free(server->mctx, server->statsfile); 10549 isc_mem_free(server->mctx, server->dumpfile); 10550 isc_mem_free(server->mctx, server->secrootsfile); 10551 isc_mem_free(server->mctx, server->recfile); 10552 10553 if (server->bindkeysfile != NULL) { 10554 isc_mem_free(server->mctx, server->bindkeysfile); 10555 } 10556 10557 if (server->version != NULL) { 10558 isc_mem_free(server->mctx, server->version); 10559 } 10560 if (server->hostname != NULL) { 10561 isc_mem_free(server->mctx, server->hostname); 10562 } 10563 10564 if (server->zonemgr != NULL) { 10565 dns_zonemgr_detach(&server->zonemgr); 10566 } 10567 10568 dst_lib_destroy(); 10569 10570 INSIST(ISC_LIST_EMPTY(server->kasplist)); 10571 INSIST(ISC_LIST_EMPTY(server->keystorelist)); 10572 INSIST(ISC_LIST_EMPTY(server->viewlist)); 10573 INSIST(ISC_LIST_EMPTY(server->cachelist)); 10574 10575 if (server->tlsctx_server_cache != NULL) { 10576 isc_tlsctx_cache_detach(&server->tlsctx_server_cache); 10577 } 10578 10579 if (server->tlsctx_client_cache != NULL) { 10580 isc_tlsctx_cache_detach(&server->tlsctx_client_cache); 10581 } 10582 10583 server->magic = 0; 10584 isc_mem_put(server->mctx, server, sizeof(*server)); 10585 *serverp = NULL; 10586 } 10587 10588 static void 10589 fatal(const char *msg, isc_result_t result) { 10590 if (named_g_loopmgr_running) { 10591 isc_loopmgr_pause(named_g_loopmgr); 10592 } 10593 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10594 NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "%s: %s", msg, 10595 isc_result_totext(result)); 10596 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10597 NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, 10598 "exiting (due to fatal error)"); 10599 named_os_shutdown(); 10600 _exit(EXIT_FAILURE); 10601 } 10602 10603 static isc_result_t 10604 loadconfig(named_server_t *server) { 10605 isc_result_t result; 10606 result = load_configuration(named_g_conffile, server, false); 10607 if (result == ISC_R_SUCCESS) { 10608 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10609 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10610 "reloading configuration succeeded"); 10611 } else { 10612 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10613 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 10614 "reloading configuration failed: %s", 10615 isc_result_totext(result)); 10616 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 10617 } 10618 10619 return result; 10620 } 10621 10622 static isc_result_t 10623 reload(named_server_t *server) { 10624 isc_result_t result; 10625 10626 atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 10627 #if HAVE_LIBSYSTEMD 10628 char buf[512]; 10629 int n = snprintf(buf, sizeof(buf), 10630 "RELOADING=1\n" 10631 "MONOTONIC_USEC=%" PRIu64 "\n" 10632 "STATUS=reload command received\n", 10633 (uint64_t)isc_time_monotonic() / NS_PER_US); 10634 if (n > 0 && (size_t)n < sizeof(buf)) { 10635 sd_notify(0, buf); 10636 } 10637 #endif /* HAVE_LIBSYSTEMD */ 10638 10639 CHECK(loadconfig(server)); 10640 10641 result = load_zones(server, false); 10642 if (result == ISC_R_SUCCESS) { 10643 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10644 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10645 "reloading zones succeeded"); 10646 } else { 10647 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10648 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 10649 "reloading zones failed: %s", 10650 isc_result_totext(result)); 10651 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 10652 } 10653 cleanup: 10654 #if HAVE_LIBSYSTEMD 10655 sd_notifyf(0, 10656 "READY=1\n" 10657 "STATUS=reload command finished: %s\n", 10658 isc_result_totext(result)); 10659 #endif /* HAVE_LIBSYSTEMD */ 10660 return result; 10661 } 10662 10663 /* 10664 * Handle a reload event (from SIGHUP). 10665 */ 10666 static void 10667 named_server_reload(void *arg) { 10668 named_server_t *server = (named_server_t *)arg; 10669 10670 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10671 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10672 "received SIGHUP signal to reload zones"); 10673 (void)reload(server); 10674 } 10675 10676 void 10677 named_server_reloadwanted(void *arg, int signum) { 10678 named_server_t *server = (named_server_t *)arg; 10679 10680 REQUIRE(signum == SIGHUP); 10681 10682 isc_async_run(named_g_mainloop, named_server_reload, server); 10683 } 10684 10685 void 10686 named_server_scan_interfaces(named_server_t *server) { 10687 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10688 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 10689 "automatic interface rescan"); 10690 10691 ns_interfacemgr_scan(server->interfacemgr, true, false); 10692 } 10693 10694 /* 10695 * Get the next token from lexer 'lex'. 10696 * 10697 * NOTE: the token value for string tokens always uses the same pointer 10698 * value. Multiple calls to this function on the same lexer will always 10699 * return either that value (lex->data) or NULL. It is necessary to copy 10700 * the token into local storage if it needs to be referenced after the next 10701 * call to next_token(). 10702 */ 10703 static char * 10704 next_token(isc_lex_t *lex, isc_buffer_t **text) { 10705 isc_result_t result; 10706 isc_token_t token; 10707 10708 token.type = isc_tokentype_unknown; 10709 result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF | ISC_LEXOPT_QSTRING, 10710 &token); 10711 10712 switch (result) { 10713 case ISC_R_NOMORE: 10714 (void)isc_lex_close(lex); 10715 break; 10716 case ISC_R_SUCCESS: 10717 if (token.type == isc_tokentype_eof) { 10718 (void)isc_lex_close(lex); 10719 } 10720 break; 10721 case ISC_R_NOSPACE: 10722 if (text != NULL) { 10723 (void)putstr(text, "token too large"); 10724 (void)putnull(text); 10725 } 10726 return NULL; 10727 default: 10728 if (text != NULL) { 10729 (void)putstr(text, isc_result_totext(result)); 10730 (void)putnull(text); 10731 } 10732 return NULL; 10733 } 10734 10735 if (token.type == isc_tokentype_string || 10736 token.type == isc_tokentype_qstring) 10737 { 10738 return token.value.as_textregion.base; 10739 } 10740 10741 return NULL; 10742 } 10743 10744 /* 10745 * Find the zone specified in the control channel command, if any. 10746 * If a zone is specified, point '*zonep' at it, otherwise 10747 * set '*zonep' to NULL, and f 'zonename' is not NULL, copy 10748 * the zone name into it (N.B. 'zonename' must have space to hold 10749 * a full DNS name). 10750 * 10751 * If 'zonetxt' is set, the caller has already pulled a token 10752 * off the command line that is to be used as the zone name. (This 10753 * is sometimes done when it's necessary to check for an optional 10754 * argument before the zone name, as in "rndc sync [-clean] zone".) 10755 */ 10756 static isc_result_t 10757 zone_from_args(named_server_t *server, isc_lex_t *lex, const char *zonetxt, 10758 dns_zone_t **zonep, char *zonename, isc_buffer_t **text, 10759 bool skip) { 10760 char *ptr; 10761 char *classtxt; 10762 const char *viewtxt = NULL; 10763 dns_fixedname_t fname; 10764 dns_name_t *name; 10765 isc_result_t result; 10766 dns_view_t *view = NULL; 10767 dns_rdataclass_t rdclass; 10768 char problem[DNS_NAME_FORMATSIZE + 500] = ""; 10769 char zonebuf[DNS_NAME_FORMATSIZE]; 10770 bool redirect = false; 10771 10772 REQUIRE(zonep != NULL && *zonep == NULL); 10773 10774 if (skip) { 10775 /* Skip the command name. */ 10776 ptr = next_token(lex, text); 10777 if (ptr == NULL) { 10778 return ISC_R_UNEXPECTEDEND; 10779 } 10780 } 10781 10782 /* Look for the zone name. */ 10783 if (zonetxt == NULL) { 10784 zonetxt = next_token(lex, text); 10785 } 10786 if (zonetxt == NULL) { 10787 return ISC_R_SUCCESS; 10788 } 10789 10790 /* Copy zonetxt because it'll be overwritten by next_token() */ 10791 /* To locate a zone named "-redirect" use "-redirect." */ 10792 if (strcmp(zonetxt, "-redirect") == 0) { 10793 redirect = true; 10794 strlcpy(zonebuf, ".", DNS_NAME_FORMATSIZE); 10795 } else { 10796 strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE); 10797 } 10798 if (zonename != NULL) { 10799 strlcpy(zonename, redirect ? "." : zonetxt, 10800 DNS_NAME_FORMATSIZE); 10801 } 10802 10803 name = dns_fixedname_initname(&fname); 10804 CHECK(dns_name_fromstring(name, zonebuf, dns_rootname, 0, NULL)); 10805 10806 /* Look for the optional class name. */ 10807 classtxt = next_token(lex, text); 10808 if (classtxt != NULL) { 10809 isc_textregion_t r; 10810 r.base = classtxt; 10811 r.length = strlen(classtxt); 10812 CHECK(dns_rdataclass_fromtext(&rdclass, &r)); 10813 10814 /* Look for the optional view name. */ 10815 viewtxt = next_token(lex, text); 10816 } else { 10817 rdclass = dns_rdataclass_in; 10818 } 10819 10820 if (viewtxt == NULL) { 10821 if (redirect) { 10822 result = dns_viewlist_find(&server->viewlist, 10823 "_default", 10824 dns_rdataclass_in, &view); 10825 if (result != ISC_R_SUCCESS || view->redirect == NULL) { 10826 result = ISC_R_NOTFOUND; 10827 snprintf(problem, sizeof(problem), 10828 "redirect zone not found in " 10829 "_default view"); 10830 } else { 10831 dns_zone_attach(view->redirect, zonep); 10832 result = ISC_R_SUCCESS; 10833 } 10834 } else { 10835 result = dns_viewlist_findzone(&server->viewlist, name, 10836 classtxt == NULL, 10837 rdclass, zonep); 10838 if (result == ISC_R_NOTFOUND) { 10839 snprintf(problem, sizeof(problem), 10840 "no matching zone '%s' in any view", 10841 zonebuf); 10842 } else if (result == ISC_R_MULTIPLE) { 10843 snprintf(problem, sizeof(problem), 10844 "zone '%s' was found in multiple " 10845 "views", 10846 zonebuf); 10847 } 10848 } 10849 } else { 10850 result = dns_viewlist_find(&server->viewlist, viewtxt, rdclass, 10851 &view); 10852 if (result != ISC_R_SUCCESS) { 10853 snprintf(problem, sizeof(problem), 10854 "no matching view '%s'", viewtxt); 10855 goto report; 10856 } 10857 10858 if (redirect) { 10859 if (view->redirect != NULL) { 10860 dns_zone_attach(view->redirect, zonep); 10861 result = ISC_R_SUCCESS; 10862 } else { 10863 result = ISC_R_NOTFOUND; 10864 } 10865 } else { 10866 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 10867 zonep); 10868 } 10869 if (result != ISC_R_SUCCESS) { 10870 snprintf(problem, sizeof(problem), 10871 "no matching zone '%s' in view '%s'", zonebuf, 10872 viewtxt); 10873 } 10874 } 10875 10876 /* Partial match? */ 10877 if (result != ISC_R_SUCCESS && *zonep != NULL) { 10878 dns_zone_detach(zonep); 10879 } 10880 if (result == DNS_R_PARTIALMATCH) { 10881 result = ISC_R_NOTFOUND; 10882 } 10883 report: 10884 if (result != ISC_R_SUCCESS) { 10885 isc_result_t tresult; 10886 10887 tresult = putstr(text, problem); 10888 if (tresult == ISC_R_SUCCESS) { 10889 (void)putnull(text); 10890 } 10891 } 10892 10893 cleanup: 10894 if (view != NULL) { 10895 dns_view_detach(&view); 10896 } 10897 10898 return result; 10899 } 10900 10901 /* 10902 * Act on a "retransfer" command from the command channel. 10903 */ 10904 isc_result_t 10905 named_server_retransfercommand(named_server_t *server, isc_lex_t *lex, 10906 isc_buffer_t **text) { 10907 isc_result_t result; 10908 const char *arg = NULL; 10909 dns_zone_t *zone = NULL; 10910 dns_zone_t *raw = NULL; 10911 dns_zonetype_t type; 10912 bool force = false; 10913 10914 REQUIRE(text != NULL); 10915 10916 /* Skip the command name. */ 10917 (void)next_token(lex, text); 10918 10919 arg = next_token(lex, text); 10920 if (arg != NULL && (strcmp(arg, "-force") == 0)) { 10921 force = true; 10922 arg = next_token(lex, text); 10923 } 10924 10925 result = zone_from_args(server, lex, arg, &zone, NULL, text, false); 10926 if (result != ISC_R_SUCCESS) { 10927 return result; 10928 } 10929 if (zone == NULL) { 10930 return ISC_R_UNEXPECTEDEND; 10931 } 10932 dns_zone_getraw(zone, &raw); 10933 if (raw != NULL) { 10934 dns_zone_detach(&zone); 10935 dns_zone_attach(raw, &zone); 10936 dns_zone_detach(&raw); 10937 } 10938 type = dns_zone_gettype(zone); 10939 if (type == dns_zone_secondary || type == dns_zone_mirror || 10940 type == dns_zone_stub || 10941 (type == dns_zone_redirect && 10942 dns_zone_getredirecttype(zone) == dns_zone_secondary)) 10943 { 10944 if (force) { 10945 dns_zone_stopxfr(zone); 10946 } 10947 dns_zone_forcexfr(zone); 10948 } else { 10949 (void)putstr(text, "retransfer: inappropriate zone type: "); 10950 (void)putstr(text, dns_zonetype_name(type)); 10951 if (type == dns_zone_redirect) { 10952 type = dns_zone_getredirecttype(zone); 10953 (void)putstr(text, "("); 10954 (void)putstr(text, dns_zonetype_name(type)); 10955 (void)putstr(text, ")"); 10956 } 10957 (void)putnull(text); 10958 result = ISC_R_FAILURE; 10959 } 10960 dns_zone_detach(&zone); 10961 return result; 10962 } 10963 10964 /* 10965 * Act on a "reload" command from the command channel. 10966 */ 10967 isc_result_t 10968 named_server_reloadcommand(named_server_t *server, isc_lex_t *lex, 10969 isc_buffer_t **text) { 10970 isc_result_t result; 10971 dns_zone_t *zone = NULL; 10972 dns_zonetype_t type; 10973 const char *msg = NULL; 10974 10975 REQUIRE(text != NULL); 10976 10977 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 10978 if (result != ISC_R_SUCCESS) { 10979 return result; 10980 } 10981 if (zone == NULL) { 10982 result = reload(server); 10983 if (result == ISC_R_SUCCESS) { 10984 msg = "server reload successful"; 10985 } 10986 } else { 10987 type = dns_zone_gettype(zone); 10988 if (type == dns_zone_secondary || type == dns_zone_mirror || 10989 type == dns_zone_stub) 10990 { 10991 dns_zone_refresh(zone); 10992 dns_zone_detach(&zone); 10993 msg = "zone refresh queued"; 10994 } else { 10995 result = dns_zone_load(zone, false); 10996 dns_zone_detach(&zone); 10997 switch (result) { 10998 case ISC_R_SUCCESS: 10999 msg = "zone reload successful"; 11000 break; 11001 case DNS_R_CONTINUE: 11002 msg = "zone reload queued"; 11003 result = ISC_R_SUCCESS; 11004 break; 11005 case DNS_R_UPTODATE: 11006 msg = "zone reload up-to-date"; 11007 result = ISC_R_SUCCESS; 11008 break; 11009 default: 11010 /* failure message will be generated by rndc */ 11011 break; 11012 } 11013 } 11014 } 11015 if (msg != NULL) { 11016 (void)putstr(text, msg); 11017 (void)putnull(text); 11018 } 11019 return result; 11020 } 11021 11022 /* 11023 * Act on a "reconfig" command from the command channel. 11024 */ 11025 isc_result_t 11026 named_server_reconfigcommand(named_server_t *server) { 11027 isc_result_t result; 11028 atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 11029 #if HAVE_LIBSYSTEMD 11030 char buf[512]; 11031 int n = snprintf(buf, sizeof(buf), 11032 "RELOADING=1\n" 11033 "MONOTONIC_USEC=%" PRIu64 "\n" 11034 "STATUS=reconfig command received\n", 11035 (uint64_t)isc_time_monotonic() / NS_PER_US); 11036 if (n > 0 && (size_t)n < sizeof(buf)) { 11037 sd_notify(0, buf); 11038 } 11039 #endif /* HAVE_LIBSYSTEMD */ 11040 11041 CHECK(loadconfig(server)); 11042 11043 result = load_zones(server, true); 11044 if (result == ISC_R_SUCCESS) { 11045 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11046 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11047 "scheduled loading new zones"); 11048 } else { 11049 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11050 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11051 "loading new zones failed: %s", 11052 isc_result_totext(result)); 11053 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 11054 } 11055 cleanup: 11056 #if HAVE_LIBSYSTEMD 11057 sd_notifyf(0, 11058 "READY=1\n" 11059 "STATUS=reconfig command finished: %s\n", 11060 isc_result_totext(result)); 11061 #endif /* HAVE_LIBSYSTEMD */ 11062 return result; 11063 } 11064 11065 /* 11066 * Act on a "notify" command from the command channel. 11067 */ 11068 isc_result_t 11069 named_server_notifycommand(named_server_t *server, isc_lex_t *lex, 11070 isc_buffer_t **text) { 11071 isc_result_t result; 11072 dns_zone_t *zone = NULL; 11073 const char msg[] = "zone notify queued"; 11074 11075 REQUIRE(text != NULL); 11076 11077 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11078 if (result != ISC_R_SUCCESS) { 11079 return result; 11080 } 11081 if (zone == NULL) { 11082 return ISC_R_UNEXPECTEDEND; 11083 } 11084 11085 dns_zone_notify(zone); 11086 dns_zone_detach(&zone); 11087 (void)putstr(text, msg); 11088 (void)putnull(text); 11089 11090 return ISC_R_SUCCESS; 11091 } 11092 11093 /* 11094 * Act on a "refresh" command from the command channel. 11095 */ 11096 isc_result_t 11097 named_server_refreshcommand(named_server_t *server, isc_lex_t *lex, 11098 isc_buffer_t **text) { 11099 isc_result_t result; 11100 dns_zone_t *zone = NULL, *raw = NULL; 11101 const char msg1[] = "zone refresh queued"; 11102 const char msg2[] = "not a secondary, mirror, or stub zone"; 11103 dns_zonetype_t type; 11104 11105 REQUIRE(text != NULL); 11106 11107 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11108 if (result != ISC_R_SUCCESS) { 11109 return result; 11110 } 11111 if (zone == NULL) { 11112 return ISC_R_UNEXPECTEDEND; 11113 } 11114 11115 dns_zone_getraw(zone, &raw); 11116 if (raw != NULL) { 11117 dns_zone_detach(&zone); 11118 dns_zone_attach(raw, &zone); 11119 dns_zone_detach(&raw); 11120 } 11121 11122 type = dns_zone_gettype(zone); 11123 if (type == dns_zone_secondary || type == dns_zone_mirror || 11124 type == dns_zone_stub) 11125 { 11126 dns_zone_refresh(zone); 11127 dns_zone_detach(&zone); 11128 (void)putstr(text, msg1); 11129 (void)putnull(text); 11130 return ISC_R_SUCCESS; 11131 } 11132 11133 dns_zone_detach(&zone); 11134 (void)putstr(text, msg2); 11135 (void)putnull(text); 11136 return ISC_R_FAILURE; 11137 } 11138 11139 isc_result_t 11140 named_server_setortoggle(named_server_t *server, const char *optname, 11141 unsigned int option, isc_lex_t *lex) { 11142 bool prev, value; 11143 char *ptr = NULL; 11144 11145 /* Skip the command name. */ 11146 ptr = next_token(lex, NULL); 11147 if (ptr == NULL) { 11148 return ISC_R_UNEXPECTEDEND; 11149 } 11150 11151 prev = ns_server_getoption(server->sctx, option); 11152 11153 ptr = next_token(lex, NULL); 11154 if (ptr == NULL) { 11155 value = !prev; 11156 } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 11157 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 11158 { 11159 value = true; 11160 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 11161 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 11162 { 11163 value = false; 11164 } else { 11165 return DNS_R_SYNTAX; 11166 } 11167 11168 if (value == prev) { 11169 return ISC_R_SUCCESS; 11170 } 11171 11172 ns_server_setoption(server->sctx, option, value); 11173 11174 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11175 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "%s is now %s", 11176 optname, value ? "on" : "off"); 11177 return ISC_R_SUCCESS; 11178 } 11179 11180 static isc_result_t 11181 listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 11182 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 11183 isc_tlsctx_cache_t *tlsctx_cache, 11184 ns_listenlist_t **target) { 11185 isc_result_t result; 11186 const cfg_listelt_t *element; 11187 ns_listenlist_t *dlist = NULL; 11188 11189 REQUIRE(target != NULL && *target == NULL); 11190 11191 result = ns_listenlist_create(mctx, &dlist); 11192 if (result != ISC_R_SUCCESS) { 11193 return result; 11194 } 11195 11196 for (element = cfg_list_first(listenlist); element != NULL; 11197 element = cfg_list_next(element)) 11198 { 11199 ns_listenelt_t *delt = NULL; 11200 const cfg_obj_t *listener = cfg_listelt_value(element); 11201 result = listenelt_fromconfig(listener, config, actx, mctx, 11202 family, tlsctx_cache, &delt); 11203 if (result != ISC_R_SUCCESS) { 11204 goto cleanup; 11205 } 11206 ISC_LIST_APPEND(dlist->elts, delt, link); 11207 } 11208 *target = dlist; 11209 return ISC_R_SUCCESS; 11210 11211 cleanup: 11212 ns_listenlist_detach(&dlist); 11213 return result; 11214 } 11215 11216 static const cfg_obj_t * 11217 find_maplist(const cfg_obj_t *config, const char *listname, const char *name) { 11218 isc_result_t result; 11219 const cfg_obj_t *maplist = NULL; 11220 const cfg_listelt_t *elt = NULL; 11221 11222 REQUIRE(config != NULL); 11223 REQUIRE(name != NULL); 11224 11225 result = cfg_map_get(config, listname, &maplist); 11226 if (result != ISC_R_SUCCESS) { 11227 return NULL; 11228 } 11229 11230 for (elt = cfg_list_first(maplist); elt != NULL; 11231 elt = cfg_list_next(elt)) 11232 { 11233 const cfg_obj_t *map = cfg_listelt_value(elt); 11234 if (strcasecmp(cfg_obj_asstring(cfg_map_getname(map)), name) == 11235 0) 11236 { 11237 return map; 11238 } 11239 } 11240 11241 return NULL; 11242 } 11243 11244 /* 11245 * Create a listen list from the corresponding configuration 11246 * data structure. 11247 */ 11248 static isc_result_t 11249 listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 11250 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 11251 isc_tlsctx_cache_t *tlsctx_cache, 11252 ns_listenelt_t **target) { 11253 isc_result_t result; 11254 const cfg_obj_t *ltup = NULL; 11255 const cfg_obj_t *tlsobj = NULL, *httpobj = NULL; 11256 const cfg_obj_t *portobj = NULL; 11257 const cfg_obj_t *http_server = NULL; 11258 const cfg_obj_t *proxyobj = NULL; 11259 in_port_t port = 0; 11260 const char *key = NULL, *cert = NULL, *ca_file = NULL, 11261 *dhparam_file = NULL, *ciphers = NULL, *cipher_suites = NULL; 11262 bool tls_prefer_server_ciphers = false, 11263 tls_prefer_server_ciphers_set = false; 11264 bool tls_session_tickets = false, tls_session_tickets_set = false; 11265 bool do_tls = false, no_tls = false, http = false; 11266 ns_listenelt_t *delt = NULL; 11267 uint32_t tls_protos = 0; 11268 ns_listen_tls_params_t tls_params = { 0 }; 11269 const char *tlsname = NULL; 11270 isc_nm_proxy_type_t proxy = ISC_NM_PROXY_NONE; 11271 11272 REQUIRE(target != NULL && *target == NULL); 11273 11274 ltup = cfg_tuple_get(listener, "tuple"); 11275 RUNTIME_CHECK(ltup != NULL); 11276 11277 tlsobj = cfg_tuple_get(ltup, "tls"); 11278 if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) { 11279 tlsname = cfg_obj_asstring(tlsobj); 11280 11281 if (strcasecmp(tlsname, "none") == 0) { 11282 no_tls = true; 11283 } else if (strcasecmp(tlsname, "ephemeral") == 0) { 11284 do_tls = true; 11285 } else { 11286 const cfg_obj_t *keyobj = NULL, *certobj = NULL, 11287 *ca_obj = NULL, *dhparam_obj = NULL; 11288 const cfg_obj_t *tlsmap = NULL; 11289 const cfg_obj_t *tls_proto_list = NULL; 11290 const cfg_obj_t *ciphers_obj = NULL; 11291 const cfg_obj_t *cipher_suites_obj = NULL; 11292 const cfg_obj_t *prefer_server_ciphers_obj = NULL; 11293 const cfg_obj_t *session_tickets_obj = NULL; 11294 11295 do_tls = true; 11296 11297 tlsmap = find_maplist(config, "tls", tlsname); 11298 if (tlsmap == NULL) { 11299 cfg_obj_log(tlsobj, named_g_lctx, ISC_LOG_ERROR, 11300 "tls '%s' is not defined", 11301 cfg_obj_asstring(tlsobj)); 11302 return ISC_R_FAILURE; 11303 } 11304 11305 CHECK(cfg_map_get(tlsmap, "key-file", &keyobj)); 11306 key = cfg_obj_asstring(keyobj); 11307 11308 CHECK(cfg_map_get(tlsmap, "cert-file", &certobj)); 11309 cert = cfg_obj_asstring(certobj); 11310 11311 if (cfg_map_get(tlsmap, "ca-file", &ca_obj) == 11312 ISC_R_SUCCESS) 11313 { 11314 ca_file = cfg_obj_asstring(ca_obj); 11315 } 11316 11317 if (cfg_map_get(tlsmap, "protocols", &tls_proto_list) == 11318 ISC_R_SUCCESS) 11319 { 11320 const cfg_listelt_t *proto = NULL; 11321 INSIST(tls_proto_list != NULL); 11322 for (proto = cfg_list_first(tls_proto_list); 11323 proto != 0; proto = cfg_list_next(proto)) 11324 { 11325 const cfg_obj_t *tls_proto_obj = 11326 cfg_listelt_value(proto); 11327 const char *tls_sver = 11328 cfg_obj_asstring(tls_proto_obj); 11329 const isc_tls_protocol_version_t ver = 11330 isc_tls_protocol_name_to_version( 11331 tls_sver); 11332 11333 INSIST(ver != 11334 ISC_TLS_PROTO_VER_UNDEFINED); 11335 INSIST(isc_tls_protocol_supported(ver)); 11336 tls_protos |= ver; 11337 } 11338 } 11339 11340 if (cfg_map_get(tlsmap, "dhparam-file", &dhparam_obj) == 11341 ISC_R_SUCCESS) 11342 { 11343 dhparam_file = cfg_obj_asstring(dhparam_obj); 11344 } 11345 11346 if (cfg_map_get(tlsmap, "ciphers", &ciphers_obj) == 11347 ISC_R_SUCCESS) 11348 { 11349 ciphers = cfg_obj_asstring(ciphers_obj); 11350 } 11351 11352 if (cfg_map_get(tlsmap, "cipher-suites", 11353 &cipher_suites_obj) == ISC_R_SUCCESS) 11354 { 11355 cipher_suites = 11356 cfg_obj_asstring(cipher_suites_obj); 11357 } 11358 11359 if (cfg_map_get(tlsmap, "prefer-server-ciphers", 11360 &prefer_server_ciphers_obj) == 11361 ISC_R_SUCCESS) 11362 { 11363 tls_prefer_server_ciphers = cfg_obj_asboolean( 11364 prefer_server_ciphers_obj); 11365 tls_prefer_server_ciphers_set = true; 11366 } 11367 11368 if (cfg_map_get(tlsmap, "session-tickets", 11369 &session_tickets_obj) == ISC_R_SUCCESS) 11370 { 11371 tls_session_tickets = 11372 cfg_obj_asboolean(session_tickets_obj); 11373 tls_session_tickets_set = true; 11374 } 11375 } 11376 } 11377 11378 tls_params = (ns_listen_tls_params_t){ 11379 .name = tlsname, 11380 .key = key, 11381 .cert = cert, 11382 .ca_file = ca_file, 11383 .protocols = tls_protos, 11384 .dhparam_file = dhparam_file, 11385 .ciphers = ciphers, 11386 .cipher_suites = cipher_suites, 11387 .prefer_server_ciphers = tls_prefer_server_ciphers, 11388 .prefer_server_ciphers_set = tls_prefer_server_ciphers_set, 11389 .session_tickets = tls_session_tickets, 11390 .session_tickets_set = tls_session_tickets_set 11391 }; 11392 11393 httpobj = cfg_tuple_get(ltup, "http"); 11394 if (httpobj != NULL && cfg_obj_isstring(httpobj)) { 11395 const char *httpname = cfg_obj_asstring(httpobj); 11396 11397 if (!do_tls && !no_tls) { 11398 return ISC_R_FAILURE; 11399 } 11400 11401 http_server = find_maplist(config, "http", httpname); 11402 if (http_server == NULL && strcasecmp(httpname, "default") != 0) 11403 { 11404 cfg_obj_log(httpobj, named_g_lctx, ISC_LOG_ERROR, 11405 "http '%s' is not defined", 11406 cfg_obj_asstring(httpobj)); 11407 return ISC_R_FAILURE; 11408 } 11409 11410 http = true; 11411 } 11412 11413 portobj = cfg_tuple_get(ltup, "port"); 11414 if (!cfg_obj_isuint32(portobj)) { 11415 if (http && do_tls) { 11416 if (named_g_httpsport != 0) { 11417 port = named_g_httpsport; 11418 } else { 11419 result = named_config_getport( 11420 config, "https-port", &port); 11421 if (result != ISC_R_SUCCESS) { 11422 return result; 11423 } 11424 } 11425 } else if (http && !do_tls) { 11426 if (named_g_httpport != 0) { 11427 port = named_g_httpport; 11428 } else { 11429 result = named_config_getport( 11430 config, "http-port", &port); 11431 if (result != ISC_R_SUCCESS) { 11432 return result; 11433 } 11434 } 11435 } else if (do_tls) { 11436 if (named_g_tlsport != 0) { 11437 port = named_g_tlsport; 11438 } else { 11439 result = named_config_getport( 11440 config, "tls-port", &port); 11441 if (result != ISC_R_SUCCESS) { 11442 return result; 11443 } 11444 } 11445 } else { 11446 if (named_g_port != 0) { 11447 port = named_g_port; 11448 } else { 11449 result = named_config_getport(config, "port", 11450 &port); 11451 if (result != ISC_R_SUCCESS) { 11452 return result; 11453 } 11454 } 11455 } 11456 } else { 11457 if (cfg_obj_asuint32(portobj) >= UINT16_MAX) { 11458 return ISC_R_RANGE; 11459 } 11460 port = (in_port_t)cfg_obj_asuint32(portobj); 11461 } 11462 11463 proxyobj = cfg_tuple_get(ltup, "proxy"); 11464 if (proxyobj != NULL && cfg_obj_isstring(proxyobj)) { 11465 const char *proxyval = cfg_obj_asstring(proxyobj); 11466 11467 if (strcasecmp(proxyval, "encrypted") == 0) { 11468 INSIST(do_tls == true); 11469 proxy = ISC_NM_PROXY_ENCRYPTED; 11470 } else if (strcasecmp(proxyval, "plain") == 0) { 11471 proxy = ISC_NM_PROXY_PLAIN; 11472 } else { 11473 UNREACHABLE(); 11474 } 11475 } 11476 11477 #ifdef HAVE_LIBNGHTTP2 11478 if (http) { 11479 CHECK(listenelt_http(http_server, family, do_tls, &tls_params, 11480 tlsctx_cache, port, mctx, proxy, &delt)); 11481 } 11482 #endif /* HAVE_LIBNGHTTP2 */ 11483 11484 if (!http) { 11485 CHECK(ns_listenelt_create(mctx, port, NULL, family, do_tls, 11486 &tls_params, tlsctx_cache, proxy, 11487 &delt)); 11488 } 11489 11490 result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"), config, 11491 named_g_lctx, actx, mctx, family, 11492 &delt->acl); 11493 if (result != ISC_R_SUCCESS) { 11494 ns_listenelt_destroy(delt); 11495 return result; 11496 } 11497 *target = delt; 11498 11499 cleanup: 11500 return result; 11501 } 11502 11503 #ifdef HAVE_LIBNGHTTP2 11504 static isc_result_t 11505 listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, 11506 const ns_listen_tls_params_t *tls_params, 11507 isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, 11508 isc_mem_t *mctx, isc_nm_proxy_type_t proxy, 11509 ns_listenelt_t **target) { 11510 isc_result_t result = ISC_R_SUCCESS; 11511 ns_listenelt_t *delt = NULL; 11512 char **endpoints = NULL; 11513 const cfg_obj_t *eplist = NULL; 11514 const cfg_listelt_t *elt = NULL; 11515 size_t len = 1, i = 0; 11516 uint32_t max_clients = named_g_http_listener_clients; 11517 uint32_t max_streams = named_g_http_streams_per_conn; 11518 11519 REQUIRE(target != NULL && *target == NULL); 11520 11521 if (tls) { 11522 INSIST(tls_params != NULL); 11523 INSIST((tls_params->key == NULL) == (tls_params->cert == NULL)); 11524 } 11525 11526 if (port == 0) { 11527 port = tls ? named_g_httpsport : named_g_httpport; 11528 } 11529 11530 /* 11531 * If "default" was used, we set up the default endpoint 11532 * of "/dns-query". 11533 */ 11534 if (http != NULL) { 11535 const cfg_obj_t *cfg_max_clients = NULL; 11536 const cfg_obj_t *cfg_max_streams = NULL; 11537 11538 if (cfg_map_get(http, "endpoints", &eplist) == ISC_R_SUCCESS) { 11539 INSIST(eplist != NULL); 11540 len = cfg_list_length(eplist, false); 11541 } 11542 11543 if (cfg_map_get(http, "listener-clients", &cfg_max_clients) == 11544 ISC_R_SUCCESS) 11545 { 11546 INSIST(cfg_max_clients != NULL); 11547 max_clients = cfg_obj_asuint32(cfg_max_clients); 11548 } 11549 11550 if (cfg_map_get(http, "streams-per-connection", 11551 &cfg_max_streams) == ISC_R_SUCCESS) 11552 { 11553 INSIST(cfg_max_streams != NULL); 11554 max_streams = cfg_obj_asuint32(cfg_max_streams); 11555 } 11556 } 11557 11558 endpoints = isc_mem_allocate(mctx, sizeof(endpoints[0]) * len); 11559 11560 if (http != NULL && eplist != NULL) { 11561 for (elt = cfg_list_first(eplist); elt != NULL; 11562 elt = cfg_list_next(elt)) 11563 { 11564 const cfg_obj_t *ep = cfg_listelt_value(elt); 11565 const char *path = cfg_obj_asstring(ep); 11566 endpoints[i++] = isc_mem_strdup(mctx, path); 11567 } 11568 } else { 11569 endpoints[i++] = isc_mem_strdup(mctx, ISC_NM_HTTP_DEFAULT_PATH); 11570 } 11571 11572 INSIST(i == len); 11573 11574 result = ns_listenelt_create_http( 11575 mctx, port, NULL, family, tls, tls_params, tlsctx_cache, proxy, 11576 endpoints, len, max_clients, max_streams, &delt); 11577 if (result != ISC_R_SUCCESS) { 11578 goto error; 11579 } 11580 11581 *target = delt; 11582 11583 return result; 11584 error: 11585 if (delt != NULL) { 11586 ns_listenelt_destroy(delt); 11587 } 11588 return result; 11589 } 11590 #endif /* HAVE_LIBNGHTTP2 */ 11591 11592 isc_result_t 11593 named_server_dumpstats(named_server_t *server) { 11594 isc_result_t result; 11595 FILE *fp = NULL; 11596 11597 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), 11598 "could not open statistics dump file", server->statsfile); 11599 11600 result = named_stats_dump(server, fp); 11601 11602 cleanup: 11603 if (fp != NULL) { 11604 (void)isc_stdio_close(fp); 11605 } 11606 if (result == ISC_R_SUCCESS) { 11607 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11608 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11609 "dumpstats complete"); 11610 } else { 11611 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11612 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11613 "dumpstats failed: %s", 11614 isc_result_totext(result)); 11615 } 11616 return result; 11617 } 11618 11619 static isc_result_t 11620 add_zone_tolist(dns_zone_t *zone, void *uap) { 11621 struct dumpcontext *dctx = uap; 11622 struct zonelistentry *zle; 11623 11624 zle = isc_mem_get(dctx->mctx, sizeof *zle); 11625 zle->zone = NULL; 11626 dns_zone_attach(zone, &zle->zone); 11627 ISC_LINK_INIT(zle, link); 11628 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); 11629 return ISC_R_SUCCESS; 11630 } 11631 11632 static isc_result_t 11633 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { 11634 struct viewlistentry *vle; 11635 isc_result_t result = ISC_R_SUCCESS; 11636 11637 /* 11638 * Prevent duplicate views. 11639 */ 11640 for (vle = ISC_LIST_HEAD(dctx->viewlist); vle != NULL; 11641 vle = ISC_LIST_NEXT(vle, link)) 11642 { 11643 if (vle->view == view) { 11644 return ISC_R_SUCCESS; 11645 } 11646 } 11647 11648 vle = isc_mem_get(dctx->mctx, sizeof *vle); 11649 vle->view = NULL; 11650 dns_view_attach(view, &vle->view); 11651 ISC_LINK_INIT(vle, link); 11652 ISC_LIST_INIT(vle->zonelist); 11653 ISC_LIST_APPEND(dctx->viewlist, vle, link); 11654 if (dctx->dumpzones) { 11655 result = dns_view_apply(view, true, NULL, add_zone_tolist, 11656 dctx); 11657 } 11658 return result; 11659 } 11660 11661 static void 11662 dumpcontext_destroy(struct dumpcontext *dctx) { 11663 struct viewlistentry *vle; 11664 struct zonelistentry *zle; 11665 11666 vle = ISC_LIST_HEAD(dctx->viewlist); 11667 while (vle != NULL) { 11668 ISC_LIST_UNLINK(dctx->viewlist, vle, link); 11669 zle = ISC_LIST_HEAD(vle->zonelist); 11670 while (zle != NULL) { 11671 ISC_LIST_UNLINK(vle->zonelist, zle, link); 11672 dns_zone_detach(&zle->zone); 11673 isc_mem_put(dctx->mctx, zle, sizeof *zle); 11674 zle = ISC_LIST_HEAD(vle->zonelist); 11675 } 11676 dns_view_detach(&vle->view); 11677 isc_mem_put(dctx->mctx, vle, sizeof *vle); 11678 vle = ISC_LIST_HEAD(dctx->viewlist); 11679 } 11680 if (dctx->version != NULL) { 11681 dns_db_closeversion(dctx->db, &dctx->version, false); 11682 } 11683 if (dctx->db != NULL) { 11684 dns_db_detach(&dctx->db); 11685 } 11686 if (dctx->cache != NULL) { 11687 dns_db_detach(&dctx->cache); 11688 } 11689 if (dctx->fp != NULL) { 11690 (void)isc_stdio_close(dctx->fp); 11691 } 11692 if (dctx->mdctx != NULL) { 11693 dns_dumpctx_detach(&dctx->mdctx); 11694 } 11695 isc_mem_put(dctx->mctx, dctx, sizeof *dctx); 11696 } 11697 11698 static void 11699 dumpdone(void *arg, isc_result_t result) { 11700 struct dumpcontext *dctx = arg; 11701 char buf[1024 + 32]; 11702 const dns_master_style_t *style; 11703 11704 if (result != ISC_R_SUCCESS) { 11705 goto cleanup; 11706 } 11707 if (dctx->mdctx != NULL) { 11708 dns_dumpctx_detach(&dctx->mdctx); 11709 } 11710 if (dctx->view == NULL) { 11711 dctx->view = ISC_LIST_HEAD(dctx->viewlist); 11712 if (dctx->view == NULL) { 11713 goto done; 11714 } 11715 INSIST(dctx->zone == NULL); 11716 } else { 11717 goto resume; 11718 } 11719 nextview: 11720 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); 11721 resume: 11722 if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { 11723 fprintf(dctx->fp, ";\n; Cache of view '%s' is shared as '%s'\n", 11724 dctx->view->view->name, 11725 dns_cache_getname(dctx->view->view->cache)); 11726 } else if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) 11727 { 11728 if (dctx->dumpexpired) { 11729 style = &dns_master_style_cache_with_expired; 11730 } else { 11731 style = &dns_master_style_cache; 11732 } 11733 /* start cache dump */ 11734 if (dctx->view->view->cachedb != NULL) { 11735 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 11736 } 11737 if (dctx->cache != NULL) { 11738 fprintf(dctx->fp, 11739 ";\n; Cache dump of view '%s' (cache %s)\n;\n", 11740 dctx->view->view->name, 11741 dns_cache_getname(dctx->view->view->cache)); 11742 result = dns_master_dumptostreamasync( 11743 dctx->mctx, dctx->cache, NULL, style, dctx->fp, 11744 named_g_mainloop, dumpdone, dctx, &dctx->mdctx); 11745 if (result == ISC_R_SUCCESS) { 11746 return; 11747 } 11748 if (result == ISC_R_NOTIMPLEMENTED) { 11749 fprintf(dctx->fp, "; %s\n", 11750 isc_result_totext(result)); 11751 } else if (result != ISC_R_SUCCESS) { 11752 goto cleanup; 11753 } 11754 } 11755 } 11756 11757 if ((dctx->dumpadb || dctx->dumpfail) && dctx->cache == NULL && 11758 dctx->view->view->cachedb != NULL) 11759 { 11760 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 11761 } 11762 11763 if (dctx->cache != NULL) { 11764 if (dctx->dumpadb) { 11765 dns_adb_t *adb = NULL; 11766 dns_view_getadb(dctx->view->view, &adb); 11767 if (adb != NULL) { 11768 dns_adb_dump(adb, dctx->fp); 11769 dns_adb_detach(&adb); 11770 } 11771 } 11772 if (dctx->dumpfail) { 11773 dns_badcache_print(dctx->view->view->failcache, 11774 "SERVFAIL cache", dctx->fp); 11775 } 11776 dns_db_detach(&dctx->cache); 11777 } 11778 if (dctx->dumpzones) { 11779 style = &dns_master_style_full; 11780 nextzone: 11781 if (dctx->version != NULL) { 11782 dns_db_closeversion(dctx->db, &dctx->version, false); 11783 } 11784 if (dctx->db != NULL) { 11785 dns_db_detach(&dctx->db); 11786 } 11787 if (dctx->zone == NULL) { 11788 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); 11789 } else { 11790 dctx->zone = ISC_LIST_NEXT(dctx->zone, link); 11791 } 11792 if (dctx->zone != NULL) { 11793 /* start zone dump */ 11794 dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); 11795 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); 11796 result = dns_zone_getdb(dctx->zone->zone, &dctx->db); 11797 if (result != ISC_R_SUCCESS) { 11798 fprintf(dctx->fp, "; %s\n", 11799 isc_result_totext(result)); 11800 goto nextzone; 11801 } 11802 dns_db_currentversion(dctx->db, &dctx->version); 11803 result = dns_master_dumptostreamasync( 11804 dctx->mctx, dctx->db, dctx->version, style, 11805 dctx->fp, dns_zone_getloop(dctx->zone->zone), 11806 dumpdone, dctx, &dctx->mdctx); 11807 if (result == ISC_R_SUCCESS) { 11808 return; 11809 } 11810 if (result == ISC_R_NOTIMPLEMENTED) { 11811 fprintf(dctx->fp, "; %s\n", 11812 isc_result_totext(result)); 11813 result = ISC_R_SUCCESS; 11814 POST(result); 11815 goto nextzone; 11816 } 11817 if (result != ISC_R_SUCCESS) { 11818 goto cleanup; 11819 } 11820 } 11821 } 11822 if (dctx->view != NULL) { 11823 dctx->view = ISC_LIST_NEXT(dctx->view, link); 11824 if (dctx->view != NULL) { 11825 goto nextview; 11826 } 11827 } 11828 done: 11829 fprintf(dctx->fp, "; Dump complete\n"); 11830 result = isc_stdio_flush(dctx->fp); 11831 if (result == ISC_R_SUCCESS) { 11832 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11833 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11834 "dumpdb complete"); 11835 } 11836 cleanup: 11837 if (result != ISC_R_SUCCESS) { 11838 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11839 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11840 "dumpdb failed: %s", isc_result_totext(result)); 11841 } 11842 dumpcontext_destroy(dctx); 11843 } 11844 11845 isc_result_t 11846 named_server_dumpdb(named_server_t *server, isc_lex_t *lex, 11847 isc_buffer_t **text) { 11848 struct dumpcontext *dctx = NULL; 11849 dns_view_t *view; 11850 isc_result_t result; 11851 char *ptr; 11852 const char *sep; 11853 bool found; 11854 11855 REQUIRE(text != NULL); 11856 11857 /* Skip the command name. */ 11858 ptr = next_token(lex, NULL); 11859 if (ptr == NULL) { 11860 return ISC_R_UNEXPECTEDEND; 11861 } 11862 11863 dctx = isc_mem_get(server->mctx, sizeof(*dctx)); 11864 *dctx = (struct dumpcontext){ 11865 .mctx = server->mctx, 11866 .dumpcache = true, 11867 .dumpadb = true, 11868 .dumpfail = true, 11869 .viewlist = ISC_LIST_INITIALIZER, 11870 }; 11871 11872 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), 11873 "could not open dump file", server->dumpfile); 11874 11875 ptr = next_token(lex, NULL); 11876 sep = (ptr == NULL) ? "" : ": "; 11877 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11878 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11879 "dumpdb started%s%s", sep, (ptr != NULL) ? ptr : ""); 11880 11881 if (ptr != NULL && strcmp(ptr, "-all") == 0) { 11882 /* also dump zones */ 11883 dctx->dumpzones = true; 11884 ptr = next_token(lex, NULL); 11885 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { 11886 /* this is the default */ 11887 ptr = next_token(lex, NULL); 11888 } else if (ptr != NULL && strcmp(ptr, "-expired") == 0) { 11889 /* this is the same as -cache but includes expired data */ 11890 dctx->dumpexpired = true; 11891 ptr = next_token(lex, NULL); 11892 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { 11893 /* only dump zones, suppress caches */ 11894 dctx->dumpadb = false; 11895 dctx->dumpcache = false; 11896 dctx->dumpfail = false; 11897 dctx->dumpzones = true; 11898 ptr = next_token(lex, NULL); 11899 } else if (ptr != NULL && strcmp(ptr, "-adb") == 0) { 11900 /* only dump adb, suppress other caches */ 11901 dctx->dumpcache = false; 11902 dctx->dumpfail = false; 11903 ptr = next_token(lex, NULL); 11904 } else if (ptr != NULL && strcmp(ptr, "-bad") == 0) { 11905 /* only dump badcache, suppress other caches */ 11906 dctx->dumpadb = false; 11907 dctx->dumpcache = false; 11908 dctx->dumpfail = false; 11909 ptr = next_token(lex, NULL); 11910 } else if (ptr != NULL && strcmp(ptr, "-fail") == 0) { 11911 /* only dump servfail cache, suppress other caches */ 11912 dctx->dumpadb = false; 11913 dctx->dumpcache = false; 11914 ptr = next_token(lex, NULL); 11915 } 11916 11917 nextview: 11918 found = false; 11919 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 11920 view = ISC_LIST_NEXT(view, link)) 11921 { 11922 if (ptr != NULL && strcmp(view->name, ptr) != 0) { 11923 continue; 11924 } 11925 found = true; 11926 CHECK(add_view_tolist(dctx, view)); 11927 } 11928 if (ptr != NULL) { 11929 if (!found) { 11930 CHECK(putstr(text, "view '")); 11931 CHECK(putstr(text, ptr)); 11932 CHECK(putstr(text, "' not found")); 11933 CHECK(putnull(text)); 11934 result = ISC_R_NOTFOUND; 11935 dumpdone(dctx, result); 11936 return result; 11937 } 11938 ptr = next_token(lex, NULL); 11939 if (ptr != NULL) { 11940 goto nextview; 11941 } 11942 } 11943 dumpdone(dctx, ISC_R_SUCCESS); 11944 return ISC_R_SUCCESS; 11945 11946 cleanup: 11947 dumpcontext_destroy(dctx); 11948 return result; 11949 } 11950 11951 isc_result_t 11952 named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex, 11953 isc_buffer_t **text) { 11954 dns_view_t *view; 11955 dns_keytable_t *secroots = NULL; 11956 dns_ntatable_t *ntatable = NULL; 11957 isc_result_t result; 11958 char *ptr; 11959 FILE *fp = NULL; 11960 isc_time_t now; 11961 char tbuf[64]; 11962 unsigned int used = isc_buffer_usedlength(*text); 11963 bool first = true; 11964 11965 REQUIRE(text != NULL); 11966 11967 /* Skip the command name. */ 11968 ptr = next_token(lex, text); 11969 if (ptr == NULL) { 11970 return ISC_R_UNEXPECTEDEND; 11971 } 11972 11973 /* "-" here means print the output instead of dumping to file */ 11974 ptr = next_token(lex, text); 11975 if (ptr != NULL && strcmp(ptr, "-") == 0) { 11976 ptr = next_token(lex, text); 11977 } else { 11978 result = isc_stdio_open(server->secrootsfile, "w", &fp); 11979 if (result != ISC_R_SUCCESS) { 11980 (void)putstr(text, "could not open "); 11981 (void)putstr(text, server->secrootsfile); 11982 CHECKMF(result, "could not open secroots dump file", 11983 server->secrootsfile); 11984 } 11985 } 11986 11987 now = isc_time_now(); 11988 isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); 11989 CHECK(putstr(text, "secure roots as of ")); 11990 CHECK(putstr(text, tbuf)); 11991 CHECK(putstr(text, ":\n")); 11992 used = isc_buffer_usedlength(*text); 11993 11994 do { 11995 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 11996 view = ISC_LIST_NEXT(view, link)) 11997 { 11998 if (ptr != NULL && strcmp(view->name, ptr) != 0) { 11999 continue; 12000 } 12001 if (secroots != NULL) { 12002 dns_keytable_detach(&secroots); 12003 } 12004 result = dns_view_getsecroots(view, &secroots); 12005 if (result == ISC_R_NOTFOUND) { 12006 result = ISC_R_SUCCESS; 12007 continue; 12008 } 12009 if (first || used != isc_buffer_usedlength(*text)) { 12010 CHECK(putstr(text, "\n")); 12011 first = false; 12012 } 12013 CHECK(putstr(text, " Start view ")); 12014 CHECK(putstr(text, view->name)); 12015 CHECK(putstr(text, "\n Secure roots:\n\n")); 12016 used = isc_buffer_usedlength(*text); 12017 CHECK(dns_keytable_totext(secroots, text)); 12018 12019 if (ntatable != NULL) { 12020 dns_ntatable_detach(&ntatable); 12021 } 12022 result = dns_view_getntatable(view, &ntatable); 12023 if (result == ISC_R_NOTFOUND) { 12024 result = ISC_R_SUCCESS; 12025 continue; 12026 } 12027 if (used != isc_buffer_usedlength(*text)) { 12028 CHECK(putstr(text, "\n")); 12029 } 12030 CHECK(putstr(text, " Negative trust anchors:\n\n")); 12031 used = isc_buffer_usedlength(*text); 12032 CHECK(dns_ntatable_totext(ntatable, NULL, text)); 12033 } 12034 12035 if (ptr != NULL) { 12036 ptr = next_token(lex, text); 12037 } 12038 } while (ptr != NULL); 12039 12040 cleanup: 12041 if (secroots != NULL) { 12042 dns_keytable_detach(&secroots); 12043 } 12044 if (ntatable != NULL) { 12045 dns_ntatable_detach(&ntatable); 12046 } 12047 12048 if (fp != NULL) { 12049 if (used != isc_buffer_usedlength(*text)) { 12050 (void)putstr(text, "\n"); 12051 } 12052 fprintf(fp, "%.*s", (int)isc_buffer_usedlength(*text), 12053 (char *)isc_buffer_base(*text)); 12054 isc_buffer_clear(*text); 12055 (void)isc_stdio_close(fp); 12056 } else if (isc_buffer_usedlength(*text) > 0) { 12057 (void)putnull(text); 12058 } 12059 12060 if (result == ISC_R_SUCCESS) { 12061 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12062 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12063 "dumpsecroots complete"); 12064 } else { 12065 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12066 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12067 "dumpsecroots failed: %s", 12068 isc_result_totext(result)); 12069 } 12070 return result; 12071 } 12072 12073 isc_result_t 12074 named_server_dumprecursing(named_server_t *server) { 12075 FILE *fp = NULL; 12076 dns_view_t *view; 12077 isc_result_t result; 12078 12079 CHECKMF(isc_stdio_open(server->recfile, "w", &fp), 12080 "could not open dump file", server->recfile); 12081 fprintf(fp, ";\n; Recursing Queries\n;\n"); 12082 ns_interfacemgr_dumprecursing(fp, server->interfacemgr); 12083 12084 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12085 view = ISC_LIST_NEXT(view, link)) 12086 { 12087 fprintf(fp, ";\n; Active fetch domains [view: %s]\n;\n", 12088 view->name); 12089 dns_resolver_dumpfetches(view->resolver, isc_statsformat_file, 12090 fp); 12091 } 12092 12093 fprintf(fp, "; Dump complete\n"); 12094 12095 cleanup: 12096 if (fp != NULL) { 12097 result = isc_stdio_close(fp); 12098 } 12099 if (result == ISC_R_SUCCESS) { 12100 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12101 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12102 "dumprecursing complete"); 12103 } else { 12104 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12105 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12106 "dumprecursing failed: %s", 12107 isc_result_totext(result)); 12108 } 12109 return result; 12110 } 12111 12112 isc_result_t 12113 named_server_setdebuglevel(named_server_t *server, isc_lex_t *lex) { 12114 char *ptr; 12115 char *endp; 12116 long newlevel; 12117 12118 UNUSED(server); 12119 12120 /* Skip the command name. */ 12121 ptr = next_token(lex, NULL); 12122 if (ptr == NULL) { 12123 return ISC_R_UNEXPECTEDEND; 12124 } 12125 12126 /* Look for the new level name. */ 12127 ptr = next_token(lex, NULL); 12128 if (ptr == NULL) { 12129 if (named_g_debuglevel < 99) { 12130 named_g_debuglevel++; 12131 } 12132 } else { 12133 newlevel = strtol(ptr, &endp, 10); 12134 if (*endp != '\0' || newlevel < 0 || newlevel > 99) { 12135 return ISC_R_RANGE; 12136 } 12137 named_g_debuglevel = (unsigned int)newlevel; 12138 } 12139 isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel); 12140 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12141 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12142 "debug level is now %u", named_g_debuglevel); 12143 return ISC_R_SUCCESS; 12144 } 12145 12146 isc_result_t 12147 named_server_validation(named_server_t *server, isc_lex_t *lex, 12148 isc_buffer_t **text) { 12149 char *ptr; 12150 dns_view_t *view; 12151 bool changed = false; 12152 isc_result_t result; 12153 bool enable = true, set = true, first = true; 12154 12155 REQUIRE(text != NULL); 12156 12157 /* Skip the command name. */ 12158 ptr = next_token(lex, text); 12159 if (ptr == NULL) { 12160 return ISC_R_UNEXPECTEDEND; 12161 } 12162 12163 /* Find out what we are to do. */ 12164 ptr = next_token(lex, text); 12165 if (ptr == NULL) { 12166 return ISC_R_UNEXPECTEDEND; 12167 } 12168 12169 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 12170 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 12171 { 12172 enable = true; 12173 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 12174 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 12175 { 12176 enable = false; 12177 } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { 12178 set = false; 12179 } else { 12180 return DNS_R_SYNTAX; 12181 } 12182 12183 /* Look for the view name. */ 12184 ptr = next_token(lex, text); 12185 12186 isc_loopmgr_pause(named_g_loopmgr); 12187 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12188 view = ISC_LIST_NEXT(view, link)) 12189 { 12190 if ((ptr != NULL && strcasecmp(ptr, view->name) != 0) || 12191 strcasecmp("_bind", view->name) == 0) 12192 { 12193 continue; 12194 } 12195 12196 if (set) { 12197 CHECK(dns_view_flushcache(view, false)); 12198 view->enablevalidation = enable; 12199 changed = true; 12200 } else { 12201 if (!first) { 12202 CHECK(putstr(text, "\n")); 12203 } 12204 CHECK(putstr(text, "DNSSEC validation is ")); 12205 CHECK(putstr(text, view->enablevalidation 12206 ? "enabled" 12207 : "disabled")); 12208 CHECK(putstr(text, " (view ")); 12209 CHECK(putstr(text, view->name)); 12210 CHECK(putstr(text, ")")); 12211 first = false; 12212 } 12213 } 12214 CHECK(putnull(text)); 12215 12216 if (!set) { 12217 result = ISC_R_SUCCESS; 12218 } else if (changed) { 12219 result = ISC_R_SUCCESS; 12220 } else { 12221 result = ISC_R_FAILURE; 12222 } 12223 cleanup: 12224 isc_loopmgr_resume(named_g_loopmgr); 12225 return result; 12226 } 12227 12228 isc_result_t 12229 named_server_flushcache(named_server_t *server, isc_lex_t *lex) { 12230 char *ptr; 12231 dns_view_t *view; 12232 bool flushed; 12233 bool found; 12234 isc_result_t result; 12235 named_cache_t *nsc; 12236 12237 /* Skip the command name. */ 12238 ptr = next_token(lex, NULL); 12239 if (ptr == NULL) { 12240 return ISC_R_UNEXPECTEDEND; 12241 } 12242 12243 /* Look for the view name. */ 12244 ptr = next_token(lex, NULL); 12245 12246 isc_loopmgr_pause(named_g_loopmgr); 12247 flushed = true; 12248 found = false; 12249 12250 /* 12251 * Flushing a cache is tricky when caches are shared by multiple views. 12252 * We first identify which caches should be flushed in the local cache 12253 * list, flush these caches, and then update other views that refer to 12254 * the flushed cache DB. 12255 */ 12256 if (ptr != NULL) { 12257 /* 12258 * Mark caches that need to be flushed. This is an O(#view^2) 12259 * operation in the very worst case, but should be normally 12260 * much more lightweight because only a few (most typically just 12261 * one) views will match. 12262 */ 12263 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12264 view = ISC_LIST_NEXT(view, link)) 12265 { 12266 if (strcasecmp(ptr, view->name) != 0) { 12267 continue; 12268 } 12269 found = true; 12270 for (nsc = ISC_LIST_HEAD(server->cachelist); 12271 nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) 12272 { 12273 if (nsc->cache == view->cache) { 12274 break; 12275 } 12276 } 12277 INSIST(nsc != NULL); 12278 nsc->needflush = true; 12279 } 12280 } else { 12281 found = true; 12282 } 12283 12284 /* Perform flush */ 12285 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12286 nsc = ISC_LIST_NEXT(nsc, link)) 12287 { 12288 if (ptr != NULL && !nsc->needflush) { 12289 continue; 12290 } 12291 nsc->needflush = true; 12292 result = dns_view_flushcache(nsc->primaryview, false); 12293 if (result != ISC_R_SUCCESS) { 12294 flushed = false; 12295 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12296 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12297 "flushing cache in view '%s' failed: %s", 12298 nsc->primaryview->name, 12299 isc_result_totext(result)); 12300 } 12301 } 12302 12303 /* 12304 * Fix up views that share a flushed cache: let the views update the 12305 * cache DB they're referring to. This could also be an expensive 12306 * operation, but should typically be marginal: the inner loop is only 12307 * necessary for views that share a cache, and if there are many such 12308 * views the number of shared cache should normally be small. 12309 * A worst case is that we have n views and n/2 caches, each shared by 12310 * two views. Then this will be a O(n^2/4) operation. 12311 */ 12312 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12313 view = ISC_LIST_NEXT(view, link)) 12314 { 12315 if (!dns_view_iscacheshared(view)) { 12316 continue; 12317 } 12318 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12319 nsc = ISC_LIST_NEXT(nsc, link)) 12320 { 12321 if (!nsc->needflush || nsc->cache != view->cache) { 12322 continue; 12323 } 12324 result = dns_view_flushcache(view, true); 12325 if (result != ISC_R_SUCCESS) { 12326 flushed = false; 12327 isc_log_write( 12328 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12329 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12330 "fixing cache in view '%s' " 12331 "failed: %s", 12332 view->name, isc_result_totext(result)); 12333 } 12334 } 12335 } 12336 12337 /* Cleanup the cache list. */ 12338 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12339 nsc = ISC_LIST_NEXT(nsc, link)) 12340 { 12341 nsc->needflush = false; 12342 } 12343 12344 if (flushed && found) { 12345 if (ptr != NULL) { 12346 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12347 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12348 "flushing cache in view '%s' succeeded", 12349 ptr); 12350 } else { 12351 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12352 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12353 "flushing caches in all views succeeded"); 12354 } 12355 result = ISC_R_SUCCESS; 12356 } else { 12357 if (!found) { 12358 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12359 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12360 "flushing cache in view '%s' failed: " 12361 "view not found", 12362 ptr); 12363 result = ISC_R_NOTFOUND; 12364 } else { 12365 result = ISC_R_FAILURE; 12366 } 12367 } 12368 isc_loopmgr_resume(named_g_loopmgr); 12369 return result; 12370 } 12371 12372 isc_result_t 12373 named_server_flushnode(named_server_t *server, isc_lex_t *lex, bool tree) { 12374 char *ptr, *viewname; 12375 char target[DNS_NAME_FORMATSIZE]; 12376 dns_view_t *view; 12377 bool flushed; 12378 bool found; 12379 isc_result_t result; 12380 isc_buffer_t b; 12381 dns_fixedname_t fixed; 12382 dns_name_t *name; 12383 12384 /* Skip the command name. */ 12385 ptr = next_token(lex, NULL); 12386 if (ptr == NULL) { 12387 return ISC_R_UNEXPECTEDEND; 12388 } 12389 12390 /* Find the domain name to flush. */ 12391 ptr = next_token(lex, NULL); 12392 if (ptr == NULL) { 12393 return ISC_R_UNEXPECTEDEND; 12394 } 12395 12396 strlcpy(target, ptr, DNS_NAME_FORMATSIZE); 12397 isc_buffer_constinit(&b, target, strlen(target)); 12398 isc_buffer_add(&b, strlen(target)); 12399 name = dns_fixedname_initname(&fixed); 12400 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 12401 if (result != ISC_R_SUCCESS) { 12402 return result; 12403 } 12404 12405 /* Look for the view name. */ 12406 viewname = next_token(lex, NULL); 12407 12408 isc_loopmgr_pause(named_g_loopmgr); 12409 flushed = true; 12410 found = false; 12411 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12412 view = ISC_LIST_NEXT(view, link)) 12413 { 12414 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) { 12415 continue; 12416 } 12417 found = true; 12418 /* 12419 * It's a little inefficient to try flushing name for all views 12420 * if some of the views share a single cache. But since the 12421 * operation is lightweight we prefer simplicity here. 12422 */ 12423 result = dns_view_flushnode(view, name, tree); 12424 if (result != ISC_R_SUCCESS) { 12425 flushed = false; 12426 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12427 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12428 "flushing %s '%s' in cache view '%s' " 12429 "failed: %s", 12430 tree ? "tree" : "name", target, 12431 view->name, isc_result_totext(result)); 12432 } 12433 } 12434 if (flushed && found) { 12435 if (viewname != NULL) { 12436 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12437 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12438 "flushing %s '%s' in cache view '%s' " 12439 "succeeded", 12440 tree ? "tree" : "name", target, viewname); 12441 } else { 12442 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12443 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12444 "flushing %s '%s' in all cache views " 12445 "succeeded", 12446 tree ? "tree" : "name", target); 12447 } 12448 result = ISC_R_SUCCESS; 12449 } else { 12450 if (!found) { 12451 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12452 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12453 "flushing %s '%s' in cache view '%s' " 12454 "failed: view not found", 12455 tree ? "tree" : "name", target, viewname); 12456 } 12457 result = ISC_R_FAILURE; 12458 } 12459 isc_loopmgr_resume(named_g_loopmgr); 12460 return result; 12461 } 12462 12463 isc_result_t 12464 named_server_status(named_server_t *server, isc_buffer_t **text) { 12465 isc_result_t result; 12466 unsigned int zonecount, xferrunning, xferdeferred, xferfirstrefresh; 12467 unsigned int soaqueries, automatic; 12468 const char *ob = "", *cb = "", *alt = ""; 12469 char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE]; 12470 char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE]; 12471 char line[1024], hostname[256]; 12472 named_reload_t reload_status; 12473 12474 REQUIRE(text != NULL); 12475 12476 if (named_g_server->version_set) { 12477 ob = " ("; 12478 cb = ")"; 12479 if (named_g_server->version == NULL) { 12480 alt = "version.bind/txt/ch disabled"; 12481 } else { 12482 alt = named_g_server->version; 12483 } 12484 } 12485 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); 12486 xferrunning = dns_zonemgr_getcount(server->zonemgr, 12487 DNS_ZONESTATE_XFERRUNNING); 12488 xferdeferred = dns_zonemgr_getcount(server->zonemgr, 12489 DNS_ZONESTATE_XFERDEFERRED); 12490 xferfirstrefresh = dns_zonemgr_getcount(server->zonemgr, 12491 DNS_ZONESTATE_XFERFIRSTREFRESH); 12492 soaqueries = dns_zonemgr_getcount(server->zonemgr, 12493 DNS_ZONESTATE_SOAQUERY); 12494 automatic = dns_zonemgr_getcount(server->zonemgr, 12495 DNS_ZONESTATE_AUTOMATIC); 12496 12497 isc_time_formathttptimestamp(&named_g_boottime, boottime, 12498 sizeof(boottime)); 12499 isc_time_formathttptimestamp(&named_g_configtime, configtime, 12500 sizeof(configtime)); 12501 12502 snprintf(line, sizeof(line), "version: %s%s <id:%s>%s%s%s\n", 12503 PACKAGE_STRING, PACKAGE_DESCRIPTION, PACKAGE_SRCID, ob, alt, 12504 cb); 12505 CHECK(putstr(text, line)); 12506 12507 if (gethostname(hostname, sizeof(hostname)) == 0) { 12508 strlcpy(hostname, "localhost", sizeof(hostname)); 12509 } 12510 snprintf(line, sizeof(line), "running on %s: %s\n", hostname, 12511 named_os_uname()); 12512 CHECK(putstr(text, line)); 12513 12514 snprintf(line, sizeof(line), "boot time: %s\n", boottime); 12515 CHECK(putstr(text, line)); 12516 12517 snprintf(line, sizeof(line), "last configured: %s\n", configtime); 12518 CHECK(putstr(text, line)); 12519 12520 if (named_g_chrootdir != NULL) { 12521 snprintf(line, sizeof(line), "configuration file: %s (%s%s)\n", 12522 named_g_conffile, named_g_chrootdir, named_g_conffile); 12523 } else { 12524 snprintf(line, sizeof(line), "configuration file: %s\n", 12525 named_g_conffile); 12526 } 12527 CHECK(putstr(text, line)); 12528 12529 snprintf(line, sizeof(line), "CPUs found: %u\n", named_g_cpus_detected); 12530 CHECK(putstr(text, line)); 12531 12532 snprintf(line, sizeof(line), "worker threads: %u\n", named_g_cpus); 12533 CHECK(putstr(text, line)); 12534 12535 snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n", 12536 zonecount, automatic); 12537 CHECK(putstr(text, line)); 12538 12539 snprintf(line, sizeof(line), "debug level: %u\n", named_g_debuglevel); 12540 CHECK(putstr(text, line)); 12541 12542 snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning); 12543 CHECK(putstr(text, line)); 12544 12545 snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred); 12546 CHECK(putstr(text, line)); 12547 12548 snprintf(line, sizeof(line), "xfers first refresh: %u\n", 12549 xferfirstrefresh); 12550 CHECK(putstr(text, line)); 12551 12552 snprintf(line, sizeof(line), "soa queries in progress: %u\n", 12553 soaqueries); 12554 CHECK(putstr(text, line)); 12555 12556 snprintf(line, sizeof(line), "query logging is %s\n", 12557 ns_server_getoption(server->sctx, NS_SERVER_LOGQUERIES) 12558 ? "ON" 12559 : "OFF"); 12560 CHECK(putstr(text, line)); 12561 12562 snprintf(line, sizeof(line), "response logging is %s\n", 12563 ns_server_getoption(server->sctx, NS_SERVER_LOGRESPONSES) 12564 ? "ON" 12565 : "OFF"); 12566 CHECK(putstr(text, line)); 12567 12568 snprintf(line, sizeof(line), "recursive clients: %u/%u/%u\n", 12569 isc_quota_getused(&server->sctx->recursionquota), 12570 isc_quota_getsoft(&server->sctx->recursionquota), 12571 isc_quota_getmax(&server->sctx->recursionquota)); 12572 CHECK(putstr(text, line)); 12573 12574 snprintf(line, sizeof(line), "recursive high-water: %u\n", 12575 (unsigned int)ns_stats_get_counter( 12576 server->sctx->nsstats, 12577 ns_statscounter_recurshighwater)); 12578 CHECK(putstr(text, line)); 12579 12580 snprintf(line, sizeof(line), "tcp clients: %u/%u\n", 12581 isc_quota_getused(&server->sctx->tcpquota), 12582 isc_quota_getmax(&server->sctx->tcpquota)); 12583 CHECK(putstr(text, line)); 12584 12585 snprintf(line, sizeof(line), "TCP high-water: %u\n", 12586 (unsigned int)ns_stats_get_counter( 12587 server->sctx->nsstats, ns_statscounter_tcphighwater)); 12588 CHECK(putstr(text, line)); 12589 12590 reload_status = atomic_load(&server->reload_status); 12591 if (reload_status != NAMED_RELOAD_DONE) { 12592 snprintf(line, sizeof(line), "reload/reconfig %s\n", 12593 reload_status == NAMED_RELOAD_FAILED ? "failed" 12594 : "in progress"); 12595 CHECK(putstr(text, line)); 12596 } 12597 12598 CHECK(putstr(text, "server is up and running")); 12599 CHECK(putnull(text)); 12600 12601 return ISC_R_SUCCESS; 12602 cleanup: 12603 return result; 12604 } 12605 12606 isc_result_t 12607 named_server_testgen(isc_lex_t *lex, isc_buffer_t **text) { 12608 isc_result_t result; 12609 char *ptr; 12610 unsigned long count; 12611 unsigned long i; 12612 const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; 12613 12614 REQUIRE(text != NULL); 12615 12616 /* Skip the command name. */ 12617 ptr = next_token(lex, text); 12618 if (ptr == NULL) { 12619 return ISC_R_UNEXPECTEDEND; 12620 } 12621 12622 ptr = next_token(lex, text); 12623 if (ptr == NULL) { 12624 count = 26; 12625 } else { 12626 count = strtoul(ptr, NULL, 10); 12627 } 12628 12629 CHECK(isc_buffer_reserve(*text, count)); 12630 for (i = 0; i < count; i++) { 12631 CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)])); 12632 } 12633 12634 CHECK(putnull(text)); 12635 12636 cleanup: 12637 return result; 12638 } 12639 12640 /* 12641 * Act on a "sign" or "loadkeys" command from the command channel. 12642 */ 12643 isc_result_t 12644 named_server_rekey(named_server_t *server, isc_lex_t *lex, 12645 isc_buffer_t **text) { 12646 isc_result_t result; 12647 dns_zone_t *zone = NULL; 12648 dns_zonetype_t type; 12649 uint16_t keyopts; 12650 bool fullsign = false; 12651 char *ptr; 12652 12653 REQUIRE(text != NULL); 12654 12655 ptr = next_token(lex, text); 12656 if (ptr == NULL) { 12657 return ISC_R_UNEXPECTEDEND; 12658 } 12659 12660 if (strcasecmp(ptr, NAMED_COMMAND_SIGN) == 0) { 12661 fullsign = true; 12662 } 12663 12664 REQUIRE(text != NULL); 12665 12666 result = zone_from_args(server, lex, NULL, &zone, NULL, text, false); 12667 if (result != ISC_R_SUCCESS) { 12668 return result; 12669 } 12670 if (zone == NULL) { 12671 return ISC_R_UNEXPECTEDEND; /* XXX: or do all zones? */ 12672 } 12673 12674 type = dns_zone_gettype(zone); 12675 if (type != dns_zone_primary) { 12676 dns_zone_detach(&zone); 12677 return DNS_R_NOTPRIMARY; 12678 } 12679 12680 keyopts = dns_zone_getkeyopts(zone); 12681 12682 /* 12683 * "rndc loadkeys" requires a "dnssec-policy". 12684 */ 12685 if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) { 12686 result = ISC_R_NOPERM; 12687 } else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) { 12688 result = ISC_R_NOPERM; 12689 } else { 12690 dns_zone_rekey(zone, fullsign); 12691 } 12692 12693 dns_zone_detach(&zone); 12694 return result; 12695 } 12696 12697 /* 12698 * Act on a "sync" command from the command channel. 12699 */ 12700 static isc_result_t 12701 synczone(dns_zone_t *zone, void *uap) { 12702 bool cleanup = *(bool *)uap; 12703 isc_result_t result; 12704 dns_zone_t *raw = NULL; 12705 char *journal; 12706 12707 dns_zone_getraw(zone, &raw); 12708 if (raw != NULL) { 12709 synczone(raw, uap); 12710 dns_zone_detach(&raw); 12711 } 12712 12713 result = dns_zone_flush(zone); 12714 if (result != ISC_R_SUCCESS) { 12715 cleanup = false; 12716 } 12717 if (cleanup) { 12718 journal = dns_zone_getjournal(zone); 12719 if (journal != NULL) { 12720 (void)isc_file_remove(journal); 12721 } 12722 } 12723 12724 return result; 12725 } 12726 12727 isc_result_t 12728 named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { 12729 isc_result_t result, tresult; 12730 dns_view_t *view = NULL; 12731 dns_zone_t *zone = NULL; 12732 char classstr[DNS_RDATACLASS_FORMATSIZE]; 12733 char zonename[DNS_NAME_FORMATSIZE]; 12734 const char *vname = NULL, *sep = NULL, *arg = NULL; 12735 bool cleanup = false; 12736 12737 REQUIRE(text != NULL); 12738 12739 (void)next_token(lex, text); 12740 12741 arg = next_token(lex, text); 12742 if (arg != NULL && 12743 (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) 12744 { 12745 cleanup = true; 12746 arg = next_token(lex, text); 12747 } 12748 12749 REQUIRE(text != NULL); 12750 12751 result = zone_from_args(server, lex, arg, &zone, NULL, text, false); 12752 if (result != ISC_R_SUCCESS) { 12753 return result; 12754 } 12755 12756 if (zone == NULL) { 12757 isc_loopmgr_pause(named_g_loopmgr); 12758 tresult = ISC_R_SUCCESS; 12759 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12760 view = ISC_LIST_NEXT(view, link)) 12761 { 12762 result = dns_view_apply(view, false, NULL, synczone, 12763 &cleanup); 12764 if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) 12765 { 12766 tresult = result; 12767 } 12768 } 12769 isc_loopmgr_resume(named_g_loopmgr); 12770 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12771 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12772 "dumping all zones%s: %s", 12773 cleanup ? ", removing journal files" : "", 12774 isc_result_totext(result)); 12775 return tresult; 12776 } 12777 12778 isc_loopmgr_pause(named_g_loopmgr); 12779 result = synczone(zone, &cleanup); 12780 isc_loopmgr_resume(named_g_loopmgr); 12781 12782 view = dns_zone_getview(zone); 12783 if (strcmp(view->name, "_default") == 0 || 12784 strcmp(view->name, "_bind") == 0) 12785 { 12786 vname = ""; 12787 sep = ""; 12788 } else { 12789 vname = view->name; 12790 sep = " "; 12791 } 12792 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 12793 sizeof(classstr)); 12794 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 12795 isc_log_write( 12796 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, 12797 ISC_LOG_INFO, "sync: dumping zone '%s/%s'%s%s%s: %s", zonename, 12798 classstr, sep, vname, cleanup ? ", removing journal file" : "", 12799 isc_result_totext(result)); 12800 dns_zone_detach(&zone); 12801 return result; 12802 } 12803 12804 /* 12805 * Act on a "freeze" or "thaw" command from the command channel. 12806 */ 12807 isc_result_t 12808 named_server_freeze(named_server_t *server, bool freeze, isc_lex_t *lex, 12809 isc_buffer_t **text) { 12810 isc_result_t result, tresult; 12811 dns_zone_t *mayberaw = NULL, *raw = NULL; 12812 dns_zonetype_t type; 12813 char classstr[DNS_RDATACLASS_FORMATSIZE]; 12814 char zonename[DNS_NAME_FORMATSIZE]; 12815 dns_view_t *view; 12816 const char *vname, *sep; 12817 bool frozen; 12818 const char *msg = NULL; 12819 12820 REQUIRE(text != NULL); 12821 12822 result = zone_from_args(server, lex, NULL, &mayberaw, NULL, text, true); 12823 if (result != ISC_R_SUCCESS) { 12824 return result; 12825 } 12826 if (mayberaw == NULL) { 12827 isc_loopmgr_pause(named_g_loopmgr); 12828 tresult = ISC_R_SUCCESS; 12829 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12830 view = ISC_LIST_NEXT(view, link)) 12831 { 12832 result = dns_view_freezezones(view, freeze); 12833 if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) 12834 { 12835 tresult = result; 12836 } 12837 } 12838 isc_loopmgr_resume(named_g_loopmgr); 12839 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12840 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12841 "%s all zones: %s", 12842 freeze ? "freezing" : "thawing", 12843 isc_result_totext(tresult)); 12844 return tresult; 12845 } 12846 dns_zone_getraw(mayberaw, &raw); 12847 if (raw != NULL) { 12848 dns_zone_detach(&mayberaw); 12849 dns_zone_attach(raw, &mayberaw); 12850 dns_zone_detach(&raw); 12851 } 12852 type = dns_zone_gettype(mayberaw); 12853 if (type != dns_zone_primary) { 12854 dns_zone_detach(&mayberaw); 12855 return DNS_R_NOTPRIMARY; 12856 } 12857 12858 if (freeze && !dns_zone_isdynamic(mayberaw, true)) { 12859 dns_zone_detach(&mayberaw); 12860 return DNS_R_NOTDYNAMIC; 12861 } 12862 12863 isc_loopmgr_pause(named_g_loopmgr); 12864 frozen = dns_zone_getupdatedisabled(mayberaw); 12865 if (freeze) { 12866 if (frozen) { 12867 msg = "WARNING: The zone was already frozen.\n" 12868 "Someone else may be editing it or " 12869 "it may still be re-loading."; 12870 result = DNS_R_FROZEN; 12871 } 12872 if (result == ISC_R_SUCCESS) { 12873 result = dns_zone_flush(mayberaw); 12874 if (result != ISC_R_SUCCESS) { 12875 msg = "Flushing the zone updates to " 12876 "disk failed."; 12877 } 12878 } 12879 if (result == ISC_R_SUCCESS) { 12880 dns_zone_setupdatedisabled(mayberaw, freeze); 12881 } 12882 } else { 12883 if (frozen) { 12884 result = dns_zone_loadandthaw(mayberaw); 12885 switch (result) { 12886 case ISC_R_SUCCESS: 12887 case DNS_R_UPTODATE: 12888 msg = "The zone reload and thaw was " 12889 "successful."; 12890 result = ISC_R_SUCCESS; 12891 break; 12892 case DNS_R_CONTINUE: 12893 msg = "A zone reload and thaw was started.\n" 12894 "Check the logs to see the result."; 12895 result = ISC_R_SUCCESS; 12896 break; 12897 default: 12898 break; 12899 } 12900 } 12901 } 12902 isc_loopmgr_resume(named_g_loopmgr); 12903 12904 if (msg != NULL) { 12905 (void)putstr(text, msg); 12906 (void)putnull(text); 12907 } 12908 12909 view = dns_zone_getview(mayberaw); 12910 if (strcmp(view->name, "_default") == 0 || 12911 strcmp(view->name, "_bind") == 0) 12912 { 12913 vname = ""; 12914 sep = ""; 12915 } else { 12916 vname = view->name; 12917 sep = " "; 12918 } 12919 dns_rdataclass_format(dns_zone_getclass(mayberaw), classstr, 12920 sizeof(classstr)); 12921 dns_name_format(dns_zone_getorigin(mayberaw), zonename, 12922 sizeof(zonename)); 12923 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12924 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12925 "%s zone '%s/%s'%s%s: %s", 12926 freeze ? "freezing" : "thawing", zonename, classstr, sep, 12927 vname, isc_result_totext(result)); 12928 dns_zone_detach(&mayberaw); 12929 return result; 12930 } 12931 12932 #ifdef HAVE_LIBSCF 12933 /* 12934 * This function adds a message for rndc to echo if named 12935 * is managed by smf and is also running chroot. 12936 */ 12937 isc_result_t 12938 named_smf_add_message(isc_buffer_t **text) { 12939 REQUIRE(text != NULL); 12940 12941 return putstr(text, "use svcadm(1M) to manage named"); 12942 } 12943 #endif /* HAVE_LIBSCF */ 12944 12945 #ifndef HAVE_LMDB 12946 12947 /* 12948 * Emit a comment at the top of the nzf file containing the viewname 12949 * Expects the fp to already be open for writing 12950 */ 12951 #define HEADER1 "# New zone file for view: " 12952 #define HEADER2 \ 12953 "\n# This file contains configuration for zones added by\n" \ 12954 "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n" 12955 static isc_result_t 12956 add_comment(FILE *fp, const char *viewname) { 12957 isc_result_t result; 12958 CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL)); 12959 CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL)); 12960 CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL)); 12961 cleanup: 12962 return result; 12963 } 12964 12965 static void 12966 dumpzone(void *arg, const char *buf, int len) { 12967 FILE *fp = arg; 12968 12969 (void)isc_stdio_write(buf, len, 1, fp, NULL); 12970 } 12971 12972 static isc_result_t 12973 nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) { 12974 isc_result_t result; 12975 off_t offset; 12976 FILE *fp = NULL; 12977 bool offsetok = false; 12978 12979 LOCK(&view->new_zone_lock); 12980 12981 CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); 12982 CHECK(isc_stdio_seek(fp, 0, SEEK_END)); 12983 12984 CHECK(isc_stdio_tell(fp, &offset)); 12985 offsetok = true; 12986 if (offset == 0) { 12987 CHECK(add_comment(fp, view->name)); 12988 } 12989 12990 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 12991 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); 12992 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); 12993 CHECK(isc_stdio_flush(fp)); 12994 result = isc_stdio_close(fp); 12995 fp = NULL; 12996 12997 cleanup: 12998 if (fp != NULL) { 12999 (void)isc_stdio_close(fp); 13000 if (offsetok) { 13001 isc_result_t result2; 13002 13003 result2 = isc_file_truncate(view->new_zone_file, 13004 offset); 13005 if (result2 != ISC_R_SUCCESS) { 13006 isc_log_write( 13007 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13008 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13009 "Error truncating NZF file '%s' " 13010 "during rollback from append: " 13011 "%s", 13012 view->new_zone_file, 13013 isc_result_totext(result2)); 13014 } 13015 } 13016 } 13017 UNLOCK(&view->new_zone_lock); 13018 return result; 13019 } 13020 13021 static isc_result_t 13022 nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { 13023 const cfg_obj_t *zl = NULL; 13024 cfg_list_t *list; 13025 const cfg_listelt_t *elt; 13026 13027 FILE *fp = NULL; 13028 char tmp[1024]; 13029 isc_result_t result; 13030 13031 result = isc_file_template(view->new_zone_file, "nzf-XXXXXXXX", tmp, 13032 sizeof(tmp)); 13033 if (result == ISC_R_SUCCESS) { 13034 result = isc_file_openunique(tmp, &fp); 13035 } 13036 if (result != ISC_R_SUCCESS) { 13037 return result; 13038 } 13039 13040 cfg_map_get(config, "zone", &zl); 13041 if (!cfg_obj_islist(zl)) { 13042 CHECK(ISC_R_FAILURE); 13043 } 13044 13045 list = UNCONST(&zl->value.list); 13046 13047 CHECK(add_comment(fp, view->name)); /* force a comment */ 13048 13049 for (elt = ISC_LIST_HEAD(*list); elt != NULL; 13050 elt = ISC_LIST_NEXT(elt, link)) 13051 { 13052 const cfg_obj_t *zconfig = cfg_listelt_value(elt); 13053 13054 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 13055 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); 13056 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); 13057 } 13058 13059 CHECK(isc_stdio_flush(fp)); 13060 result = isc_stdio_close(fp); 13061 fp = NULL; 13062 if (result != ISC_R_SUCCESS) { 13063 goto cleanup; 13064 } 13065 CHECK(isc_file_rename(tmp, view->new_zone_file)); 13066 return result; 13067 13068 cleanup: 13069 if (fp != NULL) { 13070 (void)isc_stdio_close(fp); 13071 } 13072 (void)isc_file_remove(tmp); 13073 return result; 13074 } 13075 13076 static isc_result_t 13077 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { 13078 isc_result_t result; 13079 13080 /* The new zone file may not exist. That is OK. */ 13081 if (!isc_file_exists(view->new_zone_file)) { 13082 return ISC_R_SUCCESS; 13083 } 13084 13085 /* 13086 * Parse the configuration in the NZF file. This may be called in 13087 * multiple views, so we reset the parser each time. 13088 */ 13089 cfg_parser_reset(named_g_addparser); 13090 result = cfg_parse_file(named_g_addparser, view->new_zone_file, 13091 &cfg_type_addzoneconf, &nzcfg->nzf_config); 13092 if (result != ISC_R_SUCCESS) { 13093 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13094 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13095 "Error parsing NZF file '%s': %s", 13096 view->new_zone_file, isc_result_totext(result)); 13097 } 13098 13099 return result; 13100 } 13101 #else /* HAVE_LMDB */ 13102 13103 static void 13104 nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) { 13105 dns_fixedname_t fixed; 13106 13107 dns_fixedname_init(&fixed); 13108 dns_name_downcase(name, dns_fixedname_name(&fixed), NULL); 13109 dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen); 13110 13111 key->mv_data = namebuf; 13112 key->mv_size = strlen(namebuf); 13113 } 13114 13115 static void 13116 dumpzone(void *arg, const char *buf, int len) { 13117 ns_dzarg_t *dzarg = arg; 13118 isc_result_t result; 13119 13120 REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); 13121 13122 result = putmem(dzarg->text, buf, len); 13123 if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { 13124 dzarg->result = result; 13125 } 13126 } 13127 13128 static isc_result_t 13129 nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone, 13130 const cfg_obj_t *zconfig) { 13131 isc_result_t result; 13132 int status; 13133 dns_view_t *view; 13134 bool commit = false; 13135 isc_buffer_t *text = NULL; 13136 char namebuf[1024]; 13137 MDB_val key, data; 13138 ns_dzarg_t dzarg; 13139 13140 view = dns_zone_getview(zone); 13141 13142 nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf)); 13143 13144 if (zconfig == NULL) { 13145 /* We're deleting the zone from the database */ 13146 status = mdb_del(*txnp, dbi, &key, NULL); 13147 if (status != MDB_SUCCESS && status != MDB_NOTFOUND) { 13148 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13149 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13150 "Error deleting zone %s " 13151 "from NZD database: %s", 13152 namebuf, mdb_strerror(status)); 13153 result = ISC_R_FAILURE; 13154 goto cleanup; 13155 } else if (status != MDB_NOTFOUND) { 13156 commit = true; 13157 } 13158 } else { 13159 /* We're creating or overwriting the zone */ 13160 const cfg_obj_t *zoptions; 13161 13162 isc_buffer_allocate(view->mctx, &text, 256); 13163 13164 zoptions = cfg_tuple_get(zconfig, "options"); 13165 if (zoptions == NULL) { 13166 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13167 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13168 "Unable to get options from config in " 13169 "nzd_save()"); 13170 result = ISC_R_FAILURE; 13171 goto cleanup; 13172 } 13173 13174 dzarg.magic = DZARG_MAGIC; 13175 dzarg.text = &text; 13176 dzarg.result = ISC_R_SUCCESS; 13177 cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); 13178 if (dzarg.result != ISC_R_SUCCESS) { 13179 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13180 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13181 "Error writing zone config to " 13182 "buffer in nzd_save(): %s", 13183 isc_result_totext(dzarg.result)); 13184 result = dzarg.result; 13185 goto cleanup; 13186 } 13187 13188 data.mv_data = isc_buffer_base(text); 13189 data.mv_size = isc_buffer_usedlength(text); 13190 13191 status = mdb_put(*txnp, dbi, &key, &data, 0); 13192 if (status != MDB_SUCCESS) { 13193 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13194 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13195 "Error inserting zone in " 13196 "NZD database: %s", 13197 mdb_strerror(status)); 13198 result = ISC_R_FAILURE; 13199 goto cleanup; 13200 } 13201 13202 commit = true; 13203 } 13204 13205 result = ISC_R_SUCCESS; 13206 13207 cleanup: 13208 if (!commit || result != ISC_R_SUCCESS) { 13209 (void)mdb_txn_abort(*txnp); 13210 } else { 13211 status = mdb_txn_commit(*txnp); 13212 if (status != MDB_SUCCESS) { 13213 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13214 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13215 "Error committing " 13216 "NZD database: %s", 13217 mdb_strerror(status)); 13218 result = ISC_R_FAILURE; 13219 } 13220 } 13221 *txnp = NULL; 13222 13223 if (text != NULL) { 13224 isc_buffer_free(&text); 13225 } 13226 13227 return result; 13228 } 13229 13230 /* 13231 * Check whether the new zone database for 'view' can be opened for writing. 13232 * 13233 * Caller must hold 'view->new_zone_lock'. 13234 */ 13235 static isc_result_t 13236 nzd_writable(dns_view_t *view) { 13237 isc_result_t result = ISC_R_SUCCESS; 13238 int status; 13239 MDB_dbi dbi; 13240 MDB_txn *txn = NULL; 13241 13242 REQUIRE(view != NULL); 13243 13244 status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, 0, &txn); 13245 if (status != MDB_SUCCESS) { 13246 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13247 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13248 "mdb_txn_begin: %s", mdb_strerror(status)); 13249 return ISC_R_FAILURE; 13250 } 13251 13252 status = mdb_dbi_open(txn, NULL, 0, &dbi); 13253 if (status != MDB_SUCCESS) { 13254 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13255 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13256 "mdb_dbi_open: %s", mdb_strerror(status)); 13257 result = ISC_R_FAILURE; 13258 } 13259 13260 mdb_txn_abort(txn); 13261 return result; 13262 } 13263 13264 /* 13265 * Open the new zone database for 'view' and start a transaction for it. 13266 * 13267 * Caller must hold 'view->new_zone_lock'. 13268 */ 13269 static isc_result_t 13270 nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { 13271 int status; 13272 MDB_txn *txn = NULL; 13273 13274 REQUIRE(view != NULL); 13275 REQUIRE(txnp != NULL && *txnp == NULL); 13276 REQUIRE(dbi != NULL); 13277 13278 status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, flags, &txn); 13279 if (status != MDB_SUCCESS) { 13280 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13281 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13282 "mdb_txn_begin: %s", mdb_strerror(status)); 13283 goto cleanup; 13284 } 13285 13286 status = mdb_dbi_open(txn, NULL, 0, dbi); 13287 if (status != MDB_SUCCESS) { 13288 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13289 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13290 "mdb_dbi_open: %s", mdb_strerror(status)); 13291 goto cleanup; 13292 } 13293 13294 *txnp = txn; 13295 13296 cleanup: 13297 if (status != MDB_SUCCESS) { 13298 if (txn != NULL) { 13299 mdb_txn_abort(txn); 13300 } 13301 return ISC_R_FAILURE; 13302 } 13303 13304 return ISC_R_SUCCESS; 13305 } 13306 13307 /* 13308 * nzd_env_close() and nzd_env_reopen are a kluge to address the 13309 * problem of an NZD file possibly being created before we drop 13310 * root privileges. 13311 */ 13312 static void 13313 nzd_env_close(dns_view_t *view) { 13314 const char *dbpath = NULL; 13315 char dbpath_copy[PATH_MAX]; 13316 char lockpath[PATH_MAX]; 13317 int status, ret; 13318 13319 if (view->new_zone_dbenv == NULL) { 13320 return; 13321 } 13322 13323 status = mdb_env_get_path(view->new_zone_dbenv, &dbpath); 13324 INSIST(status == MDB_SUCCESS); 13325 snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath); 13326 strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy)); 13327 mdb_env_close((MDB_env *)view->new_zone_dbenv); 13328 13329 /* 13330 * Database files must be owned by the eventual user, not by root. 13331 */ 13332 ret = chown(dbpath_copy, named_os_uid(), -1); 13333 UNUSED(ret); 13334 13335 /* 13336 * Some platforms need the lockfile not to exist when we reopen the 13337 * environment. 13338 */ 13339 (void)isc_file_remove(lockpath); 13340 13341 view->new_zone_dbenv = NULL; 13342 } 13343 13344 static isc_result_t 13345 nzd_env_reopen(dns_view_t *view) { 13346 isc_result_t result; 13347 MDB_env *env = NULL; 13348 int status; 13349 13350 if (view->new_zone_db == NULL) { 13351 return ISC_R_SUCCESS; 13352 } 13353 13354 nzd_env_close(view); 13355 13356 status = mdb_env_create(&env); 13357 if (status != MDB_SUCCESS) { 13358 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13359 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13360 "mdb_env_create failed: %s", 13361 mdb_strerror(status)); 13362 CHECK(ISC_R_FAILURE); 13363 } 13364 13365 if (view->new_zone_mapsize != 0ULL) { 13366 status = mdb_env_set_mapsize(env, view->new_zone_mapsize); 13367 if (status != MDB_SUCCESS) { 13368 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13369 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13370 "mdb_env_set_mapsize failed: %s", 13371 mdb_strerror(status)); 13372 CHECK(ISC_R_FAILURE); 13373 } 13374 } 13375 13376 status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); 13377 if (status != MDB_SUCCESS) { 13378 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13379 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13380 "mdb_env_open of '%s' failed: %s", 13381 view->new_zone_db, mdb_strerror(status)); 13382 CHECK(ISC_R_FAILURE); 13383 } 13384 13385 view->new_zone_dbenv = env; 13386 env = NULL; 13387 result = ISC_R_SUCCESS; 13388 13389 cleanup: 13390 if (env != NULL) { 13391 mdb_env_close(env); 13392 } 13393 return result; 13394 } 13395 13396 /* 13397 * If 'commit' is true, commit the new zone database transaction pointed to by 13398 * 'txnp'; otherwise, abort that transaction. 13399 * 13400 * Caller must hold 'view->new_zone_lock' for the view that the transaction 13401 * pointed to by 'txnp' was started for. 13402 */ 13403 static isc_result_t 13404 nzd_close(MDB_txn **txnp, bool commit) { 13405 isc_result_t result = ISC_R_SUCCESS; 13406 int status; 13407 13408 REQUIRE(txnp != NULL); 13409 13410 if (*txnp != NULL) { 13411 if (commit) { 13412 status = mdb_txn_commit(*txnp); 13413 if (status != MDB_SUCCESS) { 13414 result = ISC_R_FAILURE; 13415 } 13416 } else { 13417 mdb_txn_abort(*txnp); 13418 } 13419 *txnp = NULL; 13420 } 13421 13422 return result; 13423 } 13424 13425 /* 13426 * If there's an existing NZF file, load it and migrate its data 13427 * to the NZD. 13428 * 13429 * Caller must hold view->new_zone_lock. 13430 */ 13431 static isc_result_t 13432 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { 13433 isc_result_t result; 13434 cfg_obj_t *nzf_config = NULL; 13435 int status; 13436 isc_buffer_t *text = NULL; 13437 bool commit = false; 13438 const cfg_obj_t *zonelist; 13439 const cfg_listelt_t *element; 13440 char tempname[PATH_MAX]; 13441 MDB_txn *txn = NULL; 13442 MDB_dbi dbi; 13443 MDB_val key, data; 13444 ns_dzarg_t dzarg; 13445 13446 UNUSED(nzcfg); 13447 13448 /* 13449 * If NZF file doesn't exist, or NZD DB exists and already 13450 * has data, return without attempting migration. 13451 */ 13452 if (!isc_file_exists(view->new_zone_file)) { 13453 result = ISC_R_SUCCESS; 13454 goto cleanup; 13455 } 13456 13457 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13458 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13459 "Migrating zones from NZF file '%s' to " 13460 "NZD database '%s'", 13461 view->new_zone_file, view->new_zone_db); 13462 /* 13463 * Instead of blindly copying lines, we parse the NZF file using 13464 * the configuration parser, because it validates it against the 13465 * config type, giving us a guarantee that valid configuration 13466 * will be written to DB. 13467 */ 13468 cfg_parser_reset(named_g_addparser); 13469 result = cfg_parse_file(named_g_addparser, view->new_zone_file, 13470 &cfg_type_addzoneconf, &nzf_config); 13471 if (result != ISC_R_SUCCESS) { 13472 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13473 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13474 "Error parsing NZF file '%s': %s", 13475 view->new_zone_file, isc_result_totext(result)); 13476 goto cleanup; 13477 } 13478 13479 zonelist = NULL; 13480 CHECK(cfg_map_get(nzf_config, "zone", &zonelist)); 13481 if (!cfg_obj_islist(zonelist)) { 13482 CHECK(ISC_R_FAILURE); 13483 } 13484 13485 CHECK(nzd_open(view, 0, &txn, &dbi)); 13486 13487 isc_buffer_allocate(view->mctx, &text, 256); 13488 13489 for (element = cfg_list_first(zonelist); element != NULL; 13490 element = cfg_list_next(element)) 13491 { 13492 const cfg_obj_t *zconfig; 13493 const cfg_obj_t *zoptions; 13494 char zname[DNS_NAME_FORMATSIZE]; 13495 dns_fixedname_t fname; 13496 dns_name_t *name; 13497 const char *origin; 13498 isc_buffer_t b; 13499 13500 zconfig = cfg_listelt_value(element); 13501 13502 origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 13503 if (origin == NULL) { 13504 result = ISC_R_FAILURE; 13505 goto cleanup; 13506 } 13507 13508 /* Normalize zone name */ 13509 isc_buffer_constinit(&b, origin, strlen(origin)); 13510 isc_buffer_add(&b, strlen(origin)); 13511 name = dns_fixedname_initname(&fname); 13512 CHECK(dns_name_fromtext(name, &b, dns_rootname, 13513 DNS_NAME_DOWNCASE, NULL)); 13514 dns_name_format(name, zname, sizeof(zname)); 13515 13516 key.mv_data = zname; 13517 key.mv_size = strlen(zname); 13518 13519 zoptions = cfg_tuple_get(zconfig, "options"); 13520 if (zoptions == NULL) { 13521 result = ISC_R_FAILURE; 13522 goto cleanup; 13523 } 13524 13525 isc_buffer_clear(text); 13526 dzarg.magic = DZARG_MAGIC; 13527 dzarg.text = &text; 13528 dzarg.result = ISC_R_SUCCESS; 13529 cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); 13530 if (dzarg.result != ISC_R_SUCCESS) { 13531 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13532 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13533 "Error writing zone config to " 13534 "buffer in load_nzf(): %s", 13535 isc_result_totext(result)); 13536 result = dzarg.result; 13537 goto cleanup; 13538 } 13539 13540 data.mv_data = isc_buffer_base(text); 13541 data.mv_size = isc_buffer_usedlength(text); 13542 13543 status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE); 13544 if (status != MDB_SUCCESS) { 13545 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13546 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13547 "Error inserting zone in " 13548 "NZD database: %s", 13549 mdb_strerror(status)); 13550 result = ISC_R_FAILURE; 13551 goto cleanup; 13552 } 13553 13554 commit = true; 13555 } 13556 13557 result = ISC_R_SUCCESS; 13558 13559 /* 13560 * Leaving the NZF file in place is harmless as we won't use it 13561 * if an NZD database is found for the view. But we rename NZF file 13562 * to a backup name here. 13563 */ 13564 strlcpy(tempname, view->new_zone_file, sizeof(tempname)); 13565 if (strlen(tempname) < sizeof(tempname) - 1) { 13566 strlcat(tempname, "~", sizeof(tempname)); 13567 isc_file_rename(view->new_zone_file, tempname); 13568 } 13569 13570 cleanup: 13571 if (result != ISC_R_SUCCESS) { 13572 (void)nzd_close(&txn, false); 13573 } else { 13574 result = nzd_close(&txn, commit); 13575 } 13576 13577 if (text != NULL) { 13578 isc_buffer_free(&text); 13579 } 13580 13581 if (nzf_config != NULL) { 13582 cfg_obj_destroy(named_g_addparser, &nzf_config); 13583 } 13584 13585 return result; 13586 } 13587 #endif /* HAVE_LMDB */ 13588 13589 static isc_result_t 13590 newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, 13591 cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp, 13592 bool *redirectp, isc_buffer_t **text) { 13593 isc_result_t result; 13594 isc_buffer_t argbuf; 13595 bool redirect = false; 13596 cfg_obj_t *zoneconf = NULL; 13597 const cfg_obj_t *zlist = NULL; 13598 const cfg_obj_t *zoneobj = NULL; 13599 const cfg_obj_t *zoptions = NULL; 13600 const cfg_obj_t *obj = NULL; 13601 const char *viewname = NULL; 13602 dns_rdataclass_t rdclass; 13603 dns_view_t *view = NULL; 13604 const char *bn = NULL; 13605 13606 REQUIRE(viewp != NULL && *viewp == NULL); 13607 REQUIRE(zoneobjp != NULL && *zoneobjp == NULL); 13608 REQUIRE(zoneconfp != NULL && *zoneconfp == NULL); 13609 REQUIRE(redirectp != NULL); 13610 13611 /* Try to parse the argument string */ 13612 isc_buffer_init(&argbuf, command, (unsigned int)strlen(command)); 13613 isc_buffer_add(&argbuf, strlen(command)); 13614 13615 if (strncasecmp(command, "add", 3) == 0) { 13616 bn = "addzone"; 13617 } else if (strncasecmp(command, "mod", 3) == 0) { 13618 bn = "modzone"; 13619 } else { 13620 UNREACHABLE(); 13621 } 13622 13623 /* 13624 * Convert the "addzone" or "modzone" to just "zone", for 13625 * the benefit of the parser 13626 */ 13627 isc_buffer_forward(&argbuf, 3); 13628 13629 cfg_parser_reset(named_g_addparser); 13630 CHECK(cfg_parse_buffer(named_g_addparser, &argbuf, bn, 0, 13631 &cfg_type_addzoneconf, 0, &zoneconf)); 13632 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 13633 if (!cfg_obj_islist(zlist)) { 13634 CHECK(ISC_R_FAILURE); 13635 } 13636 13637 /* For now we only support adding one zone at a time */ 13638 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 13639 13640 /* Check the zone type for ones that are not supported by addzone. */ 13641 zoptions = cfg_tuple_get(zoneobj, "options"); 13642 13643 obj = NULL; 13644 (void)cfg_map_get(zoptions, "type", &obj); 13645 if (obj == NULL) { 13646 (void)cfg_map_get(zoptions, "in-view", &obj); 13647 if (obj != NULL) { 13648 (void)putstr(text, "'in-view' zones not supported by "); 13649 (void)putstr(text, bn); 13650 } else { 13651 (void)putstr(text, "zone type not specified"); 13652 } 13653 CHECK(ISC_R_FAILURE); 13654 } 13655 13656 if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 || 13657 strcasecmp(cfg_obj_asstring(obj), "forward") == 0) 13658 { 13659 (void)putstr(text, "'"); 13660 (void)putstr(text, cfg_obj_asstring(obj)); 13661 (void)putstr(text, "' zones not supported by "); 13662 (void)putstr(text, bn); 13663 CHECK(ISC_R_FAILURE); 13664 } 13665 13666 if (strcasecmp(cfg_obj_asstring(obj), "redirect") == 0) { 13667 redirect = true; 13668 } 13669 13670 /* Make sense of optional class argument */ 13671 obj = cfg_tuple_get(zoneobj, "class"); 13672 CHECK(named_config_getclass(obj, dns_rdataclass_in, &rdclass)); 13673 13674 /* Make sense of optional view argument */ 13675 obj = cfg_tuple_get(zoneobj, "view"); 13676 if (obj && cfg_obj_isstring(obj)) { 13677 viewname = cfg_obj_asstring(obj); 13678 } 13679 if (viewname == NULL || *viewname == '\0') { 13680 viewname = "_default"; 13681 } 13682 result = dns_viewlist_find(&server->viewlist, viewname, rdclass, &view); 13683 if (result == ISC_R_NOTFOUND) { 13684 (void)putstr(text, "no matching view found for '"); 13685 (void)putstr(text, viewname); 13686 (void)putstr(text, "'"); 13687 goto cleanup; 13688 } else if (result != ISC_R_SUCCESS) { 13689 goto cleanup; 13690 } 13691 13692 *viewp = view; 13693 *zoneobjp = zoneobj; 13694 *zoneconfp = zoneconf; 13695 *redirectp = redirect; 13696 13697 return ISC_R_SUCCESS; 13698 13699 cleanup: 13700 if (zoneconf != NULL) { 13701 cfg_obj_destroy(named_g_addparser, &zoneconf); 13702 } 13703 if (view != NULL) { 13704 dns_view_detach(&view); 13705 } 13706 13707 return result; 13708 } 13709 13710 static isc_result_t 13711 delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config, 13712 const dns_name_t *zname, nzfwriter_t nzfwriter) { 13713 isc_result_t result = ISC_R_NOTFOUND; 13714 const cfg_listelt_t *elt = NULL; 13715 const cfg_obj_t *zl = NULL; 13716 cfg_list_t *list; 13717 dns_fixedname_t myfixed; 13718 dns_name_t *myname; 13719 13720 REQUIRE(view != NULL); 13721 REQUIRE(pctx != NULL); 13722 REQUIRE(config != NULL); 13723 REQUIRE(zname != NULL); 13724 13725 LOCK(&view->new_zone_lock); 13726 13727 cfg_map_get(config, "zone", &zl); 13728 13729 if (!cfg_obj_islist(zl)) { 13730 CHECK(ISC_R_FAILURE); 13731 } 13732 13733 list = UNCONST(&zl->value.list); 13734 13735 myname = dns_fixedname_initname(&myfixed); 13736 13737 for (elt = ISC_LIST_HEAD(*list); elt != NULL; 13738 elt = ISC_LIST_NEXT(elt, link)) 13739 { 13740 const cfg_obj_t *zconf = cfg_listelt_value(elt); 13741 const char *zn; 13742 cfg_listelt_t *e; 13743 13744 zn = cfg_obj_asstring(cfg_tuple_get(zconf, "name")); 13745 result = dns_name_fromstring(myname, zn, dns_rootname, 0, NULL); 13746 if (result != ISC_R_SUCCESS || !dns_name_equal(zname, myname)) { 13747 continue; 13748 } 13749 13750 e = UNCONST(elt); 13751 ISC_LIST_UNLINK(*list, e, link); 13752 cfg_obj_destroy(pctx, &e->obj); 13753 isc_mem_put(pctx->mctx, e, sizeof(*e)); 13754 result = ISC_R_SUCCESS; 13755 break; 13756 } 13757 13758 /* 13759 * Write config to NZF file if appropriate 13760 */ 13761 if (nzfwriter != NULL && view->new_zone_file != NULL) { 13762 result = nzfwriter(config, view); 13763 } 13764 13765 cleanup: 13766 UNLOCK(&view->new_zone_lock); 13767 return result; 13768 } 13769 13770 static isc_result_t 13771 do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, 13772 dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj, 13773 bool redirect, isc_buffer_t **text) { 13774 isc_result_t result, tresult; 13775 dns_zone_t *zone = NULL; 13776 #ifndef HAVE_LMDB 13777 FILE *fp = NULL; 13778 bool cleanup_config = false; 13779 #else /* HAVE_LMDB */ 13780 MDB_txn *txn = NULL; 13781 MDB_dbi dbi; 13782 bool locked = false; 13783 13784 UNUSED(zoneconf); 13785 #endif 13786 13787 /* Zone shouldn't already exist */ 13788 if (redirect) { 13789 result = (view->redirect == NULL) ? ISC_R_NOTFOUND 13790 : ISC_R_EXISTS; 13791 } else { 13792 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 13793 if (result == ISC_R_SUCCESS) { 13794 result = ISC_R_EXISTS; 13795 } 13796 } 13797 if (result != ISC_R_NOTFOUND) { 13798 goto cleanup; 13799 } 13800 13801 isc_loopmgr_pause(named_g_loopmgr); 13802 13803 #ifndef HAVE_LMDB 13804 /* 13805 * Make sure we can open the configuration save file 13806 */ 13807 result = isc_stdio_open(view->new_zone_file, "a", &fp); 13808 if (result != ISC_R_SUCCESS) { 13809 isc_loopmgr_resume(named_g_loopmgr); 13810 TCHECK(putstr(text, "unable to create '")); 13811 TCHECK(putstr(text, view->new_zone_file)); 13812 TCHECK(putstr(text, "': ")); 13813 TCHECK(putstr(text, isc_result_totext(result))); 13814 goto cleanup; 13815 } 13816 13817 (void)isc_stdio_close(fp); 13818 fp = NULL; 13819 #else /* HAVE_LMDB */ 13820 LOCK(&view->new_zone_lock); 13821 locked = true; 13822 /* Make sure we can open the NZD database */ 13823 result = nzd_writable(view); 13824 if (result != ISC_R_SUCCESS) { 13825 isc_loopmgr_resume(named_g_loopmgr); 13826 TCHECK(putstr(text, "unable to open NZD database for '")); 13827 TCHECK(putstr(text, view->new_zone_db)); 13828 TCHECK(putstr(text, "'")); 13829 result = ISC_R_FAILURE; 13830 goto cleanup; 13831 } 13832 #endif /* HAVE_LMDB */ 13833 13834 /* Mark view unfrozen and configure zone */ 13835 dns_view_thaw(view); 13836 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, 13837 &server->viewlist, &server->kasplist, 13838 &server->keystorelist, cfg->actx, true, false, 13839 false, false); 13840 dns_view_freeze(view); 13841 13842 isc_loopmgr_resume(named_g_loopmgr); 13843 13844 if (result != ISC_R_SUCCESS) { 13845 TCHECK(putstr(text, "configure_zone failed: ")); 13846 TCHECK(putstr(text, isc_result_totext(result))); 13847 goto cleanup; 13848 } 13849 13850 /* Is it there yet? */ 13851 if (redirect) { 13852 if (view->redirect == NULL) { 13853 CHECK(ISC_R_NOTFOUND); 13854 } 13855 dns_zone_attach(view->redirect, &zone); 13856 } else { 13857 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 13858 if (result != ISC_R_SUCCESS) { 13859 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13860 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13861 "added new zone was not found: %s", 13862 isc_result_totext(result)); 13863 goto cleanup; 13864 } 13865 } 13866 13867 #ifndef HAVE_LMDB 13868 /* 13869 * If there wasn't a previous newzone config, just save the one 13870 * we've created. If there was a previous one, merge the new 13871 * zone into it. 13872 */ 13873 if (cfg->nzf_config == NULL) { 13874 cfg_obj_attach(zoneconf, &cfg->nzf_config); 13875 } else { 13876 cfg_obj_t *z = UNCONST(zoneobj); 13877 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, 13878 "zone")); 13879 } 13880 cleanup_config = true; 13881 #endif /* HAVE_LMDB */ 13882 13883 /* 13884 * Load the zone from the master file. If this fails, we'll 13885 * need to undo the configuration we've done already. 13886 */ 13887 result = dns_zone_load(zone, true); 13888 if (result != ISC_R_SUCCESS) { 13889 dns_db_t *dbp = NULL; 13890 13891 TCHECK(putstr(text, "dns_zone_loadnew failed: ")); 13892 TCHECK(putstr(text, isc_result_totext(result))); 13893 13894 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13895 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13896 "addzone failed; reverting."); 13897 13898 /* If the zone loaded partially, unload it */ 13899 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 13900 dns_db_detach(&dbp); 13901 dns_zone_unload(zone); 13902 } 13903 13904 /* Remove the zone from the zone table */ 13905 dns_view_delzone(view, zone); 13906 goto cleanup; 13907 } 13908 13909 /* Flag the zone as having been added at runtime */ 13910 dns_zone_setadded(zone, true); 13911 13912 #ifdef HAVE_LMDB 13913 /* Save the new zone configuration into the NZD */ 13914 CHECK(nzd_open(view, 0, &txn, &dbi)); 13915 CHECK(nzd_save(&txn, dbi, zone, zoneobj)); 13916 #else /* ifdef HAVE_LMDB */ 13917 /* Append the zone configuration to the NZF */ 13918 result = nzf_append(view, zoneobj); 13919 #endif /* HAVE_LMDB */ 13920 13921 cleanup: 13922 13923 #ifndef HAVE_LMDB 13924 if (fp != NULL) { 13925 (void)isc_stdio_close(fp); 13926 } 13927 if (result != ISC_R_SUCCESS && cleanup_config) { 13928 tresult = delete_zoneconf(view, cfg->add_parser, 13929 cfg->nzf_config, name, NULL); 13930 RUNTIME_CHECK(tresult == ISC_R_SUCCESS); 13931 } 13932 #else /* HAVE_LMDB */ 13933 if (txn != NULL) { 13934 (void)nzd_close(&txn, false); 13935 } 13936 if (locked) { 13937 UNLOCK(&view->new_zone_lock); 13938 } 13939 #endif /* HAVE_LMDB */ 13940 13941 if (zone != NULL) { 13942 dns_zone_detach(&zone); 13943 } 13944 13945 return result; 13946 } 13947 13948 static isc_result_t 13949 do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, 13950 dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj, 13951 bool redirect, isc_buffer_t **text) { 13952 isc_result_t result, tresult; 13953 dns_zone_t *zone = NULL; 13954 bool added; 13955 #ifndef HAVE_LMDB 13956 FILE *fp = NULL; 13957 cfg_obj_t *z; 13958 #else /* HAVE_LMDB */ 13959 MDB_txn *txn = NULL; 13960 MDB_dbi dbi; 13961 bool locked = false; 13962 #endif /* HAVE_LMDB */ 13963 13964 /* Zone must already exist */ 13965 if (redirect) { 13966 if (view->redirect != NULL) { 13967 dns_zone_attach(view->redirect, &zone); 13968 result = ISC_R_SUCCESS; 13969 } else { 13970 result = ISC_R_NOTFOUND; 13971 } 13972 } else { 13973 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 13974 } 13975 if (result != ISC_R_SUCCESS) { 13976 goto cleanup; 13977 } 13978 13979 added = dns_zone_getadded(zone); 13980 dns_zone_detach(&zone); 13981 13982 #ifndef HAVE_LMDB 13983 cfg = (ns_cfgctx_t *)view->new_zone_config; 13984 if (cfg == NULL) { 13985 TCHECK(putstr(text, "new zone config is not set")); 13986 CHECK(ISC_R_FAILURE); 13987 } 13988 #endif /* ifndef HAVE_LMDB */ 13989 13990 isc_loopmgr_pause(named_g_loopmgr); 13991 13992 #ifndef HAVE_LMDB 13993 /* Make sure we can open the configuration save file */ 13994 result = isc_stdio_open(view->new_zone_file, "a", &fp); 13995 if (result != ISC_R_SUCCESS) { 13996 TCHECK(putstr(text, "unable to open '")); 13997 TCHECK(putstr(text, view->new_zone_file)); 13998 TCHECK(putstr(text, "': ")); 13999 TCHECK(putstr(text, isc_result_totext(result))); 14000 isc_loopmgr_resume(named_g_loopmgr); 14001 goto cleanup; 14002 } 14003 (void)isc_stdio_close(fp); 14004 fp = NULL; 14005 #else /* HAVE_LMDB */ 14006 LOCK(&view->new_zone_lock); 14007 locked = true; 14008 /* Make sure we can open the NZD database */ 14009 result = nzd_writable(view); 14010 if (result != ISC_R_SUCCESS) { 14011 TCHECK(putstr(text, "unable to open NZD database for '")); 14012 TCHECK(putstr(text, view->new_zone_db)); 14013 TCHECK(putstr(text, "'")); 14014 result = ISC_R_FAILURE; 14015 isc_loopmgr_resume(named_g_loopmgr); 14016 goto cleanup; 14017 } 14018 #endif /* HAVE_LMDB */ 14019 14020 /* Reconfigure the zone */ 14021 dns_view_thaw(view); 14022 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, 14023 &server->viewlist, &server->kasplist, 14024 &server->keystorelist, cfg->actx, true, false, 14025 false, true); 14026 dns_view_freeze(view); 14027 14028 isc_loopmgr_resume(named_g_loopmgr); 14029 14030 if (result != ISC_R_SUCCESS) { 14031 TCHECK(putstr(text, "configure_zone failed: ")); 14032 TCHECK(putstr(text, isc_result_totext(result))); 14033 goto cleanup; 14034 } 14035 14036 /* Is it there yet? */ 14037 if (redirect) { 14038 if (view->redirect == NULL) { 14039 CHECK(ISC_R_NOTFOUND); 14040 } 14041 dns_zone_attach(view->redirect, &zone); 14042 } else { 14043 CHECK(dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone)); 14044 } 14045 14046 #ifndef HAVE_LMDB 14047 /* Remove old zone from configuration (and NZF file if applicable) */ 14048 if (added) { 14049 result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, 14050 dns_zone_getorigin(zone), 14051 nzf_writeconf); 14052 if (result != ISC_R_SUCCESS) { 14053 TCHECK(putstr(text, "former zone configuration " 14054 "not deleted: ")); 14055 TCHECK(putstr(text, isc_result_totext(result))); 14056 goto cleanup; 14057 } 14058 } 14059 #endif /* HAVE_LMDB */ 14060 14061 if (!added) { 14062 if (cfg->vconfig == NULL) { 14063 result = delete_zoneconf( 14064 view, cfg->conf_parser, cfg->config, 14065 dns_zone_getorigin(zone), NULL); 14066 } else { 14067 const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, 14068 "options"); 14069 result = delete_zoneconf( 14070 view, cfg->conf_parser, voptions, 14071 dns_zone_getorigin(zone), NULL); 14072 } 14073 14074 if (result != ISC_R_SUCCESS) { 14075 TCHECK(putstr(text, "former zone configuration " 14076 "not deleted: ")); 14077 TCHECK(putstr(text, isc_result_totext(result))); 14078 goto cleanup; 14079 } 14080 } 14081 14082 /* Load the zone from the master file if it needs reloading. */ 14083 result = dns_zone_load(zone, true); 14084 14085 /* 14086 * Dynamic zones need no reloading, so we can pass this result. 14087 */ 14088 if (result == DNS_R_DYNAMIC) { 14089 result = ISC_R_SUCCESS; 14090 } 14091 14092 if (result != ISC_R_SUCCESS) { 14093 dns_db_t *dbp = NULL; 14094 14095 TCHECK(putstr(text, "failed to load zone '")); 14096 TCHECK(putstr(text, zname)); 14097 TCHECK(putstr(text, "': ")); 14098 TCHECK(putstr(text, isc_result_totext(result))); 14099 TCHECK(putstr(text, "\nThe zone is no longer being served. ")); 14100 TCHECK(putstr(text, "Use 'rndc addzone' to correct\n")); 14101 TCHECK(putstr(text, "the problem and restore service.")); 14102 14103 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14104 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14105 "modzone failed; removing zone."); 14106 14107 /* If the zone loaded partially, unload it */ 14108 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14109 dns_db_detach(&dbp); 14110 dns_zone_unload(zone); 14111 } 14112 14113 /* Remove the zone from the zone table */ 14114 dns_view_delzone(view, zone); 14115 goto cleanup; 14116 } 14117 14118 #ifndef HAVE_LMDB 14119 /* Store the new zone configuration; also in NZF if applicable */ 14120 z = UNCONST(zoneobj); 14121 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone")); 14122 #endif /* HAVE_LMDB */ 14123 14124 if (added) { 14125 #ifdef HAVE_LMDB 14126 CHECK(nzd_open(view, 0, &txn, &dbi)); 14127 CHECK(nzd_save(&txn, dbi, zone, zoneobj)); 14128 #else /* ifdef HAVE_LMDB */ 14129 result = nzf_append(view, zoneobj); 14130 if (result != ISC_R_SUCCESS) { 14131 TCHECK(putstr(text, "\nNew zone config not saved: ")); 14132 TCHECK(putstr(text, isc_result_totext(result))); 14133 goto cleanup; 14134 } 14135 #endif /* HAVE_LMDB */ 14136 14137 TCHECK(putstr(text, "zone '")); 14138 TCHECK(putstr(text, zname)); 14139 TCHECK(putstr(text, "' reconfigured.")); 14140 } else { 14141 TCHECK(putstr(text, "zone '")); 14142 TCHECK(putstr(text, zname)); 14143 TCHECK(putstr(text, "' must also be reconfigured in\n")); 14144 TCHECK(putstr(text, "named.conf to make changes permanent.")); 14145 } 14146 14147 cleanup: 14148 14149 #ifndef HAVE_LMDB 14150 if (fp != NULL) { 14151 (void)isc_stdio_close(fp); 14152 } 14153 #else /* HAVE_LMDB */ 14154 if (txn != NULL) { 14155 (void)nzd_close(&txn, false); 14156 } 14157 if (locked) { 14158 UNLOCK(&view->new_zone_lock); 14159 } 14160 #endif /* HAVE_LMDB */ 14161 14162 if (zone != NULL) { 14163 dns_zone_detach(&zone); 14164 } 14165 14166 return result; 14167 } 14168 14169 /* 14170 * Act on an "addzone" or "modzone" command from the command channel. 14171 */ 14172 isc_result_t 14173 named_server_changezone(named_server_t *server, char *command, 14174 isc_buffer_t **text) { 14175 isc_result_t result; 14176 bool addzone; 14177 bool redirect = false; 14178 ns_cfgctx_t *cfg = NULL; 14179 cfg_obj_t *zoneconf = NULL; 14180 const cfg_obj_t *zoneobj = NULL; 14181 const char *zonename; 14182 dns_view_t *view = NULL; 14183 isc_buffer_t buf; 14184 dns_fixedname_t fname; 14185 dns_name_t *dnsname; 14186 14187 REQUIRE(text != NULL); 14188 14189 if (strncasecmp(command, "add", 3) == 0) { 14190 addzone = true; 14191 } else { 14192 INSIST(strncasecmp(command, "mod", 3) == 0); 14193 addzone = false; 14194 } 14195 14196 CHECK(newzone_parse(server, command, &view, &zoneconf, &zoneobj, 14197 &redirect, text)); 14198 14199 /* Are we accepting new zones in this view? */ 14200 #ifdef HAVE_LMDB 14201 if (view->new_zone_db == NULL) 14202 #else /* ifdef HAVE_LMDB */ 14203 if (view->new_zone_file == NULL) 14204 #endif /* HAVE_LMDB */ 14205 { 14206 (void)putstr(text, "Not allowing new zones in view '"); 14207 (void)putstr(text, view->name); 14208 (void)putstr(text, "'"); 14209 result = ISC_R_NOPERM; 14210 goto cleanup; 14211 } 14212 14213 cfg = (ns_cfgctx_t *)view->new_zone_config; 14214 if (cfg == NULL) { 14215 result = ISC_R_FAILURE; 14216 goto cleanup; 14217 } 14218 14219 zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name")); 14220 isc_buffer_constinit(&buf, zonename, strlen(zonename)); 14221 isc_buffer_add(&buf, strlen(zonename)); 14222 14223 dnsname = dns_fixedname_initname(&fname); 14224 CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, 0, NULL)); 14225 14226 if (redirect) { 14227 if (!dns_name_equal(dnsname, dns_rootname)) { 14228 (void)putstr(text, "redirect zones must be called " 14229 "\".\""); 14230 CHECK(ISC_R_FAILURE); 14231 } 14232 } 14233 14234 if (addzone) { 14235 CHECK(do_addzone(server, cfg, view, dnsname, zoneconf, zoneobj, 14236 redirect, text)); 14237 } else { 14238 CHECK(do_modzone(server, cfg, view, dnsname, zonename, zoneobj, 14239 redirect, text)); 14240 } 14241 14242 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14243 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14244 "%s zone %s in view %s via %s", 14245 addzone ? "added" : "updated", zonename, view->name, 14246 addzone ? NAMED_COMMAND_ADDZONE : NAMED_COMMAND_MODZONE); 14247 14248 /* Changing a zone counts as reconfiguration */ 14249 named_g_configtime = isc_time_now(); 14250 14251 cleanup: 14252 if (isc_buffer_usedlength(*text) > 0) { 14253 (void)putnull(text); 14254 } 14255 if (zoneconf != NULL) { 14256 cfg_obj_destroy(named_g_addparser, &zoneconf); 14257 } 14258 if (view != NULL) { 14259 dns_view_detach(&view); 14260 } 14261 14262 return result; 14263 } 14264 14265 static bool 14266 inuse(const char *file, bool first, isc_buffer_t **text) { 14267 if (file != NULL && isc_file_exists(file)) { 14268 if (first) { 14269 (void)putstr(text, "The following files were in use " 14270 "and may now be removed:\n"); 14271 } else { 14272 (void)putstr(text, "\n"); 14273 } 14274 (void)putstr(text, file); 14275 (void)putnull(text); 14276 return false; 14277 } 14278 return first; 14279 } 14280 14281 typedef struct { 14282 dns_zone_t *zone; 14283 bool cleanup; 14284 } ns_dzctx_t; 14285 14286 /* 14287 * Carry out a zone deletion scheduled by named_server_delzone(). 14288 */ 14289 static void 14290 rmzone(void *arg) { 14291 ns_dzctx_t *dz = (ns_dzctx_t *)arg; 14292 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; 14293 dns_catz_zone_t *catz = NULL; 14294 char zonename[DNS_NAME_FORMATSIZE]; 14295 dns_view_t *view = NULL; 14296 ns_cfgctx_t *cfg = NULL; 14297 dns_db_t *dbp = NULL; 14298 bool added; 14299 isc_result_t result; 14300 #ifdef HAVE_LMDB 14301 MDB_txn *txn = NULL; 14302 MDB_dbi dbi; 14303 #endif /* ifdef HAVE_LMDB */ 14304 14305 REQUIRE(dz != NULL); 14306 14307 /* Dig out configuration for this zone */ 14308 zone = dz->zone; 14309 view = dns_zone_getview(zone); 14310 cfg = (ns_cfgctx_t *)view->new_zone_config; 14311 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 14312 14313 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14314 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14315 "deleting zone %s in view %s via delzone", zonename, 14316 view->name); 14317 14318 /* 14319 * Remove the zone from configuration (and NZF file if applicable) 14320 * (If this is a catalog zone member then nzf_config can be NULL) 14321 */ 14322 added = dns_zone_getadded(zone); 14323 catz = dns_zone_get_parentcatz(zone); 14324 14325 if (added && catz == NULL && cfg != NULL) { 14326 #ifdef HAVE_LMDB 14327 /* Make sure we can open the NZD database */ 14328 LOCK(&view->new_zone_lock); 14329 result = nzd_open(view, 0, &txn, &dbi); 14330 if (result != ISC_R_SUCCESS) { 14331 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14332 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14333 "unable to open NZD database for '%s'", 14334 view->new_zone_db); 14335 } else { 14336 result = nzd_save(&txn, dbi, zone, NULL); 14337 } 14338 14339 if (result != ISC_R_SUCCESS) { 14340 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14341 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14342 "unable to delete zone configuration: %s", 14343 isc_result_totext(result)); 14344 } 14345 14346 if (txn != NULL) { 14347 (void)nzd_close(&txn, false); 14348 } 14349 UNLOCK(&view->new_zone_lock); 14350 #else /* ifdef HAVE_LMDB */ 14351 result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, 14352 dns_zone_getorigin(zone), 14353 nzf_writeconf); 14354 if (result != ISC_R_SUCCESS) { 14355 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14356 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14357 "unable to delete zone configuration: %s", 14358 isc_result_totext(result)); 14359 } 14360 #endif /* HAVE_LMDB */ 14361 } 14362 14363 if (!added && cfg != NULL) { 14364 if (cfg->vconfig != NULL) { 14365 const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, 14366 "options"); 14367 result = delete_zoneconf( 14368 view, cfg->conf_parser, voptions, 14369 dns_zone_getorigin(zone), NULL); 14370 } else { 14371 result = delete_zoneconf( 14372 view, cfg->conf_parser, cfg->config, 14373 dns_zone_getorigin(zone), NULL); 14374 } 14375 if (result != ISC_R_SUCCESS) { 14376 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14377 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14378 "unable to delete zone configuration: %s", 14379 isc_result_totext(result)); 14380 } 14381 } 14382 14383 /* Unload zone database */ 14384 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14385 dns_db_detach(&dbp); 14386 dns_zone_unload(zone); 14387 } 14388 14389 /* Clean up stub/secondary zone files if requested to do so */ 14390 dns_zone_getraw(zone, &raw); 14391 mayberaw = (raw != NULL) ? raw : zone; 14392 14393 if (added && dz->cleanup) { 14394 const char *file; 14395 14396 file = dns_zone_getfile(mayberaw); 14397 result = isc_file_remove(file); 14398 if (result != ISC_R_SUCCESS) { 14399 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14400 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14401 "file %s not removed: %s", file, 14402 isc_result_totext(result)); 14403 } 14404 14405 file = dns_zone_getjournal(mayberaw); 14406 result = isc_file_remove(file); 14407 if (result != ISC_R_SUCCESS) { 14408 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14409 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14410 "file %s not removed: %s", file, 14411 isc_result_totext(result)); 14412 } 14413 14414 if (zone != mayberaw) { 14415 file = dns_zone_getfile(zone); 14416 result = isc_file_remove(file); 14417 if (result != ISC_R_SUCCESS) { 14418 isc_log_write( 14419 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14420 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14421 "file %s not removed: %s", file, 14422 isc_result_totext(result)); 14423 } 14424 14425 file = dns_zone_getjournal(zone); 14426 result = isc_file_remove(file); 14427 if (result != ISC_R_SUCCESS) { 14428 isc_log_write( 14429 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14430 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14431 "file %s not removed: %s", file, 14432 isc_result_totext(result)); 14433 } 14434 } 14435 } 14436 14437 if (raw != NULL) { 14438 dns_zone_detach(&raw); 14439 } 14440 dns_zone_detach(&zone); 14441 isc_mem_put(named_g_mctx, dz, sizeof(*dz)); 14442 } 14443 14444 /* 14445 * Act on a "delzone" command from the command channel. 14446 */ 14447 isc_result_t 14448 named_server_delzone(named_server_t *server, isc_lex_t *lex, 14449 isc_buffer_t **text) { 14450 isc_result_t result, tresult; 14451 dns_zone_t *zone = NULL; 14452 dns_zone_t *raw = NULL; 14453 dns_zone_t *mayberaw; 14454 dns_view_t *view = NULL; 14455 char zonename[DNS_NAME_FORMATSIZE]; 14456 bool cleanup = false; 14457 const char *ptr; 14458 bool added; 14459 ns_dzctx_t *dz = NULL; 14460 14461 REQUIRE(text != NULL); 14462 14463 /* Skip the command name. */ 14464 ptr = next_token(lex, text); 14465 if (ptr == NULL) { 14466 return ISC_R_UNEXPECTEDEND; 14467 } 14468 14469 /* Find out what we are to do. */ 14470 ptr = next_token(lex, text); 14471 if (ptr == NULL) { 14472 return ISC_R_UNEXPECTEDEND; 14473 } 14474 14475 if (strcmp(ptr, "-clean") == 0 || strcmp(ptr, "-clear") == 0) { 14476 cleanup = true; 14477 ptr = next_token(lex, text); 14478 } 14479 14480 CHECK(zone_from_args(server, lex, ptr, &zone, zonename, text, false)); 14481 if (zone == NULL) { 14482 result = ISC_R_UNEXPECTEDEND; 14483 goto cleanup; 14484 } 14485 14486 INSIST(zonename != NULL); 14487 14488 /* Is this a policy zone? */ 14489 if (dns_zone_get_rpz_num(zone) != DNS_RPZ_INVALID_NUM) { 14490 TCHECK(putstr(text, "zone '")); 14491 TCHECK(putstr(text, zonename)); 14492 TCHECK(putstr(text, 14493 "' cannot be deleted: response-policy zone.")); 14494 result = ISC_R_FAILURE; 14495 goto cleanup; 14496 } 14497 14498 view = dns_zone_getview(zone); 14499 if (dns_zone_gettype(zone) == dns_zone_redirect) { 14500 dns_zone_detach(&view->redirect); 14501 } else { 14502 CHECK(dns_view_delzone(view, zone)); 14503 } 14504 14505 /* Send cleanup event */ 14506 dz = isc_mem_get(named_g_mctx, sizeof(*dz)); 14507 *dz = (ns_dzctx_t){ 14508 .cleanup = cleanup, 14509 }; 14510 dns_zone_attach(zone, &dz->zone); 14511 isc_async_run(dns_zone_getloop(zone), rmzone, dz); 14512 14513 /* Inform user about cleaning up stub/secondary zone files */ 14514 dns_zone_getraw(zone, &raw); 14515 mayberaw = (raw != NULL) ? raw : zone; 14516 14517 added = dns_zone_getadded(zone); 14518 if (!added) { 14519 TCHECK(putstr(text, "zone '")); 14520 TCHECK(putstr(text, zonename)); 14521 TCHECK(putstr(text, "' is no longer active and will be " 14522 "deleted.\n")); 14523 TCHECK(putstr(text, "To keep it from returning ")); 14524 TCHECK(putstr(text, "when the server is restarted, it\n")); 14525 TCHECK(putstr(text, "must also be removed from named.conf.")); 14526 } else if (cleanup) { 14527 TCHECK(putstr(text, "zone '")); 14528 TCHECK(putstr(text, zonename)); 14529 TCHECK(putstr(text, "' and associated files will be deleted.")); 14530 } else if (dns_zone_gettype(mayberaw) == dns_zone_secondary || 14531 dns_zone_gettype(mayberaw) == dns_zone_mirror || 14532 dns_zone_gettype(mayberaw) == dns_zone_stub) 14533 { 14534 bool first; 14535 const char *file; 14536 14537 TCHECK(putstr(text, "zone '")); 14538 TCHECK(putstr(text, zonename)); 14539 TCHECK(putstr(text, "' will be deleted.")); 14540 14541 file = dns_zone_getfile(mayberaw); 14542 first = inuse(file, true, text); 14543 14544 file = dns_zone_getjournal(mayberaw); 14545 first = inuse(file, first, text); 14546 14547 if (zone != mayberaw) { 14548 file = dns_zone_getfile(zone); 14549 first = inuse(file, first, text); 14550 14551 file = dns_zone_getjournal(zone); 14552 (void)inuse(file, first, text); 14553 } 14554 } 14555 14556 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14557 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14558 "zone %s scheduled for removal via delzone", zonename); 14559 14560 /* Removing a zone counts as reconfiguration */ 14561 named_g_configtime = isc_time_now(); 14562 14563 result = ISC_R_SUCCESS; 14564 14565 cleanup: 14566 if (isc_buffer_usedlength(*text) > 0) { 14567 (void)putnull(text); 14568 } 14569 if (raw != NULL) { 14570 dns_zone_detach(&raw); 14571 } 14572 if (zone != NULL) { 14573 dns_zone_detach(&zone); 14574 } 14575 14576 return result; 14577 } 14578 14579 static const cfg_obj_t * 14580 find_name_in_list_from_map(const cfg_obj_t *config, 14581 const char *map_key_for_list, const char *name, 14582 bool redirect) { 14583 const cfg_obj_t *list = NULL; 14584 const cfg_listelt_t *element; 14585 const cfg_obj_t *obj = NULL; 14586 dns_fixedname_t fixed1, fixed2; 14587 dns_name_t *name1 = NULL, *name2 = NULL; 14588 isc_result_t result; 14589 14590 if (strcmp(map_key_for_list, "zone") == 0) { 14591 name1 = dns_fixedname_initname(&fixed1); 14592 name2 = dns_fixedname_initname(&fixed2); 14593 result = dns_name_fromstring(name1, name, dns_rootname, 0, 14594 NULL); 14595 RUNTIME_CHECK(result == ISC_R_SUCCESS); 14596 } 14597 14598 cfg_map_get(config, map_key_for_list, &list); 14599 for (element = cfg_list_first(list); element != NULL; 14600 element = cfg_list_next(element)) 14601 { 14602 const char *vname; 14603 14604 obj = cfg_listelt_value(element); 14605 INSIST(obj != NULL); 14606 vname = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 14607 if (vname == NULL) { 14608 obj = NULL; 14609 continue; 14610 } 14611 14612 if (name1 != NULL) { 14613 result = dns_name_fromstring(name2, vname, dns_rootname, 14614 0, NULL); 14615 if (result == ISC_R_SUCCESS && 14616 dns_name_equal(name1, name2)) 14617 { 14618 const cfg_obj_t *zoptions; 14619 const cfg_obj_t *typeobj = NULL; 14620 zoptions = cfg_tuple_get(obj, "options"); 14621 14622 if (zoptions != NULL) { 14623 cfg_map_get(zoptions, "type", &typeobj); 14624 } 14625 if (redirect && typeobj != NULL && 14626 strcasecmp(cfg_obj_asstring(typeobj), 14627 "redirect") == 0) 14628 { 14629 break; 14630 } else if (!redirect) { 14631 break; 14632 } 14633 } 14634 } else if (strcasecmp(vname, name) == 0) { 14635 break; 14636 } 14637 14638 obj = NULL; 14639 } 14640 14641 return obj; 14642 } 14643 14644 static void 14645 emitzone(void *arg, const char *buf, int len) { 14646 ns_dzarg_t *dzarg = arg; 14647 isc_result_t result; 14648 14649 REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); 14650 result = putmem(dzarg->text, buf, len); 14651 if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { 14652 dzarg->result = result; 14653 } 14654 } 14655 14656 /* 14657 * Act on a "showzone" command from the command channel. 14658 */ 14659 isc_result_t 14660 named_server_showzone(named_server_t *server, isc_lex_t *lex, 14661 isc_buffer_t **text) { 14662 isc_result_t result; 14663 const cfg_obj_t *vconfig = NULL, *zconfig = NULL; 14664 char zonename[DNS_NAME_FORMATSIZE]; 14665 const cfg_obj_t *map; 14666 dns_view_t *view = NULL; 14667 dns_zone_t *zone = NULL; 14668 ns_cfgctx_t *cfg = NULL; 14669 #ifdef HAVE_LMDB 14670 cfg_obj_t *nzconfig = NULL; 14671 #endif /* HAVE_LMDB */ 14672 bool added, redirect; 14673 ns_dzarg_t dzarg; 14674 14675 REQUIRE(text != NULL); 14676 14677 /* Parse parameters */ 14678 CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); 14679 if (zone == NULL) { 14680 result = ISC_R_UNEXPECTEDEND; 14681 goto cleanup; 14682 } 14683 14684 redirect = dns_zone_gettype(zone) == dns_zone_redirect; 14685 added = dns_zone_getadded(zone); 14686 view = dns_zone_getview(zone); 14687 dns_zone_detach(&zone); 14688 14689 cfg = (ns_cfgctx_t *)view->new_zone_config; 14690 if (cfg == NULL) { 14691 result = ISC_R_FAILURE; 14692 goto cleanup; 14693 } 14694 14695 if (!added) { 14696 /* Find the view statement */ 14697 vconfig = find_name_in_list_from_map(cfg->config, "view", 14698 view->name, false); 14699 14700 /* Find the zone statement */ 14701 if (vconfig != NULL) { 14702 map = cfg_tuple_get(vconfig, "options"); 14703 } else { 14704 map = cfg->config; 14705 } 14706 14707 zconfig = find_name_in_list_from_map(map, "zone", zonename, 14708 redirect); 14709 } 14710 14711 #ifndef HAVE_LMDB 14712 if (zconfig == NULL && cfg->nzf_config != NULL) { 14713 zconfig = find_name_in_list_from_map(cfg->nzf_config, "zone", 14714 zonename, redirect); 14715 } 14716 #else /* HAVE_LMDB */ 14717 if (zconfig == NULL) { 14718 const cfg_obj_t *zlist = NULL; 14719 CHECK(get_newzone_config(view, zonename, &nzconfig)); 14720 CHECK(cfg_map_get(nzconfig, "zone", &zlist)); 14721 if (!cfg_obj_islist(zlist)) { 14722 CHECK(ISC_R_FAILURE); 14723 } 14724 14725 zconfig = cfg_listelt_value(cfg_list_first(zlist)); 14726 } 14727 #endif /* HAVE_LMDB */ 14728 14729 if (zconfig == NULL) { 14730 CHECK(ISC_R_NOTFOUND); 14731 } 14732 14733 CHECK(putstr(text, "zone ")); 14734 dzarg.magic = DZARG_MAGIC; 14735 dzarg.text = text; 14736 dzarg.result = ISC_R_SUCCESS; 14737 cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, &dzarg); 14738 CHECK(dzarg.result); 14739 14740 CHECK(putstr(text, ";")); 14741 14742 result = ISC_R_SUCCESS; 14743 14744 cleanup: 14745 #ifdef HAVE_LMDB 14746 if (nzconfig != NULL) { 14747 cfg_obj_destroy(named_g_addparser, &nzconfig); 14748 } 14749 #endif /* HAVE_LMDB */ 14750 if (isc_buffer_usedlength(*text) > 0) { 14751 (void)putnull(text); 14752 } 14753 14754 return result; 14755 } 14756 14757 static void 14758 newzone_cfgctx_destroy(void **cfgp) { 14759 ns_cfgctx_t *cfg; 14760 14761 REQUIRE(cfgp != NULL && *cfgp != NULL); 14762 14763 cfg = *cfgp; 14764 14765 if (cfg->conf_parser != NULL) { 14766 if (cfg->config != NULL) { 14767 cfg_obj_destroy(cfg->conf_parser, &cfg->config); 14768 } 14769 if (cfg->vconfig != NULL) { 14770 cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig); 14771 } 14772 cfg_parser_destroy(&cfg->conf_parser); 14773 } 14774 if (cfg->add_parser != NULL) { 14775 if (cfg->nzf_config != NULL) { 14776 cfg_obj_destroy(cfg->add_parser, &cfg->nzf_config); 14777 } 14778 cfg_parser_destroy(&cfg->add_parser); 14779 } 14780 14781 if (cfg->actx != NULL) { 14782 cfg_aclconfctx_detach(&cfg->actx); 14783 } 14784 14785 isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); 14786 *cfgp = NULL; 14787 } 14788 14789 isc_result_t 14790 named_server_signing(named_server_t *server, isc_lex_t *lex, 14791 isc_buffer_t **text) { 14792 isc_result_t result = ISC_R_SUCCESS; 14793 dns_zone_t *zone = NULL; 14794 dns_name_t *origin; 14795 dns_db_t *db = NULL; 14796 dns_dbnode_t *node = NULL; 14797 dns_dbversion_t *version = NULL; 14798 dns_rdatatype_t privatetype; 14799 dns_rdataset_t privset; 14800 bool first = true; 14801 bool list = false, clear = false; 14802 bool chain = false; 14803 bool setserial = false; 14804 bool resalt = false; 14805 uint32_t serial = 0; 14806 char keystr[DNS_SECALG_FORMATSIZE + 7]; /* <5-digit keyid>/<alg> */ 14807 unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0; 14808 unsigned char salt[255]; 14809 const char *ptr; 14810 size_t n; 14811 bool kasp = false; 14812 14813 REQUIRE(text != NULL); 14814 14815 dns_rdataset_init(&privset); 14816 14817 /* Skip the command name. */ 14818 ptr = next_token(lex, text); 14819 if (ptr == NULL) { 14820 return ISC_R_UNEXPECTEDEND; 14821 } 14822 14823 /* Find out what we are to do. */ 14824 ptr = next_token(lex, text); 14825 if (ptr == NULL) { 14826 return ISC_R_UNEXPECTEDEND; 14827 } 14828 14829 if (strcasecmp(ptr, "-list") == 0) { 14830 list = true; 14831 } else if ((strcasecmp(ptr, "-clear") == 0) || 14832 (strcasecmp(ptr, "-clean") == 0)) 14833 { 14834 clear = true; 14835 ptr = next_token(lex, text); 14836 if (ptr == NULL) { 14837 return ISC_R_UNEXPECTEDEND; 14838 } 14839 strlcpy(keystr, ptr, sizeof(keystr)); 14840 } else if (strcasecmp(ptr, "-nsec3param") == 0) { 14841 char hashbuf[64], flagbuf[64], iterbuf[64]; 14842 char nbuf[256]; 14843 14844 chain = true; 14845 ptr = next_token(lex, text); 14846 if (ptr == NULL) { 14847 return ISC_R_UNEXPECTEDEND; 14848 } 14849 14850 if (strcasecmp(ptr, "none") == 0) { 14851 hash = 0; 14852 } else { 14853 strlcpy(hashbuf, ptr, sizeof(hashbuf)); 14854 14855 ptr = next_token(lex, text); 14856 if (ptr == NULL) { 14857 return ISC_R_UNEXPECTEDEND; 14858 } 14859 strlcpy(flagbuf, ptr, sizeof(flagbuf)); 14860 14861 ptr = next_token(lex, text); 14862 if (ptr == NULL) { 14863 return ISC_R_UNEXPECTEDEND; 14864 } 14865 strlcpy(iterbuf, ptr, sizeof(iterbuf)); 14866 n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", hashbuf, 14867 flagbuf, iterbuf); 14868 if (n == sizeof(nbuf)) { 14869 return ISC_R_NOSPACE; 14870 } 14871 n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); 14872 if (n != 3U) { 14873 return ISC_R_BADNUMBER; 14874 } 14875 14876 if (hash > 0xffU || flags > 0xffU || 14877 iter > dns_nsec3_maxiterations()) 14878 { 14879 return ISC_R_RANGE; 14880 } 14881 14882 ptr = next_token(lex, text); 14883 if (ptr == NULL) { 14884 return ISC_R_UNEXPECTEDEND; 14885 } else if (strcasecmp(ptr, "auto") == 0) { 14886 /* Auto-generate a random salt. 14887 * XXXMUKS: This currently uses the 14888 * minimum recommended length by RFC 14889 * 5155 (64 bits). It should be made 14890 * configurable. 14891 */ 14892 saltlen = 8; 14893 resalt = true; 14894 } else if (strcmp(ptr, "-") != 0) { 14895 isc_buffer_t buf; 14896 14897 isc_buffer_init(&buf, salt, sizeof(salt)); 14898 CHECK(isc_hex_decodestring(ptr, &buf)); 14899 saltlen = isc_buffer_usedlength(&buf); 14900 } 14901 } 14902 } else if (strcasecmp(ptr, "-serial") == 0) { 14903 ptr = next_token(lex, text); 14904 if (ptr == NULL) { 14905 return ISC_R_UNEXPECTEDEND; 14906 } 14907 CHECK(isc_parse_uint32(&serial, ptr, 10)); 14908 setserial = true; 14909 } else { 14910 CHECK(DNS_R_SYNTAX); 14911 } 14912 14913 CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); 14914 if (zone == NULL) { 14915 CHECK(ISC_R_UNEXPECTEDEND); 14916 } 14917 14918 if (dns_zone_getkasp(zone) != NULL) { 14919 kasp = true; 14920 } 14921 14922 if (clear) { 14923 CHECK(dns_zone_keydone(zone, keystr)); 14924 (void)putstr(text, "request queued"); 14925 (void)putnull(text); 14926 } else if (chain && !kasp) { 14927 CHECK(dns_zone_setnsec3param( 14928 zone, (uint8_t)hash, (uint8_t)flags, iter, 14929 (uint8_t)saltlen, salt, true, resalt)); 14930 (void)putstr(text, "nsec3param request queued"); 14931 (void)putnull(text); 14932 } else if (setserial) { 14933 CHECK(dns_zone_setserial(zone, serial)); 14934 (void)putstr(text, "serial request queued"); 14935 (void)putnull(text); 14936 } else if (list) { 14937 privatetype = dns_zone_getprivatetype(zone); 14938 origin = dns_zone_getorigin(zone); 14939 CHECK(dns_zone_getdb(zone, &db)); 14940 CHECK(dns_db_findnode(db, origin, false, &node)); 14941 dns_db_currentversion(db, &version); 14942 14943 result = dns_db_findrdataset(db, node, version, privatetype, 14944 dns_rdatatype_none, 0, &privset, 14945 NULL); 14946 if (result == ISC_R_NOTFOUND) { 14947 (void)putstr(text, "No signing records found"); 14948 (void)putnull(text); 14949 result = ISC_R_SUCCESS; 14950 goto cleanup; 14951 } 14952 14953 for (result = dns_rdataset_first(&privset); 14954 result == ISC_R_SUCCESS; 14955 result = dns_rdataset_next(&privset)) 14956 { 14957 dns_rdata_t priv = DNS_RDATA_INIT; 14958 /* 14959 * In theory, the output buffer could hold a full RDATA 14960 * record which is 16-bit and then some text around 14961 * it 14962 */ 14963 char output[UINT16_MAX + BUFSIZ]; 14964 isc_buffer_t buf; 14965 14966 dns_rdataset_current(&privset, &priv); 14967 14968 isc_buffer_init(&buf, output, sizeof(output)); 14969 CHECK(dns_private_totext(&priv, &buf)); 14970 if (!first) { 14971 CHECK(putstr(text, "\n")); 14972 } 14973 CHECK(putstr(text, output)); 14974 first = false; 14975 } 14976 if (!first) { 14977 CHECK(putnull(text)); 14978 } 14979 14980 if (result == ISC_R_NOMORE) { 14981 result = ISC_R_SUCCESS; 14982 } 14983 } else if (kasp) { 14984 (void)putstr(text, "zone uses dnssec-policy, use rndc dnssec " 14985 "command instead"); 14986 (void)putnull(text); 14987 } 14988 14989 cleanup: 14990 if (dns_rdataset_isassociated(&privset)) { 14991 dns_rdataset_disassociate(&privset); 14992 } 14993 if (node != NULL) { 14994 dns_db_detachnode(db, &node); 14995 } 14996 if (version != NULL) { 14997 dns_db_closeversion(db, &version, false); 14998 } 14999 if (db != NULL) { 15000 dns_db_detach(&db); 15001 } 15002 if (zone != NULL) { 15003 dns_zone_detach(&zone); 15004 } 15005 15006 return result; 15007 } 15008 15009 static bool 15010 argcheck(char *cmd, const char *full) { 15011 size_t l; 15012 15013 if (cmd == NULL || cmd[0] != '-') { 15014 return false; 15015 } 15016 15017 cmd++; 15018 l = strlen(cmd); 15019 if (l > strlen(full) || strncasecmp(cmd, full, l) != 0) { 15020 return false; 15021 } 15022 15023 return true; 15024 } 15025 15026 isc_result_t 15027 named_server_dnssec(named_server_t *server, isc_lex_t *lex, 15028 isc_buffer_t **text) { 15029 isc_result_t result = ISC_R_SUCCESS; 15030 dns_zone_t *zone = NULL; 15031 dns_kasp_t *kasp = NULL; 15032 dns_dnsseckeylist_t keys; 15033 dns_dnsseckey_t *key; 15034 char *ptr, *zonetext = NULL; 15035 const char *msg = NULL; 15036 /* variables for -checkds */ 15037 bool checkds = false, dspublish = false; 15038 /* variables for -rollover */ 15039 bool rollover = false; 15040 /* variables for -key */ 15041 bool use_keyid = false; 15042 dns_keytag_t keyid = 0; 15043 uint8_t algorithm = 0; 15044 /* variables for -status */ 15045 bool status = false; 15046 char output[4096]; 15047 isc_stdtime_t now, when; 15048 isc_time_t timenow, timewhen; 15049 dns_db_t *db = NULL; 15050 dns_dbversion_t *version = NULL; 15051 15052 REQUIRE(text != NULL); 15053 15054 /* Skip the command name. */ 15055 ptr = next_token(lex, text); 15056 if (ptr == NULL) { 15057 return ISC_R_UNEXPECTEDEND; 15058 } 15059 15060 /* Find out what we are to do. */ 15061 ptr = next_token(lex, text); 15062 if (ptr == NULL) { 15063 return ISC_R_UNEXPECTEDEND; 15064 } 15065 15066 /* Initialize current time and key list. */ 15067 timenow = isc_time_now(); 15068 now = isc_time_seconds(&timenow); 15069 when = now; 15070 15071 ISC_LIST_INIT(keys); 15072 15073 if (strcasecmp(ptr, "-status") == 0) { 15074 status = true; 15075 } else if (strcasecmp(ptr, "-rollover") == 0) { 15076 rollover = true; 15077 } else if (strcasecmp(ptr, "-checkds") == 0) { 15078 checkds = true; 15079 } else { 15080 CHECK(DNS_R_SYNTAX); 15081 } 15082 15083 if (rollover || checkds) { 15084 /* Check for options */ 15085 for (;;) { 15086 ptr = next_token(lex, text); 15087 if (ptr == NULL) { 15088 msg = "Bad format"; 15089 CHECK(ISC_R_UNEXPECTEDEND); 15090 } else if (argcheck(ptr, "alg")) { 15091 isc_consttextregion_t alg; 15092 ptr = next_token(lex, text); 15093 if (ptr == NULL) { 15094 msg = "No key algorithm specified"; 15095 CHECK(ISC_R_UNEXPECTEDEND); 15096 } 15097 alg.base = ptr; 15098 alg.length = strlen(alg.base); 15099 result = dns_secalg_fromtext( 15100 &algorithm, (isc_textregion_t *)&alg); 15101 if (result != ISC_R_SUCCESS) { 15102 msg = "Bad algorithm"; 15103 CHECK(DNS_R_SYNTAX); 15104 } 15105 continue; 15106 } else if (argcheck(ptr, "key")) { 15107 uint16_t id; 15108 ptr = next_token(lex, text); 15109 if (ptr == NULL) { 15110 msg = "No key identifier specified"; 15111 CHECK(ISC_R_UNEXPECTEDEND); 15112 } 15113 CHECK(isc_parse_uint16(&id, ptr, 10)); 15114 keyid = (dns_keytag_t)id; 15115 use_keyid = true; 15116 continue; 15117 } else if (argcheck(ptr, "when")) { 15118 uint32_t tw; 15119 ptr = next_token(lex, text); 15120 if (ptr == NULL) { 15121 msg = "No time specified"; 15122 CHECK(ISC_R_UNEXPECTEDEND); 15123 } 15124 CHECK(dns_time32_fromtext(ptr, &tw)); 15125 when = (isc_stdtime_t)tw; 15126 continue; 15127 } else if (ptr[0] == '-') { 15128 msg = "Unknown option"; 15129 CHECK(DNS_R_SYNTAX); 15130 } else if (checkds) { 15131 /* 15132 * No arguments provided, so we must be 15133 * parsing "published|withdrawn". 15134 */ 15135 if (strcasecmp(ptr, "published") == 0) { 15136 dspublish = true; 15137 } else if (strcasecmp(ptr, "withdrawn") != 0) { 15138 CHECK(DNS_R_SYNTAX); 15139 } 15140 } else if (rollover) { 15141 /* 15142 * No arguments provided, so we must be 15143 * parsing the zone. 15144 */ 15145 zonetext = ptr; 15146 } 15147 break; 15148 } 15149 15150 if (rollover && !use_keyid) { 15151 msg = "Key id is required when scheduling rollover"; 15152 CHECK(DNS_R_SYNTAX); 15153 } 15154 15155 if (algorithm > 0 && !use_keyid) { 15156 msg = "Key id is required when setting algorithm"; 15157 CHECK(DNS_R_SYNTAX); 15158 } 15159 } 15160 15161 /* Get zone. */ 15162 CHECK(zone_from_args(server, lex, zonetext, &zone, NULL, text, false)); 15163 if (zone == NULL) { 15164 msg = "Zone not found"; 15165 CHECK(ISC_R_UNEXPECTEDEND); 15166 } 15167 15168 /* Trailing garbage? */ 15169 ptr = next_token(lex, text); 15170 if (ptr != NULL) { 15171 msg = "Too many arguments"; 15172 CHECK(DNS_R_SYNTAX); 15173 } 15174 15175 /* Get dnssec-policy. */ 15176 kasp = dns_zone_getkasp(zone); 15177 if (kasp == NULL) { 15178 msg = "Zone does not have dnssec-policy"; 15179 goto cleanup; 15180 } 15181 15182 /* Get DNSSEC keys. */ 15183 CHECK(dns_zone_getdb(zone, &db)); 15184 dns_db_currentversion(db, &version); 15185 LOCK(&kasp->lock); 15186 result = dns_zone_getdnsseckeys(zone, db, version, now, &keys); 15187 UNLOCK(&kasp->lock); 15188 if (result != ISC_R_SUCCESS) { 15189 if (result != ISC_R_NOTFOUND) { 15190 goto cleanup; 15191 } 15192 } 15193 15194 if (status) { 15195 /* 15196 * Output the DNSSEC status of the key and signing policy. 15197 */ 15198 LOCK(&kasp->lock); 15199 dns_keymgr_status(kasp, &keys, now, &output[0], sizeof(output)); 15200 UNLOCK(&kasp->lock); 15201 CHECK(putstr(text, output)); 15202 } else if (checkds) { 15203 /* 15204 * Mark DS record has been seen, so it may move to the 15205 * rumoured state. 15206 */ 15207 char whenbuf[80]; 15208 isc_time_set(&timewhen, when, 0); 15209 isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); 15210 isc_result_t ret; 15211 15212 LOCK(&kasp->lock); 15213 if (use_keyid) { 15214 result = dns_keymgr_checkds_id(kasp, &keys, now, when, 15215 dspublish, keyid, 15216 (unsigned int)algorithm); 15217 } else { 15218 result = dns_keymgr_checkds(kasp, &keys, now, when, 15219 dspublish); 15220 } 15221 UNLOCK(&kasp->lock); 15222 15223 switch (result) { 15224 case ISC_R_SUCCESS: 15225 /* 15226 * Rekey after checkds command because the next key 15227 * event may have changed. 15228 */ 15229 dns_zone_rekey(zone, false); 15230 15231 if (use_keyid) { 15232 char tagbuf[6]; 15233 snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); 15234 CHECK(putstr(text, "KSK ")); 15235 CHECK(putstr(text, tagbuf)); 15236 CHECK(putstr(text, ": ")); 15237 } 15238 CHECK(putstr(text, "Marked DS as ")); 15239 if (dspublish) { 15240 CHECK(putstr(text, "published ")); 15241 } else { 15242 CHECK(putstr(text, "withdrawn ")); 15243 } 15244 CHECK(putstr(text, "since ")); 15245 CHECK(putstr(text, whenbuf)); 15246 break; 15247 case DNS_R_TOOMANYKEYS: 15248 CHECK(putstr(text, 15249 "Error: multiple possible keys found, " 15250 "retry command with -key id")); 15251 break; 15252 default: 15253 ret = result; 15254 CHECK(putstr(text, 15255 "Error executing checkds command: ")); 15256 CHECK(putstr(text, isc_result_totext(ret))); 15257 break; 15258 } 15259 } else if (rollover) { 15260 /* 15261 * Manually rollover a key. 15262 */ 15263 char whenbuf[80]; 15264 isc_time_set(&timewhen, when, 0); 15265 isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); 15266 isc_result_t ret; 15267 15268 LOCK(&kasp->lock); 15269 result = dns_keymgr_rollover(kasp, &keys, now, when, keyid, 15270 (unsigned int)algorithm); 15271 UNLOCK(&kasp->lock); 15272 15273 switch (result) { 15274 case ISC_R_SUCCESS: 15275 /* 15276 * Rekey after rollover command because the next key 15277 * event may have changed. 15278 */ 15279 dns_zone_rekey(zone, false); 15280 15281 if (use_keyid) { 15282 char tagbuf[6]; 15283 snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); 15284 CHECK(putstr(text, "Key ")); 15285 CHECK(putstr(text, tagbuf)); 15286 CHECK(putstr(text, ": ")); 15287 } 15288 CHECK(putstr(text, "Rollover scheduled on ")); 15289 CHECK(putstr(text, whenbuf)); 15290 break; 15291 case DNS_R_TOOMANYKEYS: 15292 CHECK(putstr(text, 15293 "Error: multiple possible keys found, " 15294 "retry command with -alg algorithm")); 15295 break; 15296 default: 15297 ret = result; 15298 CHECK(putstr(text, 15299 "Error executing rollover command: ")); 15300 CHECK(putstr(text, isc_result_totext(ret))); 15301 break; 15302 } 15303 } 15304 CHECK(putnull(text)); 15305 15306 cleanup: 15307 if (msg != NULL) { 15308 (void)putstr(text, msg); 15309 (void)putnull(text); 15310 } 15311 15312 if (version != NULL) { 15313 dns_db_closeversion(db, &version, false); 15314 } 15315 if (db != NULL) { 15316 dns_db_detach(&db); 15317 } 15318 15319 while (!ISC_LIST_EMPTY(keys)) { 15320 key = ISC_LIST_HEAD(keys); 15321 ISC_LIST_UNLINK(keys, key, link); 15322 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key); 15323 } 15324 15325 if (zone != NULL) { 15326 dns_zone_detach(&zone); 15327 } 15328 15329 return result; 15330 } 15331 15332 static isc_result_t 15333 putmem(isc_buffer_t **b, const char *str, size_t len) { 15334 isc_result_t result; 15335 15336 result = isc_buffer_reserve(*b, (unsigned int)len); 15337 if (result != ISC_R_SUCCESS) { 15338 return ISC_R_NOSPACE; 15339 } 15340 15341 isc_buffer_putmem(*b, (const unsigned char *)str, (unsigned int)len); 15342 return ISC_R_SUCCESS; 15343 } 15344 15345 static isc_result_t 15346 putstr(isc_buffer_t **b, const char *str) { 15347 return putmem(b, str, strlen(str)); 15348 } 15349 15350 static isc_result_t 15351 putuint8(isc_buffer_t **b, uint8_t val) { 15352 isc_result_t result; 15353 15354 result = isc_buffer_reserve(*b, 1); 15355 if (result != ISC_R_SUCCESS) { 15356 return ISC_R_NOSPACE; 15357 } 15358 15359 isc_buffer_putuint8(*b, val); 15360 return ISC_R_SUCCESS; 15361 } 15362 15363 static isc_result_t 15364 putnull(isc_buffer_t **b) { 15365 return putuint8(b, 0); 15366 } 15367 15368 isc_result_t 15369 named_server_zonestatus(named_server_t *server, isc_lex_t *lex, 15370 isc_buffer_t **text) { 15371 isc_result_t result = ISC_R_SUCCESS; 15372 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; 15373 const char *type, *file; 15374 char zonename[DNS_NAME_FORMATSIZE]; 15375 uint32_t serial, signed_serial, nodes; 15376 char serbuf[16], sserbuf[16], nodebuf[16]; 15377 char resignbuf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 2]; 15378 char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15379 char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15380 char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15381 char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15382 char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15383 isc_time_t loadtime, expiretime, refreshtime; 15384 isc_time_t refreshkeytime, resigntime; 15385 dns_zonetype_t zonetype; 15386 bool dynamic = false, frozen = false; 15387 bool hasraw = false; 15388 bool secure, maintain, allow; 15389 dns_db_t *db = NULL, *rawdb = NULL; 15390 char **incfiles = NULL; 15391 int nfiles = 0; 15392 15393 REQUIRE(text != NULL); 15394 15395 isc_time_settoepoch(&loadtime); 15396 isc_time_settoepoch(&refreshtime); 15397 isc_time_settoepoch(&expiretime); 15398 isc_time_settoepoch(&refreshkeytime); 15399 isc_time_settoepoch(&resigntime); 15400 15401 CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); 15402 if (zone == NULL) { 15403 result = ISC_R_UNEXPECTEDEND; 15404 goto cleanup; 15405 } 15406 15407 /* Inline signing? */ 15408 CHECK(dns_zone_getdb(zone, &db)); 15409 dns_zone_getraw(zone, &raw); 15410 hasraw = (raw != NULL); 15411 if (hasraw) { 15412 mayberaw = raw; 15413 zonetype = dns_zone_gettype(raw); 15414 CHECK(dns_zone_getdb(raw, &rawdb)); 15415 } else { 15416 mayberaw = zone; 15417 zonetype = dns_zone_gettype(zone); 15418 } 15419 15420 type = dns_zonetype_name(zonetype); 15421 15422 /* Serial number */ 15423 result = dns_zone_getserial(mayberaw, &serial); 15424 15425 /* This is to mirror old behavior with dns_zone_getserial */ 15426 if (result != ISC_R_SUCCESS) { 15427 serial = 0; 15428 } 15429 15430 snprintf(serbuf, sizeof(serbuf), "%u", serial); 15431 if (hasraw) { 15432 result = dns_zone_getserial(zone, &signed_serial); 15433 if (result != ISC_R_SUCCESS) { 15434 serial = 0; 15435 } 15436 snprintf(sserbuf, sizeof(sserbuf), "%u", signed_serial); 15437 } 15438 15439 /* Database node count */ 15440 nodes = dns_db_nodecount(hasraw ? rawdb : db, dns_dbtree_main); 15441 snprintf(nodebuf, sizeof(nodebuf), "%u", nodes); 15442 15443 /* Security */ 15444 secure = dns_db_issecure(db); 15445 allow = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW) != 0); 15446 maintain = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0); 15447 15448 /* Master files */ 15449 file = dns_zone_getfile(mayberaw); 15450 nfiles = dns_zone_getincludes(mayberaw, &incfiles); 15451 15452 /* Load time */ 15453 dns_zone_getloadtime(zone, &loadtime); 15454 isc_time_formathttptimestamp(&loadtime, lbuf, sizeof(lbuf)); 15455 15456 /* Refresh/expire times */ 15457 if (zonetype == dns_zone_secondary || zonetype == dns_zone_mirror || 15458 zonetype == dns_zone_stub || zonetype == dns_zone_redirect) 15459 { 15460 dns_zone_getexpiretime(mayberaw, &expiretime); 15461 isc_time_formathttptimestamp(&expiretime, xbuf, sizeof(xbuf)); 15462 dns_zone_getrefreshtime(mayberaw, &refreshtime); 15463 isc_time_formathttptimestamp(&refreshtime, rbuf, sizeof(rbuf)); 15464 } 15465 15466 /* Key refresh time */ 15467 if (zonetype == dns_zone_primary || 15468 (zonetype == dns_zone_secondary && hasraw)) 15469 { 15470 dns_zone_getrefreshkeytime(zone, &refreshkeytime); 15471 isc_time_formathttptimestamp(&refreshkeytime, kbuf, 15472 sizeof(kbuf)); 15473 } 15474 15475 /* Dynamic? */ 15476 if (zonetype == dns_zone_primary) { 15477 dynamic = dns_zone_isdynamic(mayberaw, true); 15478 frozen = dynamic && !dns_zone_isdynamic(mayberaw, false); 15479 } 15480 15481 /* Next resign event */ 15482 if (secure && (zonetype == dns_zone_primary || 15483 (zonetype == dns_zone_secondary && hasraw))) 15484 { 15485 dns_name_t *name; 15486 dns_fixedname_t fixed; 15487 isc_stdtime_t resign; 15488 dns_typepair_t typepair; 15489 15490 name = dns_fixedname_initname(&fixed); 15491 15492 result = dns_db_getsigningtime(db, &resign, name, &typepair); 15493 if (result == ISC_R_SUCCESS) { 15494 char namebuf[DNS_NAME_FORMATSIZE]; 15495 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 15496 15497 resign -= dns_zone_getsigresigninginterval(zone); 15498 15499 dns_name_format(name, namebuf, sizeof(namebuf)); 15500 dns_rdatatype_format(DNS_TYPEPAIR_COVERS(typepair), 15501 typebuf, sizeof(typebuf)); 15502 snprintf(resignbuf, sizeof(resignbuf), "%s/%s", namebuf, 15503 typebuf); 15504 isc_time_set(&resigntime, resign, 0); 15505 isc_time_formathttptimestamp(&resigntime, rtbuf, 15506 sizeof(rtbuf)); 15507 } 15508 } 15509 15510 /* Create text */ 15511 CHECK(putstr(text, "name: ")); 15512 CHECK(putstr(text, zonename)); 15513 15514 CHECK(putstr(text, "\ntype: ")); 15515 CHECK(putstr(text, type)); 15516 15517 if (file != NULL) { 15518 int i; 15519 CHECK(putstr(text, "\nfiles: ")); 15520 CHECK(putstr(text, file)); 15521 for (i = 0; i < nfiles; i++) { 15522 CHECK(putstr(text, ", ")); 15523 if (incfiles[i] != NULL) { 15524 CHECK(putstr(text, incfiles[i])); 15525 } 15526 } 15527 } 15528 15529 CHECK(putstr(text, "\nserial: ")); 15530 CHECK(putstr(text, serbuf)); 15531 if (hasraw) { 15532 CHECK(putstr(text, "\nsigned serial: ")); 15533 CHECK(putstr(text, sserbuf)); 15534 } 15535 15536 CHECK(putstr(text, "\nnodes: ")); 15537 CHECK(putstr(text, nodebuf)); 15538 15539 if (!isc_time_isepoch(&loadtime)) { 15540 CHECK(putstr(text, "\nlast loaded: ")); 15541 CHECK(putstr(text, lbuf)); 15542 } 15543 15544 if (!isc_time_isepoch(&refreshtime)) { 15545 CHECK(putstr(text, "\nnext refresh: ")); 15546 CHECK(putstr(text, rbuf)); 15547 } 15548 15549 if (!isc_time_isepoch(&expiretime)) { 15550 CHECK(putstr(text, "\nexpires: ")); 15551 CHECK(putstr(text, xbuf)); 15552 } 15553 15554 if (secure) { 15555 CHECK(putstr(text, "\nsecure: yes")); 15556 if (hasraw) { 15557 CHECK(putstr(text, "\ninline signing: yes")); 15558 } else { 15559 CHECK(putstr(text, "\ninline signing: no")); 15560 } 15561 } else { 15562 CHECK(putstr(text, "\nsecure: no")); 15563 } 15564 15565 if (maintain) { 15566 CHECK(putstr(text, "\nkey maintenance: automatic")); 15567 if (!isc_time_isepoch(&refreshkeytime)) { 15568 CHECK(putstr(text, "\nnext key event: ")); 15569 CHECK(putstr(text, kbuf)); 15570 } 15571 } else if (allow) { 15572 CHECK(putstr(text, "\nkey maintenance: on command")); 15573 } else if (secure || hasraw) { 15574 CHECK(putstr(text, "\nkey maintenance: none")); 15575 } 15576 15577 if (!isc_time_isepoch(&resigntime)) { 15578 CHECK(putstr(text, "\nnext resign node: ")); 15579 CHECK(putstr(text, resignbuf)); 15580 CHECK(putstr(text, "\nnext resign time: ")); 15581 CHECK(putstr(text, rtbuf)); 15582 } 15583 15584 if (dynamic) { 15585 CHECK(putstr(text, "\ndynamic: yes")); 15586 if (frozen) { 15587 CHECK(putstr(text, "\nfrozen: yes")); 15588 } else { 15589 CHECK(putstr(text, "\nfrozen: no")); 15590 } 15591 } else { 15592 CHECK(putstr(text, "\ndynamic: no")); 15593 } 15594 15595 CHECK(putstr(text, "\nreconfigurable via modzone: ")); 15596 CHECK(putstr(text, dns_zone_getadded(zone) ? "yes" : "no")); 15597 15598 cleanup: 15599 /* Indicate truncated output if possible. */ 15600 if (result == ISC_R_NOSPACE) { 15601 (void)putstr(text, "\n..."); 15602 } 15603 if (result == ISC_R_SUCCESS || result == ISC_R_NOSPACE) { 15604 (void)putnull(text); 15605 } 15606 15607 if (db != NULL) { 15608 dns_db_detach(&db); 15609 } 15610 if (rawdb != NULL) { 15611 dns_db_detach(&rawdb); 15612 } 15613 if (incfiles != NULL && mayberaw != NULL) { 15614 int i; 15615 isc_mem_t *mctx = dns_zone_getmctx(mayberaw); 15616 15617 for (i = 0; i < nfiles; i++) { 15618 if (incfiles[i] != NULL) { 15619 isc_mem_free(mctx, incfiles[i]); 15620 } 15621 } 15622 isc_mem_free(mctx, incfiles); 15623 } 15624 if (raw != NULL) { 15625 dns_zone_detach(&raw); 15626 } 15627 if (zone != NULL) { 15628 dns_zone_detach(&zone); 15629 } 15630 return result; 15631 } 15632 15633 isc_result_t 15634 named_server_nta(named_server_t *server, isc_lex_t *lex, bool readonly, 15635 isc_buffer_t **text) { 15636 dns_view_t *view; 15637 dns_ntatable_t *ntatable = NULL; 15638 isc_result_t result = ISC_R_SUCCESS; 15639 char *ptr, *nametext = NULL, *viewname; 15640 char namebuf[DNS_NAME_FORMATSIZE]; 15641 char viewbuf[DNS_NAME_FORMATSIZE]; 15642 isc_stdtime_t now, when; 15643 isc_time_t t; 15644 char tbuf[64]; 15645 const char *msg = NULL; 15646 bool dump = false, force = false; 15647 dns_fixedname_t fn; 15648 const dns_name_t *ntaname; 15649 dns_name_t *fname; 15650 dns_ttl_t ntattl; 15651 bool ttlset = false, viewfound = false; 15652 dns_rdataclass_t rdclass = dns_rdataclass_in; 15653 bool first = true; 15654 15655 REQUIRE(text != NULL); 15656 15657 UNUSED(force); 15658 15659 fname = dns_fixedname_initname(&fn); 15660 15661 /* Skip the command name. */ 15662 ptr = next_token(lex, text); 15663 if (ptr == NULL) { 15664 return ISC_R_UNEXPECTEDEND; 15665 } 15666 15667 for (;;) { 15668 /* Check for options */ 15669 ptr = next_token(lex, text); 15670 if (ptr == NULL) { 15671 return ISC_R_UNEXPECTEDEND; 15672 } 15673 15674 if (strcmp(ptr, "--") == 0) { 15675 break; 15676 } else if (argcheck(ptr, "dump")) { 15677 dump = true; 15678 } else if (argcheck(ptr, "remove")) { 15679 ntattl = 0; 15680 ttlset = true; 15681 } else if (argcheck(ptr, "force")) { 15682 force = true; 15683 continue; 15684 } else if (argcheck(ptr, "lifetime")) { 15685 isc_textregion_t tr; 15686 15687 ptr = next_token(lex, text); 15688 if (ptr == NULL) { 15689 msg = "No lifetime specified"; 15690 CHECK(ISC_R_UNEXPECTEDEND); 15691 } 15692 15693 tr.base = ptr; 15694 tr.length = strlen(ptr); 15695 result = dns_ttl_fromtext(&tr, &ntattl); 15696 if (result != ISC_R_SUCCESS) { 15697 msg = "could not parse NTA lifetime"; 15698 CHECK(result); 15699 } 15700 15701 if (ntattl > 604800) { 15702 msg = "NTA lifetime cannot exceed one week"; 15703 CHECK(ISC_R_RANGE); 15704 } 15705 15706 ttlset = true; 15707 continue; 15708 } else if (argcheck(ptr, "class")) { 15709 isc_textregion_t tr; 15710 15711 ptr = next_token(lex, text); 15712 if (ptr == NULL) { 15713 msg = "No class specified"; 15714 CHECK(ISC_R_UNEXPECTEDEND); 15715 } 15716 15717 tr.base = ptr; 15718 tr.length = strlen(ptr); 15719 CHECK(dns_rdataclass_fromtext(&rdclass, &tr)); 15720 continue; 15721 } else if (ptr[0] == '-') { 15722 msg = "Unknown option"; 15723 CHECK(DNS_R_SYNTAX); 15724 } else { 15725 nametext = ptr; 15726 } 15727 15728 break; 15729 } 15730 15731 /* 15732 * If -dump was specified, list NTA's and return 15733 */ 15734 if (dump) { 15735 size_t last = 0; 15736 15737 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15738 view = ISC_LIST_NEXT(view, link)) 15739 { 15740 if (ntatable != NULL) { 15741 dns_ntatable_detach(&ntatable); 15742 } 15743 result = dns_view_getntatable(view, &ntatable); 15744 if (result == ISC_R_NOTFOUND) { 15745 continue; 15746 } 15747 15748 if (last != isc_buffer_usedlength(*text)) { 15749 CHECK(putstr(text, "\n")); 15750 } 15751 15752 last = isc_buffer_usedlength(*text); 15753 15754 CHECK(dns_ntatable_totext(ntatable, view->name, text)); 15755 } 15756 CHECK(putnull(text)); 15757 15758 goto cleanup; 15759 } 15760 15761 if (readonly) { 15762 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15763 NAMED_LOGMODULE_CONTROL, ISC_LOG_INFO, 15764 "rejecting restricted control channel " 15765 "NTA command"); 15766 CHECK(ISC_R_FAILURE); 15767 } 15768 15769 /* Get the NTA name if not found above. */ 15770 if (nametext == NULL) { 15771 nametext = next_token(lex, text); 15772 } 15773 if (nametext == NULL) { 15774 return ISC_R_UNEXPECTEDEND; 15775 } 15776 15777 /* Copy nametext as it'll be overwritten by next_token() */ 15778 strlcpy(namebuf, nametext, DNS_NAME_FORMATSIZE); 15779 15780 if (strcmp(namebuf, ".") == 0) { 15781 ntaname = dns_rootname; 15782 } else { 15783 isc_buffer_t b; 15784 isc_buffer_init(&b, namebuf, strlen(namebuf)); 15785 isc_buffer_add(&b, strlen(namebuf)); 15786 CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0, NULL)); 15787 ntaname = fname; 15788 } 15789 15790 /* Look for the view name. */ 15791 viewname = next_token(lex, text); 15792 if (viewname != NULL) { 15793 strlcpy(viewbuf, viewname, DNS_NAME_FORMATSIZE); 15794 viewname = viewbuf; 15795 } 15796 15797 if (next_token(lex, text) != NULL) { 15798 CHECK(DNS_R_SYNTAX); 15799 } 15800 15801 now = isc_stdtime_now(); 15802 15803 isc_loopmgr_pause(named_g_loopmgr); 15804 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15805 view = ISC_LIST_NEXT(view, link)) 15806 { 15807 if (viewname != NULL && strcmp(view->name, viewname) != 0) { 15808 continue; 15809 } 15810 viewfound = true; 15811 15812 if (view->rdclass != rdclass && rdclass != dns_rdataclass_any) { 15813 continue; 15814 } 15815 15816 if (view->nta_lifetime == 0) { 15817 continue; 15818 } 15819 15820 if (!ttlset) { 15821 ntattl = view->nta_lifetime; 15822 } 15823 15824 if (ntatable != NULL) { 15825 dns_ntatable_detach(&ntatable); 15826 } 15827 15828 result = dns_view_getntatable(view, &ntatable); 15829 if (result == ISC_R_NOTFOUND) { 15830 result = ISC_R_SUCCESS; 15831 continue; 15832 } 15833 15834 result = dns_view_flushnode(view, ntaname, true); 15835 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15836 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 15837 "flush tree '%s' in cache view '%s': %s", namebuf, 15838 view->name, isc_result_totext(result)); 15839 15840 if (ntattl != 0) { 15841 CHECK(dns_ntatable_add(ntatable, ntaname, force, now, 15842 ntattl)); 15843 15844 when = now + ntattl; 15845 isc_time_set(&t, when, 0); 15846 isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); 15847 15848 if (!first) { 15849 CHECK(putstr(text, "\n")); 15850 } 15851 first = false; 15852 15853 CHECK(putstr(text, "Negative trust anchor added: ")); 15854 CHECK(putstr(text, namebuf)); 15855 CHECK(putstr(text, "/")); 15856 CHECK(putstr(text, view->name)); 15857 CHECK(putstr(text, ", expires ")); 15858 CHECK(putstr(text, tbuf)); 15859 15860 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15861 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 15862 "added NTA '%s' (%d sec) in view '%s'", 15863 namebuf, ntattl, view->name); 15864 } else { 15865 bool wasremoved; 15866 15867 result = dns_ntatable_delete(ntatable, ntaname); 15868 if (result == ISC_R_SUCCESS) { 15869 wasremoved = true; 15870 } else if (result == ISC_R_NOTFOUND) { 15871 wasremoved = false; 15872 } else { 15873 goto cleanup_exclusive; 15874 } 15875 15876 if (!first) { 15877 CHECK(putstr(text, "\n")); 15878 } 15879 first = false; 15880 15881 CHECK(putstr(text, "Negative trust anchor ")); 15882 CHECK(putstr(text, 15883 wasremoved ? "removed: " : "not found: ")); 15884 CHECK(putstr(text, namebuf)); 15885 CHECK(putstr(text, "/")); 15886 CHECK(putstr(text, view->name)); 15887 15888 if (wasremoved) { 15889 isc_log_write( 15890 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15891 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 15892 "removed NTA '%s' in view %s", namebuf, 15893 view->name); 15894 } 15895 } 15896 15897 result = dns_view_saventa(view); 15898 if (result != ISC_R_SUCCESS) { 15899 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15900 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 15901 "error writing NTA file " 15902 "for view '%s': %s", 15903 view->name, isc_result_totext(result)); 15904 } 15905 } 15906 15907 if (!viewfound) { 15908 msg = "No such view"; 15909 result = ISC_R_NOTFOUND; 15910 } else { 15911 (void)putnull(text); 15912 } 15913 15914 cleanup_exclusive: 15915 isc_loopmgr_resume(named_g_loopmgr); 15916 15917 cleanup: 15918 15919 if (msg != NULL) { 15920 (void)putstr(text, msg); 15921 (void)putnull(text); 15922 } 15923 15924 if (ntatable != NULL) { 15925 dns_ntatable_detach(&ntatable); 15926 } 15927 return result; 15928 } 15929 15930 isc_result_t 15931 named_server_saventa(named_server_t *server) { 15932 dns_view_t *view; 15933 15934 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15935 view = ISC_LIST_NEXT(view, link)) 15936 { 15937 isc_result_t result = dns_view_saventa(view); 15938 15939 if (result != ISC_R_SUCCESS) { 15940 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15941 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 15942 "error writing NTA file " 15943 "for view '%s': %s", 15944 view->name, isc_result_totext(result)); 15945 } 15946 } 15947 15948 return ISC_R_SUCCESS; 15949 } 15950 15951 isc_result_t 15952 named_server_loadnta(named_server_t *server) { 15953 dns_view_t *view; 15954 15955 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15956 view = ISC_LIST_NEXT(view, link)) 15957 { 15958 isc_result_t result = dns_view_loadnta(view); 15959 15960 if ((result != ISC_R_SUCCESS) && 15961 (result != ISC_R_FILENOTFOUND) && 15962 (result != ISC_R_NOTFOUND)) 15963 { 15964 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15965 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 15966 "error loading NTA file " 15967 "for view '%s': %s", 15968 view->name, isc_result_totext(result)); 15969 } 15970 } 15971 15972 return ISC_R_SUCCESS; 15973 } 15974 15975 static isc_result_t 15976 mkey_refresh(dns_view_t *view, isc_buffer_t **text) { 15977 isc_result_t result; 15978 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 15979 15980 snprintf(msg, sizeof(msg), "refreshing managed keys for '%s'", 15981 view->name); 15982 CHECK(putstr(text, msg)); 15983 CHECK(dns_zone_synckeyzone(view->managed_keys)); 15984 15985 cleanup: 15986 return result; 15987 } 15988 15989 static isc_result_t 15990 mkey_destroy(dns_view_t *view, isc_buffer_t **text) { 15991 isc_result_t result; 15992 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 15993 const char *file = NULL; 15994 dns_db_t *dbp = NULL; 15995 dns_zone_t *mkzone = NULL; 15996 bool removed_a_file = false; 15997 15998 if (view->managed_keys == NULL) { 15999 CHECK(ISC_R_NOTFOUND); 16000 } 16001 16002 snprintf(msg, sizeof(msg), "destroying managed-keys database for '%s'", 16003 view->name); 16004 CHECK(putstr(text, msg)); 16005 16006 isc_loopmgr_pause(named_g_loopmgr); 16007 16008 /* Remove and clean up managed keys zone from view */ 16009 mkzone = view->managed_keys; 16010 view->managed_keys = NULL; 16011 (void)dns_zone_flush(mkzone); 16012 16013 /* Unload zone database */ 16014 if (dns_zone_getdb(mkzone, &dbp) == ISC_R_SUCCESS) { 16015 dns_db_detach(&dbp); 16016 dns_zone_unload(mkzone); 16017 } 16018 16019 /* Delete files */ 16020 file = dns_zone_getfile(mkzone); 16021 result = isc_file_remove(file); 16022 if (result == ISC_R_SUCCESS) { 16023 removed_a_file = true; 16024 } else { 16025 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16026 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 16027 "file %s not removed: %s", file, 16028 isc_result_totext(result)); 16029 } 16030 16031 file = dns_zone_getjournal(mkzone); 16032 result = isc_file_remove(file); 16033 if (result == ISC_R_SUCCESS) { 16034 removed_a_file = true; 16035 } else { 16036 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16037 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 16038 "file %s not removed: %s", file, 16039 isc_result_totext(result)); 16040 } 16041 16042 if (!removed_a_file) { 16043 CHECK(putstr(text, "error: no files could be removed")); 16044 CHECK(ISC_R_FAILURE); 16045 } 16046 16047 dns_zone_detach(&mkzone); 16048 result = ISC_R_SUCCESS; 16049 16050 cleanup: 16051 isc_loopmgr_resume(named_g_loopmgr); 16052 return result; 16053 } 16054 16055 static isc_result_t 16056 mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) { 16057 isc_result_t result; 16058 dns_db_t *db = NULL; 16059 dns_dbversion_t *ver = NULL; 16060 dns_rriterator_t rrit; 16061 isc_stdtime_t now = isc_stdtime_now(); 16062 dns_name_t *prevname = NULL; 16063 16064 CHECK(dns_zone_getdb(view->managed_keys, &db)); 16065 dns_db_currentversion(db, &ver); 16066 dns_rriterator_init(&rrit, db, ver, 0); 16067 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS; 16068 result = dns_rriterator_nextrrset(&rrit)) 16069 { 16070 char buf[DNS_NAME_FORMATSIZE + 500]; 16071 dns_name_t *name = NULL; 16072 dns_rdataset_t *kdset = NULL; 16073 dns_rdata_t rdata = DNS_RDATA_INIT; 16074 dns_rdata_keydata_t kd; 16075 uint32_t ttl; 16076 16077 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL); 16078 if (kdset == NULL || kdset->type != dns_rdatatype_keydata || 16079 !dns_rdataset_isassociated(kdset)) 16080 { 16081 continue; 16082 } 16083 16084 if (name != prevname) { 16085 char nbuf[DNS_NAME_FORMATSIZE]; 16086 dns_name_format(name, nbuf, sizeof(nbuf)); 16087 snprintf(buf, sizeof(buf), "\n\n name: %s", nbuf); 16088 CHECK(putstr(text, buf)); 16089 } 16090 16091 for (result = dns_rdataset_first(kdset); 16092 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset)) 16093 { 16094 char alg[DNS_SECALG_FORMATSIZE]; 16095 char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 16096 dns_keytag_t keyid; 16097 isc_region_t r; 16098 isc_time_t t; 16099 bool revoked; 16100 16101 dns_rdata_reset(&rdata); 16102 dns_rdataset_current(kdset, &rdata); 16103 result = dns_rdata_tostruct(&rdata, &kd, NULL); 16104 RUNTIME_CHECK(result == ISC_R_SUCCESS); 16105 16106 dns_rdata_toregion(&rdata, &r); 16107 isc_region_consume(&r, 12); 16108 keyid = dst_region_computeid(&r); 16109 16110 snprintf(buf, sizeof(buf), "\n keyid: %u", keyid); 16111 CHECK(putstr(text, buf)); 16112 16113 dns_secalg_format(kd.algorithm, alg, sizeof(alg)); 16114 snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg); 16115 CHECK(putstr(text, buf)); 16116 16117 revoked = ((kd.flags & DNS_KEYFLAG_REVOKE) != 0); 16118 snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s", 16119 revoked ? " REVOKE" : "", 16120 ((kd.flags & DNS_KEYFLAG_KSK) != 0) ? " SEP" 16121 : "", 16122 (kd.flags == 0) ? " (none)" : ""); 16123 CHECK(putstr(text, buf)); 16124 16125 isc_time_set(&t, kd.refresh, 0); 16126 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); 16127 snprintf(buf, sizeof(buf), "\n\tnext refresh: %s", 16128 tbuf); 16129 CHECK(putstr(text, buf)); 16130 16131 if (kd.removehd != 0) { 16132 isc_time_set(&t, kd.removehd, 0); 16133 isc_time_formathttptimestamp(&t, tbuf, 16134 sizeof(tbuf)); 16135 snprintf(buf, sizeof(buf), "\n\tremove at: %s", 16136 tbuf); 16137 CHECK(putstr(text, buf)); 16138 } 16139 16140 isc_time_set(&t, kd.addhd, 0); 16141 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); 16142 if (kd.addhd == 0) { 16143 snprintf(buf, sizeof(buf), "\n\tno trust"); 16144 } else if (revoked) { 16145 snprintf(buf, sizeof(buf), "\n\ttrust revoked"); 16146 } else if (kd.addhd <= now) { 16147 snprintf(buf, sizeof(buf), 16148 "\n\ttrusted since: %s", tbuf); 16149 } else if (kd.addhd > now) { 16150 snprintf(buf, sizeof(buf), 16151 "\n\ttrust pending: %s", tbuf); 16152 } 16153 CHECK(putstr(text, buf)); 16154 } 16155 } 16156 16157 if (result == ISC_R_NOMORE) { 16158 result = ISC_R_SUCCESS; 16159 } 16160 16161 cleanup: 16162 if (ver != NULL) { 16163 dns_rriterator_destroy(&rrit); 16164 dns_db_closeversion(db, &ver, false); 16165 } 16166 if (db != NULL) { 16167 dns_db_detach(&db); 16168 } 16169 16170 return result; 16171 } 16172 16173 static isc_result_t 16174 mkey_status(dns_view_t *view, isc_buffer_t **text) { 16175 isc_result_t result; 16176 char msg[ISC_FORMATHTTPTIMESTAMP_SIZE]; 16177 isc_time_t t; 16178 16179 CHECK(putstr(text, "view: ")); 16180 CHECK(putstr(text, view->name)); 16181 16182 CHECK(putstr(text, "\nnext scheduled event: ")); 16183 16184 dns_zone_getrefreshkeytime(view->managed_keys, &t); 16185 if (isc_time_isepoch(&t)) { 16186 CHECK(putstr(text, "never")); 16187 } else { 16188 isc_time_formathttptimestamp(&t, msg, sizeof(msg)); 16189 CHECK(putstr(text, msg)); 16190 } 16191 16192 CHECK(mkey_dumpzone(view, text)); 16193 16194 cleanup: 16195 return result; 16196 } 16197 16198 isc_result_t 16199 named_server_mkeys(named_server_t *server, isc_lex_t *lex, 16200 isc_buffer_t **text) { 16201 char *cmd, *classtxt, *viewtxt = NULL; 16202 isc_result_t result = ISC_R_SUCCESS; 16203 dns_view_t *view = NULL; 16204 dns_rdataclass_t rdclass; 16205 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16206 enum { NONE, STAT, REFRESH, SYNC, DESTROY } opt = NONE; 16207 bool found = false; 16208 bool first = true; 16209 16210 REQUIRE(text != NULL); 16211 16212 /* Skip rndc command name */ 16213 cmd = next_token(lex, text); 16214 if (cmd == NULL) { 16215 return ISC_R_UNEXPECTEDEND; 16216 } 16217 16218 /* Get managed-keys subcommand */ 16219 cmd = next_token(lex, text); 16220 if (cmd == NULL) { 16221 return ISC_R_UNEXPECTEDEND; 16222 } 16223 16224 if (strcasecmp(cmd, "status") == 0) { 16225 opt = STAT; 16226 } else if (strcasecmp(cmd, "refresh") == 0) { 16227 opt = REFRESH; 16228 } else if (strcasecmp(cmd, "sync") == 0) { 16229 opt = SYNC; 16230 } else if (strcasecmp(cmd, "destroy") == 0) { 16231 opt = DESTROY; 16232 } else { 16233 snprintf(msg, sizeof(msg), "unknown command '%s'", cmd); 16234 (void)putstr(text, msg); 16235 result = ISC_R_UNEXPECTED; 16236 goto cleanup; 16237 } 16238 16239 /* Look for the optional class name. */ 16240 classtxt = next_token(lex, text); 16241 if (classtxt != NULL) { 16242 isc_textregion_t r; 16243 r.base = classtxt; 16244 r.length = strlen(classtxt); 16245 result = dns_rdataclass_fromtext(&rdclass, &r); 16246 if (result != ISC_R_SUCCESS) { 16247 snprintf(msg, sizeof(msg), "unknown class '%s'", 16248 classtxt); 16249 (void)putstr(text, msg); 16250 goto cleanup; 16251 } 16252 viewtxt = next_token(lex, text); 16253 } 16254 16255 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16256 view = ISC_LIST_NEXT(view, link)) 16257 { 16258 if (viewtxt != NULL && (rdclass != view->rdclass || 16259 strcmp(view->name, viewtxt) != 0)) 16260 { 16261 continue; 16262 } 16263 16264 if (view->managed_keys == NULL) { 16265 if (viewtxt != NULL) { 16266 snprintf(msg, sizeof(msg), 16267 "view '%s': no managed keys", viewtxt); 16268 CHECK(putstr(text, msg)); 16269 goto cleanup; 16270 } else { 16271 continue; 16272 } 16273 } 16274 16275 found = true; 16276 16277 switch (opt) { 16278 case REFRESH: 16279 if (!first) { 16280 CHECK(putstr(text, "\n")); 16281 } 16282 CHECK(mkey_refresh(view, text)); 16283 break; 16284 case STAT: 16285 if (!first) { 16286 CHECK(putstr(text, "\n\n")); 16287 } 16288 CHECK(mkey_status(view, text)); 16289 break; 16290 case SYNC: 16291 CHECK(dns_zone_flush(view->managed_keys)); 16292 break; 16293 case DESTROY: 16294 if (!first) { 16295 CHECK(putstr(text, "\n")); 16296 } 16297 CHECK(mkey_destroy(view, text)); 16298 break; 16299 default: 16300 UNREACHABLE(); 16301 } 16302 16303 if (viewtxt != NULL) { 16304 break; 16305 } 16306 first = false; 16307 } 16308 16309 if (!found) { 16310 CHECK(putstr(text, "no views with managed keys")); 16311 } 16312 16313 cleanup: 16314 if (isc_buffer_usedlength(*text) > 0) { 16315 (void)putnull(text); 16316 } 16317 16318 return result; 16319 } 16320 16321 isc_result_t 16322 named_server_dnstap(named_server_t *server, isc_lex_t *lex, 16323 isc_buffer_t **text) { 16324 #ifdef HAVE_DNSTAP 16325 char *ptr; 16326 isc_result_t result; 16327 bool reopen = false; 16328 int backups = 0; 16329 16330 REQUIRE(text != NULL); 16331 16332 if (server->dtenv == NULL) { 16333 return ISC_R_NOTFOUND; 16334 } 16335 16336 /* Check the command name. */ 16337 ptr = next_token(lex, text); 16338 if (ptr == NULL) { 16339 return ISC_R_UNEXPECTEDEND; 16340 } 16341 16342 /* "dnstap-reopen" was used in 9.11.0b1 */ 16343 if (strcasecmp(ptr, "dnstap-reopen") == 0) { 16344 reopen = true; 16345 } else { 16346 ptr = next_token(lex, text); 16347 if (ptr == NULL) { 16348 return ISC_R_UNEXPECTEDEND; 16349 } 16350 } 16351 16352 if (reopen || strcasecmp(ptr, "-reopen") == 0) { 16353 backups = ISC_LOG_ROLLNEVER; 16354 } else if (strcasecmp(ptr, "-roll") == 0) { 16355 unsigned int n; 16356 ptr = next_token(lex, text); 16357 if (ptr != NULL) { 16358 unsigned int u; 16359 n = sscanf(ptr, "%u", &u); 16360 if (n != 1U || u > INT_MAX) { 16361 return ISC_R_BADNUMBER; 16362 } 16363 backups = u; 16364 } else { 16365 backups = ISC_LOG_ROLLINFINITE; 16366 } 16367 } else { 16368 return DNS_R_SYNTAX; 16369 } 16370 16371 result = dns_dt_reopen(server->dtenv, backups); 16372 return result; 16373 #else /* ifdef HAVE_DNSTAP */ 16374 UNUSED(server); 16375 UNUSED(lex); 16376 UNUSED(text); 16377 return ISC_R_NOTIMPLEMENTED; 16378 #endif /* ifdef HAVE_DNSTAP */ 16379 } 16380 16381 isc_result_t 16382 named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) { 16383 char *ptr; 16384 isc_result_t result = ISC_R_SUCCESS; 16385 uint32_t initial, idle, keepalive, advertised; 16386 char msg[128]; 16387 16388 /* Skip the command name. */ 16389 ptr = next_token(lex, text); 16390 if (ptr == NULL) { 16391 return ISC_R_UNEXPECTEDEND; 16392 } 16393 16394 isc_nm_gettimeouts(named_g_netmgr, &initial, &idle, &keepalive, 16395 &advertised); 16396 16397 /* Look for optional arguments. */ 16398 ptr = next_token(lex, NULL); 16399 if (ptr != NULL) { 16400 CHECK(isc_parse_uint32(&initial, ptr, 10)); 16401 initial *= 100; 16402 if (initial > MAX_INITIAL_TIMEOUT) { 16403 CHECK(ISC_R_RANGE); 16404 } 16405 if (initial < MIN_INITIAL_TIMEOUT) { 16406 CHECK(ISC_R_RANGE); 16407 } 16408 16409 ptr = next_token(lex, text); 16410 if (ptr == NULL) { 16411 return ISC_R_UNEXPECTEDEND; 16412 } 16413 CHECK(isc_parse_uint32(&idle, ptr, 10)); 16414 idle *= 100; 16415 if (idle > MAX_IDLE_TIMEOUT) { 16416 CHECK(ISC_R_RANGE); 16417 } 16418 if (idle < MIN_IDLE_TIMEOUT) { 16419 CHECK(ISC_R_RANGE); 16420 } 16421 16422 ptr = next_token(lex, text); 16423 if (ptr == NULL) { 16424 return ISC_R_UNEXPECTEDEND; 16425 } 16426 CHECK(isc_parse_uint32(&keepalive, ptr, 10)); 16427 keepalive *= 100; 16428 if (keepalive > MAX_KEEPALIVE_TIMEOUT) { 16429 CHECK(ISC_R_RANGE); 16430 } 16431 if (keepalive < MIN_KEEPALIVE_TIMEOUT) { 16432 CHECK(ISC_R_RANGE); 16433 } 16434 16435 ptr = next_token(lex, text); 16436 if (ptr == NULL) { 16437 return ISC_R_UNEXPECTEDEND; 16438 } 16439 CHECK(isc_parse_uint32(&advertised, ptr, 10)); 16440 advertised *= 100; 16441 if (advertised > MAX_ADVERTISED_TIMEOUT) { 16442 CHECK(ISC_R_RANGE); 16443 } 16444 16445 isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, 16446 advertised); 16447 } 16448 16449 snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial / 100); 16450 CHECK(putstr(text, msg)); 16451 snprintf(msg, sizeof(msg), "tcp-idle-timeout=%u\n", idle / 100); 16452 CHECK(putstr(text, msg)); 16453 snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n", 16454 keepalive / 100); 16455 CHECK(putstr(text, msg)); 16456 snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u", 16457 advertised / 100); 16458 CHECK(putstr(text, msg)); 16459 16460 cleanup: 16461 if (isc_buffer_usedlength(*text) > 0) { 16462 (void)putnull(text); 16463 } 16464 16465 return result; 16466 } 16467 16468 isc_result_t 16469 named_server_servestale(named_server_t *server, isc_lex_t *lex, 16470 isc_buffer_t **text) { 16471 char *ptr, *classtxt, *viewtxt = NULL; 16472 char msg[128]; 16473 dns_rdataclass_t rdclass = dns_rdataclass_in; 16474 dns_view_t *view; 16475 bool found = false; 16476 dns_stale_answer_t staleanswersok = dns_stale_answer_conf; 16477 bool wantstatus = false; 16478 isc_result_t result = ISC_R_SUCCESS; 16479 16480 REQUIRE(text != NULL); 16481 16482 /* Skip the command name. */ 16483 ptr = next_token(lex, text); 16484 if (ptr == NULL) { 16485 return ISC_R_UNEXPECTEDEND; 16486 } 16487 16488 ptr = next_token(lex, NULL); 16489 if (ptr == NULL) { 16490 return ISC_R_UNEXPECTEDEND; 16491 } 16492 16493 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 16494 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 16495 { 16496 staleanswersok = dns_stale_answer_yes; 16497 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 16498 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 16499 { 16500 staleanswersok = dns_stale_answer_no; 16501 } else if (strcasecmp(ptr, "reset") == 0) { 16502 staleanswersok = dns_stale_answer_conf; 16503 } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { 16504 wantstatus = true; 16505 } else { 16506 return DNS_R_SYNTAX; 16507 } 16508 16509 /* Look for the optional class name. */ 16510 classtxt = next_token(lex, text); 16511 if (classtxt != NULL) { 16512 isc_textregion_t r; 16513 16514 /* Look for the optional view name. */ 16515 viewtxt = next_token(lex, text); 16516 16517 /* 16518 * If 'classtext' is not a valid class then it us a view name. 16519 */ 16520 r.base = classtxt; 16521 r.length = strlen(classtxt); 16522 result = dns_rdataclass_fromtext(&rdclass, &r); 16523 if (result != ISC_R_SUCCESS) { 16524 if (viewtxt != NULL) { 16525 snprintf(msg, sizeof(msg), "unknown class '%s'", 16526 classtxt); 16527 (void)putstr(text, msg); 16528 goto cleanup; 16529 } 16530 16531 viewtxt = classtxt; 16532 classtxt = NULL; 16533 } 16534 } 16535 16536 isc_loopmgr_pause(named_g_loopmgr); 16537 16538 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16539 view = ISC_LIST_NEXT(view, link)) 16540 { 16541 dns_ttl_t stale_ttl = 0; 16542 uint32_t stale_refresh = 0; 16543 dns_db_t *db = NULL; 16544 16545 if (classtxt != NULL && rdclass != view->rdclass) { 16546 continue; 16547 } 16548 16549 if (viewtxt != NULL && strcmp(view->name, viewtxt) != 0) { 16550 continue; 16551 } 16552 16553 if (!wantstatus) { 16554 view->staleanswersok = staleanswersok; 16555 found = true; 16556 continue; 16557 } 16558 16559 db = NULL; 16560 dns_db_attach(view->cachedb, &db); 16561 (void)dns_db_getservestalettl(db, &stale_ttl); 16562 (void)dns_db_getservestalerefresh(db, &stale_refresh); 16563 dns_db_detach(&db); 16564 if (found) { 16565 CHECK(putstr(text, "\n")); 16566 } 16567 CHECK(putstr(text, view->name)); 16568 CHECK(putstr(text, ": ")); 16569 switch (view->staleanswersok) { 16570 case dns_stale_answer_yes: 16571 if (stale_ttl > 0) { 16572 CHECK(putstr(text, "stale cache " 16573 "enabled; stale " 16574 "answers enabled")); 16575 } else { 16576 CHECK(putstr(text, "stale cache disabled; " 16577 "stale " 16578 "answers unavailable")); 16579 } 16580 break; 16581 case dns_stale_answer_no: 16582 if (stale_ttl > 0) { 16583 CHECK(putstr(text, "stale cache " 16584 "enabled; stale " 16585 "answers disabled")); 16586 } else { 16587 CHECK(putstr(text, "stale cache disabled; " 16588 "stale " 16589 "answers unavailable")); 16590 } 16591 break; 16592 case dns_stale_answer_conf: 16593 if (view->staleanswersenable && stale_ttl > 0) { 16594 CHECK(putstr(text, "stale cache " 16595 "enabled; stale " 16596 "answers enabled")); 16597 } else if (stale_ttl > 0) { 16598 CHECK(putstr(text, "stale cache " 16599 "enabled; stale " 16600 "answers disabled")); 16601 } else { 16602 CHECK(putstr(text, "stale cache disabled; " 16603 "stale " 16604 "answers unavailable")); 16605 } 16606 break; 16607 } 16608 if (stale_ttl > 0) { 16609 snprintf(msg, sizeof(msg), 16610 " (stale-answer-ttl=%u " 16611 "max-stale-ttl=%u " 16612 "stale-refresh-time=%u)", 16613 view->staleanswerttl, stale_ttl, 16614 stale_refresh); 16615 CHECK(putstr(text, msg)); 16616 } 16617 found = true; 16618 } 16619 16620 if (!found) { 16621 result = ISC_R_NOTFOUND; 16622 } 16623 16624 cleanup: 16625 isc_loopmgr_resume(named_g_loopmgr); 16626 16627 if (isc_buffer_usedlength(*text) > 0) { 16628 (void)putnull(text); 16629 } 16630 16631 return result; 16632 } 16633 16634 isc_result_t 16635 named_server_fetchlimit(named_server_t *server, isc_lex_t *lex, 16636 isc_buffer_t **text) { 16637 isc_result_t result = ISC_R_SUCCESS; 16638 dns_view_t *view = NULL; 16639 char *ptr = NULL, *viewname = NULL; 16640 bool first = true; 16641 dns_adb_t *adb = NULL; 16642 16643 REQUIRE(text != NULL); 16644 16645 /* Skip the command name. */ 16646 ptr = next_token(lex, text); 16647 if (ptr == NULL) { 16648 return ISC_R_UNEXPECTEDEND; 16649 } 16650 16651 /* Look for the view name. */ 16652 viewname = next_token(lex, text); 16653 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16654 view = ISC_LIST_NEXT(view, link)) 16655 { 16656 char tbuf[100]; 16657 unsigned int used; 16658 uint32_t val; 16659 int s; 16660 16661 if (view->rdclass != dns_rdataclass_in) { 16662 continue; 16663 } 16664 16665 if (viewname != NULL && strcasecmp(view->name, viewname) != 0) { 16666 continue; 16667 } 16668 16669 dns_view_getadb(view, &adb); 16670 if (adb == NULL) { 16671 continue; 16672 } 16673 16674 if (!first) { 16675 CHECK(putstr(text, "\n")); 16676 } 16677 CHECK(putstr(text, "Rate limited servers, view ")); 16678 CHECK(putstr(text, view->name)); 16679 16680 dns_adb_getquota(adb, &val, NULL, NULL, NULL, NULL); 16681 s = snprintf(tbuf, sizeof(tbuf), 16682 " (fetches-per-server %u):", val); 16683 if (s < 0 || (unsigned int)s > sizeof(tbuf)) { 16684 CHECK(ISC_R_NOSPACE); 16685 } 16686 first = false; 16687 CHECK(putstr(text, tbuf)); 16688 used = isc_buffer_usedlength(*text); 16689 CHECK(dns_adb_dumpquota(adb, text)); 16690 if (used == isc_buffer_usedlength(*text)) { 16691 CHECK(putstr(text, "\n None.")); 16692 } 16693 16694 CHECK(putstr(text, "\nRate limited servers, view ")); 16695 CHECK(putstr(text, view->name)); 16696 val = dns_resolver_getfetchesperzone(view->resolver); 16697 s = snprintf(tbuf, sizeof(tbuf), 16698 " (fetches-per-zone %u):", val); 16699 if (s < 0 || (unsigned int)s > sizeof(tbuf)) { 16700 CHECK(ISC_R_NOSPACE); 16701 } 16702 CHECK(putstr(text, tbuf)); 16703 used = isc_buffer_usedlength(*text); 16704 CHECK(dns_resolver_dumpquota(view->resolver, text)); 16705 if (used == isc_buffer_usedlength(*text)) { 16706 CHECK(putstr(text, "\n None.")); 16707 } 16708 dns_adb_detach(&adb); 16709 } 16710 cleanup: 16711 if (adb != NULL) { 16712 dns_adb_detach(&adb); 16713 } 16714 if (isc_buffer_usedlength(*text) > 0) { 16715 (void)putnull(text); 16716 } 16717 16718 return result; 16719 } 16720 16721 isc_result_t 16722 named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { 16723 isc_result_t result = ISC_R_SUCCESS; 16724 dns_zone_t *zone = NULL; 16725 dns_kasp_t *kasp = NULL; 16726 const char *ptr; 16727 char skrfile[PATH_MAX]; 16728 16729 /* Skip the command name. */ 16730 ptr = next_token(lex, text); 16731 if (ptr == NULL) { 16732 return ISC_R_UNEXPECTEDEND; 16733 } 16734 16735 /* Find out what we are to do. */ 16736 ptr = next_token(lex, text); 16737 if (ptr == NULL) { 16738 return ISC_R_UNEXPECTEDEND; 16739 } 16740 16741 if (strcasecmp(ptr, "-import") != 0) { 16742 CHECK(DNS_R_SYNTAX); 16743 } 16744 16745 ptr = next_token(lex, NULL); 16746 if (ptr == NULL) { 16747 return ISC_R_UNEXPECTEDEND; 16748 } 16749 (void)snprintf(skrfile, sizeof(skrfile), "%s", ptr); 16750 16751 CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); 16752 if (zone == NULL) { 16753 CHECK(ISC_R_UNEXPECTEDEND); 16754 } 16755 kasp = dns_zone_getkasp(zone); 16756 if (kasp == NULL) { 16757 CHECK(putstr(text, "zone does not have a dnssec-policy")); 16758 CHECK(putnull(text)); 16759 goto cleanup; 16760 } 16761 16762 if (!dns_kasp_offlineksk(kasp)) { 16763 CHECK(putstr(text, "zone does not have offline-ksk enabled")); 16764 CHECK(putnull(text)); 16765 goto cleanup; 16766 } 16767 16768 result = dns_zone_import_skr(zone, skrfile); 16769 if (result != ISC_R_SUCCESS) { 16770 CHECK(putstr(text, "import failed: ")); 16771 CHECK(putstr(text, isc_result_totext(result))); 16772 CHECK(putnull(text)); 16773 } else { 16774 /* Schedule a rekey */ 16775 dns_zone_rekey(zone, false); 16776 } 16777 16778 cleanup: 16779 if (zone != NULL) { 16780 dns_zone_detach(&zone); 16781 } 16782 16783 return result; 16784 } 16785