1 /* $NetBSD: server.c,v 1.28 2026/05/20 16:53:43 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 #include <dns/acl.h> 30 31 #ifdef HAVE_DNSTAP 32 #include <fstrm.h> 33 #endif 34 35 #include <isc/async.h> 36 #include <isc/attributes.h> 37 #include <isc/base64.h> 38 #include <isc/commandline.h> 39 #include <isc/dir.h> 40 #include <isc/file.h> 41 #include <isc/fips.h> 42 #include <isc/hash.h> 43 #include <isc/hex.h> 44 #include <isc/hmac.h> 45 #include <isc/httpd.h> 46 #include <isc/job.h> 47 #include <isc/lex.h> 48 #include <isc/loop.h> 49 #include <isc/meminfo.h> 50 #include <isc/netmgr.h> 51 #include <isc/nonce.h> 52 #include <isc/parseint.h> 53 #include <isc/portset.h> 54 #include <isc/refcount.h> 55 #include <isc/result.h> 56 #include <isc/signal.h> 57 #include <isc/siphash.h> 58 #include <isc/stats.h> 59 #include <isc/stdio.h> 60 #include <isc/string.h> 61 #include <isc/time.h> 62 #include <isc/timer.h> 63 #include <isc/util.h> 64 65 #include <dns/adb.h> 66 #include <dns/badcache.h> 67 #include <dns/cache.h> 68 #include <dns/catz.h> 69 #include <dns/db.h> 70 #include <dns/dispatch.h> 71 #include <dns/dlz.h> 72 #include <dns/dns64.h> 73 #include <dns/dnsrps.h> 74 #include <dns/dnssec.h> 75 #include <dns/dyndb.h> 76 #include <dns/fixedname.h> 77 #include <dns/forward.h> 78 #include <dns/geoip.h> 79 #include <dns/journal.h> 80 #include <dns/kasp.h> 81 #include <dns/keymgr.h> 82 #include <dns/keystore.h> 83 #include <dns/keytable.h> 84 #include <dns/keyvalues.h> 85 #include <dns/master.h> 86 #include <dns/masterdump.h> 87 #include <dns/nametree.h> 88 #include <dns/nsec3.h> 89 #include <dns/nta.h> 90 #include <dns/order.h> 91 #include <dns/peer.h> 92 #include <dns/private.h> 93 #include <dns/rbt.h> 94 #include <dns/rdataclass.h> 95 #include <dns/rdatalist.h> 96 #include <dns/rdataset.h> 97 #include <dns/rdatastruct.h> 98 #include <dns/resolver.h> 99 #include <dns/rootns.h> 100 #include <dns/rriterator.h> 101 #include <dns/secalg.h> 102 #include <dns/soa.h> 103 #include <dns/stats.h> 104 #include <dns/time.h> 105 #include <dns/tkey.h> 106 #include <dns/tsig.h> 107 #include <dns/ttl.h> 108 #include <dns/view.h> 109 #include <dns/zone.h> 110 #include <dns/zt.h> 111 112 #include <dst/dst.h> 113 114 #include <isccfg/check.h> 115 #include <isccfg/grammar.h> 116 #include <isccfg/kaspconf.h> 117 #include <isccfg/namedconf.h> 118 119 #include <ns/client.h> 120 #include <ns/hooks.h> 121 #include <ns/interfacemgr.h> 122 #include <ns/listenlist.h> 123 124 #include <named/config.h> 125 #include <named/control.h> 126 #if defined(HAVE_GEOIP2) 127 #include <named/geoip.h> 128 #endif /* HAVE_GEOIP2 */ 129 #include <named/log.h> 130 #include <named/logconf.h> 131 #include <named/main.h> 132 #include <named/os.h> 133 #include <named/server.h> 134 #include <named/statschannel.h> 135 #include <named/tkeyconf.h> 136 #include <named/transportconf.h> 137 #include <named/tsigconf.h> 138 #include <named/zoneconf.h> 139 #ifdef HAVE_LIBSCF 140 #include <stdlib.h> 141 142 #include <named/smf_globals.h> 143 #endif /* ifdef HAVE_LIBSCF */ 144 145 /* On DragonFly BSD the header does not provide jemalloc API */ 146 #if defined(HAVE_MALLOC_NP_H) && !defined(__DragonFly__) 147 #include <malloc_np.h> 148 #define JEMALLOC_API_SUPPORTED 1 149 #elif defined(HAVE_JEMALLOC) 150 #include <jemalloc/jemalloc.h> 151 #define JEMALLOC_API_SUPPORTED 1 152 #endif 153 154 #ifdef HAVE_LMDB 155 #include <lmdb.h> 156 #define configure_newzones configure_newzones_db 157 #define dumpzone dumpzone_db 158 #else /* HAVE_LMDB */ 159 #define configure_newzones configure_newzones_file 160 #define dumpzone dumpzone_file 161 #endif /* HAVE_LMDB */ 162 163 #ifndef SIZE_MAX 164 #define SIZE_MAX ((size_t)-1) 165 #endif /* ifndef SIZE_MAX */ 166 167 #ifndef SIZE_AS_PERCENT 168 #define SIZE_AS_PERCENT ((size_t)-2) 169 #endif /* ifndef SIZE_AS_PERCENT */ 170 171 /* RFC7828 defines timeout as 16-bit value specified in units of 100 172 * milliseconds, so the maximum and minimum advertised and keepalive 173 * timeouts are capped by the data type (it's ~109 minutes) 174 */ 175 #define MIN_INITIAL_TIMEOUT UINT32_C(2500) /* 2.5 seconds */ 176 #define MAX_INITIAL_TIMEOUT UINT32_C(120000) /* 2 minutes */ 177 #define MIN_IDLE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ 178 #define MAX_IDLE_TIMEOUT UINT32_C(120000) /* 2 minutes */ 179 #define MIN_KEEPALIVE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ 180 #define MAX_KEEPALIVE_TIMEOUT UINT32_C(UINT16_MAX * 100) 181 #define MIN_ADVERTISED_TIMEOUT UINT32_C(0) /* No minimum */ 182 #define MAX_ADVERTISED_TIMEOUT UINT32_C(UINT16_MAX * 100) 183 184 /*% 185 * Check an operation for failure. Assumes that the function 186 * using it has a 'result' variable and a 'cleanup' label. 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 *aclenv; 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 typedef enum { 366 MEMPROF_UNSUPPORTED = 0x00, 367 MEMPROF_INACTIVE = 0x01, 368 MEMPROF_FAILING = 0x02, 369 MEMPROF_OFF = 0x03, 370 MEMPROF_ON = 0x04, 371 } memprof_status; 372 373 static const char *memprof_status_text[] = { 374 [MEMPROF_UNSUPPORTED] = "UNSUPPORTED", 375 [MEMPROF_INACTIVE] = "INACTIVE", 376 [MEMPROF_FAILING] = "FAILING", 377 [MEMPROF_OFF] = "OFF", 378 [MEMPROF_ON] = "ON", 379 }; 380 381 /* 382 * These zones should not leak onto the Internet. 383 */ 384 const char *empty_zones[] = { 385 /* RFC 1918 */ 386 "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA", 387 "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA", 388 "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA", 389 "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA", 390 "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA", 391 "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA", 392 393 /* RFC 6598 */ 394 "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA", 395 "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA", 396 "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA", 397 "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA", 398 "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA", 399 "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA", 400 "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA", 401 "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA", 402 "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA", 403 "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA", 404 "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA", 405 "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA", 406 "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA", "102.100.IN-ADDR.ARPA", 407 "103.100.IN-ADDR.ARPA", "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA", 408 "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA", "108.100.IN-ADDR.ARPA", 409 "109.100.IN-ADDR.ARPA", "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA", 410 "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA", "114.100.IN-ADDR.ARPA", 411 "115.100.IN-ADDR.ARPA", "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA", 412 "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA", "120.100.IN-ADDR.ARPA", 413 "121.100.IN-ADDR.ARPA", "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA", 414 "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA", "126.100.IN-ADDR.ARPA", 415 "127.100.IN-ADDR.ARPA", 416 417 /* RFC 5735 and RFC 5737 */ 418 "0.IN-ADDR.ARPA", /* THIS NETWORK */ 419 "127.IN-ADDR.ARPA", /* LOOPBACK */ 420 "254.169.IN-ADDR.ARPA", /* LINK LOCAL */ 421 "2.0.192.IN-ADDR.ARPA", /* TEST NET */ 422 "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */ 423 "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */ 424 "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */ 425 426 /* Local IPv6 Unicast Addresses */ 427 /* clang-format off */ 428 "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", 429 "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", 430 /* clang-format on */ 431 432 /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ 433 "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", /* LINK LOCAL */ 434 "9.E.F.IP6.ARPA", /* LINK LOCAL */ 435 "A.E.F.IP6.ARPA", /* LINK LOCAL */ 436 "B.E.F.IP6.ARPA", /* LINK LOCAL */ 437 438 /* Example Prefix, RFC 3849. */ 439 "8.B.D.0.1.0.0.2.IP6.ARPA", 440 441 /* RFC 7534 */ 442 "EMPTY.AS112.ARPA", 443 444 /* RFC 8375 */ 445 "HOME.ARPA", 446 447 /* RFC 9462 */ 448 "RESOLVER.ARPA", 449 450 NULL 451 }; 452 453 noreturn static void 454 fatal(const char *msg, isc_result_t result); 455 456 static void 457 named_server_reload(void *arg); 458 459 #ifdef HAVE_LIBNGHTTP2 460 static isc_result_t 461 listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, 462 const ns_listen_tls_params_t *tls_params, 463 isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, 464 isc_mem_t *mctx, isc_nm_proxy_type_t proxy, 465 ns_listenelt_t **target); 466 #endif 467 468 static isc_result_t 469 listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 470 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 471 isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target); 472 473 static isc_result_t 474 listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 475 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 476 isc_tlsctx_cache_t *tlsctx_cache, 477 ns_listenlist_t **target); 478 479 static isc_result_t 480 configure_forward(const cfg_obj_t *config, dns_view_t *view, 481 const dns_name_t *origin, const cfg_obj_t *forwarders, 482 const cfg_obj_t *forwardtype); 483 484 static isc_result_t 485 configure_alternates(const cfg_obj_t *config, dns_view_t *view, 486 const cfg_obj_t *alternates); 487 488 static isc_result_t 489 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 490 const cfg_obj_t *vconfig, dns_view_t *view, 491 dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, 492 dns_keystorelist_t *keystores, cfg_aclconfctx_t *aclconf, 493 bool added, bool old_rpz_ok, bool is_catz_member, bool modify); 494 495 static void 496 configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, 497 dns_view_t *view); 498 499 static isc_result_t 500 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 501 cfg_aclconfctx_t *actx); 502 503 static const cfg_obj_t * 504 find_maplist(const cfg_obj_t *config, const char *listname, const char *name); 505 506 static isc_result_t 507 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); 508 509 static void 510 newzone_cfgctx_destroy(void **cfgp); 511 512 static isc_result_t 513 putstr(isc_buffer_t **b, const char *str); 514 515 static isc_result_t 516 putmem(isc_buffer_t **b, const char *str, size_t len); 517 518 static isc_result_t 519 putuint8(isc_buffer_t **b, uint8_t val); 520 521 static isc_result_t 522 putnull(isc_buffer_t **b); 523 524 #ifdef HAVE_LMDB 525 static isc_result_t 526 nzd_writable(dns_view_t *view); 527 528 static isc_result_t 529 nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi); 530 531 static isc_result_t 532 nzd_env_reopen(dns_view_t *view); 533 534 static void 535 nzd_env_close(dns_view_t *view); 536 537 static isc_result_t 538 nzd_close(MDB_txn **txnp, bool commit); 539 #else /* ifdef HAVE_LMDB */ 540 static isc_result_t 541 nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); 542 #endif /* ifdef HAVE_LMDB */ 543 544 static isc_result_t 545 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg); 546 547 /*% 548 * Configure a single view ACL at '*aclp'. Get its configuration from 549 * 'vconfig' (for per-view configuration) and maybe from 'config' 550 */ 551 static isc_result_t 552 configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, 553 const cfg_obj_t *gconfig, const char *aclname, 554 const char *acltuplename, cfg_aclconfctx_t *actx, 555 isc_mem_t *mctx, dns_acl_t **aclp) { 556 isc_result_t result; 557 const cfg_obj_t *maps[4]; 558 const cfg_obj_t *aclobj = NULL; 559 int i = 0; 560 561 if (*aclp != NULL) { 562 dns_acl_detach(aclp); 563 } 564 if (vconfig != NULL) { 565 maps[i++] = cfg_tuple_get(vconfig, "options"); 566 } 567 if (config != NULL) { 568 const cfg_obj_t *options = NULL; 569 (void)cfg_map_get(config, "options", &options); 570 if (options != NULL) { 571 maps[i++] = options; 572 } 573 } 574 if (gconfig != NULL) { 575 const cfg_obj_t *options = NULL; 576 (void)cfg_map_get(gconfig, "options", &options); 577 if (options != NULL) { 578 maps[i++] = options; 579 } 580 } 581 maps[i] = NULL; 582 583 (void)named_config_get(maps, aclname, &aclobj); 584 if (aclobj == NULL) { 585 /* 586 * No value available. *aclp == NULL. 587 */ 588 return ISC_R_SUCCESS; 589 } 590 591 if (acltuplename != NULL) { 592 /* 593 * If the ACL is given in an optional tuple, retrieve it. 594 * The parser should have ensured that a valid object be 595 * returned. 596 */ 597 aclobj = cfg_tuple_get(aclobj, acltuplename); 598 } 599 600 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 0, 601 aclp); 602 603 return result; 604 } 605 606 /*% 607 * Configure a sortlist at '*aclp'. Essentially the same as 608 * configure_view_acl() except it calls cfg_acl_fromconfig with a 609 * nest_level value of 2. 610 */ 611 static isc_result_t 612 configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, 613 cfg_aclconfctx_t *actx, isc_mem_t *mctx, 614 dns_acl_t **aclp) { 615 isc_result_t result; 616 const cfg_obj_t *maps[3]; 617 const cfg_obj_t *aclobj = NULL; 618 int i = 0; 619 620 if (*aclp != NULL) { 621 dns_acl_detach(aclp); 622 } 623 if (vconfig != NULL) { 624 maps[i++] = cfg_tuple_get(vconfig, "options"); 625 } 626 if (config != NULL) { 627 const cfg_obj_t *options = NULL; 628 (void)cfg_map_get(config, "options", &options); 629 if (options != NULL) { 630 maps[i++] = options; 631 } 632 } 633 maps[i] = NULL; 634 635 (void)named_config_get(maps, "sortlist", &aclobj); 636 if (aclobj == NULL) { 637 return ISC_R_SUCCESS; 638 } 639 640 /* 641 * Use a nest level of 3 for the "top level" of the sortlist; 642 * this means each entry in the top three levels will be stored 643 * as lists of separate, nested ACLs, rather than merged together 644 * into IP tables as is usually done with ACLs. 645 */ 646 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 3, 647 aclp); 648 649 return result; 650 } 651 652 static isc_result_t 653 configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, 654 const char *confname, const char *conftuplename, 655 isc_mem_t *mctx, dns_nametree_t **ntp) { 656 isc_result_t result = ISC_R_SUCCESS; 657 const cfg_obj_t *maps[3]; 658 const cfg_obj_t *obj = NULL; 659 const cfg_listelt_t *element = NULL; 660 int i = 0; 661 dns_fixedname_t fixed; 662 dns_name_t *name = NULL; 663 isc_buffer_t b; 664 const char *str = NULL; 665 const cfg_obj_t *nameobj = NULL; 666 667 if (*ntp != NULL) { 668 dns_nametree_detach(ntp); 669 } 670 dns_nametree_create(mctx, DNS_NAMETREE_BOOL, confname, ntp); 671 672 if (vconfig != NULL) { 673 maps[i++] = cfg_tuple_get(vconfig, "options"); 674 } 675 if (config != NULL) { 676 const cfg_obj_t *options = NULL; 677 (void)cfg_map_get(config, "options", &options); 678 if (options != NULL) { 679 maps[i++] = options; 680 } 681 } 682 maps[i] = NULL; 683 684 (void)named_config_get(maps, confname, &obj); 685 if (obj == NULL) { 686 /* 687 * No value available. *ntp == NULL. 688 */ 689 return ISC_R_SUCCESS; 690 } 691 692 if (conftuplename != NULL) { 693 obj = cfg_tuple_get(obj, conftuplename); 694 if (cfg_obj_isvoid(obj)) { 695 return ISC_R_SUCCESS; 696 } 697 } 698 699 name = dns_fixedname_initname(&fixed); 700 for (element = cfg_list_first(obj); element != NULL; 701 element = cfg_list_next(element)) 702 { 703 nameobj = cfg_listelt_value(element); 704 str = cfg_obj_asstring(nameobj); 705 isc_buffer_constinit(&b, str, strlen(str)); 706 isc_buffer_add(&b, strlen(str)); 707 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 708 result = dns_nametree_add(*ntp, name, true); 709 if (result != ISC_R_SUCCESS) { 710 cfg_obj_log(nameobj, named_g_lctx, ISC_LOG_ERROR, 711 "failed to add %s for %s: %s", str, 712 confname, isc_result_totext(result)); 713 goto cleanup; 714 } 715 } 716 717 return ISC_R_SUCCESS; 718 719 cleanup: 720 dns_nametree_detach(ntp); 721 return result; 722 } 723 724 static isc_result_t 725 ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp, 726 unsigned char *digest, dns_rdata_ds_t *ds) { 727 isc_result_t result; 728 dns_rdata_dnskey_t keystruct; 729 dns_rdata_t rdata = DNS_RDATA_INIT; 730 uint32_t rdata1, rdata2, rdata3; 731 const char *datastr = NULL, *namestr = NULL; 732 unsigned char data[4096]; 733 isc_buffer_t databuf; 734 unsigned char rrdata[4096]; 735 isc_buffer_t rrdatabuf; 736 isc_region_t r; 737 dns_fixedname_t fname; 738 dns_name_t *name = NULL; 739 isc_buffer_t namebuf; 740 const char *atstr = NULL; 741 enum { 742 INIT_DNSKEY, 743 STATIC_DNSKEY, 744 INIT_DS, 745 STATIC_DS, 746 TRUSTED 747 } anchortype; 748 749 REQUIRE(namestrp != NULL && *namestrp == NULL); 750 REQUIRE(ds != NULL); 751 752 /* if DNSKEY, flags; if DS, key tag */ 753 rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1")); 754 755 /* if DNSKEY, protocol; if DS, algorithm */ 756 rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2")); 757 758 /* if DNSKEY, algorithm; if DS, digest type */ 759 rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3")); 760 761 namestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 762 *namestrp = namestr; 763 764 name = dns_fixedname_initname(&fname); 765 isc_buffer_constinit(&namebuf, namestr, strlen(namestr)); 766 isc_buffer_add(&namebuf, strlen(namestr)); 767 CHECK(dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL)); 768 769 if (*initialp) { 770 atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype")); 771 772 if (strcasecmp(atstr, "static-key") == 0) { 773 *initialp = false; 774 anchortype = STATIC_DNSKEY; 775 } else if (strcasecmp(atstr, "static-ds") == 0) { 776 *initialp = false; 777 anchortype = STATIC_DS; 778 } else if (strcasecmp(atstr, "initial-key") == 0) { 779 anchortype = INIT_DNSKEY; 780 } else if (strcasecmp(atstr, "initial-ds") == 0) { 781 anchortype = INIT_DS; 782 } else { 783 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 784 "key '%s': " 785 "invalid initialization method '%s'", 786 namestr, atstr); 787 result = ISC_R_FAILURE; 788 goto cleanup; 789 } 790 } else { 791 anchortype = TRUSTED; 792 } 793 794 isc_buffer_init(&databuf, data, sizeof(data)); 795 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 796 797 *ds = (dns_rdata_ds_t){ .common.rdclass = dns_rdataclass_in, 798 .common.rdtype = dns_rdatatype_ds }; 799 800 ISC_LINK_INIT(&ds->common, link); 801 802 switch (anchortype) { 803 case INIT_DNSKEY: 804 case STATIC_DNSKEY: 805 case TRUSTED: 806 /* 807 * This function should never be reached for view 808 * class other than IN 809 */ 810 keystruct.common.rdclass = dns_rdataclass_in; 811 keystruct.common.rdtype = dns_rdatatype_dnskey; 812 813 /* 814 * The key data in keystruct is not dynamically allocated. 815 */ 816 keystruct.mctx = NULL; 817 818 ISC_LINK_INIT(&keystruct.common, link); 819 820 if (rdata1 > 0xffff) { 821 CHECKM(ISC_R_RANGE, "key flags"); 822 } 823 if (rdata1 & DNS_KEYFLAG_REVOKE) { 824 CHECKM(DST_R_BADKEYTYPE, "key flags revoke bit set"); 825 } 826 if (rdata2 > 0xff) { 827 CHECKM(ISC_R_RANGE, "key protocol"); 828 } 829 if (rdata3 > 0xff) { 830 CHECKM(ISC_R_RANGE, "key algorithm"); 831 } 832 833 keystruct.flags = (uint16_t)rdata1; 834 keystruct.protocol = (uint8_t)rdata2; 835 keystruct.algorithm = (uint8_t)rdata3; 836 837 if (!dst_algorithm_supported(keystruct.algorithm)) { 838 CHECK(DST_R_UNSUPPORTEDALG); 839 } 840 841 datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); 842 CHECK(isc_base64_decodestring(datastr, &databuf)); 843 isc_buffer_usedregion(&databuf, &r); 844 keystruct.datalen = r.length; 845 keystruct.data = r.base; 846 847 CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass, 848 keystruct.common.rdtype, &keystruct, 849 &rrdatabuf)); 850 CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, 851 digest, ds)); 852 break; 853 854 case INIT_DS: 855 case STATIC_DS: 856 if (rdata1 > 0xffff) { 857 CHECKM(ISC_R_RANGE, "key tag"); 858 } 859 if (rdata2 > 0xff) { 860 CHECKM(ISC_R_RANGE, "key algorithm"); 861 } 862 if (rdata3 > 0xff) { 863 CHECKM(ISC_R_RANGE, "digest type"); 864 } 865 866 ds->key_tag = (uint16_t)rdata1; 867 ds->algorithm = (uint8_t)rdata2; 868 ds->digest_type = (uint8_t)rdata3; 869 870 datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); 871 CHECK(isc_hex_decodestring(datastr, &databuf)); 872 isc_buffer_usedregion(&databuf, &r); 873 874 switch (ds->digest_type) { 875 case DNS_DSDIGEST_SHA1: 876 if (r.length != ISC_SHA1_DIGESTLENGTH) { 877 CHECK(ISC_R_UNEXPECTEDEND); 878 } 879 break; 880 case DNS_DSDIGEST_SHA256: 881 if (r.length != ISC_SHA256_DIGESTLENGTH) { 882 CHECK(ISC_R_UNEXPECTEDEND); 883 } 884 break; 885 case DNS_DSDIGEST_SHA384: 886 if (r.length != ISC_SHA384_DIGESTLENGTH) { 887 CHECK(ISC_R_UNEXPECTEDEND); 888 } 889 break; 890 default: 891 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 892 "key '%s': " 893 "unknown ds digest type %u", 894 namestr, ds->digest_type); 895 result = ISC_R_FAILURE; 896 goto cleanup; 897 break; 898 } 899 900 ds->length = r.length; 901 ds->digest = digest; 902 memmove(ds->digest, r.base, r.length); 903 904 break; 905 906 default: 907 UNREACHABLE(); 908 } 909 910 return ISC_R_SUCCESS; 911 912 cleanup: 913 return result; 914 } 915 916 static void 917 sfd_add(const dns_name_t *name, void *arg) { 918 if (arg != NULL) { 919 dns_view_sfd_add(arg, name); 920 } 921 } 922 923 /*% 924 * Parse 'key' in the context of view configuration 'vconfig'. If successful, 925 * add the key to 'secroots' if both of the following conditions are true: 926 * 927 * - 'keyname_match' is NULL or it matches the owner name of 'key', 928 * - support for the algorithm used by 'key' is not disabled by 'resolver' 929 * for the owner name of 'key'. 930 * 931 * 'managed' is true for managed keys and false for trusted keys. 'mctx' is 932 * the memory context to use for allocating memory. 933 */ 934 static isc_result_t 935 process_key(const cfg_obj_t *key, dns_keytable_t *secroots, 936 const dns_name_t *keyname_match, dns_view_t *view, bool managed) { 937 dns_fixedname_t fkeyname; 938 dns_name_t *keyname = NULL; 939 const char *namestr = NULL; 940 dns_rdata_ds_t ds; 941 isc_result_t result; 942 bool initializing = managed; 943 unsigned char digest[ISC_MAX_MD_SIZE]; 944 isc_buffer_t b; 945 946 result = ta_fromconfig(key, &initializing, &namestr, digest, &ds); 947 948 switch (result) { 949 case ISC_R_SUCCESS: 950 /* 951 * Trust anchor was parsed correctly. 952 */ 953 isc_buffer_constinit(&b, namestr, strlen(namestr)); 954 isc_buffer_add(&b, strlen(namestr)); 955 keyname = dns_fixedname_initname(&fkeyname); 956 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); 957 if (result != ISC_R_SUCCESS) { 958 return result; 959 } 960 break; 961 case DST_R_UNSUPPORTEDALG: 962 case DST_R_BADKEYTYPE: 963 /* 964 * Key was parsed correctly, but it cannot be used; this is not 965 * a fatal error - log a warning about this key being ignored, 966 * but do not prevent any further ones from being processed. 967 */ 968 cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, 969 "ignoring %s for '%s': %s", 970 initializing ? "initial-key" : "static-key", 971 namestr, isc_result_totext(result)); 972 return ISC_R_SUCCESS; 973 case DST_R_NOCRYPTO: 974 /* 975 * Crypto support is not available. 976 */ 977 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 978 "ignoring %s for '%s': no crypto support", 979 initializing ? "initial-key" : "static-key", 980 namestr); 981 return result; 982 default: 983 /* 984 * Something unexpected happened; we have no choice but to 985 * indicate an error so that the configuration loading process 986 * is interrupted. 987 */ 988 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 989 "configuring %s for '%s': %s", 990 initializing ? "initial-key" : "static-key", 991 namestr, isc_result_totext(result)); 992 return ISC_R_FAILURE; 993 } 994 995 /* 996 * If the caller requested to only load keys for a specific name and 997 * the owner name of this key does not match the requested name, do not 998 * load it. 999 */ 1000 if (keyname_match != NULL && !dns_name_equal(keyname_match, keyname)) { 1001 goto done; 1002 } 1003 1004 /* 1005 * Ensure that 'resolver' allows using the algorithm of this key for 1006 * its owner name. If it does not, do not load the key and log a 1007 * warning, but do not prevent further keys from being processed. 1008 */ 1009 if (!dns_resolver_algorithm_supported(view->resolver, keyname, 1010 ds.algorithm)) 1011 { 1012 cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, 1013 "ignoring %s for '%s': algorithm is disabled", 1014 initializing ? "initial-key" : "static-key", 1015 namestr); 1016 goto done; 1017 } 1018 1019 /* 1020 * Add the key to 'secroots'. Keys from a "trust-anchors" or 1021 * "managed-keys" statement may be either static or initializing 1022 * keys. If it's not initializing, we don't want to treat it as 1023 * managed, so we use 'initializing' twice here, for both the 1024 * 'managed' and 'initializing' arguments to dns_keytable_add(). 1025 */ 1026 result = dns_keytable_add(secroots, initializing, initializing, keyname, 1027 &ds, sfd_add, view); 1028 1029 done: 1030 return result; 1031 } 1032 1033 /* 1034 * Load keys from configuration into key table. If 'keyname' is specified, 1035 * only load keys matching that name. If 'managed' is true, load the key as 1036 * an initializing key. 1037 */ 1038 static isc_result_t 1039 load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, 1040 const dns_name_t *keyname) { 1041 const cfg_listelt_t *elt, *elt2; 1042 const cfg_obj_t *keylist; 1043 isc_result_t result; 1044 dns_keytable_t *secroots = NULL; 1045 1046 CHECK(dns_view_getsecroots(view, &secroots)); 1047 1048 for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) 1049 { 1050 keylist = cfg_listelt_value(elt); 1051 1052 for (elt2 = cfg_list_first(keylist); elt2 != NULL; 1053 elt2 = cfg_list_next(elt2)) 1054 { 1055 CHECK(process_key(cfg_listelt_value(elt2), secroots, 1056 keyname, view, managed)); 1057 } 1058 } 1059 1060 cleanup: 1061 if (secroots != NULL) { 1062 dns_keytable_detach(&secroots); 1063 } 1064 if (result == DST_R_NOCRYPTO) { 1065 result = ISC_R_SUCCESS; 1066 } 1067 return result; 1068 } 1069 1070 /*% 1071 * Check whether a key has been successfully loaded. 1072 */ 1073 static bool 1074 keyloaded(dns_view_t *view, const dns_name_t *name) { 1075 isc_result_t result; 1076 dns_keytable_t *secroots = NULL; 1077 dns_keynode_t *keynode = NULL; 1078 1079 result = dns_view_getsecroots(view, &secroots); 1080 if (result != ISC_R_SUCCESS) { 1081 return false; 1082 } 1083 1084 result = dns_keytable_find(secroots, name, &keynode); 1085 1086 if (keynode != NULL) { 1087 dns_keynode_detach(&keynode); 1088 } 1089 if (secroots != NULL) { 1090 dns_keytable_detach(&secroots); 1091 } 1092 1093 return result == ISC_R_SUCCESS; 1094 } 1095 1096 /*% 1097 * Configure DNSSEC keys for a view. 1098 * 1099 * The per-view configuration values and the server-global defaults are read 1100 * from 'vconfig' and 'config'. 1101 */ 1102 static isc_result_t 1103 configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, 1104 const cfg_obj_t *config, const cfg_obj_t *bindkeys, 1105 bool auto_root) { 1106 isc_result_t result = ISC_R_SUCCESS; 1107 const cfg_obj_t *view_keys = NULL; 1108 const cfg_obj_t *global_keys = NULL; 1109 const cfg_obj_t *view_managed_keys = NULL; 1110 const cfg_obj_t *view_trust_anchors = NULL; 1111 const cfg_obj_t *global_managed_keys = NULL; 1112 const cfg_obj_t *global_trust_anchors = NULL; 1113 const cfg_obj_t *maps[4]; 1114 const cfg_obj_t *voptions = NULL; 1115 const cfg_obj_t *options = NULL; 1116 const cfg_obj_t *obj = NULL; 1117 const char *directory; 1118 int i = 0; 1119 1120 /* We don't need trust anchors for the _bind view */ 1121 if (strcmp(view->name, "_bind") == 0 && 1122 view->rdclass == dns_rdataclass_chaos) 1123 { 1124 return ISC_R_SUCCESS; 1125 } 1126 1127 if (vconfig != NULL) { 1128 voptions = cfg_tuple_get(vconfig, "options"); 1129 if (voptions != NULL) { 1130 (void)cfg_map_get(voptions, "trusted-keys", &view_keys); 1131 1132 /* managed-keys and trust-anchors are synonyms. */ 1133 (void)cfg_map_get(voptions, "managed-keys", 1134 &view_managed_keys); 1135 (void)cfg_map_get(voptions, "trust-anchors", 1136 &view_trust_anchors); 1137 1138 maps[i++] = voptions; 1139 } 1140 } 1141 1142 if (config != NULL) { 1143 (void)cfg_map_get(config, "trusted-keys", &global_keys); 1144 1145 /* managed-keys and trust-anchors are synonyms. */ 1146 (void)cfg_map_get(config, "managed-keys", &global_managed_keys); 1147 (void)cfg_map_get(config, "trust-anchors", 1148 &global_trust_anchors); 1149 1150 (void)cfg_map_get(config, "options", &options); 1151 if (options != NULL) { 1152 maps[i++] = options; 1153 } 1154 } 1155 1156 maps[i++] = named_g_defaults; 1157 maps[i] = NULL; 1158 1159 dns_view_initsecroots(view); 1160 dns_view_initntatable(view, named_g_loopmgr); 1161 1162 if (auto_root && view->rdclass == dns_rdataclass_in) { 1163 const cfg_obj_t *builtin_keys = NULL; 1164 1165 /* 1166 * If bind.keys exists and is populated, it overrides 1167 * the trust-anchors clause hard-coded in named_g_config. 1168 */ 1169 if (bindkeys != NULL) { 1170 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1171 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1172 "obtaining root key for view %s " 1173 "from '%s'", 1174 view->name, named_g_server->bindkeysfile); 1175 1176 (void)cfg_map_get(bindkeys, "trust-anchors", 1177 &builtin_keys); 1178 1179 if (builtin_keys == NULL) { 1180 isc_log_write( 1181 named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1182 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 1183 "dnssec-validation auto: " 1184 "WARNING: root zone key " 1185 "not found"); 1186 } 1187 } 1188 1189 if (builtin_keys == NULL) { 1190 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1191 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1192 "using built-in root key for view %s", 1193 view->name); 1194 1195 (void)cfg_map_get(named_g_config, "trust-anchors", 1196 &builtin_keys); 1197 } 1198 1199 if (builtin_keys != NULL) { 1200 CHECK(load_view_keys(builtin_keys, view, true, 1201 dns_rootname)); 1202 } 1203 1204 if (!keyloaded(view, dns_rootname)) { 1205 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1206 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1207 "root key not loaded"); 1208 result = ISC_R_FAILURE; 1209 goto cleanup; 1210 } 1211 } 1212 1213 if (view->rdclass == dns_rdataclass_in) { 1214 CHECK(load_view_keys(view_keys, view, false, NULL)); 1215 CHECK(load_view_keys(view_trust_anchors, view, true, NULL)); 1216 CHECK(load_view_keys(view_managed_keys, view, true, NULL)); 1217 1218 CHECK(load_view_keys(global_keys, view, false, NULL)); 1219 CHECK(load_view_keys(global_trust_anchors, view, true, NULL)); 1220 CHECK(load_view_keys(global_managed_keys, view, true, NULL)); 1221 } 1222 1223 /* 1224 * Add key zone for managed keys. 1225 */ 1226 obj = NULL; 1227 (void)named_config_get(maps, "managed-keys-directory", &obj); 1228 directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL); 1229 if (directory != NULL) { 1230 result = isc_file_isdirectory(directory); 1231 } 1232 if (result != ISC_R_SUCCESS) { 1233 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1234 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1235 "invalid managed-keys-directory %s: %s", 1236 directory, isc_result_totext(result)); 1237 goto cleanup; 1238 } else if (directory != NULL) { 1239 if (!isc_file_isdirwritable(directory)) { 1240 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1241 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1242 "managed-keys-directory '%s' " 1243 "is not writable", 1244 directory); 1245 result = ISC_R_NOPERM; 1246 goto cleanup; 1247 } 1248 } 1249 1250 if (auto_root) { 1251 CHECK(add_keydata_zone(view, directory, named_g_mctx)); 1252 } 1253 1254 cleanup: 1255 return result; 1256 } 1257 1258 static isc_result_t 1259 mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { 1260 const cfg_listelt_t *element; 1261 const cfg_obj_t *obj; 1262 const char *str; 1263 dns_fixedname_t fixed; 1264 dns_name_t *name; 1265 bool value; 1266 isc_result_t result; 1267 isc_buffer_t b; 1268 1269 name = dns_fixedname_initname(&fixed); 1270 for (element = cfg_list_first(mbs); element != NULL; 1271 element = cfg_list_next(element)) 1272 { 1273 obj = cfg_listelt_value(element); 1274 str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 1275 isc_buffer_constinit(&b, str, strlen(str)); 1276 isc_buffer_add(&b, strlen(str)); 1277 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1278 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); 1279 CHECK(dns_resolver_setmustbesecure(resolver, name, value)); 1280 } 1281 1282 result = ISC_R_SUCCESS; 1283 1284 cleanup: 1285 return result; 1286 } 1287 1288 /*% 1289 * Get a dispatch appropriate for the resolver of a given view. 1290 */ 1291 static isc_result_t 1292 get_view_querysource_dispatch(const cfg_obj_t **maps, int af, 1293 dns_dispatch_t **dispatchp, bool is_firstview) { 1294 isc_result_t result = ISC_R_FAILURE; 1295 dns_dispatch_t *disp = NULL; 1296 isc_sockaddr_t sa; 1297 const cfg_obj_t *obj = NULL; 1298 1299 switch (af) { 1300 case AF_INET: 1301 result = named_config_get(maps, "query-source", &obj); 1302 INSIST(result == ISC_R_SUCCESS); 1303 break; 1304 case AF_INET6: 1305 result = named_config_get(maps, "query-source-v6", &obj); 1306 INSIST(result == ISC_R_SUCCESS); 1307 break; 1308 default: 1309 UNREACHABLE(); 1310 } 1311 1312 if (cfg_obj_isvoid(obj)) { 1313 /* 1314 * We don't want to use this address family, let's 1315 * bail now. The dispatch object for this family will 1316 * be null then not used to run queries. 1317 */ 1318 return ISC_R_SUCCESS; 1319 } else { 1320 /* 1321 * obj _has_ to be sockaddr here, cfg_obj_assockaddr() 1322 * asserts this internally. 1323 */ 1324 sa = *(cfg_obj_assockaddr(obj)); 1325 INSIST(isc_sockaddr_pf(&sa) == af); 1326 } 1327 1328 /* 1329 * If we don't support this address family, we're done! 1330 */ 1331 switch (af) { 1332 case AF_INET: 1333 result = isc_net_probeipv4(); 1334 break; 1335 case AF_INET6: 1336 result = isc_net_probeipv6(); 1337 break; 1338 default: 1339 UNREACHABLE(); 1340 } 1341 if (result != ISC_R_SUCCESS) { 1342 return ISC_R_SUCCESS; 1343 } 1344 1345 /* 1346 * Try to find a dispatcher that we can share. 1347 */ 1348 if (isc_sockaddr_getport(&sa) != 0) { 1349 INSIST(obj != NULL); 1350 if (is_firstview) { 1351 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 1352 "using specific query-source port " 1353 "suppresses port randomization and can be " 1354 "insecure."); 1355 } 1356 } 1357 1358 result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, &disp); 1359 if (result != ISC_R_SUCCESS) { 1360 isc_sockaddr_t any; 1361 char buf[ISC_SOCKADDR_FORMATSIZE]; 1362 1363 switch (af) { 1364 case AF_INET: 1365 isc_sockaddr_any(&any); 1366 break; 1367 case AF_INET6: 1368 isc_sockaddr_any6(&any); 1369 break; 1370 } 1371 if (isc_sockaddr_equal(&sa, &any)) { 1372 return ISC_R_SUCCESS; 1373 } 1374 isc_sockaddr_format(&sa, buf, sizeof(buf)); 1375 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1376 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1377 "could not get query source dispatcher (%s): %s", 1378 buf, isc_result_totext(result)); 1379 return result; 1380 } 1381 1382 *dispatchp = disp; 1383 1384 return ISC_R_SUCCESS; 1385 } 1386 1387 static isc_result_t 1388 configure_order(dns_order_t *order, const cfg_obj_t *ent) { 1389 dns_rdataclass_t rdclass; 1390 dns_rdatatype_t rdtype; 1391 const cfg_obj_t *obj; 1392 dns_fixedname_t fixed; 1393 unsigned int mode = 0; 1394 const char *str; 1395 isc_buffer_t b; 1396 isc_result_t result; 1397 bool addroot; 1398 1399 result = named_config_getclass(cfg_tuple_get(ent, "class"), 1400 dns_rdataclass_any, &rdclass); 1401 if (result != ISC_R_SUCCESS) { 1402 return result; 1403 } 1404 1405 result = named_config_gettype(cfg_tuple_get(ent, "type"), 1406 dns_rdatatype_any, &rdtype); 1407 if (result != ISC_R_SUCCESS) { 1408 return result; 1409 } 1410 1411 obj = cfg_tuple_get(ent, "name"); 1412 if (cfg_obj_isstring(obj)) { 1413 str = cfg_obj_asstring(obj); 1414 } else { 1415 str = "*"; 1416 } 1417 addroot = (strcmp(str, "*") == 0); 1418 isc_buffer_constinit(&b, str, strlen(str)); 1419 isc_buffer_add(&b, strlen(str)); 1420 dns_fixedname_init(&fixed); 1421 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, dns_rootname, 1422 0, NULL); 1423 if (result != ISC_R_SUCCESS) { 1424 return result; 1425 } 1426 1427 obj = cfg_tuple_get(ent, "ordering"); 1428 INSIST(cfg_obj_isstring(obj)); 1429 str = cfg_obj_asstring(obj); 1430 if (!strcasecmp(str, "fixed")) { 1431 #if DNS_RDATASET_FIXED 1432 mode = DNS_RDATASETATTR_FIXEDORDER; 1433 #else /* if DNS_RDATASET_FIXED */ 1434 mode = DNS_RDATASETATTR_CYCLIC; 1435 #endif /* DNS_RDATASET_FIXED */ 1436 } else if (!strcasecmp(str, "random")) { 1437 mode = DNS_RDATASETATTR_RANDOMIZE; 1438 } else if (!strcasecmp(str, "cyclic")) { 1439 mode = DNS_RDATASETATTR_CYCLIC; 1440 } else if (!strcasecmp(str, "none")) { 1441 mode = DNS_RDATASETATTR_NONE; 1442 } else { 1443 UNREACHABLE(); 1444 } 1445 1446 /* 1447 * "*" should match everything including the root (BIND 8 compat). 1448 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a 1449 * explicit entry for "." when the name is "*". 1450 */ 1451 if (addroot) { 1452 result = dns_order_add(order, dns_rootname, rdtype, rdclass, 1453 mode); 1454 if (result != ISC_R_SUCCESS) { 1455 return result; 1456 } 1457 } 1458 1459 return dns_order_add(order, dns_fixedname_name(&fixed), rdtype, rdclass, 1460 mode); 1461 } 1462 1463 static isc_result_t 1464 configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { 1465 isc_netaddr_t na; 1466 dns_peer_t *peer; 1467 const cfg_obj_t *obj; 1468 const char *str; 1469 isc_result_t result; 1470 unsigned int prefixlen; 1471 1472 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); 1473 1474 peer = NULL; 1475 result = dns_peer_newprefix(mctx, &na, prefixlen, &peer); 1476 if (result != ISC_R_SUCCESS) { 1477 return result; 1478 } 1479 1480 obj = NULL; 1481 (void)cfg_map_get(cpeer, "bogus", &obj); 1482 if (obj != NULL) { 1483 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); 1484 } 1485 1486 obj = NULL; 1487 (void)cfg_map_get(cpeer, "provide-ixfr", &obj); 1488 if (obj != NULL) { 1489 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); 1490 } 1491 1492 obj = NULL; 1493 (void)cfg_map_get(cpeer, "request-expire", &obj); 1494 if (obj != NULL) { 1495 CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj))); 1496 } 1497 1498 obj = NULL; 1499 (void)cfg_map_get(cpeer, "request-ixfr", &obj); 1500 if (obj != NULL) { 1501 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); 1502 } 1503 1504 obj = NULL; 1505 (void)cfg_map_get(cpeer, "request-nsid", &obj); 1506 if (obj != NULL) { 1507 CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); 1508 } 1509 1510 obj = NULL; 1511 (void)cfg_map_get(cpeer, "send-cookie", &obj); 1512 if (obj != NULL) { 1513 CHECK(dns_peer_setsendcookie(peer, cfg_obj_asboolean(obj))); 1514 } 1515 1516 obj = NULL; 1517 (void)cfg_map_get(cpeer, "require-cookie", &obj); 1518 if (obj != NULL) { 1519 CHECK(dns_peer_setrequirecookie(peer, cfg_obj_asboolean(obj))); 1520 } 1521 1522 obj = NULL; 1523 (void)cfg_map_get(cpeer, "edns", &obj); 1524 if (obj != NULL) { 1525 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); 1526 } 1527 1528 obj = NULL; 1529 (void)cfg_map_get(cpeer, "edns-udp-size", &obj); 1530 if (obj != NULL) { 1531 uint32_t udpsize = cfg_obj_asuint32(obj); 1532 if (udpsize < 512U) { 1533 udpsize = 512U; 1534 } 1535 if (udpsize > 4096U) { 1536 udpsize = 4096U; 1537 } 1538 CHECK(dns_peer_setudpsize(peer, (uint16_t)udpsize)); 1539 } 1540 1541 obj = NULL; 1542 (void)cfg_map_get(cpeer, "edns-version", &obj); 1543 if (obj != NULL) { 1544 uint32_t ednsversion = cfg_obj_asuint32(obj); 1545 if (ednsversion > 255U) { 1546 ednsversion = 255U; 1547 } 1548 CHECK(dns_peer_setednsversion(peer, (uint8_t)ednsversion)); 1549 } 1550 1551 obj = NULL; 1552 (void)cfg_map_get(cpeer, "max-udp-size", &obj); 1553 if (obj != NULL) { 1554 uint32_t udpsize = cfg_obj_asuint32(obj); 1555 if (udpsize < 512U) { 1556 udpsize = 512U; 1557 } 1558 if (udpsize > 4096U) { 1559 udpsize = 4096U; 1560 } 1561 CHECK(dns_peer_setmaxudp(peer, (uint16_t)udpsize)); 1562 } 1563 1564 obj = NULL; 1565 (void)cfg_map_get(cpeer, "padding", &obj); 1566 if (obj != NULL) { 1567 uint32_t padding = cfg_obj_asuint32(obj); 1568 if (padding > 512U) { 1569 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 1570 "server padding value cannot " 1571 "exceed 512: lowering"); 1572 padding = 512U; 1573 } 1574 CHECK(dns_peer_setpadding(peer, (uint16_t)padding)); 1575 } 1576 1577 obj = NULL; 1578 (void)cfg_map_get(cpeer, "tcp-only", &obj); 1579 if (obj != NULL) { 1580 CHECK(dns_peer_setforcetcp(peer, cfg_obj_asboolean(obj))); 1581 } 1582 1583 obj = NULL; 1584 (void)cfg_map_get(cpeer, "tcp-keepalive", &obj); 1585 if (obj != NULL) { 1586 CHECK(dns_peer_settcpkeepalive(peer, cfg_obj_asboolean(obj))); 1587 } 1588 1589 obj = NULL; 1590 (void)cfg_map_get(cpeer, "transfers", &obj); 1591 if (obj != NULL) { 1592 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); 1593 } 1594 1595 obj = NULL; 1596 (void)cfg_map_get(cpeer, "transfer-format", &obj); 1597 if (obj != NULL) { 1598 str = cfg_obj_asstring(obj); 1599 if (strcasecmp(str, "many-answers") == 0) { 1600 CHECK(dns_peer_settransferformat(peer, 1601 dns_many_answers)); 1602 } else if (strcasecmp(str, "one-answer") == 0) { 1603 CHECK(dns_peer_settransferformat(peer, dns_one_answer)); 1604 } else { 1605 UNREACHABLE(); 1606 } 1607 } 1608 1609 obj = NULL; 1610 (void)cfg_map_get(cpeer, "keys", &obj); 1611 if (obj != NULL) { 1612 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); 1613 if (result != ISC_R_SUCCESS) { 1614 goto cleanup; 1615 } 1616 } 1617 1618 obj = NULL; 1619 if (na.family == AF_INET) { 1620 (void)cfg_map_get(cpeer, "transfer-source", &obj); 1621 } else { 1622 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); 1623 } 1624 if (obj != NULL) { 1625 result = dns_peer_settransfersource(peer, 1626 cfg_obj_assockaddr(obj)); 1627 if (result != ISC_R_SUCCESS) { 1628 goto cleanup; 1629 } 1630 } 1631 1632 obj = NULL; 1633 if (na.family == AF_INET) { 1634 (void)cfg_map_get(cpeer, "notify-source", &obj); 1635 } else { 1636 (void)cfg_map_get(cpeer, "notify-source-v6", &obj); 1637 } 1638 if (obj != NULL) { 1639 result = dns_peer_setnotifysource(peer, 1640 cfg_obj_assockaddr(obj)); 1641 if (result != ISC_R_SUCCESS) { 1642 goto cleanup; 1643 } 1644 } 1645 1646 obj = NULL; 1647 if (na.family == AF_INET) { 1648 (void)cfg_map_get(cpeer, "query-source", &obj); 1649 } else { 1650 (void)cfg_map_get(cpeer, "query-source-v6", &obj); 1651 } 1652 if (obj != NULL) { 1653 INSIST(cfg_obj_issockaddr(obj)); 1654 result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj)); 1655 if (result != ISC_R_SUCCESS) { 1656 goto cleanup; 1657 } 1658 } 1659 1660 *peerp = peer; 1661 return ISC_R_SUCCESS; 1662 1663 cleanup: 1664 dns_peer_detach(&peer); 1665 return result; 1666 } 1667 1668 static isc_result_t 1669 configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, 1670 const dns_dyndbctx_t *dctx) { 1671 isc_result_t result = ISC_R_SUCCESS; 1672 const cfg_obj_t *obj; 1673 const char *name, *library; 1674 1675 /* Get the name of the dyndb instance and the library path . */ 1676 name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name")); 1677 library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library")); 1678 1679 obj = cfg_tuple_get(dyndb, "parameters"); 1680 if (obj != NULL) { 1681 result = dns_dyndb_load(library, name, cfg_obj_asstring(obj), 1682 cfg_obj_file(obj), cfg_obj_line(obj), 1683 mctx, dctx); 1684 } 1685 1686 if (result != ISC_R_SUCCESS) { 1687 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1688 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1689 "dynamic database '%s' configuration failed: %s", 1690 name, isc_result_totext(result)); 1691 } 1692 return result; 1693 } 1694 1695 static isc_result_t 1696 disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1697 isc_result_t result; 1698 const cfg_obj_t *algorithms; 1699 const cfg_listelt_t *element; 1700 const char *str; 1701 dns_fixedname_t fixed; 1702 dns_name_t *name; 1703 isc_buffer_t b; 1704 1705 name = dns_fixedname_initname(&fixed); 1706 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1707 isc_buffer_constinit(&b, str, strlen(str)); 1708 isc_buffer_add(&b, strlen(str)); 1709 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1710 1711 algorithms = cfg_tuple_get(disabled, "algorithms"); 1712 for (element = cfg_list_first(algorithms); element != NULL; 1713 element = cfg_list_next(element)) 1714 { 1715 isc_textregion_t r; 1716 dns_secalg_t alg; 1717 1718 r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element))); 1719 r.length = strlen(r.base); 1720 1721 result = dns_secalg_fromtext(&alg, &r); 1722 if (result != ISC_R_SUCCESS) { 1723 uint8_t ui; 1724 result = isc_parse_uint8(&ui, r.base, 10); 1725 alg = ui; 1726 } 1727 if (result != ISC_R_SUCCESS) { 1728 cfg_obj_log(cfg_listelt_value(element), named_g_lctx, 1729 ISC_LOG_ERROR, "invalid algorithm"); 1730 CHECK(result); 1731 } 1732 CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); 1733 } 1734 cleanup: 1735 return result; 1736 } 1737 1738 static isc_result_t 1739 disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1740 isc_result_t result; 1741 const cfg_obj_t *digests; 1742 const cfg_listelt_t *element; 1743 const char *str; 1744 dns_fixedname_t fixed; 1745 dns_name_t *name; 1746 isc_buffer_t b; 1747 1748 name = dns_fixedname_initname(&fixed); 1749 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1750 isc_buffer_constinit(&b, str, strlen(str)); 1751 isc_buffer_add(&b, strlen(str)); 1752 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1753 1754 digests = cfg_tuple_get(disabled, "digests"); 1755 for (element = cfg_list_first(digests); element != NULL; 1756 element = cfg_list_next(element)) 1757 { 1758 isc_textregion_t r; 1759 dns_dsdigest_t digest; 1760 1761 r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element))); 1762 r.length = strlen(r.base); 1763 1764 /* disable_ds_digests handles numeric values. */ 1765 result = dns_dsdigest_fromtext(&digest, &r); 1766 if (result != ISC_R_SUCCESS) { 1767 cfg_obj_log(cfg_listelt_value(element), named_g_lctx, 1768 ISC_LOG_ERROR, "invalid algorithm"); 1769 CHECK(result); 1770 } 1771 CHECK(dns_resolver_disable_ds_digest(resolver, name, digest)); 1772 } 1773 cleanup: 1774 return result; 1775 } 1776 1777 static bool 1778 on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { 1779 const cfg_listelt_t *element; 1780 dns_fixedname_t fixed; 1781 dns_name_t *name; 1782 isc_result_t result; 1783 const cfg_obj_t *value; 1784 const char *str; 1785 isc_buffer_t b; 1786 1787 name = dns_fixedname_initname(&fixed); 1788 1789 for (element = cfg_list_first(disablelist); element != NULL; 1790 element = cfg_list_next(element)) 1791 { 1792 value = cfg_listelt_value(element); 1793 str = cfg_obj_asstring(value); 1794 isc_buffer_constinit(&b, str, strlen(str)); 1795 isc_buffer_add(&b, strlen(str)); 1796 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 1797 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1798 if (dns_name_equal(name, zonename)) { 1799 return true; 1800 } 1801 } 1802 return false; 1803 } 1804 1805 static isc_result_t 1806 check_dbtype(dns_zone_t *zone, unsigned int dbtypec, const char **dbargv, 1807 isc_mem_t *mctx) { 1808 char **argv = NULL; 1809 unsigned int i; 1810 isc_result_t result = ISC_R_SUCCESS; 1811 1812 CHECK(dns_zone_getdbtype(zone, &argv, mctx)); 1813 1814 /* 1815 * Check that all the arguments match. 1816 */ 1817 for (i = 0; i < dbtypec; i++) { 1818 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) { 1819 CHECK(ISC_R_FAILURE); 1820 } 1821 } 1822 1823 /* 1824 * Check that there are not extra arguments. 1825 */ 1826 if (i == dbtypec && argv[i] != NULL) { 1827 result = ISC_R_FAILURE; 1828 } 1829 1830 cleanup: 1831 isc_mem_free(mctx, argv); 1832 return result; 1833 } 1834 1835 static void 1836 setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) { 1837 isc_stats_t *zoneqrystats; 1838 1839 dns_zone_setstatlevel(zone, level); 1840 1841 zoneqrystats = NULL; 1842 if (level == dns_zonestat_full) { 1843 isc_stats_create(mctx, &zoneqrystats, ns_statscounter_max); 1844 } 1845 dns_zone_setrequeststats(zone, zoneqrystats); 1846 if (zoneqrystats != NULL) { 1847 isc_stats_detach(&zoneqrystats); 1848 } 1849 } 1850 1851 static named_cache_t * 1852 cachelist_find(named_cachelist_t *cachelist, const char *cachename, 1853 dns_rdataclass_t rdclass) { 1854 for (named_cache_t *nsc = ISC_LIST_HEAD(*cachelist); nsc != NULL; 1855 nsc = ISC_LIST_NEXT(nsc, link)) 1856 { 1857 if (nsc->rdclass == rdclass && 1858 strcmp(dns_cache_getname(nsc->cache), cachename) == 0) 1859 { 1860 return nsc; 1861 } 1862 } 1863 1864 return NULL; 1865 } 1866 1867 static bool 1868 cache_reusable(dns_view_t *originview, dns_view_t *view, 1869 bool new_zero_no_soattl) { 1870 if (originview->rdclass != view->rdclass || 1871 originview->checknames != view->checknames || 1872 originview->acceptexpired != view->acceptexpired || 1873 originview->enablevalidation != view->enablevalidation || 1874 originview->maxcachettl != view->maxcachettl || 1875 originview->maxncachettl != view->maxncachettl || 1876 originview->resolver == NULL || 1877 dns_resolver_getzeronosoattl(originview->resolver) != 1878 new_zero_no_soattl) 1879 { 1880 return false; 1881 } 1882 1883 return true; 1884 } 1885 1886 static bool 1887 cache_sharable(dns_view_t *originview, dns_view_t *view, 1888 bool new_zero_no_soattl, uint64_t new_max_cache_size, 1889 uint32_t new_stale_ttl, uint32_t new_stale_refresh_time) { 1890 /* 1891 * If the cache cannot even reused for the same view, it cannot be 1892 * shared with other views. 1893 */ 1894 if (!cache_reusable(originview, view, new_zero_no_soattl)) { 1895 return false; 1896 } 1897 1898 /* 1899 * Check other cache related parameters that must be consistent among 1900 * the sharing views. 1901 */ 1902 if (dns_cache_getservestalettl(originview->cache) != new_stale_ttl || 1903 dns_cache_getservestalerefresh(originview->cache) != 1904 new_stale_refresh_time || 1905 dns_cache_getcachesize(originview->cache) != new_max_cache_size) 1906 { 1907 return false; 1908 } 1909 1910 return true; 1911 } 1912 1913 /* 1914 * Callback from DLZ configure when the driver sets up a writeable zone 1915 */ 1916 static isc_result_t 1917 dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) { 1918 dns_name_t *origin = dns_zone_getorigin(zone); 1919 dns_rdataclass_t zclass = view->rdclass; 1920 isc_result_t result; 1921 1922 dns_zone_setclass(zone, zclass); 1923 result = dns_zonemgr_managezone(named_g_server->zonemgr, zone); 1924 if (result != ISC_R_SUCCESS) { 1925 return result; 1926 } 1927 1928 dns_zone_setstats(zone, named_g_server->zonestats); 1929 1930 return named_zone_configure_writeable_dlz(dlzdb, zone, zclass, origin); 1931 } 1932 1933 static isc_result_t 1934 dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, 1935 unsigned int prefixlen, const char *server, const char *contact) { 1936 char reverse[48 + sizeof("ip6.arpa.")] = { 0 }; 1937 char buf[sizeof("x.x.")]; 1938 const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." }; 1939 const char *sep = ": view "; 1940 const char *viewname = view->name; 1941 const unsigned char *s6; 1942 dns_fixedname_t fixed; 1943 dns_name_t *name; 1944 dns_zone_t *zone = NULL; 1945 int dns64_dbtypec = 4; 1946 isc_buffer_t b; 1947 isc_result_t result; 1948 1949 REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || 1950 prefixlen == 56 || prefixlen == 64 || prefixlen == 96); 1951 1952 if (!strcmp(viewname, "_default")) { 1953 sep = ""; 1954 viewname = ""; 1955 } 1956 1957 /* 1958 * Construct the reverse name of the zone. 1959 */ 1960 s6 = na->type.in6.s6_addr; 1961 while (prefixlen > 0) { 1962 prefixlen -= 8; 1963 snprintf(buf, sizeof(buf), "%x.%x.", s6[prefixlen / 8] & 0xf, 1964 (s6[prefixlen / 8] >> 4) & 0xf); 1965 strlcat(reverse, buf, sizeof(reverse)); 1966 } 1967 strlcat(reverse, "ip6.arpa.", sizeof(reverse)); 1968 1969 /* 1970 * Create the actual zone. 1971 */ 1972 if (server != NULL) { 1973 dns64_dbtype[2] = server; 1974 } 1975 if (contact != NULL) { 1976 dns64_dbtype[3] = contact; 1977 } 1978 name = dns_fixedname_initname(&fixed); 1979 isc_buffer_constinit(&b, reverse, strlen(reverse)); 1980 isc_buffer_add(&b, strlen(reverse)); 1981 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1982 dns_zone_create(&zone, mctx, 0); 1983 CHECK(dns_zone_setorigin(zone, name)); 1984 dns_zone_setview(zone, view); 1985 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 1986 dns_zone_setclass(zone, view->rdclass); 1987 dns_zone_settype(zone, dns_zone_primary); 1988 dns_zone_setstats(zone, named_g_server->zonestats); 1989 dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype); 1990 if (view->queryacl != NULL) { 1991 dns_zone_setqueryacl(zone, view->queryacl); 1992 } 1993 if (view->queryonacl != NULL) { 1994 dns_zone_setqueryonacl(zone, view->queryonacl); 1995 } 1996 dns_zone_setdialup(zone, dns_dialuptype_no); 1997 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 1998 dns_zone_setnotifytype(zone, dns_notifytype_no); 1999 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 2000 setquerystats(zone, mctx, dns_zonestat_none); 2001 CHECK(dns_view_addzone(view, zone)); 2002 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2003 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 2004 "dns64 reverse zone%s%s: %s", sep, viewname, reverse); 2005 2006 cleanup: 2007 if (zone != NULL) { 2008 dns_zone_detach(&zone); 2009 } 2010 return result; 2011 } 2012 2013 #ifdef USE_DNSRPS 2014 typedef struct conf_dnsrps_ctx conf_dnsrps_ctx_t; 2015 struct conf_dnsrps_ctx { 2016 isc_result_t result; 2017 char *cstr; 2018 size_t cstr_size; 2019 isc_mem_t *mctx; 2020 }; 2021 2022 /* 2023 * Add to the DNSRPS configuration string. 2024 */ 2025 static bool 2026 conf_dnsrps_sadd(conf_dnsrps_ctx_t *ctx, const char *p, ...) { 2027 size_t new_len, cur_len, new_cstr_size; 2028 char *new_cstr; 2029 va_list args; 2030 2031 if (ctx->cstr == NULL) { 2032 ctx->cstr = isc_mem_get(ctx->mctx, 256); 2033 ctx->cstr[0] = '\0'; 2034 ctx->cstr_size = 256; 2035 } 2036 2037 cur_len = strlen(ctx->cstr); 2038 va_start(args, p); 2039 new_len = vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, 2040 args) + 2041 1; 2042 va_end(args); 2043 2044 if (cur_len + new_len <= ctx->cstr_size) { 2045 return true; 2046 } 2047 2048 new_cstr_size = ((cur_len + new_len) / 256 + 1) * 256; 2049 new_cstr = isc_mem_get(ctx->mctx, new_cstr_size); 2050 2051 memmove(new_cstr, ctx->cstr, cur_len); 2052 isc_mem_put(ctx->mctx, ctx->cstr, ctx->cstr_size); 2053 ctx->cstr_size = new_cstr_size; 2054 ctx->cstr = new_cstr; 2055 2056 /* cannot use args twice after a single va_start()on some systems */ 2057 va_start(args, p); 2058 vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, args); 2059 va_end(args); 2060 return true; 2061 } 2062 2063 /* 2064 * Get a DNSRPS configuration value using the global and view options 2065 * for the default. Return false upon failure. 2066 */ 2067 static bool 2068 conf_dnsrps_get(const cfg_obj_t **sub_obj, const cfg_obj_t **maps, 2069 const cfg_obj_t *obj, const char *name, 2070 conf_dnsrps_ctx_t *ctx) { 2071 if (ctx != NULL && ctx->result != ISC_R_SUCCESS) { 2072 *sub_obj = NULL; 2073 return false; 2074 } 2075 2076 *sub_obj = cfg_tuple_get(obj, name); 2077 if (cfg_obj_isvoid(*sub_obj)) { 2078 *sub_obj = NULL; 2079 if (maps != NULL && 2080 ISC_R_SUCCESS != named_config_get(maps, name, sub_obj)) 2081 { 2082 *sub_obj = NULL; 2083 } 2084 } 2085 return true; 2086 } 2087 2088 /* 2089 * Handle a DNSRPS boolean configuration value with the global and view 2090 * options providing the default. 2091 */ 2092 static void 2093 conf_dnsrps_yes_no(const cfg_obj_t *obj, const char *name, 2094 conf_dnsrps_ctx_t *ctx) { 2095 const cfg_obj_t *sub_obj; 2096 2097 if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { 2098 return; 2099 } 2100 if (sub_obj == NULL) { 2101 return; 2102 } 2103 if (ctx == NULL) { 2104 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 2105 "\"%s\" without \"dnsrps-enable yes\"", name); 2106 return; 2107 } 2108 2109 conf_dnsrps_sadd(ctx, " %s %s", name, 2110 cfg_obj_asboolean(sub_obj) ? "yes" : "no"); 2111 } 2112 2113 static void 2114 conf_dnsrps_num(const cfg_obj_t *obj, const char *name, 2115 conf_dnsrps_ctx_t *ctx) { 2116 const cfg_obj_t *sub_obj; 2117 2118 if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { 2119 return; 2120 } 2121 if (sub_obj == NULL) { 2122 return; 2123 } 2124 if (ctx == NULL) { 2125 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 2126 "\"%s\" without \"dnsrps-enable yes\"", name); 2127 return; 2128 } 2129 2130 if (cfg_obj_isduration(sub_obj)) { 2131 conf_dnsrps_sadd(ctx, " %s %d", name, 2132 cfg_obj_asduration(sub_obj)); 2133 } else { 2134 conf_dnsrps_sadd(ctx, " %s %d", name, 2135 cfg_obj_asuint32(sub_obj)); 2136 } 2137 } 2138 2139 /* 2140 * Convert the parsed RPZ configuration statement to a string for 2141 * dns_rpz_new_zones(). 2142 */ 2143 static isc_result_t 2144 conf_dnsrps(dns_view_t *view, const cfg_obj_t **maps, bool nsip_enabled, 2145 bool nsdname_enabled, dns_rpz_zbits_t *nsip_on, 2146 dns_rpz_zbits_t *nsdname_on, char **rps_cstr, size_t *rps_cstr_size, 2147 const cfg_obj_t *rpz_obj, const cfg_listelt_t *zone_element) { 2148 conf_dnsrps_ctx_t ctx; 2149 const cfg_obj_t *zone_obj, *obj; 2150 dns_rpz_num_t rpz_num; 2151 bool on; 2152 const char *s; 2153 2154 memset(&ctx, 0, sizeof(ctx)); 2155 ctx.result = ISC_R_SUCCESS; 2156 ctx.mctx = view->mctx; 2157 2158 for (rpz_num = 0; zone_element != NULL && ctx.result == ISC_R_SUCCESS; 2159 ++rpz_num) 2160 { 2161 zone_obj = cfg_listelt_value(zone_element); 2162 2163 s = cfg_obj_asstring(cfg_tuple_get(zone_obj, "zone name")); 2164 conf_dnsrps_sadd(&ctx, "zone \"%s\"", s); 2165 2166 obj = cfg_tuple_get(zone_obj, "policy"); 2167 if (!cfg_obj_isvoid(obj)) { 2168 s = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 2169 conf_dnsrps_sadd(&ctx, " policy %s", s); 2170 if (strcasecmp(s, "cname") == 0) { 2171 s = cfg_obj_asstring( 2172 cfg_tuple_get(obj, "cname")); 2173 conf_dnsrps_sadd(&ctx, " %s", s); 2174 } 2175 } 2176 2177 conf_dnsrps_yes_no(zone_obj, "recursive-only", &ctx); 2178 conf_dnsrps_yes_no(zone_obj, "log", &ctx); 2179 conf_dnsrps_num(zone_obj, "max-policy-ttl", &ctx); 2180 obj = cfg_tuple_get(rpz_obj, "nsip-enable"); 2181 if (!cfg_obj_isvoid(obj)) { 2182 if (cfg_obj_asboolean(obj)) { 2183 *nsip_on |= DNS_RPZ_ZBIT(rpz_num); 2184 } else { 2185 *nsip_on &= ~DNS_RPZ_ZBIT(rpz_num); 2186 } 2187 } 2188 on = ((*nsip_on & DNS_RPZ_ZBIT(rpz_num)) != 0); 2189 if (nsip_enabled != on) { 2190 conf_dnsrps_sadd(&ctx, on ? " nsip-enable yes " 2191 : " nsip-enable no "); 2192 } 2193 obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); 2194 if (!cfg_obj_isvoid(obj)) { 2195 if (cfg_obj_asboolean(obj)) { 2196 *nsdname_on |= DNS_RPZ_ZBIT(rpz_num); 2197 } else { 2198 *nsdname_on &= ~DNS_RPZ_ZBIT(rpz_num); 2199 } 2200 } 2201 on = ((*nsdname_on & DNS_RPZ_ZBIT(rpz_num)) != 0); 2202 if (nsdname_enabled != on) { 2203 conf_dnsrps_sadd(&ctx, on ? " nsdname-enable yes " 2204 : " nsdname-enable no "); 2205 } 2206 conf_dnsrps_sadd(&ctx, ";\n"); 2207 zone_element = cfg_list_next(zone_element); 2208 } 2209 2210 conf_dnsrps_yes_no(rpz_obj, "recursive-only", &ctx); 2211 conf_dnsrps_num(rpz_obj, "max-policy-ttl", &ctx); 2212 conf_dnsrps_num(rpz_obj, "min-ns-dots", &ctx); 2213 conf_dnsrps_yes_no(rpz_obj, "qname-wait-recurse", &ctx); 2214 conf_dnsrps_yes_no(rpz_obj, "break-dnssec", &ctx); 2215 if (!nsip_enabled) { 2216 conf_dnsrps_sadd(&ctx, " nsip-enable no "); 2217 } 2218 if (!nsdname_enabled) { 2219 conf_dnsrps_sadd(&ctx, " nsdname-enable no "); 2220 } 2221 2222 /* 2223 * Get the general dnsrpzd parameters from the response-policy 2224 * statement in the view and the general options. 2225 */ 2226 if (conf_dnsrps_get(&obj, maps, rpz_obj, "dnsrps-options", &ctx) && 2227 obj != NULL) 2228 { 2229 conf_dnsrps_sadd(&ctx, " %s\n", cfg_obj_asstring(obj)); 2230 } 2231 2232 if (ctx.result == ISC_R_SUCCESS) { 2233 *rps_cstr = ctx.cstr; 2234 *rps_cstr_size = ctx.cstr_size; 2235 } else { 2236 if (ctx.cstr != NULL) { 2237 isc_mem_put(ctx.mctx, ctx.cstr, ctx.cstr_size); 2238 } 2239 *rps_cstr = NULL; 2240 *rps_cstr_size = 0; 2241 } 2242 return ctx.result; 2243 } 2244 #endif /* ifdef USE_DNSRPS */ 2245 2246 static isc_result_t 2247 configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 2248 const char *str, const char *msg) { 2249 isc_result_t result; 2250 2251 result = dns_name_fromstring(name, str, dns_rootname, DNS_NAME_DOWNCASE, 2252 view->mctx); 2253 if (result != ISC_R_SUCCESS) { 2254 cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2255 "invalid %s '%s'", msg, str); 2256 } 2257 return result; 2258 } 2259 2260 static isc_result_t 2261 configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 2262 const char *str, const dns_name_t *origin) { 2263 isc_result_t result; 2264 2265 result = dns_name_fromstring(name, str, origin, DNS_NAME_DOWNCASE, 2266 view->mctx); 2267 if (result != ISC_R_SUCCESS) { 2268 cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2269 "invalid zone '%s'", str); 2270 } 2271 return result; 2272 } 2273 2274 static isc_result_t 2275 configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, 2276 bool recursive_only_default, bool add_soa_default, 2277 dns_ttl_t ttl_default, uint32_t minupdateinterval_default, 2278 const dns_rpz_zone_t *old, bool *old_rpz_okp) { 2279 const cfg_obj_t *rpz_obj, *obj; 2280 const char *str; 2281 dns_rpz_zone_t *zone = NULL; 2282 isc_result_t result; 2283 dns_rpz_num_t rpz_num; 2284 2285 REQUIRE(old != NULL || !*old_rpz_okp); 2286 2287 rpz_obj = cfg_listelt_value(element); 2288 2289 if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) { 2290 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2291 "limit of %d response policy zones exceeded", 2292 DNS_RPZ_MAX_ZONES); 2293 return ISC_R_FAILURE; 2294 } 2295 2296 result = dns_rpz_new_zone(view->rpzs, &zone); 2297 if (result != ISC_R_SUCCESS) { 2298 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2299 "Error creating new RPZ zone : %s", 2300 isc_result_totext(result)); 2301 return result; 2302 } 2303 2304 obj = cfg_tuple_get(rpz_obj, "recursive-only"); 2305 if (cfg_obj_isvoid(obj) ? recursive_only_default 2306 : cfg_obj_asboolean(obj)) 2307 { 2308 view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(zone->num); 2309 } else { 2310 view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(zone->num); 2311 } 2312 2313 obj = cfg_tuple_get(rpz_obj, "log"); 2314 if (!cfg_obj_isvoid(obj) && !cfg_obj_asboolean(obj)) { 2315 view->rpzs->p.no_log |= DNS_RPZ_ZBIT(zone->num); 2316 } else { 2317 view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(zone->num); 2318 } 2319 2320 obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 2321 if (cfg_obj_isduration(obj)) { 2322 zone->max_policy_ttl = cfg_obj_asduration(obj); 2323 } else { 2324 zone->max_policy_ttl = ttl_default; 2325 } 2326 if (*old_rpz_okp && zone->max_policy_ttl != old->max_policy_ttl) { 2327 *old_rpz_okp = false; 2328 } 2329 2330 obj = cfg_tuple_get(rpz_obj, "min-update-interval"); 2331 if (cfg_obj_isduration(obj)) { 2332 zone->min_update_interval = cfg_obj_asduration(obj); 2333 } else { 2334 zone->min_update_interval = minupdateinterval_default; 2335 } 2336 if (*old_rpz_okp && 2337 zone->min_update_interval != old->min_update_interval) 2338 { 2339 *old_rpz_okp = false; 2340 } 2341 2342 str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); 2343 result = configure_rpz_name(view, rpz_obj, &zone->origin, str, "zone"); 2344 if (result != ISC_R_SUCCESS) { 2345 return result; 2346 } 2347 if (dns_name_equal(&zone->origin, dns_rootname)) { 2348 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2349 "invalid zone name '%s'", str); 2350 return DNS_R_EMPTYLABEL; 2351 } 2352 if (!view->rpzs->p.dnsrps_enabled) { 2353 for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones - 1; 2354 ++rpz_num) 2355 { 2356 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, 2357 &zone->origin)) 2358 { 2359 cfg_obj_log(rpz_obj, named_g_lctx, 2360 DNS_RPZ_ERROR_LEVEL, 2361 "duplicate '%s'", str); 2362 result = DNS_R_DUPLICATE; 2363 return result; 2364 } 2365 } 2366 } 2367 if (*old_rpz_okp && !dns_name_equal(&old->origin, &zone->origin)) { 2368 *old_rpz_okp = false; 2369 } 2370 2371 result = configure_rpz_name2(view, rpz_obj, &zone->client_ip, 2372 DNS_RPZ_CLIENT_IP_ZONE, &zone->origin); 2373 if (result != ISC_R_SUCCESS) { 2374 return result; 2375 } 2376 2377 result = configure_rpz_name2(view, rpz_obj, &zone->ip, DNS_RPZ_IP_ZONE, 2378 &zone->origin); 2379 if (result != ISC_R_SUCCESS) { 2380 return result; 2381 } 2382 2383 result = configure_rpz_name2(view, rpz_obj, &zone->nsdname, 2384 DNS_RPZ_NSDNAME_ZONE, &zone->origin); 2385 if (result != ISC_R_SUCCESS) { 2386 return result; 2387 } 2388 2389 result = configure_rpz_name2(view, rpz_obj, &zone->nsip, 2390 DNS_RPZ_NSIP_ZONE, &zone->origin); 2391 if (result != ISC_R_SUCCESS) { 2392 return result; 2393 } 2394 2395 result = configure_rpz_name(view, rpz_obj, &zone->passthru, 2396 DNS_RPZ_PASSTHRU_NAME, "name"); 2397 if (result != ISC_R_SUCCESS) { 2398 return result; 2399 } 2400 2401 result = configure_rpz_name(view, rpz_obj, &zone->drop, 2402 DNS_RPZ_DROP_NAME, "name"); 2403 if (result != ISC_R_SUCCESS) { 2404 return result; 2405 } 2406 2407 result = configure_rpz_name(view, rpz_obj, &zone->tcp_only, 2408 DNS_RPZ_TCP_ONLY_NAME, "name"); 2409 if (result != ISC_R_SUCCESS) { 2410 return result; 2411 } 2412 2413 obj = cfg_tuple_get(rpz_obj, "policy"); 2414 if (cfg_obj_isvoid(obj)) { 2415 zone->policy = DNS_RPZ_POLICY_GIVEN; 2416 } else { 2417 str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 2418 zone->policy = dns_rpz_str2policy(str); 2419 INSIST(zone->policy != DNS_RPZ_POLICY_ERROR); 2420 if (zone->policy == DNS_RPZ_POLICY_CNAME) { 2421 str = cfg_obj_asstring(cfg_tuple_get(obj, "cname")); 2422 result = configure_rpz_name(view, rpz_obj, &zone->cname, 2423 str, "cname"); 2424 if (result != ISC_R_SUCCESS) { 2425 return result; 2426 } 2427 } 2428 } 2429 if (*old_rpz_okp && (zone->policy != old->policy || 2430 !dns_name_equal(&old->cname, &zone->cname))) 2431 { 2432 *old_rpz_okp = false; 2433 } 2434 2435 obj = cfg_tuple_get(rpz_obj, "ede"); 2436 if (!cfg_obj_isstring(obj)) { 2437 zone->ede = 0; 2438 } else { 2439 str = cfg_obj_asstring(obj); 2440 zone->ede = dns_rpz_str2ede(str); 2441 INSIST(zone->ede != UINT16_MAX); 2442 } 2443 if (*old_rpz_okp && zone->ede != old->ede) { 2444 *old_rpz_okp = false; 2445 } 2446 2447 obj = cfg_tuple_get(rpz_obj, "add-soa"); 2448 if (cfg_obj_isvoid(obj)) { 2449 zone->addsoa = add_soa_default; 2450 } else { 2451 zone->addsoa = cfg_obj_asboolean(obj); 2452 } 2453 if (*old_rpz_okp && zone->addsoa != old->addsoa) { 2454 *old_rpz_okp = false; 2455 } 2456 2457 return ISC_R_SUCCESS; 2458 } 2459 2460 static isc_result_t 2461 configure_rpz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t **maps, 2462 const cfg_obj_t *rpz_obj, bool *old_rpz_okp, bool first_time) { 2463 bool dnsrps_enabled; 2464 const cfg_listelt_t *zone_element; 2465 char *rps_cstr; 2466 size_t rps_cstr_size; 2467 const cfg_obj_t *sub_obj; 2468 bool recursive_only_default, add_soa_default; 2469 bool nsip_enabled, nsdname_enabled; 2470 dns_rpz_zbits_t nsip_on, nsdname_on; 2471 dns_ttl_t ttl_default; 2472 uint32_t minupdateinterval_default; 2473 dns_rpz_zones_t *zones; 2474 const dns_rpz_zones_t *old; 2475 bool pview_must_detach = false; 2476 const dns_rpz_zone_t *old_zone; 2477 isc_result_t result; 2478 int i; 2479 2480 *old_rpz_okp = false; 2481 2482 zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list")); 2483 if (zone_element == NULL) { 2484 return ISC_R_SUCCESS; 2485 } 2486 2487 nsip_enabled = true; 2488 sub_obj = cfg_tuple_get(rpz_obj, "nsip-enable"); 2489 if (!cfg_obj_isvoid(sub_obj)) { 2490 nsip_enabled = cfg_obj_asboolean(sub_obj); 2491 } 2492 nsip_on = nsip_enabled ? DNS_RPZ_ALL_ZBITS : 0; 2493 2494 nsdname_enabled = true; 2495 sub_obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); 2496 if (!cfg_obj_isvoid(sub_obj)) { 2497 nsdname_enabled = cfg_obj_asboolean(sub_obj); 2498 } 2499 nsdname_on = nsdname_enabled ? DNS_RPZ_ALL_ZBITS : 0; 2500 2501 /* 2502 * "dnsrps-enable yes|no" can be either a global or response-policy 2503 * clause. 2504 */ 2505 dnsrps_enabled = false; 2506 rps_cstr = NULL; 2507 rps_cstr_size = 0; 2508 sub_obj = NULL; 2509 (void)named_config_get(maps, "dnsrps-enable", &sub_obj); 2510 if (sub_obj != NULL) { 2511 dnsrps_enabled = cfg_obj_asboolean(sub_obj); 2512 } 2513 sub_obj = cfg_tuple_get(rpz_obj, "dnsrps-enable"); 2514 if (!cfg_obj_isvoid(sub_obj)) { 2515 dnsrps_enabled = cfg_obj_asboolean(sub_obj); 2516 } 2517 #ifndef USE_DNSRPS 2518 if (dnsrps_enabled) { 2519 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2520 "\"dnsrps-enable yes\" but" 2521 " without `./configure --enable-dnsrps`"); 2522 return ISC_R_FAILURE; 2523 } 2524 #else /* ifndef USE_DNSRPS */ 2525 if (dnsrps_enabled) { 2526 if (librpz == NULL) { 2527 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2528 "\"dnsrps-enable yes\" but %s", 2529 librpz_lib_open_emsg.c); 2530 return ISC_R_FAILURE; 2531 } 2532 2533 /* 2534 * Generate the DNS Response Policy Service 2535 * configuration string. 2536 */ 2537 result = conf_dnsrps(view, maps, nsip_enabled, nsdname_enabled, 2538 &nsip_on, &nsdname_on, &rps_cstr, 2539 &rps_cstr_size, rpz_obj, zone_element); 2540 if (result != ISC_R_SUCCESS) { 2541 return result; 2542 } 2543 } 2544 #endif /* ifndef USE_DNSRPS */ 2545 2546 result = dns_rpz_new_zones(view, named_g_loopmgr, rps_cstr, 2547 rps_cstr_size, &view->rpzs, first_time); 2548 if (result != ISC_R_SUCCESS) { 2549 return result; 2550 } 2551 2552 zones = view->rpzs; 2553 2554 zones->p.nsip_on = nsip_on; 2555 zones->p.nsdname_on = nsdname_on; 2556 zones->p.slow_mode = ns_server_getoption(named_g_server->sctx, 2557 NS_SERVER_RPZSLOW); 2558 2559 sub_obj = cfg_tuple_get(rpz_obj, "recursive-only"); 2560 if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { 2561 recursive_only_default = false; 2562 } else { 2563 recursive_only_default = true; 2564 } 2565 2566 sub_obj = cfg_tuple_get(rpz_obj, "add-soa"); 2567 if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { 2568 add_soa_default = false; 2569 } else { 2570 add_soa_default = true; 2571 } 2572 2573 sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec"); 2574 if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) { 2575 zones->p.break_dnssec = true; 2576 } else { 2577 zones->p.break_dnssec = false; 2578 } 2579 2580 sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 2581 if (cfg_obj_isduration(sub_obj)) { 2582 ttl_default = cfg_obj_asduration(sub_obj); 2583 } else { 2584 ttl_default = DNS_RPZ_MAX_TTL_DEFAULT; 2585 } 2586 2587 sub_obj = cfg_tuple_get(rpz_obj, "min-update-interval"); 2588 if (cfg_obj_isduration(sub_obj)) { 2589 minupdateinterval_default = cfg_obj_asduration(sub_obj); 2590 } else { 2591 minupdateinterval_default = DNS_RPZ_MINUPDATEINTERVAL_DEFAULT; 2592 } 2593 2594 sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots"); 2595 if (cfg_obj_isuint32(sub_obj)) { 2596 zones->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1; 2597 } else { 2598 zones->p.min_ns_labels = 2; 2599 } 2600 2601 sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse"); 2602 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2603 zones->p.qname_wait_recurse = true; 2604 } else { 2605 zones->p.qname_wait_recurse = false; 2606 } 2607 2608 sub_obj = cfg_tuple_get(rpz_obj, "nsdname-wait-recurse"); 2609 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2610 zones->p.nsdname_wait_recurse = true; 2611 } else { 2612 zones->p.nsdname_wait_recurse = false; 2613 } 2614 2615 sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse"); 2616 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2617 zones->p.nsip_wait_recurse = true; 2618 } else { 2619 zones->p.nsip_wait_recurse = false; 2620 } 2621 2622 sub_obj = cfg_tuple_get(rpz_obj, "servfail-until-ready"); 2623 if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) { 2624 zones->p.servfail_until_ready = true; 2625 } else { 2626 zones->p.servfail_until_ready = false; 2627 } 2628 2629 if (dnsrps_enabled && zones->p.servfail_until_ready) { 2630 zones->p.servfail_until_ready = false; 2631 cfg_obj_log(rpz_obj, named_g_lctx, ISC_LOG_WARNING, 2632 "\"servfail-until-ready yes\" has no effect when " 2633 "used with \"dnsrps-enable yes\""); 2634 } 2635 2636 if (pview != NULL) { 2637 old = pview->rpzs; 2638 } else { 2639 result = dns_viewlist_find(&named_g_server->viewlist, 2640 view->name, view->rdclass, &pview); 2641 if (result == ISC_R_SUCCESS) { 2642 pview_must_detach = true; 2643 old = pview->rpzs; 2644 } else { 2645 old = NULL; 2646 } 2647 } 2648 2649 if (old == NULL) { 2650 *old_rpz_okp = false; 2651 } else { 2652 *old_rpz_okp = true; 2653 } 2654 2655 for (i = 0; zone_element != NULL; 2656 ++i, zone_element = cfg_list_next(zone_element)) 2657 { 2658 INSIST(!*old_rpz_okp || old != NULL); 2659 if (*old_rpz_okp && i < old->p.num_zones) { 2660 old_zone = old->zones[i]; 2661 } else { 2662 *old_rpz_okp = false; 2663 old_zone = NULL; 2664 } 2665 result = configure_rpz_zone( 2666 view, zone_element, recursive_only_default, 2667 add_soa_default, ttl_default, minupdateinterval_default, 2668 old_zone, old_rpz_okp); 2669 if (result != ISC_R_SUCCESS) { 2670 if (pview_must_detach) { 2671 dns_view_detach(&pview); 2672 } 2673 return result; 2674 } 2675 } 2676 2677 /* 2678 * If this is a reloading and the parameters and list of policy 2679 * zones are unchanged, then use the same policy data. 2680 * Data for individual zones that must be reloaded will be merged. 2681 */ 2682 if (*old_rpz_okp) { 2683 if (old != NULL && 2684 memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0) 2685 { 2686 *old_rpz_okp = false; 2687 } else if ((old == NULL || old->rps_cstr == NULL) != 2688 (zones->rps_cstr == NULL)) 2689 { 2690 *old_rpz_okp = false; 2691 } else if (old != NULL && zones->rps_cstr != NULL && 2692 strcmp(old->rps_cstr, zones->rps_cstr) != 0) 2693 { 2694 *old_rpz_okp = false; 2695 } 2696 } 2697 2698 if (*old_rpz_okp) { 2699 INSIST(pview->rpzs != NULL); 2700 2701 /* Discard the newly created rpzs. */ 2702 dns_rpz_zones_shutdown(view->rpzs); 2703 dns_rpz_zones_detach(&view->rpzs); 2704 2705 /* 2706 * We are reusing the old rpzs, so it can no longer be its 2707 * first time. 2708 */ 2709 pview->rpzs->first_time = false; 2710 2711 /* Reuse rpzs from the old view. */ 2712 dns_rpz_zones_attach(pview->rpzs, &view->rpzs); 2713 dns_rpz_zones_detach(&pview->rpzs); 2714 } else if (old != NULL && pview != NULL) { 2715 INSIST(pview->rpzs != NULL); 2716 2717 ++pview->rpzs->rpz_ver; 2718 view->rpzs->rpz_ver = pview->rpzs->rpz_ver; 2719 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_DEBUG_LEVEL1, 2720 "updated RPZ policy: version %d", 2721 view->rpzs->rpz_ver); 2722 } 2723 2724 if (pview_must_detach) { 2725 dns_view_detach(&pview); 2726 } 2727 2728 return ISC_R_SUCCESS; 2729 } 2730 2731 static void 2732 catz_addmodzone_cb(void *arg) { 2733 catz_chgzone_t *cz = (catz_chgzone_t *)arg; 2734 isc_result_t result; 2735 dns_forwarders_t *dnsforwarders = NULL; 2736 dns_name_t *name = NULL; 2737 isc_buffer_t namebuf; 2738 isc_buffer_t *confbuf = NULL; 2739 char nameb[DNS_NAME_FORMATSIZE]; 2740 const cfg_obj_t *zlist = NULL; 2741 cfg_obj_t *zoneconf = NULL; 2742 cfg_obj_t *zoneobj = NULL; 2743 ns_cfgctx_t *cfg = NULL; 2744 dns_zone_t *zone = NULL; 2745 2746 if (isc_loop_shuttingdown(isc_loop_get(named_g_loopmgr, isc_tid()))) { 2747 goto cleanup; 2748 } 2749 2750 /* 2751 * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' 2752 * is true, so this is expected to be non-NULL. 2753 */ 2754 cfg = (ns_cfgctx_t *)cz->view->new_zone_config; 2755 if (cfg == NULL) { 2756 CHECK(ISC_R_FAILURE); 2757 } 2758 2759 name = dns_catz_entry_getname(cz->entry); 2760 2761 isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); 2762 dns_name_totext(name, DNS_NAME_OMITFINALDOT, &namebuf); 2763 isc_buffer_putuint8(&namebuf, 0); 2764 2765 result = dns_fwdtable_find(cz->view->fwdtable, name, &dnsforwarders); 2766 if (result == ISC_R_SUCCESS && 2767 dnsforwarders->fwdpolicy == dns_fwdpolicy_only) 2768 { 2769 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2770 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2771 "catz: catz_addmodzone_cb: " 2772 "zone '%s' will not be processed because of the " 2773 "explicitly configured forwarding for that zone", 2774 nameb); 2775 goto cleanup; 2776 } 2777 2778 result = dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone); 2779 2780 if (cz->mod) { 2781 dns_catz_zone_t *parentcatz; 2782 2783 if (result != ISC_R_SUCCESS) { 2784 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2785 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2786 "catz: error \"%s\" while trying to " 2787 "modify zone '%s'", 2788 isc_result_totext(result), nameb); 2789 goto cleanup; 2790 } 2791 2792 if (!dns_zone_getadded(zone)) { 2793 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2794 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2795 "catz: catz_addmodzone_cb: " 2796 "zone '%s' is not a dynamically " 2797 "added zone", 2798 nameb); 2799 goto cleanup; 2800 } 2801 2802 parentcatz = dns_zone_get_parentcatz(zone); 2803 2804 if (parentcatz == NULL) { 2805 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2806 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2807 "catz: catz_addmodzone_cb: " 2808 "zone '%s' exists and is not added by " 2809 "a catalog zone, so won't be modified", 2810 nameb); 2811 goto cleanup; 2812 } 2813 if (parentcatz != cz->origin) { 2814 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2815 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2816 "catz: catz_addmodzone_cb: " 2817 "zone '%s' exists in multiple " 2818 "catalog zones", 2819 nameb); 2820 goto cleanup; 2821 } 2822 2823 dns_zone_detach(&zone); 2824 } else { 2825 /* Zone shouldn't already exist when adding */ 2826 if (result == ISC_R_SUCCESS) { 2827 if (dns_zone_get_parentcatz(zone) == NULL) { 2828 isc_log_write( 2829 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2830 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2831 "catz: " 2832 "catz_addmodzone_cb: " 2833 "zone '%s' will not be added " 2834 "because it is an explicitly " 2835 "configured zone", 2836 nameb); 2837 } else { 2838 isc_log_write( 2839 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2840 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2841 "catz: " 2842 "catz_addmodzone_cb: " 2843 "zone '%s' will not be added " 2844 "because another catalog zone " 2845 "already contains an entry with " 2846 "that zone", 2847 nameb); 2848 } 2849 goto cleanup; 2850 } else { 2851 RUNTIME_CHECK(result == ISC_R_NOTFOUND); 2852 } 2853 } 2854 RUNTIME_CHECK(zone == NULL); 2855 /* Create a config for new zone */ 2856 confbuf = NULL; 2857 result = dns_catz_generate_zonecfg(cz->origin, cz->entry, &confbuf); 2858 if (result == ISC_R_SUCCESS) { 2859 cfg_parser_reset(cfg->add_parser); 2860 result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, 2861 &cfg_type_addzoneconf, 0, &zoneconf); 2862 } 2863 /* 2864 * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() 2865 * failed. 2866 */ 2867 if (result != ISC_R_SUCCESS) { 2868 isc_log_write( 2869 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2870 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 2871 "catz: error \"%s\" while trying to generate " 2872 "config for zone '%s'%s%.*s%s", 2873 isc_result_totext(result), nameb, 2874 confbuf != NULL ? " buffer '" : "", 2875 confbuf != NULL ? (int)isc_buffer_usedlength(confbuf) 2876 : 0, 2877 confbuf != NULL ? (char *)isc_buffer_base(confbuf) : "", 2878 confbuf != NULL ? "'" : ""); 2879 goto cleanup; 2880 } 2881 isc_buffer_free(&confbuf); 2882 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 2883 if (!cfg_obj_islist(zlist)) { 2884 CHECK(ISC_R_FAILURE); 2885 } 2886 2887 /* For now we only support adding one zone at a time */ 2888 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 2889 2890 /* Mark view unfrozen so that zone can be added */ 2891 isc_loopmgr_pause(named_g_loopmgr); 2892 dns_view_thaw(cz->view); 2893 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, cz->view, 2894 &cz->cbd->server->viewlist, 2895 &cz->cbd->server->kasplist, 2896 &cz->cbd->server->keystorelist, cfg->actx, true, 2897 false, true, cz->mod); 2898 dns_view_freeze(cz->view); 2899 isc_loopmgr_resume(named_g_loopmgr); 2900 2901 if (result != ISC_R_SUCCESS) { 2902 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2903 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2904 "catz: failed to configure zone '%s' - %d", nameb, 2905 result); 2906 goto cleanup; 2907 } 2908 2909 /* Is it there yet? */ 2910 CHECK(dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone)); 2911 2912 /* 2913 * Load the zone from the master file. If this fails, we'll 2914 * need to undo the configuration we've done already. 2915 */ 2916 result = dns_zone_load(zone, true); 2917 if (result != ISC_R_SUCCESS) { 2918 dns_db_t *dbp = NULL; 2919 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2920 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 2921 "catz: dns_zone_load() failed " 2922 "with %s; reverting.", 2923 isc_result_totext(result)); 2924 2925 /* If the zone loaded partially, unload it */ 2926 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 2927 dns_db_detach(&dbp); 2928 dns_zone_unload(zone); 2929 } 2930 2931 /* Remove the zone from the zone table */ 2932 dns_view_delzone(cz->view, zone); 2933 goto cleanup; 2934 } 2935 2936 /* Flag the zone as having been added at runtime */ 2937 dns_zone_setadded(zone, true); 2938 dns_zone_set_parentcatz(zone, cz->origin); 2939 2940 cleanup: 2941 if (confbuf != NULL) { 2942 isc_buffer_free(&confbuf); 2943 } 2944 if (zone != NULL) { 2945 dns_zone_detach(&zone); 2946 } 2947 if (zoneconf != NULL) { 2948 cfg_obj_destroy(cfg->add_parser, &zoneconf); 2949 } 2950 if (dnsforwarders != NULL) { 2951 dns_forwarders_detach(&dnsforwarders); 2952 } 2953 dns_catz_entry_detach(cz->origin, &cz->entry); 2954 dns_catz_zone_detach(&cz->origin); 2955 dns_view_weakdetach(&cz->view); 2956 isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); 2957 } 2958 2959 static void 2960 catz_delzone_cb(void *arg) { 2961 catz_chgzone_t *cz = (catz_chgzone_t *)arg; 2962 isc_result_t result; 2963 dns_zone_t *zone = NULL; 2964 dns_db_t *dbp = NULL; 2965 char cname[DNS_NAME_FORMATSIZE]; 2966 const char *file = NULL; 2967 2968 if (isc_loop_shuttingdown(isc_loop_get(named_g_loopmgr, isc_tid()))) { 2969 goto cleanup; 2970 } 2971 2972 isc_loopmgr_pause(named_g_loopmgr); 2973 2974 dns_name_format(dns_catz_entry_getname(cz->entry), cname, 2975 DNS_NAME_FORMATSIZE); 2976 result = dns_view_findzone(cz->view, dns_catz_entry_getname(cz->entry), 2977 DNS_ZTFIND_EXACT, &zone); 2978 if (result != ISC_R_SUCCESS) { 2979 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2980 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2981 "catz: catz_delzone_cb: " 2982 "zone '%s' not found", 2983 cname); 2984 goto resume; 2985 } 2986 2987 if (!dns_zone_getadded(zone)) { 2988 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2989 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2990 "catz: catz_delzone_cb: " 2991 "zone '%s' is not a dynamically added zone", 2992 cname); 2993 goto resume; 2994 } 2995 2996 if (dns_zone_get_parentcatz(zone) != cz->origin) { 2997 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2998 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2999 "catz: catz_delzone_cb: zone " 3000 "'%s' exists in multiple catalog zones", 3001 cname); 3002 goto resume; 3003 } 3004 3005 /* Stop answering for this zone */ 3006 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 3007 dns_db_detach(&dbp); 3008 dns_zone_unload(zone); 3009 } 3010 3011 if (dns_view_delzone(cz->view, zone) != ISC_R_SUCCESS) { 3012 goto resume; 3013 } 3014 file = dns_zone_getfile(zone); 3015 if (file != NULL) { 3016 isc_file_remove(file); 3017 file = dns_zone_getjournal(zone); 3018 if (file != NULL) { 3019 isc_file_remove(file); 3020 } 3021 } 3022 3023 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3024 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 3025 "catz: catz_delzone_cb: " 3026 "zone '%s' deleted", 3027 cname); 3028 resume: 3029 isc_loopmgr_resume(named_g_loopmgr); 3030 cleanup: 3031 if (zone != NULL) { 3032 dns_zone_detach(&zone); 3033 } 3034 dns_catz_entry_detach(cz->origin, &cz->entry); 3035 dns_catz_zone_detach(&cz->origin); 3036 dns_view_weakdetach(&cz->view); 3037 isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); 3038 } 3039 3040 static isc_result_t 3041 catz_run(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3042 void *udata, catz_type_t type) { 3043 catz_chgzone_t *cz = NULL; 3044 isc_job_cb action = NULL; 3045 3046 switch (type) { 3047 case CATZ_ADDZONE: 3048 case CATZ_MODZONE: 3049 action = catz_addmodzone_cb; 3050 break; 3051 case CATZ_DELZONE: 3052 action = catz_delzone_cb; 3053 break; 3054 default: 3055 REQUIRE(0); 3056 UNREACHABLE(); 3057 } 3058 3059 cz = isc_mem_get(view->mctx, sizeof(*cz)); 3060 *cz = (catz_chgzone_t){ 3061 .cbd = (catz_cb_data_t *)udata, 3062 .mod = (type == CATZ_MODZONE), 3063 }; 3064 isc_mem_attach(view->mctx, &cz->mctx); 3065 3066 dns_catz_entry_attach(entry, &cz->entry); 3067 dns_catz_zone_attach(origin, &cz->origin); 3068 dns_view_weakattach(view, &cz->view); 3069 3070 isc_async_run(named_g_mainloop, action, cz); 3071 3072 return ISC_R_SUCCESS; 3073 } 3074 3075 static isc_result_t 3076 catz_addzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3077 void *udata) { 3078 return catz_run(entry, origin, view, udata, CATZ_ADDZONE); 3079 } 3080 3081 static isc_result_t 3082 catz_delzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3083 void *udata) { 3084 return catz_run(entry, origin, view, udata, CATZ_DELZONE); 3085 } 3086 3087 static isc_result_t 3088 catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3089 void *udata) { 3090 return catz_run(entry, origin, view, udata, CATZ_MODZONE); 3091 } 3092 3093 static void 3094 catz_changeview(dns_catz_entry_t *entry, void *arg1, void *arg2) { 3095 dns_view_t *pview = arg1; 3096 dns_view_t *view = arg2; 3097 3098 dns_zone_t *zone = NULL; 3099 isc_result_t result = dns_view_findzone( 3100 pview, dns_catz_entry_getname(entry), DNS_ZTFIND_EXACT, &zone); 3101 3102 if (result != ISC_R_SUCCESS) { 3103 return; 3104 } 3105 3106 dns_zone_setview(zone, view); 3107 dns_view_addzone(view, zone); 3108 3109 dns_zone_detach(&zone); 3110 } 3111 3112 static void 3113 catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { 3114 dns_view_t *view = arg1; 3115 catz_reconfig_data_t *data = arg2; 3116 isc_buffer_t namebuf; 3117 isc_buffer_t *confbuf = NULL; 3118 const cfg_obj_t *zlist = NULL; 3119 char nameb[DNS_NAME_FORMATSIZE]; 3120 cfg_obj_t *zoneconf = NULL; 3121 cfg_obj_t *zoneobj = NULL; 3122 ns_cfgctx_t *cfg = NULL; 3123 dns_zone_t *zone = NULL; 3124 isc_result_t result; 3125 3126 isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); 3127 dns_name_totext(dns_catz_entry_getname(entry), DNS_NAME_OMITFINALDOT, 3128 &namebuf); 3129 isc_buffer_putuint8(&namebuf, 0); 3130 3131 result = dns_view_findzone(view, dns_catz_entry_getname(entry), 3132 DNS_ZTFIND_EXACT, &zone); 3133 if (result != ISC_R_SUCCESS) { 3134 return; 3135 } 3136 3137 /* 3138 * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' 3139 * is true, so this is expected to be non-NULL. 3140 */ 3141 cfg = (ns_cfgctx_t *)view->new_zone_config; 3142 if (cfg == NULL) { 3143 CHECK(ISC_R_FAILURE); 3144 } 3145 3146 result = dns_catz_generate_zonecfg(data->catz, entry, &confbuf); 3147 if (result == ISC_R_SUCCESS) { 3148 cfg_parser_reset(cfg->add_parser); 3149 result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, 3150 &cfg_type_addzoneconf, 0, &zoneconf); 3151 isc_buffer_free(&confbuf); 3152 } 3153 /* 3154 * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() 3155 * failed. 3156 */ 3157 if (result != ISC_R_SUCCESS) { 3158 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3159 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 3160 "catz_reconfigure: error \"%s\" while trying to " 3161 "generate config for member zone '%s'", 3162 isc_result_totext(result), nameb); 3163 goto cleanup; 3164 } 3165 3166 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 3167 if (!cfg_obj_islist(zlist)) { 3168 CHECK(ISC_R_FAILURE); 3169 } 3170 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 3171 3172 result = configure_zone(data->config, zoneobj, cfg->vconfig, view, 3173 &data->cbd->server->viewlist, 3174 &data->cbd->server->kasplist, 3175 &data->cbd->server->keystorelist, cfg->actx, 3176 true, false, true, true); 3177 if (result != ISC_R_SUCCESS) { 3178 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3179 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 3180 "catz_reconfigure : error \"%s\" while trying to " 3181 "reconfigure member zone '%s'", 3182 isc_result_totext(result), nameb); 3183 goto cleanup; 3184 } 3185 3186 cleanup: 3187 if (zoneconf != NULL) { 3188 cfg_obj_destroy(cfg->add_parser, &zoneconf); 3189 } 3190 3191 dns_zone_detach(&zone); 3192 } 3193 3194 static isc_result_t 3195 configure_catz_zone(dns_view_t *view, dns_view_t *pview, 3196 const cfg_obj_t *config, const cfg_listelt_t *element) { 3197 const cfg_obj_t *catz_obj, *obj; 3198 dns_catz_zone_t *zone = NULL; 3199 const char *str; 3200 isc_result_t result; 3201 dns_name_t origin; 3202 dns_ipkeylist_t ipkl; 3203 dns_catz_options_t *opts; 3204 3205 dns_name_init(&origin, NULL); 3206 dns_ipkeylist_init(&ipkl); 3207 catz_obj = cfg_listelt_value(element); 3208 3209 str = cfg_obj_asstring(cfg_tuple_get(catz_obj, "zone name")); 3210 3211 result = dns_name_fromstring(&origin, str, dns_rootname, 3212 DNS_NAME_DOWNCASE, view->mctx); 3213 if (result == ISC_R_SUCCESS && dns_name_equal(&origin, dns_rootname)) { 3214 result = DNS_R_EMPTYLABEL; 3215 } 3216 3217 if (result != ISC_R_SUCCESS) { 3218 cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3219 "catz: invalid zone name '%s'", str); 3220 goto cleanup; 3221 } 3222 3223 obj = cfg_tuple_get(catz_obj, "default-masters"); 3224 if (obj == NULL || !cfg_obj_istuple(obj)) { 3225 obj = cfg_tuple_get(catz_obj, "default-primaries"); 3226 } 3227 if (obj != NULL && cfg_obj_istuple(obj)) { 3228 result = named_config_getipandkeylist(config, obj, view->mctx, 3229 &ipkl); 3230 if (result != ISC_R_SUCCESS) { 3231 cfg_obj_log(catz_obj, named_g_lctx, 3232 DNS_CATZ_ERROR_LEVEL, 3233 "catz: default-primaries parse error: %s", 3234 isc_result_totext(result)); 3235 goto cleanup; 3236 } 3237 } 3238 3239 result = dns_catz_zone_add(view->catzs, &origin, &zone); 3240 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) { 3241 cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3242 "catz: dns_catz_zone_add failed: %s", 3243 isc_result_totext(result)); 3244 goto cleanup; 3245 } 3246 3247 dns_catz_zone_prereconfig(zone); 3248 3249 if (result == ISC_R_EXISTS) { 3250 catz_reconfig_data_t data = { 3251 .catz = zone, 3252 .config = config, 3253 .cbd = (catz_cb_data_t *)dns_catz_zones_get_udata( 3254 view->catzs), 3255 }; 3256 3257 /* 3258 * We have to walk through all the member zones, re-attach 3259 * them to the current view and reconfigure 3260 */ 3261 dns_catz_zone_for_each_entry2(zone, catz_changeview, pview, 3262 view); 3263 dns_catz_zone_for_each_entry2(zone, catz_reconfigure, view, 3264 &data); 3265 3266 result = ISC_R_SUCCESS; 3267 } 3268 3269 dns_catz_zone_resetdefoptions(zone); 3270 opts = dns_catz_zone_getdefoptions(zone); 3271 if (ipkl.count != 0) { 3272 /* 3273 * Transfer the ownership of the pointers inside 'ipkl' and 3274 * set its count to 0 in order to not cleanup it later below. 3275 */ 3276 opts->masters = ipkl; 3277 ipkl.count = 0; 3278 } 3279 3280 obj = cfg_tuple_get(catz_obj, "in-memory"); 3281 if (obj != NULL && cfg_obj_isboolean(obj)) { 3282 opts->in_memory = cfg_obj_asboolean(obj); 3283 } 3284 3285 obj = cfg_tuple_get(catz_obj, "zone-directory"); 3286 if (!opts->in_memory && obj != NULL && cfg_obj_isstring(obj)) { 3287 opts->zonedir = isc_mem_strdup(view->mctx, 3288 cfg_obj_asstring(obj)); 3289 if (isc_file_isdirectory(opts->zonedir) != ISC_R_SUCCESS) { 3290 cfg_obj_log(obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3291 "catz: zone-directory '%s' " 3292 "not found; zone files will not be " 3293 "saved", 3294 opts->zonedir); 3295 opts->in_memory = true; 3296 } 3297 } 3298 3299 obj = cfg_tuple_get(catz_obj, "min-update-interval"); 3300 if (obj != NULL && cfg_obj_isduration(obj)) { 3301 opts->min_update_interval = cfg_obj_asduration(obj); 3302 } 3303 3304 dns_catz_zone_postreconfig(zone); 3305 3306 cleanup: 3307 dns_name_free(&origin, view->mctx); 3308 if (ipkl.count != 0) { 3309 dns_ipkeylist_clear(view->mctx, &ipkl); 3310 } 3311 3312 return result; 3313 } 3314 3315 static catz_cb_data_t ns_catz_cbdata; 3316 static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = { 3317 catz_addzone, catz_modzone, catz_delzone, &ns_catz_cbdata 3318 }; 3319 3320 static isc_result_t 3321 configure_catz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t *config, 3322 const cfg_obj_t *catz_obj) { 3323 const cfg_listelt_t *zone_element = NULL; 3324 const dns_catz_zones_t *old = NULL; 3325 bool pview_must_detach = false; 3326 isc_result_t result; 3327 3328 /* xxxwpk TODO do it cleaner, once, somewhere */ 3329 ns_catz_cbdata.server = named_g_server; 3330 3331 zone_element = cfg_list_first(cfg_tuple_get(catz_obj, "zone list")); 3332 if (zone_element == NULL) { 3333 return ISC_R_SUCCESS; 3334 } 3335 3336 if (pview != NULL) { 3337 old = pview->catzs; 3338 } else { 3339 result = dns_viewlist_find(&named_g_server->viewlist, 3340 view->name, view->rdclass, &pview); 3341 if (result == ISC_R_SUCCESS) { 3342 pview_must_detach = true; 3343 old = pview->catzs; 3344 } 3345 } 3346 3347 if (old != NULL) { 3348 dns_catz_zones_attach(pview->catzs, &view->catzs); 3349 dns_catz_zones_detach(&pview->catzs); 3350 dns_catz_prereconfig(view->catzs); 3351 } else { 3352 view->catzs = dns_catz_zones_new(view->mctx, named_g_loopmgr, 3353 &ns_catz_zonemodmethods); 3354 } 3355 3356 while (zone_element != NULL) { 3357 CHECK(configure_catz_zone(view, pview, config, zone_element)); 3358 zone_element = cfg_list_next(zone_element); 3359 } 3360 3361 if (old != NULL) { 3362 dns_catz_postreconfig(view->catzs); 3363 } 3364 3365 result = ISC_R_SUCCESS; 3366 3367 cleanup: 3368 if (pview_must_detach) { 3369 dns_view_detach(&pview); 3370 } 3371 3372 return result; 3373 } 3374 3375 #define CHECK_RRL(cond, pat, val1, val2) \ 3376 do { \ 3377 if (!(cond)) { \ 3378 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, pat, \ 3379 val1, val2); \ 3380 result = ISC_R_RANGE; \ 3381 goto cleanup; \ 3382 } \ 3383 } while (0) 3384 3385 #define CHECK_RRL_RATE(rate, def, max_rate, name) \ 3386 do { \ 3387 obj = NULL; \ 3388 rrl->rate.str = name; \ 3389 result = cfg_map_get(map, name, &obj); \ 3390 if (result == ISC_R_SUCCESS) { \ 3391 rrl->rate.r = cfg_obj_asuint32(obj); \ 3392 CHECK_RRL(rrl->rate.r <= max_rate, name " %d > %d", \ 3393 rrl->rate.r, max_rate); \ 3394 } else { \ 3395 rrl->rate.r = def; \ 3396 } \ 3397 rrl->rate.scaled = rrl->rate.r; \ 3398 } while (0) 3399 3400 static isc_result_t 3401 configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) { 3402 const cfg_obj_t *obj; 3403 dns_rrl_t *rrl; 3404 isc_result_t result; 3405 int min_entries, i, j; 3406 3407 /* 3408 * Most DNS servers have few clients, but intentinally open 3409 * recursive and authoritative servers often have many. 3410 * So start with a small number of entries unless told otherwise 3411 * to reduce cold-start costs. 3412 */ 3413 min_entries = 500; 3414 obj = NULL; 3415 result = cfg_map_get(map, "min-table-size", &obj); 3416 if (result == ISC_R_SUCCESS) { 3417 min_entries = cfg_obj_asuint32(obj); 3418 if (min_entries < 1) { 3419 min_entries = 1; 3420 } 3421 } 3422 result = dns_rrl_init(&rrl, view, min_entries); 3423 if (result != ISC_R_SUCCESS) { 3424 return result; 3425 } 3426 3427 i = ISC_MAX(20000, min_entries); 3428 obj = NULL; 3429 result = cfg_map_get(map, "max-table-size", &obj); 3430 if (result == ISC_R_SUCCESS) { 3431 i = cfg_obj_asuint32(obj); 3432 CHECK_RRL(i >= min_entries, 3433 "max-table-size %d < min-table-size %d", i, 3434 min_entries); 3435 } 3436 rrl->max_entries = i; 3437 3438 CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE, 3439 "responses-per-second"); 3440 CHECK_RRL_RATE(referrals_per_second, rrl->responses_per_second.r, 3441 DNS_RRL_MAX_RATE, "referrals-per-second"); 3442 CHECK_RRL_RATE(nodata_per_second, rrl->responses_per_second.r, 3443 DNS_RRL_MAX_RATE, "nodata-per-second"); 3444 CHECK_RRL_RATE(nxdomains_per_second, rrl->responses_per_second.r, 3445 DNS_RRL_MAX_RATE, "nxdomains-per-second"); 3446 CHECK_RRL_RATE(errors_per_second, rrl->responses_per_second.r, 3447 DNS_RRL_MAX_RATE, "errors-per-second"); 3448 3449 CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, "all-per-second"); 3450 3451 CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, "slip"); 3452 3453 i = 15; 3454 obj = NULL; 3455 result = cfg_map_get(map, "window", &obj); 3456 if (result == ISC_R_SUCCESS) { 3457 i = cfg_obj_asuint32(obj); 3458 CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW, 3459 "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW); 3460 } 3461 rrl->window = i; 3462 3463 i = 0; 3464 obj = NULL; 3465 result = cfg_map_get(map, "qps-scale", &obj); 3466 if (result == ISC_R_SUCCESS) { 3467 i = cfg_obj_asuint32(obj); 3468 CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, ""); 3469 } 3470 rrl->qps_scale = i; 3471 rrl->qps = 1.0; 3472 3473 i = 24; 3474 obj = NULL; 3475 result = cfg_map_get(map, "ipv4-prefix-length", &obj); 3476 if (result == ISC_R_SUCCESS) { 3477 i = cfg_obj_asuint32(obj); 3478 CHECK_RRL(i >= 8 && i <= 32, 3479 "invalid 'ipv4-prefix-length %d'%s", i, ""); 3480 } 3481 rrl->ipv4_prefixlen = i; 3482 if (i == 32) { 3483 rrl->ipv4_mask = 0xffffffff; 3484 } else { 3485 rrl->ipv4_mask = htonl(0xffffffff << (32 - i)); 3486 } 3487 3488 i = 56; 3489 obj = NULL; 3490 result = cfg_map_get(map, "ipv6-prefix-length", &obj); 3491 if (result == ISC_R_SUCCESS) { 3492 i = cfg_obj_asuint32(obj); 3493 CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX, 3494 "ipv6-prefix-length %d < 16 or > %d", i, 3495 DNS_RRL_MAX_PREFIX); 3496 } 3497 rrl->ipv6_prefixlen = i; 3498 for (j = 0; j < 4; ++j) { 3499 if (i <= 0) { 3500 rrl->ipv6_mask[j] = 0; 3501 } else if (i < 32) { 3502 rrl->ipv6_mask[j] = htonl(0xffffffff << (32 - i)); 3503 } else { 3504 rrl->ipv6_mask[j] = 0xffffffff; 3505 } 3506 i -= 32; 3507 } 3508 3509 obj = NULL; 3510 result = cfg_map_get(map, "exempt-clients", &obj); 3511 if (result == ISC_R_SUCCESS) { 3512 result = cfg_acl_fromconfig(obj, config, named_g_lctx, 3513 named_g_aclconfctx, named_g_mctx, 0, 3514 &rrl->exempt); 3515 CHECK_RRL(result == ISC_R_SUCCESS, "invalid %s%s", 3516 "address match list", ""); 3517 } 3518 3519 obj = NULL; 3520 result = cfg_map_get(map, "log-only", &obj); 3521 if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj)) { 3522 rrl->log_only = true; 3523 } else { 3524 rrl->log_only = false; 3525 } 3526 3527 return ISC_R_SUCCESS; 3528 3529 cleanup: 3530 dns_rrl_view_destroy(view); 3531 return result; 3532 } 3533 3534 static isc_result_t 3535 add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 3536 const dns_name_t *origin, const dns_name_t *contact) { 3537 dns_dbnode_t *node = NULL; 3538 dns_rdata_t rdata = DNS_RDATA_INIT; 3539 dns_rdatalist_t rdatalist; 3540 dns_rdataset_t rdataset; 3541 isc_result_t result; 3542 unsigned char buf[DNS_SOA_BUFFERSIZE]; 3543 3544 CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800, 3545 7200, 604800, 86400, buf, &rdata)); 3546 3547 dns_rdatalist_init(&rdatalist); 3548 rdatalist.type = rdata.type; 3549 rdatalist.rdclass = rdata.rdclass; 3550 rdatalist.ttl = 86400; 3551 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 3552 3553 dns_rdataset_init(&rdataset); 3554 dns_rdatalist_tordataset(&rdatalist, &rdataset); 3555 CHECK(dns_db_findnode(db, name, true, &node)); 3556 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 3557 3558 cleanup: 3559 if (node != NULL) { 3560 dns_db_detachnode(db, &node); 3561 } 3562 return result; 3563 } 3564 3565 static isc_result_t 3566 add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 3567 const dns_name_t *nsname) { 3568 dns_dbnode_t *node = NULL; 3569 dns_rdata_ns_t ns; 3570 dns_rdata_t rdata = DNS_RDATA_INIT; 3571 dns_rdatalist_t rdatalist; 3572 dns_rdataset_t rdataset; 3573 isc_result_t result; 3574 isc_buffer_t b; 3575 unsigned char buf[DNS_NAME_MAXWIRE]; 3576 3577 isc_buffer_init(&b, buf, sizeof(buf)); 3578 3579 ns.common.rdtype = dns_rdatatype_ns; 3580 ns.common.rdclass = dns_db_class(db); 3581 ns.mctx = NULL; 3582 dns_name_init(&ns.name, NULL); 3583 dns_name_clone(nsname, &ns.name); 3584 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, 3585 &ns, &b)); 3586 3587 dns_rdatalist_init(&rdatalist); 3588 rdatalist.type = rdata.type; 3589 rdatalist.rdclass = rdata.rdclass; 3590 rdatalist.ttl = 86400; 3591 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 3592 3593 dns_rdataset_init(&rdataset); 3594 dns_rdatalist_tordataset(&rdatalist, &rdataset); 3595 CHECK(dns_db_findnode(db, name, true, &node)); 3596 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 3597 3598 cleanup: 3599 if (node != NULL) { 3600 dns_db_detachnode(db, &node); 3601 } 3602 return result; 3603 } 3604 3605 static isc_result_t 3606 create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view, 3607 const cfg_obj_t *zonelist, const char **empty_dbtype, 3608 int empty_dbtypec, dns_zonestat_level_t statlevel) { 3609 char namebuf[DNS_NAME_FORMATSIZE]; 3610 const cfg_listelt_t *element; 3611 const cfg_obj_t *obj; 3612 const cfg_obj_t *zconfig; 3613 const cfg_obj_t *zoptions; 3614 const char *default_dbtype[4] = { ZONEDB_DEFAULT }; 3615 const char *sep = ": view "; 3616 const char *str; 3617 const char *viewname = view->name; 3618 dns_db_t *db = NULL; 3619 dns_dbversion_t *version = NULL; 3620 dns_fixedname_t cfixed; 3621 dns_fixedname_t fixed; 3622 dns_fixedname_t nsfixed; 3623 dns_name_t *contact; 3624 dns_name_t *ns; 3625 dns_name_t *zname; 3626 dns_zone_t *zone = NULL; 3627 int default_dbtypec = 1; 3628 isc_result_t result; 3629 dns_namereln_t namereln; 3630 int order; 3631 unsigned int nlabels; 3632 3633 zname = dns_fixedname_initname(&fixed); 3634 ns = dns_fixedname_initname(&nsfixed); 3635 contact = dns_fixedname_initname(&cfixed); 3636 3637 /* 3638 * Look for forward "zones" beneath this empty zone and if so 3639 * create a custom db for the empty zone. 3640 */ 3641 for (element = cfg_list_first(zonelist); element != NULL; 3642 element = cfg_list_next(element)) 3643 { 3644 zconfig = cfg_listelt_value(element); 3645 str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 3646 CHECK(dns_name_fromstring(zname, str, dns_rootname, 0, NULL)); 3647 namereln = dns_name_fullcompare(zname, name, &order, &nlabels); 3648 if (namereln != dns_namereln_subdomain) { 3649 continue; 3650 } 3651 3652 zoptions = cfg_tuple_get(zconfig, "options"); 3653 3654 obj = NULL; 3655 (void)cfg_map_get(zoptions, "type", &obj); 3656 if (obj != NULL && 3657 strcasecmp(cfg_obj_asstring(obj), "forward") == 0) 3658 { 3659 obj = NULL; 3660 (void)cfg_map_get(zoptions, "forward", &obj); 3661 if (obj == NULL) { 3662 continue; 3663 } 3664 if (strcasecmp(cfg_obj_asstring(obj), "only") != 0) { 3665 continue; 3666 } 3667 } 3668 if (db == NULL) { 3669 CHECK(dns_db_create(view->mctx, ZONEDB_DEFAULT, name, 3670 dns_dbtype_zone, view->rdclass, 0, 3671 NULL, &db)); 3672 CHECK(dns_db_newversion(db, &version)); 3673 if (strcmp(empty_dbtype[2], "@") == 0) { 3674 dns_name_clone(name, ns); 3675 } else { 3676 CHECK(dns_name_fromstring(ns, empty_dbtype[2], 3677 dns_rootname, 0, 3678 NULL)); 3679 } 3680 CHECK(dns_name_fromstring(contact, empty_dbtype[3], 3681 dns_rootname, 0, NULL)); 3682 CHECK(add_soa(db, version, name, ns, contact)); 3683 CHECK(add_ns(db, version, name, ns)); 3684 } 3685 CHECK(add_ns(db, version, zname, dns_rootname)); 3686 } 3687 3688 /* 3689 * Is the existing zone ok to use? 3690 */ 3691 if (pzone != NULL) { 3692 unsigned int typec; 3693 const char **dbargv = NULL; 3694 3695 if (db != NULL) { 3696 typec = default_dbtypec; 3697 dbargv = default_dbtype; 3698 } else { 3699 typec = empty_dbtypec; 3700 dbargv = empty_dbtype; 3701 } 3702 3703 result = check_dbtype(pzone, typec, dbargv, view->mctx); 3704 if (result != ISC_R_SUCCESS) { 3705 pzone = NULL; 3706 } 3707 3708 if (pzone != NULL && 3709 dns_zone_gettype(pzone) != dns_zone_primary) 3710 { 3711 pzone = NULL; 3712 } 3713 if (pzone != NULL && dns_zone_getfile(pzone) != NULL) { 3714 pzone = NULL; 3715 } 3716 if (pzone != NULL) { 3717 dns_zone_getraw(pzone, &zone); 3718 if (zone != NULL) { 3719 dns_zone_detach(&zone); 3720 pzone = NULL; 3721 } 3722 } 3723 } 3724 3725 if (pzone == NULL) { 3726 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 3727 CHECK(dns_zone_setorigin(zone, name)); 3728 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 3729 if (db == NULL) { 3730 dns_zone_setdbtype(zone, empty_dbtypec, empty_dbtype); 3731 } 3732 dns_zone_setclass(zone, view->rdclass); 3733 dns_zone_settype(zone, dns_zone_primary); 3734 dns_zone_setstats(zone, named_g_server->zonestats); 3735 } else { 3736 dns_zone_attach(pzone, &zone); 3737 } 3738 3739 dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, false); 3740 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 3741 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 3742 dns_zone_setnotifytype(zone, dns_notifytype_no); 3743 dns_zone_setdialup(zone, dns_dialuptype_no); 3744 dns_zone_setautomatic(zone, true); 3745 if (view->queryacl != NULL) { 3746 dns_zone_setqueryacl(zone, view->queryacl); 3747 } else { 3748 dns_zone_clearqueryacl(zone); 3749 } 3750 if (view->queryonacl != NULL) { 3751 dns_zone_setqueryonacl(zone, view->queryonacl); 3752 } else { 3753 dns_zone_clearqueryonacl(zone); 3754 } 3755 dns_zone_clearupdateacl(zone); 3756 if (view->transferacl != NULL) { 3757 dns_zone_setxfracl(zone, view->transferacl); 3758 } else { 3759 dns_zone_clearxfracl(zone); 3760 } 3761 3762 setquerystats(zone, view->mctx, statlevel); 3763 if (db != NULL) { 3764 dns_db_closeversion(db, &version, true); 3765 CHECK(dns_zone_replacedb(zone, db, false)); 3766 } 3767 dns_zone_setoption(zone, DNS_ZONEOPT_AUTOEMPTY, true); 3768 dns_zone_setview(zone, view); 3769 CHECK(dns_view_addzone(view, zone)); 3770 3771 if (!strcmp(viewname, "_default")) { 3772 sep = ""; 3773 viewname = ""; 3774 } 3775 dns_name_format(name, namebuf, sizeof(namebuf)); 3776 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_ZONELOAD, 3777 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 3778 "automatic empty zone%s%s: %s", sep, viewname, namebuf); 3779 3780 cleanup: 3781 if (zone != NULL) { 3782 dns_zone_detach(&zone); 3783 } 3784 if (version != NULL) { 3785 dns_db_closeversion(db, &version, false); 3786 } 3787 if (db != NULL) { 3788 dns_db_detach(&db); 3789 } 3790 3791 INSIST(version == NULL); 3792 3793 return result; 3794 } 3795 3796 static isc_result_t 3797 create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view, 3798 const dns_name_t *name, const char *type, isc_mem_t *mctx, 3799 const char *server, const char *contact) { 3800 char namebuf[DNS_NAME_FORMATSIZE]; 3801 const char *dbtype[4] = { "_builtin", NULL, "@", "." }; 3802 const char *sep = ": view "; 3803 const char *viewname = view->name; 3804 dns_zone_t *zone = NULL; 3805 int dbtypec = 4; 3806 isc_result_t result; 3807 3808 REQUIRE(type != NULL); 3809 3810 if (!strcmp(viewname, "_default")) { 3811 sep = ""; 3812 viewname = ""; 3813 } 3814 3815 dbtype[1] = type; 3816 if (server != NULL) { 3817 dbtype[2] = server; 3818 } 3819 if (contact != NULL) { 3820 dbtype[3] = contact; 3821 } 3822 3823 if (pzone != NULL) { 3824 result = check_dbtype(pzone, dbtypec, dbtype, view->mctx); 3825 if (result != ISC_R_SUCCESS) { 3826 pzone = NULL; 3827 } 3828 } 3829 3830 if (pzone == NULL) { 3831 /* 3832 * Create the actual zone. 3833 */ 3834 dns_zone_create(&zone, mctx, 0); 3835 CHECK(dns_zone_setorigin(zone, name)); 3836 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 3837 dns_zone_setclass(zone, view->rdclass); 3838 dns_zone_settype(zone, dns_zone_primary); 3839 dns_zone_setstats(zone, named_g_server->zonestats); 3840 dns_zone_setdbtype(zone, dbtypec, dbtype); 3841 dns_zone_setdialup(zone, dns_dialuptype_no); 3842 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 3843 dns_zone_setnotifytype(zone, dns_notifytype_no); 3844 dns_zone_setautomatic(zone, true); 3845 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 3846 } else { 3847 dns_zone_attach(pzone, &zone); 3848 } 3849 if (view->queryacl != NULL) { 3850 dns_zone_setqueryacl(zone, view->queryacl); 3851 } else { 3852 dns_zone_clearqueryacl(zone); 3853 } 3854 if (view->queryonacl != NULL) { 3855 dns_zone_setqueryonacl(zone, view->queryonacl); 3856 } else { 3857 dns_zone_clearqueryonacl(zone); 3858 } 3859 dns_zone_setview(zone, view); 3860 CHECK(dns_view_addzone(view, zone)); 3861 3862 dns_name_format(name, namebuf, sizeof(namebuf)); 3863 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3864 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 3865 "automatic ipv4only zone%s%s: %s", sep, viewname, 3866 namebuf); 3867 3868 cleanup: 3869 if (zone != NULL) { 3870 dns_zone_detach(&zone); 3871 } 3872 return result; 3873 } 3874 3875 #ifdef HAVE_DNSTAP 3876 static isc_result_t 3877 configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) { 3878 isc_result_t result; 3879 const cfg_obj_t *obj, *obj2; 3880 const cfg_listelt_t *element; 3881 const char *dpath; 3882 const cfg_obj_t *dlist = NULL; 3883 dns_dtmsgtype_t dttypes = 0; 3884 unsigned int i; 3885 struct fstrm_iothr_options *fopt = NULL; 3886 3887 result = named_config_get(maps, "dnstap", &dlist); 3888 if (result != ISC_R_SUCCESS) { 3889 return ISC_R_SUCCESS; 3890 } 3891 3892 for (element = cfg_list_first(dlist); element != NULL; 3893 element = cfg_list_next(element)) 3894 { 3895 const char *str; 3896 dns_dtmsgtype_t dt = 0; 3897 3898 obj = cfg_listelt_value(element); 3899 obj2 = cfg_tuple_get(obj, "type"); 3900 str = cfg_obj_asstring(obj2); 3901 if (strcasecmp(str, "client") == 0) { 3902 dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR; 3903 } else if (strcasecmp(str, "auth") == 0) { 3904 dt |= DNS_DTTYPE_AQ | DNS_DTTYPE_AR; 3905 } else if (strcasecmp(str, "resolver") == 0) { 3906 dt |= DNS_DTTYPE_RQ | DNS_DTTYPE_RR; 3907 } else if (strcasecmp(str, "forwarder") == 0) { 3908 dt |= DNS_DTTYPE_FQ | DNS_DTTYPE_FR; 3909 } else if (strcasecmp(str, "update") == 0) { 3910 dt |= DNS_DTTYPE_UQ | DNS_DTTYPE_UR; 3911 } else if (strcasecmp(str, "all") == 0) { 3912 dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR | DNS_DTTYPE_AQ | 3913 DNS_DTTYPE_AR | DNS_DTTYPE_RQ | DNS_DTTYPE_RR | 3914 DNS_DTTYPE_FQ | DNS_DTTYPE_FR | DNS_DTTYPE_UQ | 3915 DNS_DTTYPE_UR; 3916 } 3917 3918 obj2 = cfg_tuple_get(obj, "mode"); 3919 if (obj2 == NULL || cfg_obj_isvoid(obj2)) { 3920 dttypes |= dt; 3921 continue; 3922 } 3923 3924 str = cfg_obj_asstring(obj2); 3925 if (strcasecmp(str, "query") == 0) { 3926 dt &= ~DNS_DTTYPE_RESPONSE; 3927 } else if (strcasecmp(str, "response") == 0) { 3928 dt &= ~DNS_DTTYPE_QUERY; 3929 } 3930 3931 dttypes |= dt; 3932 } 3933 3934 if (named_g_server->dtenv == NULL && dttypes != 0) { 3935 dns_dtmode_t dmode; 3936 uint64_t max_size = 0; 3937 uint32_t rolls = 0; 3938 isc_log_rollsuffix_t suffix = isc_log_rollsuffix_increment; 3939 3940 obj = NULL; 3941 CHECKM(named_config_get(maps, "dnstap-output", &obj), 3942 "'dnstap-output' must be set if 'dnstap' is set"); 3943 3944 obj2 = cfg_tuple_get(obj, "mode"); 3945 if (obj2 == NULL) { 3946 CHECKM(ISC_R_FAILURE, "dnstap-output mode not found"); 3947 } 3948 if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0) { 3949 dmode = dns_dtmode_file; 3950 } else { 3951 dmode = dns_dtmode_unix; 3952 } 3953 3954 obj2 = cfg_tuple_get(obj, "path"); 3955 if (obj2 == NULL) { 3956 CHECKM(ISC_R_FAILURE, "dnstap-output path not found"); 3957 } 3958 3959 dpath = cfg_obj_asstring(obj2); 3960 3961 obj2 = cfg_tuple_get(obj, "size"); 3962 if (obj2 != NULL && cfg_obj_isuint64(obj2)) { 3963 max_size = cfg_obj_asuint64(obj2); 3964 if (max_size > SIZE_MAX) { 3965 cfg_obj_log(obj2, named_g_lctx, ISC_LOG_WARNING, 3966 "'dnstap-output size " 3967 "%" PRIu64 "' " 3968 "is too large for this " 3969 "system; reducing to %lu", 3970 max_size, (unsigned long)SIZE_MAX); 3971 max_size = SIZE_MAX; 3972 } 3973 } 3974 3975 obj2 = cfg_tuple_get(obj, "versions"); 3976 if (obj2 != NULL && cfg_obj_isuint32(obj2)) { 3977 rolls = cfg_obj_asuint32(obj2); 3978 } else { 3979 rolls = ISC_LOG_ROLLINFINITE; 3980 } 3981 3982 obj2 = cfg_tuple_get(obj, "suffix"); 3983 if (obj2 != NULL && cfg_obj_isstring(obj2) && 3984 strcasecmp(cfg_obj_asstring(obj2), "timestamp") == 0) 3985 { 3986 suffix = isc_log_rollsuffix_timestamp; 3987 } 3988 3989 fopt = fstrm_iothr_options_init(); 3990 /* 3991 * Both network threads and worker threads may log dnstap data. 3992 */ 3993 fstrm_iothr_options_set_num_input_queues(fopt, 3994 2 * named_g_cpus); 3995 fstrm_iothr_options_set_queue_model( 3996 fopt, FSTRM_IOTHR_QUEUE_MODEL_MPSC); 3997 3998 obj = NULL; 3999 result = named_config_get(maps, "fstrm-set-buffer-hint", &obj); 4000 if (result == ISC_R_SUCCESS) { 4001 i = cfg_obj_asuint32(obj); 4002 fstrm_iothr_options_set_buffer_hint(fopt, i); 4003 } 4004 4005 obj = NULL; 4006 result = named_config_get(maps, "fstrm-set-flush-timeout", 4007 &obj); 4008 if (result == ISC_R_SUCCESS) { 4009 i = cfg_obj_asuint32(obj); 4010 fstrm_iothr_options_set_flush_timeout(fopt, i); 4011 } 4012 4013 obj = NULL; 4014 result = named_config_get(maps, "fstrm-set-input-queue-size", 4015 &obj); 4016 if (result == ISC_R_SUCCESS) { 4017 i = cfg_obj_asuint32(obj); 4018 fstrm_iothr_options_set_input_queue_size(fopt, i); 4019 } 4020 4021 obj = NULL; 4022 result = named_config_get( 4023 maps, "fstrm-set-output-notify-threshold", &obj); 4024 if (result == ISC_R_SUCCESS) { 4025 i = cfg_obj_asuint32(obj); 4026 fstrm_iothr_options_set_queue_notify_threshold(fopt, i); 4027 } 4028 4029 obj = NULL; 4030 result = named_config_get(maps, "fstrm-set-output-queue-model", 4031 &obj); 4032 if (result == ISC_R_SUCCESS) { 4033 if (strcasecmp(cfg_obj_asstring(obj), "spsc") == 0) { 4034 i = FSTRM_IOTHR_QUEUE_MODEL_SPSC; 4035 } else { 4036 i = FSTRM_IOTHR_QUEUE_MODEL_MPSC; 4037 } 4038 fstrm_iothr_options_set_queue_model(fopt, i); 4039 } 4040 4041 obj = NULL; 4042 result = named_config_get(maps, "fstrm-set-output-queue-size", 4043 &obj); 4044 if (result == ISC_R_SUCCESS) { 4045 i = cfg_obj_asuint32(obj); 4046 fstrm_iothr_options_set_output_queue_size(fopt, i); 4047 } 4048 4049 obj = NULL; 4050 result = named_config_get(maps, "fstrm-set-reopen-interval", 4051 &obj); 4052 if (result == ISC_R_SUCCESS) { 4053 i = cfg_obj_asduration(obj); 4054 fstrm_iothr_options_set_reopen_interval(fopt, i); 4055 } 4056 4057 CHECKM(dns_dt_create(named_g_mctx, dmode, dpath, &fopt, 4058 named_g_mainloop, &named_g_server->dtenv), 4059 "unable to create dnstap environment"); 4060 4061 CHECKM(dns_dt_setupfile(named_g_server->dtenv, max_size, rolls, 4062 suffix), 4063 "unable to set up dnstap logfile"); 4064 } 4065 4066 if (named_g_server->dtenv == NULL) { 4067 return ISC_R_SUCCESS; 4068 } 4069 4070 obj = NULL; 4071 result = named_config_get(maps, "dnstap-version", &obj); 4072 if (result != ISC_R_SUCCESS) { 4073 /* not specified; use the product and version */ 4074 dns_dt_setversion(named_g_server->dtenv, PACKAGE_STRING); 4075 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 4076 /* Quoted string */ 4077 dns_dt_setversion(named_g_server->dtenv, cfg_obj_asstring(obj)); 4078 } 4079 4080 obj = NULL; 4081 result = named_config_get(maps, "dnstap-identity", &obj); 4082 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 4083 /* "hostname" is interpreted as boolean true */ 4084 char buf[256]; 4085 if (gethostname(buf, sizeof(buf)) == 0) { 4086 dns_dt_setidentity(named_g_server->dtenv, buf); 4087 } 4088 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 4089 /* Quoted string */ 4090 dns_dt_setidentity(named_g_server->dtenv, 4091 cfg_obj_asstring(obj)); 4092 } 4093 4094 dns_dtenv_attach(named_g_server->dtenv, &view->dtenv); 4095 view->dttypes = dttypes; 4096 4097 result = ISC_R_SUCCESS; 4098 4099 cleanup: 4100 if (fopt != NULL) { 4101 fstrm_iothr_options_destroy(&fopt); 4102 } 4103 4104 return result; 4105 } 4106 #endif /* HAVE_DNSTAP */ 4107 4108 static isc_result_t 4109 create_mapped_acl(void) { 4110 isc_result_t result; 4111 dns_acl_t *acl = NULL; 4112 struct in6_addr in6 = IN6ADDR_V4MAPPED_INIT; 4113 isc_netaddr_t addr; 4114 4115 isc_netaddr_fromin6(&addr, &in6); 4116 4117 dns_acl_create(named_g_mctx, 1, &acl); 4118 4119 result = dns_iptable_addprefix(acl->iptable, &addr, 96, true); 4120 if (result == ISC_R_SUCCESS) { 4121 dns_acl_attach(acl, &named_g_mapped); 4122 } 4123 dns_acl_detach(&acl); 4124 return result; 4125 } 4126 4127 /*% 4128 * A callback for the cfg_pluginlist_foreach() call in configure_view() below. 4129 * If registering any plugin fails, registering subsequent ones is not 4130 * attempted. 4131 */ 4132 static isc_result_t 4133 register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj, 4134 const char *plugin_path, const char *parameters, 4135 void *callback_data) { 4136 dns_view_t *view = callback_data; 4137 char full_path[PATH_MAX]; 4138 isc_result_t result; 4139 4140 result = ns_plugin_expandpath(plugin_path, full_path, 4141 sizeof(full_path)); 4142 if (result != ISC_R_SUCCESS) { 4143 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4144 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4145 "%s: plugin configuration failed: " 4146 "unable to get full plugin path: %s", 4147 plugin_path, isc_result_totext(result)); 4148 return result; 4149 } 4150 4151 result = ns_plugin_register(full_path, parameters, config, 4152 cfg_obj_file(obj), cfg_obj_line(obj), 4153 named_g_mctx, named_g_lctx, 4154 named_g_aclconfctx, view); 4155 if (result != ISC_R_SUCCESS) { 4156 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4157 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4158 "%s: plugin configuration failed: %s", full_path, 4159 isc_result_totext(result)); 4160 } 4161 4162 return result; 4163 } 4164 4165 static const char *const response_synonyms[] = { "response", NULL }; 4166 4167 /* 4168 * Configure 'view' according to 'vconfig', taking defaults from 4169 * 'config' where values are missing in 'vconfig'. 4170 * 4171 * When configuring the default view, 'vconfig' will be NULL and the 4172 * global defaults in 'config' used exclusively. 4173 */ 4174 static isc_result_t 4175 configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, 4176 cfg_obj_t *vconfig, named_cachelist_t *cachelist, 4177 named_cachelist_t *oldcachelist, dns_kasplist_t *kasplist, 4178 dns_keystorelist_t *keystores, const cfg_obj_t *bindkeys, 4179 isc_mem_t *mctx, cfg_aclconfctx_t *actx, bool need_hints, 4180 bool first_time) { 4181 const cfg_obj_t *maps[4] = { 0 }; 4182 const cfg_obj_t *cfgmaps[3] = { 0 }; 4183 const cfg_obj_t *options = NULL; 4184 const cfg_obj_t *voptions = NULL; 4185 const cfg_obj_t *forwardtype; 4186 const cfg_obj_t *forwarders; 4187 const cfg_obj_t *alternates; 4188 const cfg_obj_t *zonelist; 4189 const cfg_obj_t *dlzlist; 4190 const cfg_obj_t *dlz; 4191 const cfg_obj_t *prefetch_trigger; 4192 const cfg_obj_t *prefetch_eligible; 4193 unsigned int dlzargc; 4194 char **dlzargv; 4195 const cfg_obj_t *dyndb_list, *plugin_list; 4196 const cfg_obj_t *disabled; 4197 const cfg_obj_t *obj, *obj2; 4198 const cfg_listelt_t *element = NULL; 4199 const cfg_listelt_t *zone_element_latest = NULL; 4200 in_port_t port; 4201 dns_cache_t *cache = NULL; 4202 isc_result_t result; 4203 size_t max_cache_size; 4204 uint32_t max_cache_size_percent = 0; 4205 size_t max_adb_size; 4206 uint32_t lame_ttl, fail_ttl; 4207 uint32_t max_stale_ttl = 0; 4208 uint32_t stale_refresh_time = 0; 4209 dns_tsigkeyring_t *ring = NULL; 4210 dns_transport_list_t *transports = NULL; 4211 dns_view_t *pview = NULL; /* Production view */ 4212 dns_dispatch_t *dispatch4 = NULL; 4213 dns_dispatch_t *dispatch6 = NULL; 4214 bool rpz_configured = false; 4215 bool catz_configured = false; 4216 bool shared_cache = false; 4217 int i = 0, j = 0; 4218 const char *str = NULL; 4219 const char *cachename = NULL; 4220 dns_order_t *order = NULL; 4221 uint32_t udpsize; 4222 uint32_t maxbits; 4223 unsigned int resopts = 0; 4224 dns_zone_t *zone = NULL; 4225 uint32_t clients_per_query, max_clients_per_query; 4226 bool empty_zones_enable; 4227 const cfg_obj_t *disablelist = NULL; 4228 isc_stats_t *resstats = NULL; 4229 dns_stats_t *resquerystats = NULL; 4230 bool auto_root = false; 4231 named_cache_t *nsc = NULL; 4232 bool zero_no_soattl; 4233 dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; 4234 unsigned int query_timeout; 4235 bool old_rpz_ok = false; 4236 dns_dyndbctx_t *dctx = NULL; 4237 dns_ntatable_t *ntatable = NULL; 4238 const char *qminmode = NULL; 4239 dns_adb_t *adb = NULL; 4240 bool oldcache = false; 4241 uint32_t padding; 4242 4243 REQUIRE(DNS_VIEW_VALID(view)); 4244 4245 if (config != NULL) { 4246 (void)cfg_map_get(config, "options", &options); 4247 } 4248 4249 /* 4250 * maps: view options, options, defaults 4251 * cfgmaps: view options, top-level config 4252 */ 4253 if (vconfig != NULL) { 4254 voptions = cfg_tuple_get(vconfig, "options"); 4255 maps[i++] = voptions; 4256 cfgmaps[j++] = voptions; 4257 } 4258 if (options != NULL) { 4259 maps[i++] = options; 4260 } 4261 maps[i++] = named_g_defaults; 4262 4263 if (config != NULL) { 4264 cfgmaps[j++] = config; 4265 } 4266 4267 /* 4268 * Set the view's port number for outgoing queries. 4269 */ 4270 CHECKM(named_config_getport(config, "port", &port), "port"); 4271 dns_view_setdstport(view, port); 4272 4273 /* 4274 * Make the list of response policy zone names for a view that 4275 * is used for real lookups and so cares about hints. 4276 */ 4277 obj = NULL; 4278 if (view->rdclass == dns_rdataclass_in && need_hints && 4279 named_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) 4280 { 4281 CHECK(configure_rpz(view, NULL, maps, obj, &old_rpz_ok, 4282 first_time)); 4283 rpz_configured = true; 4284 } 4285 4286 obj = NULL; 4287 if (view->rdclass != dns_rdataclass_in && need_hints && 4288 named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) 4289 { 4290 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4291 "'catalog-zones' option is only supported " 4292 "for views with class IN"); 4293 } 4294 4295 obj = NULL; 4296 if (view->rdclass == dns_rdataclass_in && need_hints && 4297 named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) 4298 { 4299 CHECK(configure_catz(view, NULL, config, obj)); 4300 catz_configured = true; 4301 } 4302 4303 /* 4304 * Configure the zones. 4305 */ 4306 zonelist = NULL; 4307 if (voptions != NULL) { 4308 (void)cfg_map_get(voptions, "zone", &zonelist); 4309 } else { 4310 (void)cfg_map_get(config, "zone", &zonelist); 4311 } 4312 4313 /* 4314 * Load zone configuration 4315 */ 4316 for (element = cfg_list_first(zonelist); element != NULL; 4317 element = cfg_list_next(element)) 4318 { 4319 const cfg_obj_t *zconfig = cfg_listelt_value(element); 4320 CHECK(configure_zone(config, zconfig, vconfig, view, viewlist, 4321 kasplist, keystores, actx, false, 4322 old_rpz_ok, false, false)); 4323 zone_element_latest = element; 4324 } 4325 4326 /* 4327 * Check that a primary or secondary zone was found for each 4328 * zone named in the response policy statement, unless we are 4329 * using RPZ service interface. 4330 */ 4331 if (view->rpzs != NULL && !view->rpzs->p.dnsrps_enabled) { 4332 dns_rpz_num_t n; 4333 4334 for (n = 0; n < view->rpzs->p.num_zones; ++n) { 4335 if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) { 4336 char namebuf[DNS_NAME_FORMATSIZE]; 4337 4338 dns_name_format(&view->rpzs->zones[n]->origin, 4339 namebuf, sizeof(namebuf)); 4340 isc_log_write(named_g_lctx, 4341 NAMED_LOGCATEGORY_GENERAL, 4342 NAMED_LOGMODULE_SERVER, 4343 DNS_RPZ_ERROR_LEVEL, 4344 "rpz '%s' is not a primary or a " 4345 "secondary zone", 4346 namebuf); 4347 result = ISC_R_NOTFOUND; 4348 goto cleanup; 4349 } 4350 } 4351 } 4352 4353 /* 4354 * If we're allowing added zones, then load zone configuration 4355 * from the newzone file for zones that were added during previous 4356 * runs. 4357 */ 4358 CHECK(configure_newzones(view, config, vconfig, actx)); 4359 4360 /* 4361 * Create Dynamically Loadable Zone driver. 4362 */ 4363 dlzlist = NULL; 4364 if (voptions != NULL) { 4365 (void)cfg_map_get(voptions, "dlz", &dlzlist); 4366 } else { 4367 (void)cfg_map_get(config, "dlz", &dlzlist); 4368 } 4369 4370 for (element = cfg_list_first(dlzlist); element != NULL; 4371 element = cfg_list_next(element)) 4372 { 4373 dlz = cfg_listelt_value(element); 4374 4375 obj = NULL; 4376 (void)cfg_map_get(dlz, "database", &obj); 4377 if (obj != NULL) { 4378 dns_dlzdb_t *dlzdb = NULL; 4379 const cfg_obj_t *name, *search = NULL; 4380 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 4381 4382 if (s == NULL) { 4383 result = ISC_R_NOMEMORY; 4384 goto cleanup; 4385 } 4386 4387 result = isc_commandline_strtoargv(mctx, s, &dlzargc, 4388 &dlzargv, 0); 4389 if (result != ISC_R_SUCCESS) { 4390 isc_mem_free(mctx, s); 4391 goto cleanup; 4392 } 4393 4394 name = cfg_map_getname(dlz); 4395 result = dns_dlzcreate(mctx, cfg_obj_asstring(name), 4396 dlzargv[0], dlzargc, dlzargv, 4397 &dlzdb); 4398 isc_mem_free(mctx, s); 4399 isc_mem_cput(mctx, dlzargv, dlzargc, sizeof(*dlzargv)); 4400 if (result != ISC_R_SUCCESS) { 4401 goto cleanup; 4402 } 4403 4404 /* 4405 * If the DLZ backend supports configuration, 4406 * and is searchable, then call its configure 4407 * method now. If not searchable, we'll take 4408 * care of it when we process the zone statement. 4409 */ 4410 (void)cfg_map_get(dlz, "search", &search); 4411 if (search == NULL || cfg_obj_asboolean(search)) { 4412 dlzdb->search = true; 4413 result = dns_dlzconfigure( 4414 view, dlzdb, dlzconfigure_callback); 4415 if (result != ISC_R_SUCCESS) { 4416 goto cleanup; 4417 } 4418 ISC_LIST_APPEND(view->dlz_searched, dlzdb, 4419 link); 4420 } else { 4421 dlzdb->search = false; 4422 ISC_LIST_APPEND(view->dlz_unsearched, dlzdb, 4423 link); 4424 } 4425 } 4426 } 4427 4428 /* 4429 * Obtain configuration parameters that affect the decision of whether 4430 * we can reuse/share an existing cache. 4431 */ 4432 obj = NULL; 4433 result = named_config_get(maps, "recursion", &obj); 4434 INSIST(result == ISC_R_SUCCESS); 4435 view->recursion = (view->rdclass == dns_rdataclass_in && 4436 cfg_obj_asboolean(obj)); 4437 4438 if (named_g_maxcachesize != 0) { 4439 /* 4440 * If "-T maxcachesize=..." is in effect, it overrides any 4441 * other "max-cache-size" setting found in configuration, 4442 * either implicit or explicit. For simplicity, the value 4443 * passed to that command line option is always treated as 4444 * the number of bytes to set "max-cache-size" to. 4445 */ 4446 max_cache_size = named_g_maxcachesize; 4447 } else { 4448 obj = NULL; 4449 result = named_config_get(maps, "max-cache-size", &obj); 4450 INSIST(result == ISC_R_SUCCESS); 4451 if (cfg_obj_isstring(obj) && 4452 strcasecmp(cfg_obj_asstring(obj), "default") == 0) 4453 { 4454 /* 4455 * The default for a view with recursion 4456 * is 90% of memory. With no recursion, 4457 * it's the minimum cache size allowed by 4458 * dns_cache_setcachesize(). 4459 */ 4460 if (view->recursion) { 4461 max_cache_size = SIZE_AS_PERCENT; 4462 max_cache_size_percent = 90; 4463 } else { 4464 max_cache_size = 1; 4465 } 4466 } else if (cfg_obj_isstring(obj)) { 4467 str = cfg_obj_asstring(obj); 4468 INSIST(strcasecmp(str, "unlimited") == 0); 4469 max_cache_size = 0; 4470 } else if (cfg_obj_ispercentage(obj)) { 4471 max_cache_size = SIZE_AS_PERCENT; 4472 max_cache_size_percent = cfg_obj_aspercentage(obj); 4473 } else if (cfg_obj_isuint64(obj)) { 4474 uint64_t value = cfg_obj_asuint64(obj); 4475 if (value > SIZE_MAX) { 4476 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4477 "'max-cache-size " 4478 "%" PRIu64 "' " 4479 "is too large for this " 4480 "system; reducing to %lu", 4481 value, (unsigned long)SIZE_MAX); 4482 value = SIZE_MAX; 4483 } 4484 max_cache_size = (size_t)value; 4485 } else { 4486 UNREACHABLE(); 4487 } 4488 } 4489 4490 if (max_cache_size == SIZE_AS_PERCENT) { 4491 uint64_t totalphys = isc_meminfo_totalphys(); 4492 4493 max_cache_size = 4494 (size_t)(totalphys * max_cache_size_percent / 100); 4495 if (totalphys == 0) { 4496 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4497 "Unable to determine amount of physical " 4498 "memory, setting 'max-cache-size' to " 4499 "unlimited"); 4500 } else { 4501 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 4502 "'max-cache-size %d%%' " 4503 "- setting to %" PRIu64 "MB " 4504 "(out of %" PRIu64 "MB)", 4505 max_cache_size_percent, 4506 (uint64_t)(max_cache_size / (1024 * 1024)), 4507 totalphys / (1024 * 1024)); 4508 } 4509 } 4510 4511 /* Check-names. */ 4512 obj = NULL; 4513 result = named_checknames_get(maps, response_synonyms, &obj); 4514 INSIST(result == ISC_R_SUCCESS); 4515 4516 str = cfg_obj_asstring(obj); 4517 if (strcasecmp(str, "fail") == 0) { 4518 resopts |= DNS_RESOLVER_CHECKNAMES | 4519 DNS_RESOLVER_CHECKNAMESFAIL; 4520 view->checknames = true; 4521 } else if (strcasecmp(str, "warn") == 0) { 4522 resopts |= DNS_RESOLVER_CHECKNAMES; 4523 view->checknames = false; 4524 } else if (strcasecmp(str, "ignore") == 0) { 4525 view->checknames = false; 4526 } else { 4527 UNREACHABLE(); 4528 } 4529 4530 obj = NULL; 4531 result = named_config_get(maps, "zero-no-soa-ttl-cache", &obj); 4532 INSIST(result == ISC_R_SUCCESS); 4533 zero_no_soattl = cfg_obj_asboolean(obj); 4534 4535 obj = NULL; 4536 result = named_config_get(maps, "resolver-use-dns64", &obj); 4537 INSIST(result == ISC_R_SUCCESS); 4538 view->usedns64 = cfg_obj_asboolean(obj); 4539 4540 obj = NULL; 4541 result = named_config_get(maps, "dns64", &obj); 4542 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && 4543 strcmp(view->name, "_meta")) 4544 { 4545 isc_netaddr_t na, suffix, *sp; 4546 unsigned int prefixlen; 4547 const char *server, *contact; 4548 const cfg_obj_t *myobj; 4549 4550 myobj = NULL; 4551 result = named_config_get(maps, "dns64-server", &myobj); 4552 if (result == ISC_R_SUCCESS) { 4553 server = cfg_obj_asstring(myobj); 4554 } else { 4555 server = NULL; 4556 } 4557 4558 myobj = NULL; 4559 result = named_config_get(maps, "dns64-contact", &myobj); 4560 if (result == ISC_R_SUCCESS) { 4561 contact = cfg_obj_asstring(myobj); 4562 } else { 4563 contact = NULL; 4564 } 4565 4566 for (element = cfg_list_first(obj); element != NULL; 4567 element = cfg_list_next(element)) 4568 { 4569 const cfg_obj_t *map = cfg_listelt_value(element); 4570 dns_dns64_t *dns64 = NULL; 4571 unsigned int dns64options = 0; 4572 4573 cfg_obj_asnetprefix(cfg_map_getname(map), &na, 4574 &prefixlen); 4575 4576 obj = NULL; 4577 (void)cfg_map_get(map, "suffix", &obj); 4578 if (obj != NULL) { 4579 sp = &suffix; 4580 isc_netaddr_fromsockaddr( 4581 sp, cfg_obj_assockaddr(obj)); 4582 } else { 4583 sp = NULL; 4584 } 4585 4586 clients = mapped = excluded = NULL; 4587 obj = NULL; 4588 (void)cfg_map_get(map, "clients", &obj); 4589 if (obj != NULL) { 4590 result = cfg_acl_fromconfig(obj, config, 4591 named_g_lctx, actx, 4592 mctx, 0, &clients); 4593 if (result != ISC_R_SUCCESS) { 4594 goto cleanup; 4595 } 4596 } 4597 obj = NULL; 4598 (void)cfg_map_get(map, "mapped", &obj); 4599 if (obj != NULL) { 4600 result = cfg_acl_fromconfig(obj, config, 4601 named_g_lctx, actx, 4602 mctx, 0, &mapped); 4603 if (result != ISC_R_SUCCESS) { 4604 goto cleanup; 4605 } 4606 } 4607 obj = NULL; 4608 (void)cfg_map_get(map, "exclude", &obj); 4609 if (obj != NULL) { 4610 result = cfg_acl_fromconfig(obj, config, 4611 named_g_lctx, actx, 4612 mctx, 0, &excluded); 4613 if (result != ISC_R_SUCCESS) { 4614 goto cleanup; 4615 } 4616 } else { 4617 if (named_g_mapped == NULL) { 4618 result = create_mapped_acl(); 4619 if (result != ISC_R_SUCCESS) { 4620 goto cleanup; 4621 } 4622 } 4623 dns_acl_attach(named_g_mapped, &excluded); 4624 } 4625 4626 obj = NULL; 4627 (void)cfg_map_get(map, "recursive-only", &obj); 4628 if (obj != NULL && cfg_obj_asboolean(obj)) { 4629 dns64options |= DNS_DNS64_RECURSIVE_ONLY; 4630 } 4631 4632 obj = NULL; 4633 (void)cfg_map_get(map, "break-dnssec", &obj); 4634 if (obj != NULL && cfg_obj_asboolean(obj)) { 4635 dns64options |= DNS_DNS64_BREAK_DNSSEC; 4636 } 4637 4638 result = dns_dns64_create(mctx, &na, prefixlen, sp, 4639 clients, mapped, excluded, 4640 dns64options, &dns64); 4641 if (result != ISC_R_SUCCESS) { 4642 goto cleanup; 4643 } 4644 dns_dns64_append(&view->dns64, dns64); 4645 view->dns64cnt++; 4646 result = dns64_reverse(view, mctx, &na, prefixlen, 4647 server, contact); 4648 if (result != ISC_R_SUCCESS) { 4649 goto cleanup; 4650 } 4651 if (clients != NULL) { 4652 dns_acl_detach(&clients); 4653 } 4654 if (mapped != NULL) { 4655 dns_acl_detach(&mapped); 4656 } 4657 if (excluded != NULL) { 4658 dns_acl_detach(&excluded); 4659 } 4660 } 4661 } 4662 4663 obj = NULL; 4664 result = named_config_get(maps, "dnssec-accept-expired", &obj); 4665 INSIST(result == ISC_R_SUCCESS); 4666 view->acceptexpired = cfg_obj_asboolean(obj); 4667 4668 obj = NULL; 4669 result = named_config_get(maps, "dnssec-validation", &obj); 4670 INSIST(result == ISC_R_SUCCESS); 4671 if (cfg_obj_isboolean(obj)) { 4672 view->enablevalidation = cfg_obj_asboolean(obj); 4673 } else { 4674 /* 4675 * If dnssec-validation is set but not boolean, 4676 * then it must be "auto" 4677 */ 4678 view->enablevalidation = true; 4679 auto_root = true; 4680 } 4681 4682 obj = NULL; 4683 result = named_config_get(maps, "max-cache-ttl", &obj); 4684 INSIST(result == ISC_R_SUCCESS); 4685 view->maxcachettl = cfg_obj_asduration(obj); 4686 4687 obj = NULL; 4688 result = named_config_get(maps, "max-ncache-ttl", &obj); 4689 INSIST(result == ISC_R_SUCCESS); 4690 view->maxncachettl = cfg_obj_asduration(obj); 4691 4692 obj = NULL; 4693 result = named_config_get(maps, "min-cache-ttl", &obj); 4694 INSIST(result == ISC_R_SUCCESS); 4695 view->mincachettl = cfg_obj_asduration(obj); 4696 4697 obj = NULL; 4698 result = named_config_get(maps, "min-ncache-ttl", &obj); 4699 INSIST(result == ISC_R_SUCCESS); 4700 view->minncachettl = cfg_obj_asduration(obj); 4701 4702 obj = NULL; 4703 result = named_config_get(maps, "synth-from-dnssec", &obj); 4704 INSIST(result == ISC_R_SUCCESS); 4705 view->synthfromdnssec = cfg_obj_asboolean(obj); 4706 4707 obj = NULL; 4708 result = named_config_get(maps, "stale-cache-enable", &obj); 4709 INSIST(result == ISC_R_SUCCESS); 4710 if (cfg_obj_asboolean(obj)) { 4711 obj = NULL; 4712 result = named_config_get(maps, "max-stale-ttl", &obj); 4713 INSIST(result == ISC_R_SUCCESS); 4714 max_stale_ttl = ISC_MAX(cfg_obj_asduration(obj), 1); 4715 } 4716 /* 4717 * If 'stale-cache-enable' is false, max_stale_ttl is set to 0, 4718 * meaning keeping stale RRsets in cache is disabled. 4719 */ 4720 4721 obj = NULL; 4722 result = named_config_get(maps, "stale-answer-enable", &obj); 4723 INSIST(result == ISC_R_SUCCESS); 4724 view->staleanswersenable = cfg_obj_asboolean(obj); 4725 4726 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 4727 view->rdclass, &pview); 4728 if (result == ISC_R_SUCCESS) { 4729 view->staleanswersok = pview->staleanswersok; 4730 dns_view_detach(&pview); 4731 } else { 4732 view->staleanswersok = dns_stale_answer_conf; 4733 } 4734 4735 obj = NULL; 4736 result = named_config_get(maps, "stale-answer-client-timeout", &obj); 4737 INSIST(result == ISC_R_SUCCESS); 4738 if (cfg_obj_isstring(obj)) { 4739 /* 4740 * The only string values available for this option 4741 * are "disabled" and "off". 4742 * We use (uint32_t) -1 to represent disabled since 4743 * a value of zero means that stale data can be used 4744 * to promptly answer the query, while an attempt to 4745 * refresh the RRset will still be made in background. 4746 */ 4747 view->staleanswerclienttimeout = (uint32_t)-1; 4748 } else { 4749 view->staleanswerclienttimeout = cfg_obj_asuint32(obj); 4750 4751 /* 4752 * BIND 9 no longer supports non-zero values of 4753 * stale-answer-client-timeout. 4754 */ 4755 if (view->staleanswerclienttimeout != 0) { 4756 view->staleanswerclienttimeout = 0; 4757 isc_log_write( 4758 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4759 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 4760 "BIND 9 no longer supports non-zero values of " 4761 "stale-answer-client-timeout, adjusted to 0"); 4762 } 4763 } 4764 4765 obj = NULL; 4766 result = named_config_get(maps, "stale-refresh-time", &obj); 4767 INSIST(result == ISC_R_SUCCESS); 4768 stale_refresh_time = cfg_obj_asduration(obj); 4769 4770 /* 4771 * Configure the view's cache. 4772 * 4773 * First, check to see if there are any attach-cache options. If yes, 4774 * attempt to lookup an existing cache at attach it to the view. If 4775 * there is not one, then try to reuse an existing cache if possible; 4776 * otherwise create a new cache. 4777 * 4778 * Note that the ADB is not preserved or shared in either case. 4779 * 4780 * When a matching view is found, the associated statistics are also 4781 * retrieved and reused. 4782 * 4783 * XXX Determining when it is safe to reuse or share a cache is tricky. 4784 * When the view's configuration changes, the cached data may become 4785 * invalid because it reflects our old view of the world. We check 4786 * some of the configuration parameters that could invalidate the cache 4787 * or otherwise make it unshareable, but there are other configuration 4788 * options that should be checked. For example, if a view uses a 4789 * forwarder, changes in the forwarder configuration may invalidate 4790 * the cache. At the moment, it's the administrator's responsibility to 4791 * ensure these configuration options don't invalidate reusing/sharing. 4792 */ 4793 obj = NULL; 4794 result = named_config_get(maps, "attach-cache", &obj); 4795 if (result == ISC_R_SUCCESS) { 4796 cachename = cfg_obj_asstring(obj); 4797 } else { 4798 cachename = view->name; 4799 } 4800 4801 nsc = cachelist_find(cachelist, cachename, view->rdclass); 4802 if (result == ISC_R_SUCCESS && nsc == NULL) { 4803 /* 4804 * If we're using 'attach-cache' but didn't find the 4805 * specified cache in the cache list already, check 4806 * the old list. 4807 */ 4808 nsc = cachelist_find(oldcachelist, cachename, view->rdclass); 4809 oldcache = true; 4810 } 4811 if (nsc != NULL) { 4812 if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, 4813 max_cache_size, max_stale_ttl, 4814 stale_refresh_time)) 4815 { 4816 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4817 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 4818 "view %s can't use existing cache %s due " 4819 "to configuration parameter mismatch", 4820 view->name, 4821 dns_cache_getname(nsc->cache)); 4822 nsc = NULL; 4823 } else { 4824 shared_cache = true; 4825 dns_cache_attach(nsc->cache, &cache); 4826 if (oldcache) { 4827 /* 4828 * We need to re-use the cache, but we don't 4829 * want to mutate the old production list. 4830 */ 4831 nsc = NULL; 4832 } 4833 } 4834 } else if (strcmp(cachename, view->name) == 0) { 4835 result = dns_viewlist_find(&named_g_server->viewlist, cachename, 4836 view->rdclass, &pview); 4837 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 4838 goto cleanup; 4839 } 4840 if (pview != NULL) { 4841 if (!cache_reusable(pview, view, zero_no_soattl)) { 4842 isc_log_write(named_g_lctx, 4843 NAMED_LOGCATEGORY_GENERAL, 4844 NAMED_LOGMODULE_SERVER, 4845 ISC_LOG_DEBUG(1), 4846 "cache cannot be reused " 4847 "for view %s due to " 4848 "configuration parameter " 4849 "mismatch", 4850 view->name); 4851 } else { 4852 INSIST(pview->cache != NULL); 4853 isc_log_write(named_g_lctx, 4854 NAMED_LOGCATEGORY_GENERAL, 4855 NAMED_LOGMODULE_SERVER, 4856 ISC_LOG_DEBUG(3), 4857 "reusing existing cache"); 4858 dns_cache_attach(pview->cache, &cache); 4859 } 4860 dns_resolver_getstats(pview->resolver, &resstats); 4861 dns_resolver_getquerystats(pview->resolver, 4862 &resquerystats); 4863 dns_view_detach(&pview); 4864 } 4865 } 4866 4867 if (nsc == NULL) { 4868 /* 4869 * Create a cache with the desired name. This normally 4870 * equals the view name, but may also be a forward 4871 * reference to a view that share the cache with this 4872 * view but is not yet configured. If it is not the 4873 * view name but not a forward reference either, then it 4874 * is simply a named cache that is not shared. 4875 */ 4876 if (cache == NULL) { 4877 CHECK(dns_cache_create(named_g_loopmgr, view->rdclass, 4878 cachename, mctx, &cache)); 4879 } 4880 4881 nsc = isc_mem_get(mctx, sizeof(*nsc)); 4882 *nsc = (named_cache_t){ 4883 .primaryview = view, 4884 .rdclass = view->rdclass, 4885 .link = ISC_LINK_INITIALIZER, 4886 }; 4887 4888 dns_cache_attach(cache, &nsc->cache); 4889 ISC_LIST_APPEND(*cachelist, nsc, link); 4890 } 4891 4892 dns_view_setcache(view, cache, shared_cache); 4893 4894 dns_cache_setcachesize(cache, max_cache_size); 4895 dns_cache_setservestalettl(cache, max_stale_ttl); 4896 dns_cache_setservestalerefresh(cache, stale_refresh_time); 4897 4898 dns_cache_detach(&cache); 4899 4900 obj = NULL; 4901 result = named_config_get(maps, "stale-answer-ttl", &obj); 4902 INSIST(result == ISC_R_SUCCESS); 4903 view->staleanswerttl = ISC_MAX(cfg_obj_asduration(obj), 1); 4904 4905 /* 4906 * Resolver. 4907 */ 4908 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4, 4909 ISC_LIST_PREV(view, link) == NULL)); 4910 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6, 4911 ISC_LIST_PREV(view, link) == NULL)); 4912 if (dispatch4 == NULL && dispatch6 == NULL) { 4913 UNEXPECTED_ERROR("unable to obtain either an IPv4 or" 4914 " an IPv6 dispatch"); 4915 result = ISC_R_UNEXPECTED; 4916 goto cleanup; 4917 } 4918 4919 CHECK(dns_view_createresolver(view, named_g_netmgr, resopts, 4920 named_g_server->tlsctx_client_cache, 4921 dispatch4, dispatch6)); 4922 4923 if (resstats == NULL) { 4924 isc_stats_create(mctx, &resstats, dns_resstatscounter_max); 4925 } 4926 dns_resolver_setstats(view->resolver, resstats); 4927 if (resquerystats == NULL) { 4928 dns_rdatatypestats_create(mctx, &resquerystats); 4929 } 4930 dns_resolver_setquerystats(view->resolver, resquerystats); 4931 4932 /* 4933 * Set the ADB cache size to 1/8th of the max-cache-size or 4934 * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. 4935 */ 4936 max_adb_size = 0; 4937 if (max_cache_size != 0U) { 4938 max_adb_size = max_cache_size / 8; 4939 if (max_adb_size == 0U) { 4940 max_adb_size = 1; /* Force minimum. */ 4941 } 4942 if (view != nsc->primaryview && 4943 max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) 4944 { 4945 max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; 4946 if (!nsc->adbsizeadjusted) { 4947 dns_view_getadb(nsc->primaryview, &adb); 4948 if (adb != NULL) { 4949 dns_adb_setadbsize( 4950 adb, 4951 MAX_ADB_SIZE_FOR_CACHESHARE); 4952 nsc->adbsizeadjusted = true; 4953 dns_adb_detach(&adb); 4954 } 4955 } 4956 } 4957 } 4958 dns_view_getadb(view, &adb); 4959 if (adb != NULL) { 4960 dns_adb_setadbsize(adb, max_adb_size); 4961 dns_adb_detach(&adb); 4962 } 4963 4964 /* 4965 * Set up ADB quotas 4966 */ 4967 { 4968 uint32_t fps, freq; 4969 double low, high, discount; 4970 4971 obj = NULL; 4972 result = named_config_get(maps, "fetches-per-server", &obj); 4973 INSIST(result == ISC_R_SUCCESS); 4974 obj2 = cfg_tuple_get(obj, "fetches"); 4975 fps = cfg_obj_asuint32(obj2); 4976 obj2 = cfg_tuple_get(obj, "response"); 4977 if (!cfg_obj_isvoid(obj2)) { 4978 const char *resp = cfg_obj_asstring(obj2); 4979 isc_result_t r = DNS_R_SERVFAIL; 4980 4981 if (strcasecmp(resp, "drop") == 0) { 4982 r = DNS_R_DROP; 4983 } else if (strcasecmp(resp, "fail") == 0) { 4984 r = DNS_R_SERVFAIL; 4985 } else { 4986 UNREACHABLE(); 4987 } 4988 4989 dns_resolver_setquotaresponse(view->resolver, 4990 dns_quotatype_server, r); 4991 } 4992 4993 obj = NULL; 4994 result = named_config_get(maps, "fetch-quota-params", &obj); 4995 INSIST(result == ISC_R_SUCCESS); 4996 4997 obj2 = cfg_tuple_get(obj, "frequency"); 4998 freq = cfg_obj_asuint32(obj2); 4999 5000 obj2 = cfg_tuple_get(obj, "low"); 5001 low = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 5002 5003 obj2 = cfg_tuple_get(obj, "high"); 5004 high = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 5005 5006 obj2 = cfg_tuple_get(obj, "discount"); 5007 discount = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 5008 5009 dns_view_getadb(view, &adb); 5010 if (adb != NULL) { 5011 dns_adb_setquota(adb, fps, freq, low, high, discount); 5012 dns_adb_detach(&adb); 5013 } 5014 } 5015 5016 /* 5017 * Set resolver's lame-ttl. 5018 */ 5019 obj = NULL; 5020 result = named_config_get(maps, "lame-ttl", &obj); 5021 INSIST(result == ISC_R_SUCCESS); 5022 lame_ttl = cfg_obj_asduration(obj); 5023 if (lame_ttl > 0) { 5024 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 5025 "disabling lame cache despite lame-ttl > 0 as it " 5026 "may cause performance issues"); 5027 } 5028 5029 /* 5030 * Set the resolver's query timeout. 5031 */ 5032 obj = NULL; 5033 result = named_config_get(maps, "resolver-query-timeout", &obj); 5034 INSIST(result == ISC_R_SUCCESS); 5035 query_timeout = cfg_obj_asuint32(obj); 5036 dns_resolver_settimeout(view->resolver, query_timeout); 5037 5038 /* Specify whether to use 0-TTL for negative response for SOA query */ 5039 dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); 5040 5041 /* 5042 * Set the resolver's EDNS UDP size. 5043 */ 5044 obj = NULL; 5045 result = named_config_get(maps, "edns-udp-size", &obj); 5046 INSIST(result == ISC_R_SUCCESS); 5047 udpsize = cfg_obj_asuint32(obj); 5048 if (udpsize < 512) { 5049 udpsize = 512; 5050 } 5051 if (udpsize > 4096) { 5052 udpsize = 4096; 5053 } 5054 dns_view_setudpsize(view, (uint16_t)udpsize); 5055 5056 /* 5057 * Set the maximum UDP response size. 5058 */ 5059 obj = NULL; 5060 result = named_config_get(maps, "max-udp-size", &obj); 5061 INSIST(result == ISC_R_SUCCESS); 5062 udpsize = cfg_obj_asuint32(obj); 5063 if (udpsize < 512) { 5064 udpsize = 512; 5065 } 5066 if (udpsize > 4096) { 5067 udpsize = 4096; 5068 } 5069 view->maxudp = udpsize; 5070 5071 /* 5072 * Set the maximum UDP when a COOKIE is not provided. 5073 */ 5074 obj = NULL; 5075 result = named_config_get(maps, "nocookie-udp-size", &obj); 5076 INSIST(result == ISC_R_SUCCESS); 5077 udpsize = cfg_obj_asuint32(obj); 5078 if (udpsize < 128) { 5079 udpsize = 128; 5080 } 5081 if (udpsize > view->maxudp) { 5082 udpsize = view->maxudp; 5083 } 5084 view->nocookieudp = udpsize; 5085 5086 /* 5087 * Set the maximum rsa exponent bits. 5088 */ 5089 obj = NULL; 5090 result = named_config_get(maps, "max-rsa-exponent-size", &obj); 5091 INSIST(result == ISC_R_SUCCESS); 5092 maxbits = cfg_obj_asuint32(obj); 5093 if (maxbits != 0 && maxbits < 35) { 5094 maxbits = 35; 5095 } 5096 if (maxbits > 4096) { 5097 maxbits = 4096; 5098 } 5099 view->maxbits = maxbits; 5100 5101 /* 5102 * Set supported DNSSEC algorithms. 5103 */ 5104 disabled = NULL; 5105 (void)named_config_get(maps, "disable-algorithms", &disabled); 5106 if (disabled != NULL) { 5107 for (element = cfg_list_first(disabled); element != NULL; 5108 element = cfg_list_next(element)) 5109 { 5110 CHECK(disable_algorithms(cfg_listelt_value(element), 5111 view->resolver)); 5112 } 5113 } 5114 5115 /* 5116 * Set supported DS digest types. 5117 */ 5118 disabled = NULL; 5119 (void)named_config_get(maps, "disable-ds-digests", &disabled); 5120 if (disabled != NULL) { 5121 for (element = cfg_list_first(disabled); element != NULL; 5122 element = cfg_list_next(element)) 5123 { 5124 CHECK(disable_ds_digests(cfg_listelt_value(element), 5125 view->resolver)); 5126 } 5127 } 5128 5129 /* 5130 * A global or view "forwarders" option, if present, 5131 * creates an entry for "." in the forwarding table. 5132 */ 5133 forwardtype = NULL; 5134 forwarders = NULL; 5135 (void)named_config_get(maps, "forward", &forwardtype); 5136 (void)named_config_get(maps, "forwarders", &forwarders); 5137 if (forwarders != NULL) { 5138 CHECK(configure_forward(config, view, dns_rootname, forwarders, 5139 forwardtype)); 5140 } 5141 5142 /* 5143 * Dual Stack Servers. 5144 */ 5145 alternates = NULL; 5146 (void)named_config_get(maps, "dual-stack-servers", &alternates); 5147 if (alternates != NULL) { 5148 CHECK(configure_alternates(config, view, alternates)); 5149 } 5150 5151 /* 5152 * We have default root hints for class IN if we need them. 5153 * Each view gets its own rootdb so a priming response only 5154 * writes into that view's copy. Other classes don't support 5155 * recursion and don't need hints. 5156 */ 5157 if (view->rdclass == dns_rdataclass_in && view->hints == NULL) { 5158 dns_view_sethints(view, named_g_server->in_roothints); 5159 } 5160 5161 /* 5162 * Configure the view's transports (DoT/DoH) 5163 */ 5164 CHECK(named_transports_fromconfig(config, vconfig, view->mctx, 5165 &transports)); 5166 dns_view_settransports(view, transports); 5167 dns_transport_list_detach(&transports); 5168 5169 /* 5170 * Configure SIG(0) check limits when matching a DNS message to a view. 5171 */ 5172 obj = NULL; 5173 result = named_config_get(maps, "sig0key-checks-limit", &obj); 5174 INSIST(result == ISC_R_SUCCESS); 5175 view->sig0key_checks_limit = cfg_obj_asuint32(obj); 5176 5177 obj = NULL; 5178 result = named_config_get(maps, "sig0message-checks-limit", &obj); 5179 INSIST(result == ISC_R_SUCCESS); 5180 view->sig0message_checks_limit = cfg_obj_asuint32(obj); 5181 5182 /* 5183 * Configure the view's TSIG keys. 5184 */ 5185 CHECK(named_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); 5186 if (named_g_server->sessionkey != NULL) { 5187 dns_tsigkey_t *tsigkey = NULL; 5188 result = dns_tsigkey_createfromkey( 5189 named_g_server->session_keyname, 5190 named_g_server->session_keyalg, 5191 named_g_server->sessionkey, false, false, NULL, 0, 0, 5192 mctx, &tsigkey); 5193 if (result == ISC_R_SUCCESS) { 5194 result = dns_tsigkeyring_add(ring, tsigkey); 5195 dns_tsigkey_detach(&tsigkey); 5196 } 5197 CHECK(result); 5198 } 5199 dns_view_setkeyring(view, ring); 5200 dns_tsigkeyring_detach(&ring); 5201 5202 /* 5203 * See if we can re-use a dynamic key ring. 5204 */ 5205 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 5206 view->rdclass, &pview); 5207 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 5208 goto cleanup; 5209 } 5210 if (pview != NULL) { 5211 dns_view_getdynamickeyring(pview, &ring); 5212 if (ring != NULL) { 5213 dns_view_setdynamickeyring(view, ring); 5214 } 5215 dns_tsigkeyring_detach(&ring); 5216 dns_view_detach(&pview); 5217 } else { 5218 dns_view_restorekeyring(view); 5219 } 5220 5221 /* 5222 * Configure the view's peer list. 5223 */ 5224 { 5225 const cfg_obj_t *peers = NULL; 5226 dns_peerlist_t *newpeers = NULL; 5227 5228 (void)named_config_get(cfgmaps, "server", &peers); 5229 CHECK(dns_peerlist_new(mctx, &newpeers)); 5230 for (element = cfg_list_first(peers); element != NULL; 5231 element = cfg_list_next(element)) 5232 { 5233 const cfg_obj_t *cpeer = cfg_listelt_value(element); 5234 dns_peer_t *peer; 5235 5236 CHECK(configure_peer(cpeer, mctx, &peer)); 5237 dns_peerlist_addpeer(newpeers, peer); 5238 dns_peer_detach(&peer); 5239 } 5240 dns_peerlist_detach(&view->peers); 5241 view->peers = newpeers; /* Transfer ownership. */ 5242 } 5243 5244 /* 5245 * Configure the views rrset-order. 5246 */ 5247 { 5248 const cfg_obj_t *rrsetorder = NULL; 5249 5250 (void)named_config_get(maps, "rrset-order", &rrsetorder); 5251 CHECK(dns_order_create(mctx, &order)); 5252 for (element = cfg_list_first(rrsetorder); element != NULL; 5253 element = cfg_list_next(element)) 5254 { 5255 const cfg_obj_t *ent = cfg_listelt_value(element); 5256 5257 CHECK(configure_order(order, ent)); 5258 } 5259 if (view->order != NULL) { 5260 dns_order_detach(&view->order); 5261 } 5262 dns_order_attach(order, &view->order); 5263 dns_order_detach(&order); 5264 } 5265 /* 5266 * Copy the aclenv object. 5267 */ 5268 dns_aclenv_copy(view->aclenv, ns_interfacemgr_getaclenv( 5269 named_g_server->interfacemgr)); 5270 5271 /* 5272 * Configure the "match-clients" and "match-destinations" ACL. 5273 * (These are only meaningful at the view level, but 'config' 5274 * must be passed so that named ACLs defined at the global level 5275 * can be retrieved.) 5276 */ 5277 CHECK(configure_view_acl(vconfig, config, NULL, "match-clients", NULL, 5278 actx, named_g_mctx, &view->matchclients)); 5279 CHECK(configure_view_acl(vconfig, config, NULL, "match-destinations", 5280 NULL, actx, named_g_mctx, 5281 &view->matchdestinations)); 5282 5283 /* 5284 * Configure the "match-recursive-only" option. 5285 */ 5286 obj = NULL; 5287 (void)named_config_get(maps, "match-recursive-only", &obj); 5288 if (obj != NULL && cfg_obj_asboolean(obj)) { 5289 view->matchrecursiveonly = true; 5290 } else { 5291 view->matchrecursiveonly = false; 5292 } 5293 5294 /* 5295 * Configure other configurable data. 5296 */ 5297 obj = NULL; 5298 result = named_config_get(maps, "qname-minimization", &obj); 5299 INSIST(result == ISC_R_SUCCESS); 5300 qminmode = cfg_obj_asstring(obj); 5301 INSIST(qminmode != NULL); 5302 if (!strcmp(qminmode, "strict")) { 5303 view->qminimization = true; 5304 view->qmin_strict = true; 5305 } else if (!strcmp(qminmode, "relaxed")) { 5306 view->qminimization = true; 5307 view->qmin_strict = false; 5308 } else { /* "disabled" or "off" */ 5309 view->qminimization = false; 5310 view->qmin_strict = false; 5311 } 5312 5313 obj = NULL; 5314 result = named_config_get(maps, "auth-nxdomain", &obj); 5315 INSIST(result == ISC_R_SUCCESS); 5316 view->auth_nxdomain = cfg_obj_asboolean(obj); 5317 5318 obj = NULL; 5319 result = named_config_get(maps, "minimal-any", &obj); 5320 INSIST(result == ISC_R_SUCCESS); 5321 view->minimal_any = cfg_obj_asboolean(obj); 5322 5323 obj = NULL; 5324 result = named_config_get(maps, "minimal-responses", &obj); 5325 INSIST(result == ISC_R_SUCCESS); 5326 if (cfg_obj_isboolean(obj)) { 5327 if (cfg_obj_asboolean(obj)) { 5328 view->minimalresponses = dns_minimal_yes; 5329 } else { 5330 view->minimalresponses = dns_minimal_no; 5331 } 5332 } else { 5333 str = cfg_obj_asstring(obj); 5334 if (strcasecmp(str, "no-auth") == 0) { 5335 view->minimalresponses = dns_minimal_noauth; 5336 } else if (strcasecmp(str, "no-auth-recursive") == 0) { 5337 view->minimalresponses = dns_minimal_noauthrec; 5338 } else { 5339 UNREACHABLE(); 5340 } 5341 } 5342 5343 obj = NULL; 5344 result = named_config_get(maps, "transfer-format", &obj); 5345 INSIST(result == ISC_R_SUCCESS); 5346 str = cfg_obj_asstring(obj); 5347 if (strcasecmp(str, "many-answers") == 0) { 5348 view->transfer_format = dns_many_answers; 5349 } else if (strcasecmp(str, "one-answer") == 0) { 5350 view->transfer_format = dns_one_answer; 5351 } else { 5352 UNREACHABLE(); 5353 } 5354 5355 obj = NULL; 5356 result = named_config_get(maps, "trust-anchor-telemetry", &obj); 5357 INSIST(result == ISC_R_SUCCESS); 5358 view->trust_anchor_telemetry = cfg_obj_asboolean(obj); 5359 5360 obj = NULL; 5361 result = named_config_get(maps, "root-key-sentinel", &obj); 5362 INSIST(result == ISC_R_SUCCESS); 5363 view->root_key_sentinel = cfg_obj_asboolean(obj); 5364 5365 /* 5366 * Set the "allow-query", "allow-query-cache", "allow-recursion", 5367 * "allow-recursion-on" and "allow-query-cache-on" ACLs if 5368 * configured in named.conf, but NOT from the global defaults. 5369 * This is done by leaving the third argument to configure_view_acl() 5370 * NULL. 5371 * 5372 * We ignore the global defaults here because these ACLs 5373 * can inherit from each other. If any are still unset after 5374 * applying the inheritance rules, we'll look up the defaults at 5375 * that time. 5376 */ 5377 5378 /* named.conf only */ 5379 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query", NULL, 5380 actx, named_g_mctx, &view->queryacl)); 5381 5382 /* named.conf only */ 5383 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache", 5384 NULL, actx, named_g_mctx, &view->cacheacl)); 5385 /* named.conf only */ 5386 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on", 5387 NULL, actx, named_g_mctx, &view->cacheonacl)); 5388 5389 CHECK(configure_view_acl(vconfig, config, named_g_config, "allow-proxy", 5390 NULL, actx, named_g_mctx, &view->proxyacl)); 5391 5392 CHECK(configure_view_acl(vconfig, config, named_g_config, 5393 "allow-proxy-on", NULL, actx, named_g_mctx, 5394 &view->proxyonacl)); 5395 5396 if (view->rdclass != dns_rdataclass_in) { 5397 dns_acl_none(named_g_mctx, &view->recursionacl); 5398 dns_acl_none(named_g_mctx, &view->recursiononacl); 5399 } else { 5400 CHECK(configure_view_acl(vconfig, config, NULL, 5401 "allow-recursion", NULL, actx, 5402 named_g_mctx, &view->recursionacl)); 5403 CHECK(configure_view_acl(vconfig, config, NULL, 5404 "allow-recursion-on", NULL, actx, 5405 named_g_mctx, &view->recursiononacl)); 5406 } 5407 5408 if (view->recursion) { 5409 /* 5410 * "allow-query-cache" inherits from "allow-recursion" if set, 5411 * otherwise from "allow-query" if set. 5412 */ 5413 if (view->cacheacl == NULL) { 5414 if (view->recursionacl != NULL) { 5415 dns_acl_attach(view->recursionacl, 5416 &view->cacheacl); 5417 } else if (view->queryacl != NULL) { 5418 dns_acl_attach(view->queryacl, &view->cacheacl); 5419 } 5420 } 5421 5422 /* 5423 * "allow-recursion" inherits from "allow-query-cache" if set, 5424 * otherwise from "allow-query" if set. 5425 */ 5426 if (view->recursionacl == NULL) { 5427 if (view->cacheacl != NULL) { 5428 dns_acl_attach(view->cacheacl, 5429 &view->recursionacl); 5430 } else if (view->queryacl != NULL) { 5431 dns_acl_attach(view->queryacl, 5432 &view->recursionacl); 5433 } 5434 } 5435 5436 /* 5437 * "allow-query-cache-on" inherits from "allow-recursion-on" 5438 * if set. 5439 */ 5440 if (view->cacheonacl == NULL) { 5441 if (view->recursiononacl != NULL) { 5442 dns_acl_attach(view->recursiononacl, 5443 &view->cacheonacl); 5444 } 5445 } 5446 5447 /* 5448 * "allow-recursion-on" inherits from "allow-query-cache-on" 5449 * if set. 5450 */ 5451 if (view->recursiononacl == NULL) { 5452 if (view->cacheonacl != NULL) { 5453 dns_acl_attach(view->cacheonacl, 5454 &view->recursiononacl); 5455 } 5456 } 5457 5458 /* 5459 * If any are still unset at this point, we now get default 5460 * values for from the global config. 5461 */ 5462 5463 if (view->recursionacl == NULL) { 5464 /* global default only */ 5465 CHECK(configure_view_acl( 5466 NULL, NULL, named_g_config, "allow-recursion", 5467 NULL, actx, named_g_mctx, &view->recursionacl)); 5468 } 5469 if (view->recursiononacl == NULL) { 5470 /* global default only */ 5471 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5472 "allow-recursion-on", NULL, 5473 actx, named_g_mctx, 5474 &view->recursiononacl)); 5475 } 5476 if (view->cacheacl == NULL) { 5477 /* global default only */ 5478 CHECK(configure_view_acl( 5479 NULL, NULL, named_g_config, "allow-query-cache", 5480 NULL, actx, named_g_mctx, &view->cacheacl)); 5481 } 5482 if (view->cacheonacl == NULL) { 5483 /* global default only */ 5484 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5485 "allow-query-cache-on", NULL, 5486 actx, named_g_mctx, 5487 &view->cacheonacl)); 5488 } 5489 } else { 5490 /* 5491 * We're not recursive; if the query-cache ACLs haven't 5492 * been set at the options/view level, set them to none. 5493 */ 5494 if (view->cacheacl == NULL) { 5495 CHECK(dns_acl_none(mctx, &view->cacheacl)); 5496 } 5497 if (view->cacheonacl == NULL) { 5498 CHECK(dns_acl_none(mctx, &view->cacheonacl)); 5499 } 5500 } 5501 5502 /* 5503 * Finished setting recursion and query-cache ACLs, so now we 5504 * can get the allow-query default if it wasn't set in named.conf 5505 */ 5506 if (view->queryacl == NULL) { 5507 /* global default only */ 5508 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5509 "allow-query", NULL, actx, 5510 named_g_mctx, &view->queryacl)); 5511 } 5512 5513 /* 5514 * Ignore case when compressing responses to the specified 5515 * clients. This causes case not always to be preserved, 5516 * and is needed by some broken clients. 5517 */ 5518 CHECK(configure_view_acl(vconfig, config, named_g_config, 5519 "no-case-compress", NULL, actx, named_g_mctx, 5520 &view->nocasecompress)); 5521 5522 /* 5523 * Disable name compression completely, this is a tradeoff 5524 * between CPU and network usage. 5525 */ 5526 obj = NULL; 5527 result = named_config_get(maps, "message-compression", &obj); 5528 INSIST(result == ISC_R_SUCCESS); 5529 view->msgcompression = cfg_obj_asboolean(obj); 5530 5531 /* 5532 * Filter setting on addresses in the answer section. 5533 */ 5534 CHECK(configure_view_acl(vconfig, config, named_g_config, 5535 "deny-answer-addresses", "acl", actx, 5536 named_g_mctx, &view->denyansweracl)); 5537 CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", 5538 "except-from", named_g_mctx, 5539 &view->answeracl_exclude)); 5540 5541 /* 5542 * Filter setting on names (CNAME/DNAME targets) in the answer section. 5543 */ 5544 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 5545 "name", named_g_mctx, 5546 &view->denyanswernames)); 5547 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 5548 "except-from", named_g_mctx, 5549 &view->answernames_exclude)); 5550 5551 /* 5552 * Configure sortlist, if set 5553 */ 5554 CHECK(configure_view_sortlist(vconfig, config, actx, named_g_mctx, 5555 &view->sortlist)); 5556 5557 /* 5558 * Configure default allow-update and allow-update-forwarding ACLs, 5559 * so they can be inherited by zones. (XXX: These are not 5560 * read from the options/view level here. However, they may be 5561 * read from there in zoneconf.c:configure_zone_acl() later.) 5562 */ 5563 if (view->updateacl == NULL) { 5564 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5565 "allow-update", NULL, actx, 5566 named_g_mctx, &view->updateacl)); 5567 } 5568 if (view->upfwdacl == NULL) { 5569 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5570 "allow-update-forwarding", NULL, actx, 5571 named_g_mctx, &view->upfwdacl)); 5572 } 5573 5574 /* 5575 * Configure default allow-transfer and allow-notify ACLs so they 5576 * can be inherited by zones. 5577 */ 5578 if (view->transferacl == NULL) { 5579 CHECK(configure_view_acl(vconfig, config, named_g_config, 5580 "allow-transfer", NULL, actx, 5581 named_g_mctx, &view->transferacl)); 5582 } 5583 if (view->notifyacl == NULL) { 5584 CHECK(configure_view_acl(vconfig, config, named_g_config, 5585 "allow-notify", NULL, actx, 5586 named_g_mctx, &view->notifyacl)); 5587 } 5588 5589 obj = NULL; 5590 result = named_config_get(maps, "provide-ixfr", &obj); 5591 INSIST(result == ISC_R_SUCCESS); 5592 view->provideixfr = cfg_obj_asboolean(obj); 5593 5594 obj = NULL; 5595 result = named_config_get(maps, "request-nsid", &obj); 5596 INSIST(result == ISC_R_SUCCESS); 5597 view->requestnsid = cfg_obj_asboolean(obj); 5598 5599 obj = NULL; 5600 result = named_config_get(maps, "send-cookie", &obj); 5601 INSIST(result == ISC_R_SUCCESS); 5602 view->sendcookie = cfg_obj_asboolean(obj); 5603 5604 obj = NULL; 5605 if (view->pad_acl != NULL) { 5606 dns_acl_detach(&view->pad_acl); 5607 } 5608 result = named_config_get(maps, "response-padding", &obj); 5609 INSIST(result == ISC_R_SUCCESS); 5610 padding = cfg_obj_asuint32(cfg_tuple_get(obj, "block-size")); 5611 if (padding > 512U) { 5612 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 5613 "response-padding block-size cannot " 5614 "exceed 512: lowering"); 5615 padding = 512U; 5616 } 5617 view->padding = (uint16_t)padding; 5618 CHECK(cfg_acl_fromconfig(cfg_tuple_get(obj, "acl"), config, 5619 named_g_lctx, actx, named_g_mctx, 0, 5620 &view->pad_acl)); 5621 5622 obj = NULL; 5623 result = named_config_get(maps, "require-server-cookie", &obj); 5624 INSIST(result == ISC_R_SUCCESS); 5625 view->requireservercookie = cfg_obj_asboolean(obj); 5626 5627 obj = NULL; 5628 result = named_config_get(maps, "v6-bias", &obj); 5629 INSIST(result == ISC_R_SUCCESS); 5630 view->v6bias = cfg_obj_asuint32(obj) * 1000; 5631 5632 obj = NULL; 5633 result = named_config_get(maps, "clients-per-query", &obj); 5634 INSIST(result == ISC_R_SUCCESS); 5635 clients_per_query = cfg_obj_asuint32(obj); 5636 5637 obj = NULL; 5638 result = named_config_get(maps, "max-clients-per-query", &obj); 5639 INSIST(result == ISC_R_SUCCESS); 5640 max_clients_per_query = cfg_obj_asuint32(obj); 5641 5642 if (max_clients_per_query < clients_per_query) { 5643 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 5644 "configured clients-per-query (%u) exceeds " 5645 "max-clients-per-query (%u); automatically " 5646 "adjusting max-clients-per-query to (%u)", 5647 clients_per_query, max_clients_per_query, 5648 clients_per_query); 5649 max_clients_per_query = clients_per_query; 5650 } 5651 dns_resolver_setclientsperquery(view->resolver, clients_per_query, 5652 max_clients_per_query); 5653 5654 /* 5655 * This is used for the cache and also as a default value 5656 * for zone databases. 5657 */ 5658 obj = NULL; 5659 result = named_config_get(maps, "max-records-per-type", &obj); 5660 INSIST(result == ISC_R_SUCCESS); 5661 dns_view_setmaxrrperset(view, cfg_obj_asuint32(obj)); 5662 5663 /* 5664 * This is used for the cache and also as a default value 5665 * for zone databases. 5666 */ 5667 obj = NULL; 5668 result = named_config_get(maps, "max-types-per-name", &obj); 5669 INSIST(result == ISC_R_SUCCESS); 5670 dns_view_setmaxtypepername(view, cfg_obj_asuint32(obj)); 5671 5672 obj = NULL; 5673 result = named_config_get(maps, "max-recursion-depth", &obj); 5674 INSIST(result == ISC_R_SUCCESS); 5675 dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); 5676 5677 obj = NULL; 5678 result = named_config_get(maps, "max-recursion-queries", &obj); 5679 INSIST(result == ISC_R_SUCCESS); 5680 dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); 5681 5682 obj = NULL; 5683 result = named_config_get(maps, "max-query-restarts", &obj); 5684 INSIST(result == ISC_R_SUCCESS); 5685 dns_view_setmaxrestarts(view, cfg_obj_asuint32(obj)); 5686 5687 obj = NULL; 5688 result = named_config_get(maps, "max-query-count", &obj); 5689 INSIST(result == ISC_R_SUCCESS); 5690 dns_view_setmaxqueries(view, cfg_obj_asuint32(obj)); 5691 5692 obj = NULL; 5693 result = named_config_get(maps, "max-validations-per-fetch", &obj); 5694 if (result == ISC_R_SUCCESS) { 5695 dns_resolver_setmaxvalidations(view->resolver, 5696 cfg_obj_asuint32(obj)); 5697 } 5698 5699 obj = NULL; 5700 result = named_config_get(maps, "max-validation-failures-per-fetch", 5701 &obj); 5702 if (result == ISC_R_SUCCESS) { 5703 dns_resolver_setmaxvalidationfails(view->resolver, 5704 cfg_obj_asuint32(obj)); 5705 } 5706 5707 obj = NULL; 5708 result = named_config_get(maps, "fetches-per-zone", &obj); 5709 INSIST(result == ISC_R_SUCCESS); 5710 obj2 = cfg_tuple_get(obj, "fetches"); 5711 dns_resolver_setfetchesperzone(view->resolver, cfg_obj_asuint32(obj2)); 5712 obj2 = cfg_tuple_get(obj, "response"); 5713 if (!cfg_obj_isvoid(obj2)) { 5714 const char *resp = cfg_obj_asstring(obj2); 5715 isc_result_t r = DNS_R_SERVFAIL; 5716 5717 if (strcasecmp(resp, "drop") == 0) { 5718 r = DNS_R_DROP; 5719 } else if (strcasecmp(resp, "fail") == 0) { 5720 r = DNS_R_SERVFAIL; 5721 } else { 5722 UNREACHABLE(); 5723 } 5724 5725 dns_resolver_setquotaresponse(view->resolver, 5726 dns_quotatype_zone, r); 5727 } 5728 5729 obj = NULL; 5730 result = named_config_get(maps, "prefetch", &obj); 5731 INSIST(result == ISC_R_SUCCESS); 5732 prefetch_trigger = cfg_tuple_get(obj, "trigger"); 5733 view->prefetch_trigger = cfg_obj_asuint32(prefetch_trigger); 5734 if (view->prefetch_trigger > 10) { 5735 view->prefetch_trigger = 10; 5736 } 5737 prefetch_eligible = cfg_tuple_get(obj, "eligible"); 5738 if (cfg_obj_isvoid(prefetch_eligible)) { 5739 int m; 5740 for (m = 1; maps[m] != NULL; m++) { 5741 obj = NULL; 5742 result = named_config_get(&maps[m], "prefetch", &obj); 5743 INSIST(result == ISC_R_SUCCESS); 5744 prefetch_eligible = cfg_tuple_get(obj, "eligible"); 5745 if (cfg_obj_isuint32(prefetch_eligible)) { 5746 break; 5747 } 5748 } 5749 INSIST(cfg_obj_isuint32(prefetch_eligible)); 5750 } 5751 view->prefetch_eligible = cfg_obj_asuint32(prefetch_eligible); 5752 if (view->prefetch_eligible < view->prefetch_trigger + 6) { 5753 view->prefetch_eligible = view->prefetch_trigger + 6; 5754 } 5755 5756 /* 5757 * For now, there is only one kind of trusted keys, the 5758 * "security roots". 5759 */ 5760 CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, 5761 auto_root)); 5762 5763 obj = NULL; 5764 result = named_config_get(maps, "dnssec-must-be-secure", &obj); 5765 if (result == ISC_R_SUCCESS) { 5766 CHECK(mustbesecure(obj, view->resolver)); 5767 } 5768 5769 obj = NULL; 5770 result = named_config_get(maps, "nta-recheck", &obj); 5771 INSIST(result == ISC_R_SUCCESS); 5772 view->nta_recheck = cfg_obj_asduration(obj); 5773 5774 obj = NULL; 5775 result = named_config_get(maps, "nta-lifetime", &obj); 5776 INSIST(result == ISC_R_SUCCESS); 5777 view->nta_lifetime = cfg_obj_asduration(obj); 5778 5779 obj = NULL; 5780 result = named_config_get(maps, "preferred-glue", &obj); 5781 if (result == ISC_R_SUCCESS) { 5782 str = cfg_obj_asstring(obj); 5783 if (strcasecmp(str, "a") == 0) { 5784 view->preferred_glue = dns_rdatatype_a; 5785 } else if (strcasecmp(str, "aaaa") == 0) { 5786 view->preferred_glue = dns_rdatatype_aaaa; 5787 } else { 5788 view->preferred_glue = 0; 5789 } 5790 } else { 5791 view->preferred_glue = 0; 5792 } 5793 5794 /* 5795 * Load DynDB modules. 5796 */ 5797 dyndb_list = NULL; 5798 if (voptions != NULL) { 5799 (void)cfg_map_get(voptions, "dyndb", &dyndb_list); 5800 } else { 5801 (void)cfg_map_get(config, "dyndb", &dyndb_list); 5802 } 5803 5804 for (element = cfg_list_first(dyndb_list); element != NULL; 5805 element = cfg_list_next(element)) 5806 { 5807 const cfg_obj_t *dyndb = cfg_listelt_value(element); 5808 5809 if (dctx == NULL) { 5810 const void *hashinit = isc_hash_get_initializer(); 5811 CHECK(dns_dyndb_createctx(mctx, hashinit, named_g_lctx, 5812 view, named_g_server->zonemgr, 5813 named_g_loopmgr, &dctx)); 5814 } 5815 5816 CHECK(configure_dyndb(dyndb, mctx, dctx)); 5817 } 5818 5819 /* 5820 * Load plugins. 5821 */ 5822 plugin_list = NULL; 5823 if (voptions != NULL) { 5824 (void)cfg_map_get(voptions, "plugin", &plugin_list); 5825 } else { 5826 (void)cfg_map_get(config, "plugin", &plugin_list); 5827 } 5828 5829 if (plugin_list != NULL) { 5830 INSIST(view->hooktable == NULL); 5831 CHECK(ns_hooktable_create(view->mctx, 5832 (ns_hooktable_t **)&view->hooktable)); 5833 view->hooktable_free = ns_hooktable_free; 5834 5835 ns_plugins_create(view->mctx, (ns_plugins_t **)&view->plugins); 5836 view->plugins_free = ns_plugins_free; 5837 5838 CHECK(cfg_pluginlist_foreach(config, plugin_list, named_g_lctx, 5839 register_one_plugin, view)); 5840 } 5841 5842 /* 5843 * Setup automatic empty zones. If recursion is off then 5844 * they are disabled by default. 5845 */ 5846 obj = NULL; 5847 (void)named_config_get(maps, "empty-zones-enable", &obj); 5848 (void)named_config_get(maps, "disable-empty-zone", &disablelist); 5849 if (obj == NULL && disablelist == NULL && 5850 view->rdclass == dns_rdataclass_in) 5851 { 5852 empty_zones_enable = view->recursion; 5853 } else if (view->rdclass == dns_rdataclass_in) { 5854 if (obj != NULL) { 5855 empty_zones_enable = cfg_obj_asboolean(obj); 5856 } else { 5857 empty_zones_enable = view->recursion; 5858 } 5859 } else { 5860 empty_zones_enable = false; 5861 } 5862 5863 if (empty_zones_enable) { 5864 const char *empty; 5865 int empty_zone = 0; 5866 dns_fixedname_t fixed; 5867 dns_name_t *name; 5868 isc_buffer_t buffer; 5869 char server[DNS_NAME_FORMATSIZE + 1]; 5870 char contact[DNS_NAME_FORMATSIZE + 1]; 5871 const char *empty_dbtype[4] = { "_builtin", "empty", NULL, 5872 NULL }; 5873 int empty_dbtypec = 4; 5874 dns_zonestat_level_t statlevel = dns_zonestat_none; 5875 5876 name = dns_fixedname_initname(&fixed); 5877 5878 obj = NULL; 5879 result = named_config_get(maps, "empty-server", &obj); 5880 if (result == ISC_R_SUCCESS) { 5881 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 5882 dns_rootname, 0, NULL)); 5883 isc_buffer_init(&buffer, server, sizeof(server) - 1); 5884 CHECK(dns_name_totext(name, 0, &buffer)); 5885 server[isc_buffer_usedlength(&buffer)] = 0; 5886 empty_dbtype[2] = server; 5887 } else { 5888 empty_dbtype[2] = "@"; 5889 } 5890 5891 obj = NULL; 5892 result = named_config_get(maps, "empty-contact", &obj); 5893 if (result == ISC_R_SUCCESS) { 5894 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 5895 dns_rootname, 0, NULL)); 5896 isc_buffer_init(&buffer, contact, sizeof(contact) - 1); 5897 CHECK(dns_name_totext(name, 0, &buffer)); 5898 contact[isc_buffer_usedlength(&buffer)] = 0; 5899 empty_dbtype[3] = contact; 5900 } else { 5901 empty_dbtype[3] = "."; 5902 } 5903 5904 obj = NULL; 5905 result = named_config_get(maps, "zone-statistics", &obj); 5906 INSIST(result == ISC_R_SUCCESS); 5907 if (cfg_obj_isboolean(obj)) { 5908 if (cfg_obj_asboolean(obj)) { 5909 statlevel = dns_zonestat_full; 5910 } else { 5911 statlevel = dns_zonestat_none; 5912 } 5913 } else { 5914 const char *levelstr = cfg_obj_asstring(obj); 5915 if (strcasecmp(levelstr, "full") == 0) { 5916 statlevel = dns_zonestat_full; 5917 } else if (strcasecmp(levelstr, "terse") == 0) { 5918 statlevel = dns_zonestat_terse; 5919 } else if (strcasecmp(levelstr, "none") == 0) { 5920 statlevel = dns_zonestat_none; 5921 } else { 5922 UNREACHABLE(); 5923 } 5924 } 5925 5926 for (empty = empty_zones[empty_zone]; empty != NULL; 5927 empty = empty_zones[++empty_zone]) 5928 { 5929 dns_forwarders_t *dnsforwarders = NULL; 5930 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 5931 5932 /* 5933 * Look for zone on drop list. 5934 */ 5935 CHECK(dns_name_fromstring(name, empty, dns_rootname, 0, 5936 NULL)); 5937 if (disablelist != NULL && 5938 on_disable_list(disablelist, name)) 5939 { 5940 continue; 5941 } 5942 5943 /* 5944 * This zone already exists. 5945 */ 5946 (void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 5947 &zone); 5948 if (zone != NULL) { 5949 dns_zone_detach(&zone); 5950 continue; 5951 } 5952 5953 /* 5954 * If we would forward this name don't add a 5955 * empty zone for it. 5956 */ 5957 result = dns_fwdtable_find(view->fwdtable, name, 5958 &dnsforwarders); 5959 if (result == ISC_R_SUCCESS || 5960 result == DNS_R_PARTIALMATCH) 5961 { 5962 fwdpolicy = dnsforwarders->fwdpolicy; 5963 dns_forwarders_detach(&dnsforwarders); 5964 } 5965 if (fwdpolicy == dns_fwdpolicy_only) { 5966 continue; 5967 } 5968 5969 /* 5970 * See if we can re-use a existing zone. 5971 */ 5972 result = dns_viewlist_find(&named_g_server->viewlist, 5973 view->name, view->rdclass, 5974 &pview); 5975 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 5976 { 5977 goto cleanup; 5978 } 5979 5980 if (pview != NULL) { 5981 (void)dns_view_findzone( 5982 pview, name, DNS_ZTFIND_EXACT, &zone); 5983 dns_view_detach(&pview); 5984 } 5985 5986 CHECK(create_empty_zone(zone, name, view, zonelist, 5987 empty_dbtype, empty_dbtypec, 5988 statlevel)); 5989 if (zone != NULL) { 5990 dns_zone_detach(&zone); 5991 } 5992 } 5993 } 5994 5995 obj = NULL; 5996 if (view->rdclass == dns_rdataclass_in) { 5997 (void)named_config_get(maps, "ipv4only-enable", &obj); 5998 } 5999 if (view->rdclass == dns_rdataclass_in && (obj != NULL) 6000 ? cfg_obj_asboolean(obj) 6001 : !ISC_LIST_EMPTY(view->dns64)) 6002 { 6003 const char *server, *contact; 6004 dns_fixedname_t fixed; 6005 dns_name_t *name; 6006 struct { 6007 const char *name; 6008 const char *type; 6009 } zones[] = { 6010 { "ipv4only.arpa", "ipv4only" }, 6011 { "170.0.0.192.in-addr.arpa", "ipv4reverse" }, 6012 { "171.0.0.192.in-addr.arpa", "ipv4reverse" }, 6013 }; 6014 size_t ipv4only_zone; 6015 6016 obj = NULL; 6017 result = named_config_get(maps, "ipv4only-server", &obj); 6018 if (result == ISC_R_SUCCESS) { 6019 server = cfg_obj_asstring(obj); 6020 } else { 6021 server = NULL; 6022 } 6023 6024 obj = NULL; 6025 result = named_config_get(maps, "ipv4only-contact", &obj); 6026 if (result == ISC_R_SUCCESS) { 6027 contact = cfg_obj_asstring(obj); 6028 } else { 6029 contact = NULL; 6030 } 6031 6032 name = dns_fixedname_initname(&fixed); 6033 for (ipv4only_zone = 0; ipv4only_zone < ARRAY_SIZE(zones); 6034 ipv4only_zone++) 6035 { 6036 dns_forwarders_t *dnsforwarders = NULL; 6037 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 6038 6039 CHECK(dns_name_fromstring(name, 6040 zones[ipv4only_zone].name, 6041 dns_rootname, 0, NULL)); 6042 6043 (void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 6044 &zone); 6045 if (zone != NULL) { 6046 dns_zone_detach(&zone); 6047 continue; 6048 } 6049 6050 /* 6051 * If we would forward this name don't add it. 6052 */ 6053 result = dns_fwdtable_find(view->fwdtable, name, 6054 &dnsforwarders); 6055 if (result == ISC_R_SUCCESS || 6056 result == DNS_R_PARTIALMATCH) 6057 { 6058 fwdpolicy = dnsforwarders->fwdpolicy; 6059 dns_forwarders_detach(&dnsforwarders); 6060 } 6061 if (fwdpolicy == dns_fwdpolicy_only) { 6062 continue; 6063 } 6064 6065 /* 6066 * See if we can re-use a existing zone. 6067 */ 6068 result = dns_viewlist_find(&named_g_server->viewlist, 6069 view->name, view->rdclass, 6070 &pview); 6071 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 6072 { 6073 goto cleanup; 6074 } 6075 6076 if (pview != NULL) { 6077 (void)dns_view_findzone( 6078 pview, name, DNS_ZTFIND_EXACT, &zone); 6079 dns_view_detach(&pview); 6080 } 6081 6082 CHECK(create_ipv4only_zone(zone, view, name, 6083 zones[ipv4only_zone].type, 6084 mctx, server, contact)); 6085 if (zone != NULL) { 6086 dns_zone_detach(&zone); 6087 } 6088 } 6089 } 6090 6091 obj = NULL; 6092 result = named_config_get(maps, "rate-limit", &obj); 6093 if (result == ISC_R_SUCCESS) { 6094 result = configure_rrl(view, config, obj); 6095 if (result != ISC_R_SUCCESS) { 6096 goto cleanup; 6097 } 6098 } 6099 6100 /* 6101 * Set the servfail-ttl. 6102 */ 6103 obj = NULL; 6104 result = named_config_get(maps, "servfail-ttl", &obj); 6105 INSIST(result == ISC_R_SUCCESS); 6106 fail_ttl = cfg_obj_asduration(obj); 6107 if (fail_ttl > 30) { 6108 fail_ttl = 30; 6109 } 6110 dns_view_setfailttl(view, fail_ttl); 6111 6112 /* 6113 * Name space to look up redirect information in. 6114 */ 6115 obj = NULL; 6116 result = named_config_get(maps, "nxdomain-redirect", &obj); 6117 if (result == ISC_R_SUCCESS) { 6118 dns_name_t *name = dns_fixedname_name(&view->redirectfixed); 6119 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 6120 dns_rootname, 0, NULL)); 6121 view->redirectzone = name; 6122 } else { 6123 view->redirectzone = NULL; 6124 } 6125 6126 /* 6127 * Exceptions to DNSSEC validation. 6128 */ 6129 obj = NULL; 6130 result = named_config_get(maps, "validate-except", &obj); 6131 if (result == ISC_R_SUCCESS) { 6132 result = dns_view_getntatable(view, &ntatable); 6133 } 6134 if (result == ISC_R_SUCCESS) { 6135 for (element = cfg_list_first(obj); element != NULL; 6136 element = cfg_list_next(element)) 6137 { 6138 dns_fixedname_t fntaname; 6139 dns_name_t *ntaname; 6140 6141 ntaname = dns_fixedname_initname(&fntaname); 6142 obj = cfg_listelt_value(element); 6143 CHECK(dns_name_fromstring(ntaname, 6144 cfg_obj_asstring(obj), 6145 dns_rootname, 0, NULL)); 6146 CHECK(dns_ntatable_add(ntatable, ntaname, true, 0, 6147 0xffffffffU)); 6148 } 6149 } 6150 6151 #ifdef HAVE_DNSTAP 6152 /* 6153 * Set up the dnstap environment and configure message 6154 * types to log. 6155 */ 6156 CHECK(configure_dnstap(maps, view)); 6157 #endif /* HAVE_DNSTAP */ 6158 6159 result = ISC_R_SUCCESS; 6160 6161 cleanup: 6162 /* 6163 * Revert to the old view if there was an error. 6164 */ 6165 if (result != ISC_R_SUCCESS) { 6166 isc_result_t result2; 6167 6168 result2 = dns_viewlist_find(&named_g_server->viewlist, 6169 view->name, view->rdclass, &pview); 6170 if (result2 == ISC_R_SUCCESS) { 6171 dns_view_thaw(pview); 6172 6173 obj = NULL; 6174 if (rpz_configured && 6175 pview->rdclass == dns_rdataclass_in && need_hints && 6176 named_config_get(maps, "response-policy", &obj) == 6177 ISC_R_SUCCESS) 6178 { 6179 /* 6180 * We are swapping the places of the `view` and 6181 * `pview` in the function's parameters list 6182 * because we are reverting the same operation 6183 * done previously in the "correct" order. 6184 */ 6185 result2 = configure_rpz(pview, view, maps, obj, 6186 &old_rpz_ok, 6187 first_time); 6188 if (result2 != ISC_R_SUCCESS) { 6189 isc_log_write(named_g_lctx, 6190 NAMED_LOGCATEGORY_GENERAL, 6191 NAMED_LOGMODULE_SERVER, 6192 ISC_LOG_ERROR, 6193 "rpz configuration " 6194 "revert failed for view " 6195 "'%s'", 6196 pview->name); 6197 } 6198 } 6199 6200 obj = NULL; 6201 if (catz_configured && 6202 pview->rdclass == dns_rdataclass_in && need_hints && 6203 named_config_get(maps, "catalog-zones", &obj) == 6204 ISC_R_SUCCESS) 6205 { 6206 /* 6207 * We are swapping the places of the `view` and 6208 * `pview` in the function's parameters list 6209 * because we are reverting the same operation 6210 * done previously in the "correct" order. 6211 */ 6212 result2 = configure_catz(pview, view, config, 6213 obj); 6214 if (result2 != ISC_R_SUCCESS) { 6215 isc_log_write(named_g_lctx, 6216 NAMED_LOGCATEGORY_GENERAL, 6217 NAMED_LOGMODULE_SERVER, 6218 ISC_LOG_ERROR, 6219 "catz configuration " 6220 "revert failed for view " 6221 "'%s'", 6222 pview->name); 6223 } 6224 } 6225 6226 dns_view_freeze(pview); 6227 } 6228 6229 if (pview != NULL) { 6230 dns_view_detach(&pview); 6231 } 6232 6233 if (zone_element_latest != NULL) { 6234 for (element = cfg_list_first(zonelist); 6235 element != NULL; element = cfg_list_next(element)) 6236 { 6237 const cfg_obj_t *zconfig = 6238 cfg_listelt_value(element); 6239 configure_zone_setviewcommit(result, zconfig, 6240 view); 6241 if (element == zone_element_latest) { 6242 /* 6243 * This was the latest element that was 6244 * successfully configured earlier. 6245 */ 6246 break; 6247 } 6248 } 6249 } 6250 } 6251 6252 if (ntatable != NULL) { 6253 dns_ntatable_detach(&ntatable); 6254 } 6255 if (clients != NULL) { 6256 dns_acl_detach(&clients); 6257 } 6258 if (mapped != NULL) { 6259 dns_acl_detach(&mapped); 6260 } 6261 if (excluded != NULL) { 6262 dns_acl_detach(&excluded); 6263 } 6264 if (ring != NULL) { 6265 dns_tsigkeyring_detach(&ring); 6266 } 6267 if (zone != NULL) { 6268 dns_zone_detach(&zone); 6269 } 6270 if (dispatch4 != NULL) { 6271 dns_dispatch_detach(&dispatch4); 6272 } 6273 if (dispatch6 != NULL) { 6274 dns_dispatch_detach(&dispatch6); 6275 } 6276 if (resstats != NULL) { 6277 isc_stats_detach(&resstats); 6278 } 6279 if (resquerystats != NULL) { 6280 dns_stats_detach(&resquerystats); 6281 } 6282 if (order != NULL) { 6283 dns_order_detach(&order); 6284 } 6285 if (cache != NULL) { 6286 dns_cache_detach(&cache); 6287 } 6288 if (dctx != NULL) { 6289 dns_dyndb_destroyctx(&dctx); 6290 } 6291 6292 return result; 6293 } 6294 6295 static isc_result_t 6296 configure_hints(dns_view_t *view, const char *filename) { 6297 isc_result_t result; 6298 dns_db_t *db; 6299 6300 db = NULL; 6301 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); 6302 if (result == ISC_R_SUCCESS) { 6303 dns_view_sethints(view, db); 6304 dns_db_detach(&db); 6305 } 6306 6307 return result; 6308 } 6309 6310 static isc_result_t 6311 configure_alternates(const cfg_obj_t *config, dns_view_t *view, 6312 const cfg_obj_t *alternates) { 6313 const cfg_obj_t *portobj; 6314 const cfg_obj_t *addresses; 6315 const cfg_listelt_t *element; 6316 isc_result_t result = ISC_R_SUCCESS; 6317 in_port_t port; 6318 6319 /* 6320 * Determine which port to send requests to. 6321 */ 6322 CHECKM(named_config_getport(config, "port", &port), "port"); 6323 6324 if (alternates != NULL) { 6325 portobj = cfg_tuple_get(alternates, "port"); 6326 if (cfg_obj_isuint32(portobj)) { 6327 uint32_t val = cfg_obj_asuint32(portobj); 6328 if (val > UINT16_MAX) { 6329 cfg_obj_log(portobj, named_g_lctx, 6330 ISC_LOG_ERROR, 6331 "port '%u' out of range", val); 6332 return ISC_R_RANGE; 6333 } 6334 port = (in_port_t)val; 6335 } 6336 } 6337 6338 addresses = NULL; 6339 if (alternates != NULL) { 6340 addresses = cfg_tuple_get(alternates, "addresses"); 6341 } 6342 6343 for (element = cfg_list_first(addresses); element != NULL; 6344 element = cfg_list_next(element)) 6345 { 6346 const cfg_obj_t *alternate = cfg_listelt_value(element); 6347 isc_sockaddr_t sa; 6348 6349 if (!cfg_obj_issockaddr(alternate)) { 6350 dns_fixedname_t fixed; 6351 dns_name_t *name; 6352 const char *str = cfg_obj_asstring( 6353 cfg_tuple_get(alternate, "name")); 6354 isc_buffer_t buffer; 6355 in_port_t myport = port; 6356 6357 isc_buffer_constinit(&buffer, str, strlen(str)); 6358 isc_buffer_add(&buffer, strlen(str)); 6359 name = dns_fixedname_initname(&fixed); 6360 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, 6361 NULL)); 6362 6363 portobj = cfg_tuple_get(alternate, "port"); 6364 if (cfg_obj_isuint32(portobj)) { 6365 uint32_t val = cfg_obj_asuint32(portobj); 6366 if (val > UINT16_MAX) { 6367 cfg_obj_log(portobj, named_g_lctx, 6368 ISC_LOG_ERROR, 6369 "port '%u' out of range", 6370 val); 6371 return ISC_R_RANGE; 6372 } 6373 myport = (in_port_t)val; 6374 } 6375 dns_resolver_addalternate(view->resolver, NULL, name, 6376 myport); 6377 continue; 6378 } 6379 6380 sa = *cfg_obj_assockaddr(alternate); 6381 if (isc_sockaddr_getport(&sa) == 0) { 6382 isc_sockaddr_setport(&sa, port); 6383 } 6384 dns_resolver_addalternate(view->resolver, &sa, NULL, 0); 6385 } 6386 6387 cleanup: 6388 return result; 6389 } 6390 6391 static isc_result_t 6392 validate_tls(const cfg_obj_t *config, dns_view_t *view, const cfg_obj_t *obj, 6393 isc_log_t *logctx, const char *str, dns_name_t **name) { 6394 dns_fixedname_t fname; 6395 dns_name_t *nm = dns_fixedname_initname(&fname); 6396 isc_result_t result = dns_name_fromstring(nm, str, dns_rootname, 0, 6397 NULL); 6398 6399 if (result != ISC_R_SUCCESS) { 6400 cfg_obj_log(obj, logctx, ISC_LOG_ERROR, 6401 "'%s' is not a valid name", str); 6402 return result; 6403 } 6404 6405 if (strcasecmp(str, "ephemeral") != 0) { 6406 const cfg_obj_t *tlsmap = find_maplist(config, "tls", str); 6407 6408 if (tlsmap == NULL) { 6409 cfg_obj_log(obj, logctx, ISC_LOG_ERROR, 6410 "tls '%s' is not defined", str); 6411 return ISC_R_FAILURE; 6412 } 6413 } 6414 6415 if (name != NULL && *name == NULL) { 6416 *name = isc_mem_get(view->mctx, sizeof(dns_name_t)); 6417 dns_name_init(*name, NULL); 6418 dns_name_dup(nm, view->mctx, *name); 6419 } 6420 6421 return ISC_R_SUCCESS; 6422 } 6423 6424 static isc_result_t 6425 configure_forward(const cfg_obj_t *config, dns_view_t *view, 6426 const dns_name_t *origin, const cfg_obj_t *forwarders, 6427 const cfg_obj_t *forwardtype) { 6428 const cfg_obj_t *portobj = NULL; 6429 const cfg_obj_t *tlspobj = NULL; 6430 const cfg_obj_t *faddresses = NULL; 6431 const cfg_listelt_t *element = NULL; 6432 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 6433 dns_forwarderlist_t fwdlist; 6434 dns_forwarder_t *fwd = NULL; 6435 isc_result_t result; 6436 in_port_t port; 6437 in_port_t tls_port; 6438 const char *tls = NULL; 6439 6440 ISC_LIST_INIT(fwdlist); 6441 6442 /* 6443 * Determine which port to send forwarded requests to. 6444 */ 6445 CHECKM(named_config_getport(config, "port", &port), "port"); 6446 CHECKM(named_config_getport(config, "tls-port", &tls_port), "tls-port"); 6447 6448 if (forwarders != NULL) { 6449 portobj = cfg_tuple_get(forwarders, "port"); 6450 if (cfg_obj_isuint32(portobj)) { 6451 uint32_t val = cfg_obj_asuint32(portobj); 6452 if (val > UINT16_MAX) { 6453 cfg_obj_log(portobj, named_g_lctx, 6454 ISC_LOG_ERROR, 6455 "port '%u' out of range", val); 6456 return ISC_R_RANGE; 6457 } 6458 port = tls_port = (in_port_t)val; 6459 } 6460 } 6461 6462 /* 6463 * TLS value for forwarded requests. 6464 */ 6465 if (forwarders != NULL) { 6466 tlspobj = cfg_tuple_get(forwarders, "tls"); 6467 if (cfg_obj_isstring(tlspobj)) { 6468 tls = cfg_obj_asstring(tlspobj); 6469 if (tls != NULL) { 6470 result = validate_tls(config, view, tlspobj, 6471 named_g_lctx, tls, NULL); 6472 if (result != ISC_R_SUCCESS) { 6473 return result; 6474 } 6475 } 6476 } 6477 } 6478 6479 faddresses = NULL; 6480 if (forwarders != NULL) { 6481 faddresses = cfg_tuple_get(forwarders, "addresses"); 6482 } 6483 6484 for (element = cfg_list_first(faddresses); element != NULL; 6485 element = cfg_list_next(element)) 6486 { 6487 const cfg_obj_t *forwarder = cfg_listelt_value(element); 6488 const char *cur_tls = NULL; 6489 6490 fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t)); 6491 fwd->tlsname = NULL; 6492 cur_tls = cfg_obj_getsockaddrtls(forwarder); 6493 if (cur_tls == NULL) { 6494 cur_tls = tls; 6495 } 6496 if (cur_tls != NULL) { 6497 result = validate_tls(config, view, faddresses, 6498 named_g_lctx, cur_tls, 6499 &fwd->tlsname); 6500 if (result != ISC_R_SUCCESS) { 6501 isc_mem_put(view->mctx, fwd, 6502 sizeof(dns_forwarder_t)); 6503 goto cleanup; 6504 } 6505 } 6506 fwd->addr = *cfg_obj_assockaddr(forwarder); 6507 if (isc_sockaddr_getport(&fwd->addr) == 0) { 6508 isc_sockaddr_setport(&fwd->addr, 6509 cur_tls != NULL ? tls_port : port); 6510 } 6511 ISC_LINK_INIT(fwd, link); 6512 ISC_LIST_APPEND(fwdlist, fwd, link); 6513 } 6514 6515 if (ISC_LIST_EMPTY(fwdlist)) { 6516 if (forwardtype != NULL) { 6517 cfg_obj_log(forwardtype, named_g_lctx, ISC_LOG_WARNING, 6518 "no forwarders seen; disabling " 6519 "forwarding"); 6520 } 6521 fwdpolicy = dns_fwdpolicy_none; 6522 } else { 6523 if (forwardtype == NULL) { 6524 fwdpolicy = dns_fwdpolicy_first; 6525 } else { 6526 const char *forwardstr = cfg_obj_asstring(forwardtype); 6527 if (strcasecmp(forwardstr, "first") == 0) { 6528 fwdpolicy = dns_fwdpolicy_first; 6529 } else if (strcasecmp(forwardstr, "only") == 0) { 6530 fwdpolicy = dns_fwdpolicy_only; 6531 } else { 6532 UNREACHABLE(); 6533 } 6534 } 6535 } 6536 6537 result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist, 6538 fwdpolicy); 6539 if (result != ISC_R_SUCCESS) { 6540 char namebuf[DNS_NAME_FORMATSIZE]; 6541 dns_name_format(origin, namebuf, sizeof(namebuf)); 6542 cfg_obj_log(forwarders, named_g_lctx, ISC_LOG_WARNING, 6543 "could not set up forwarding for domain '%s': %s", 6544 namebuf, isc_result_totext(result)); 6545 goto cleanup; 6546 } 6547 6548 if (fwdpolicy == dns_fwdpolicy_only) { 6549 dns_view_sfd_add(view, origin); 6550 } 6551 6552 result = ISC_R_SUCCESS; 6553 6554 cleanup: 6555 6556 while (!ISC_LIST_EMPTY(fwdlist)) { 6557 fwd = ISC_LIST_HEAD(fwdlist); 6558 ISC_LIST_UNLINK(fwdlist, fwd, link); 6559 if (fwd->tlsname != NULL) { 6560 dns_name_free(fwd->tlsname, view->mctx); 6561 isc_mem_put(view->mctx, fwd->tlsname, 6562 sizeof(dns_name_t)); 6563 } 6564 isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t)); 6565 } 6566 6567 return result; 6568 } 6569 6570 static isc_result_t 6571 get_viewinfo(const cfg_obj_t *vconfig, const char **namep, 6572 dns_rdataclass_t *classp) { 6573 isc_result_t result = ISC_R_SUCCESS; 6574 const char *viewname; 6575 dns_rdataclass_t viewclass; 6576 6577 REQUIRE(namep != NULL && *namep == NULL); 6578 REQUIRE(classp != NULL); 6579 6580 if (vconfig != NULL) { 6581 const cfg_obj_t *classobj = NULL; 6582 6583 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 6584 classobj = cfg_tuple_get(vconfig, "class"); 6585 CHECK(named_config_getclass(classobj, dns_rdataclass_in, 6586 &viewclass)); 6587 if (dns_rdataclass_ismeta(viewclass)) { 6588 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6589 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6590 "view '%s': class must not be meta", 6591 viewname); 6592 CHECK(ISC_R_FAILURE); 6593 } 6594 } else { 6595 viewname = "_default"; 6596 viewclass = dns_rdataclass_in; 6597 } 6598 6599 *namep = viewname; 6600 *classp = viewclass; 6601 6602 cleanup: 6603 return result; 6604 } 6605 6606 /* 6607 * Find a view based on its configuration info and attach to it. 6608 * 6609 * If 'vconfig' is NULL, attach to the default view. 6610 */ 6611 static isc_result_t 6612 find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 6613 dns_view_t **viewp) { 6614 isc_result_t result; 6615 const char *viewname = NULL; 6616 dns_rdataclass_t viewclass; 6617 dns_view_t *view = NULL; 6618 6619 result = get_viewinfo(vconfig, &viewname, &viewclass); 6620 if (result != ISC_R_SUCCESS) { 6621 return result; 6622 } 6623 6624 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 6625 if (result != ISC_R_SUCCESS) { 6626 return result; 6627 } 6628 6629 *viewp = view; 6630 return ISC_R_SUCCESS; 6631 } 6632 6633 /* 6634 * Create a new view and add it to the list. 6635 * 6636 * If 'vconfig' is NULL, create the default view. 6637 * 6638 * The view created is attached to '*viewp'. 6639 */ 6640 static isc_result_t 6641 create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 6642 dns_view_t **viewp) { 6643 isc_result_t result; 6644 const char *viewname = NULL; 6645 dns_rdataclass_t viewclass; 6646 dns_view_t *view = NULL; 6647 6648 result = get_viewinfo(vconfig, &viewname, &viewclass); 6649 if (result != ISC_R_SUCCESS) { 6650 return result; 6651 } 6652 6653 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 6654 if (result == ISC_R_SUCCESS) { 6655 return ISC_R_EXISTS; 6656 } 6657 if (result != ISC_R_NOTFOUND) { 6658 return result; 6659 } 6660 INSIST(view == NULL); 6661 6662 result = dns_view_create(named_g_mctx, named_g_loopmgr, 6663 named_g_dispatchmgr, viewclass, viewname, 6664 &view); 6665 if (result != ISC_R_SUCCESS) { 6666 return result; 6667 } 6668 6669 isc_nonce_buf(view->secret, sizeof(view->secret)); 6670 6671 ISC_LIST_APPEND(*viewlist, view, link); 6672 dns_view_attach(view, viewp); 6673 return ISC_R_SUCCESS; 6674 } 6675 6676 /* 6677 * Configure or reconfigure a zone. 6678 */ 6679 static isc_result_t 6680 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 6681 const cfg_obj_t *vconfig, dns_view_t *view, 6682 dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, 6683 dns_keystorelist_t *keystores, cfg_aclconfctx_t *aclconf, 6684 bool added, bool old_rpz_ok, bool is_catz_member, bool modify) { 6685 dns_view_t *pview = NULL; /* Production view */ 6686 dns_zone_t *zone = NULL; /* New or reused zone */ 6687 dns_zone_t *raw = NULL; /* New or reused raw zone */ 6688 dns_zone_t *dupzone = NULL; 6689 const cfg_obj_t *options = NULL; 6690 const cfg_obj_t *zoptions = NULL; 6691 const cfg_obj_t *typeobj = NULL; 6692 const cfg_obj_t *forwarders = NULL; 6693 const cfg_obj_t *forwardtype = NULL; 6694 const cfg_obj_t *ixfrfromdiffs = NULL; 6695 const cfg_obj_t *viewobj = NULL; 6696 isc_result_t result = ISC_R_SUCCESS; 6697 isc_result_t tresult; 6698 isc_buffer_t buffer; 6699 dns_fixedname_t fixorigin; 6700 dns_name_t *origin; 6701 const char *zname; 6702 dns_rdataclass_t zclass; 6703 const char *ztypestr; 6704 dns_rpz_num_t rpz_num; 6705 bool zone_is_catz = false; 6706 bool zone_maybe_inline = false; 6707 bool inline_signing = false; 6708 bool fullsign = false; 6709 6710 options = NULL; 6711 (void)cfg_map_get(config, "options", &options); 6712 6713 zoptions = cfg_tuple_get(zconfig, "options"); 6714 6715 /* 6716 * Get the zone origin as a dns_name_t. 6717 */ 6718 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 6719 isc_buffer_constinit(&buffer, zname, strlen(zname)); 6720 isc_buffer_add(&buffer, strlen(zname)); 6721 dns_fixedname_init(&fixorigin); 6722 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, 6723 dns_rootname, 0, NULL)); 6724 origin = dns_fixedname_name(&fixorigin); 6725 6726 CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"), 6727 view->rdclass, &zclass)); 6728 if (zclass != view->rdclass) { 6729 const char *vname = NULL; 6730 if (vconfig != NULL) { 6731 vname = cfg_obj_asstring( 6732 cfg_tuple_get(vconfig, "name")); 6733 } else { 6734 vname = "<default view>"; 6735 } 6736 6737 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6738 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6739 "zone '%s': wrong class for view '%s'", zname, 6740 vname); 6741 result = ISC_R_FAILURE; 6742 goto cleanup; 6743 } 6744 6745 (void)cfg_map_get(zoptions, "in-view", &viewobj); 6746 if (viewobj != NULL) { 6747 const char *inview = cfg_obj_asstring(viewobj); 6748 dns_view_t *otherview = NULL; 6749 6750 if (viewlist == NULL) { 6751 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6752 "'in-view' option is not permitted in " 6753 "dynamically added zones"); 6754 result = ISC_R_FAILURE; 6755 goto cleanup; 6756 } 6757 6758 result = dns_viewlist_find(viewlist, inview, view->rdclass, 6759 &otherview); 6760 if (result != ISC_R_SUCCESS) { 6761 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6762 "view '%s' is not yet defined.", inview); 6763 result = ISC_R_FAILURE; 6764 goto cleanup; 6765 } 6766 6767 result = dns_view_findzone(otherview, origin, DNS_ZTFIND_EXACT, 6768 &zone); 6769 dns_view_detach(&otherview); 6770 if (result != ISC_R_SUCCESS) { 6771 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6772 "zone '%s' not defined in view '%s'", zname, 6773 inview); 6774 result = ISC_R_FAILURE; 6775 goto cleanup; 6776 } 6777 6778 CHECK(dns_view_addzone(view, zone)); 6779 dns_zone_detach(&zone); 6780 6781 /* 6782 * If the zone contains a 'forwarders' statement, configure 6783 * selective forwarding. Note: this is not inherited from the 6784 * other view. 6785 */ 6786 forwarders = NULL; 6787 result = cfg_map_get(zoptions, "forwarders", &forwarders); 6788 if (result == ISC_R_SUCCESS) { 6789 forwardtype = NULL; 6790 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6791 CHECK(configure_forward(config, view, origin, 6792 forwarders, forwardtype)); 6793 } 6794 result = ISC_R_SUCCESS; 6795 goto cleanup; 6796 } 6797 6798 (void)cfg_map_get(zoptions, "type", &typeobj); 6799 if (typeobj == NULL) { 6800 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6801 "zone '%s' 'type' not specified", zname); 6802 result = ISC_R_FAILURE; 6803 goto cleanup; 6804 } 6805 ztypestr = cfg_obj_asstring(typeobj); 6806 6807 /* 6808 * "hints zones" aren't zones. If we've got one, 6809 * configure it and return. 6810 */ 6811 if (strcasecmp(ztypestr, "hint") == 0) { 6812 const cfg_obj_t *fileobj = NULL; 6813 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { 6814 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6815 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6816 "zone '%s': 'file' not specified", zname); 6817 result = ISC_R_FAILURE; 6818 goto cleanup; 6819 } 6820 if (dns_name_equal(origin, dns_rootname)) { 6821 const char *hintsfile = cfg_obj_asstring(fileobj); 6822 6823 CHECK(configure_hints(view, hintsfile)); 6824 } else { 6825 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6826 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 6827 "ignoring non-root hint zone '%s'", 6828 zname); 6829 result = ISC_R_SUCCESS; 6830 } 6831 /* Skip ordinary zone processing. */ 6832 goto cleanup; 6833 } 6834 6835 /* 6836 * "forward zones" aren't zones either. Translate this syntax into 6837 * the appropriate selective forwarding configuration and return. 6838 */ 6839 if (strcasecmp(ztypestr, "forward") == 0) { 6840 forwardtype = NULL; 6841 forwarders = NULL; 6842 6843 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6844 (void)cfg_map_get(zoptions, "forwarders", &forwarders); 6845 CHECK(configure_forward(config, view, origin, forwarders, 6846 forwardtype)); 6847 goto cleanup; 6848 } 6849 6850 /* 6851 * Redirect zones only require minimal configuration. 6852 */ 6853 if (strcasecmp(ztypestr, "redirect") == 0) { 6854 if (view->redirect != NULL) { 6855 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6856 "redirect zone already exists"); 6857 result = ISC_R_EXISTS; 6858 goto cleanup; 6859 } 6860 result = dns_viewlist_find(viewlist, view->name, view->rdclass, 6861 &pview); 6862 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6863 goto cleanup; 6864 } 6865 if (pview != NULL && pview->redirect != NULL) { 6866 dns_zone_attach(pview->redirect, &zone); 6867 dns_zone_setview(zone, view); 6868 } else { 6869 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, 6870 &zone)); 6871 CHECK(dns_zone_setorigin(zone, origin)); 6872 dns_zone_setview(zone, view); 6873 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, 6874 zone)); 6875 dns_zone_setstats(zone, named_g_server->zonestats); 6876 } 6877 CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, 6878 kasplist, keystores, zone, NULL)); 6879 dns_zone_attach(zone, &view->redirect); 6880 goto cleanup; 6881 } 6882 6883 if (!modify) { 6884 /* 6885 * Check for duplicates in the new zone table. 6886 */ 6887 result = dns_view_findzone(view, origin, DNS_ZTFIND_EXACT, 6888 &dupzone); 6889 if (result == ISC_R_SUCCESS) { 6890 /* 6891 * We already have this zone! 6892 */ 6893 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6894 "zone '%s' already exists", zname); 6895 dns_zone_detach(&dupzone); 6896 result = ISC_R_EXISTS; 6897 goto cleanup; 6898 } 6899 INSIST(dupzone == NULL); 6900 } 6901 6902 /* 6903 * Note whether this is a response policy zone and which one if so, 6904 * unless we are using RPZ service interface. In that case, the 6905 * BIND zone database has nothing to do with rpz and so we don't care. 6906 */ 6907 for (rpz_num = 0;; ++rpz_num) { 6908 if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones || 6909 view->rpzs->p.dnsrps_enabled) 6910 { 6911 rpz_num = DNS_RPZ_INVALID_NUM; 6912 break; 6913 } 6914 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin)) 6915 { 6916 break; 6917 } 6918 } 6919 6920 if (!is_catz_member && view->catzs != NULL && 6921 dns_catz_zone_get(view->catzs, origin) != NULL) 6922 { 6923 zone_is_catz = true; 6924 } 6925 6926 /* 6927 * See if we can reuse an existing zone. This is 6928 * only possible if all of these are true: 6929 * - The zone's view exists 6930 * - A zone with the right name exists in the view 6931 * - The zone is compatible with the config 6932 * options (e.g., an existing primary zone cannot 6933 * be reused if the options specify a secondary zone) 6934 * - The zone was not and is still not a response policy zone 6935 * or the zone is a policy zone with an unchanged number 6936 * and we are using the old policy zone summary data. 6937 */ 6938 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 6939 view->rdclass, &pview); 6940 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6941 goto cleanup; 6942 } 6943 if (pview != NULL) { 6944 result = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, 6945 &zone); 6946 } 6947 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6948 goto cleanup; 6949 } 6950 6951 if (zone != NULL && 6952 !named_zone_reusable(zone, zconfig, vconfig, config, kasplist)) 6953 { 6954 dns_zone_detach(&zone); 6955 fullsign = true; 6956 } 6957 6958 if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) || 6959 (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok))) 6960 { 6961 dns_zone_detach(&zone); 6962 } 6963 6964 if (zone != NULL) { 6965 /* 6966 * We found a reusable zone. Make it use the 6967 * new view. 6968 */ 6969 dns_zone_setview(zone, view); 6970 } else { 6971 /* 6972 * We cannot reuse an existing zone, we have 6973 * to create a new one. 6974 */ 6975 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 6976 CHECK(dns_zone_setorigin(zone, origin)); 6977 dns_zone_setview(zone, view); 6978 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 6979 dns_zone_setstats(zone, named_g_server->zonestats); 6980 } 6981 if (rpz_num != DNS_RPZ_INVALID_NUM) { 6982 result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num); 6983 if (result != ISC_R_SUCCESS) { 6984 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6985 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6986 "zone '%s': incompatible" 6987 " masterfile-format or database" 6988 " for a response policy zone", 6989 zname); 6990 goto cleanup; 6991 } 6992 } 6993 6994 if (zone_is_catz) { 6995 dns_zone_catz_enable(zone, view->catzs); 6996 } else if (dns_zone_catz_is_enabled(zone)) { 6997 dns_zone_catz_disable(zone); 6998 } 6999 7000 /* 7001 * If the zone contains a 'forwarders' statement, configure 7002 * selective forwarding. 7003 */ 7004 forwarders = NULL; 7005 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) { 7006 forwardtype = NULL; 7007 (void)cfg_map_get(zoptions, "forward", &forwardtype); 7008 CHECK(configure_forward(config, view, origin, forwarders, 7009 forwardtype)); 7010 } 7011 7012 /* 7013 * Mark whether the zone was originally added at runtime or not 7014 */ 7015 if (!modify) { 7016 dns_zone_setadded(zone, added); 7017 } 7018 7019 /* 7020 * Determine if we need to set up inline signing. 7021 */ 7022 zone_maybe_inline = (strcasecmp(ztypestr, "primary") == 0 || 7023 strcasecmp(ztypestr, "master") == 0 || 7024 strcasecmp(ztypestr, "secondary") == 0 || 7025 strcasecmp(ztypestr, "slave") == 0); 7026 7027 if (zone_maybe_inline) { 7028 inline_signing = named_zone_inlinesigning(zconfig, vconfig, 7029 config, kasplist); 7030 } 7031 if (inline_signing) { 7032 dns_zone_getraw(zone, &raw); 7033 if (raw == NULL) { 7034 dns_zone_create(&raw, dns_zone_getmem(zone), 7035 dns_zone_gettid(zone)); 7036 CHECK(dns_zone_setorigin(raw, origin)); 7037 dns_zone_setview(raw, view); 7038 dns_zone_setstats(raw, named_g_server->zonestats); 7039 CHECK(dns_zone_link(zone, raw)); 7040 } 7041 if (cfg_map_get(zoptions, "ixfr-from-differences", 7042 &ixfrfromdiffs) == ISC_R_SUCCESS) 7043 { 7044 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7045 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7046 "zone '%s': 'ixfr-from-differences' is " 7047 "ignored for inline-signed zones", 7048 zname); 7049 } 7050 } 7051 7052 /* 7053 * Configure the zone. 7054 */ 7055 CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, kasplist, 7056 keystores, zone, raw)); 7057 7058 /* 7059 * Add the zone to its view in the new view list. 7060 */ 7061 if (!modify) { 7062 CHECK(dns_view_addzone(view, zone)); 7063 } 7064 7065 if (zone_is_catz) { 7066 /* 7067 * force catz reload if the zone is loaded; 7068 * if it's not it'll get reloaded on zone load 7069 */ 7070 dns_db_t *db = NULL; 7071 7072 tresult = dns_zone_getdb(zone, &db); 7073 if (tresult == ISC_R_SUCCESS) { 7074 dns_catz_dbupdate_callback(db, view->catzs); 7075 dns_db_detach(&db); 7076 } 7077 } 7078 7079 /* 7080 * Ensure that zone keys are reloaded on reconfig 7081 */ 7082 if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0) { 7083 dns_zone_rekey(zone, fullsign, false); 7084 } 7085 7086 cleanup: 7087 if (zone != NULL) { 7088 dns_zone_detach(&zone); 7089 } 7090 if (raw != NULL) { 7091 dns_zone_detach(&raw); 7092 } 7093 if (pview != NULL) { 7094 dns_view_detach(&pview); 7095 } 7096 7097 return result; 7098 } 7099 7100 /* 7101 * Configure built-in zone for storing managed-key data. 7102 */ 7103 static isc_result_t 7104 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { 7105 isc_result_t result; 7106 dns_view_t *pview = NULL; 7107 dns_zone_t *zone = NULL; 7108 dns_acl_t *none = NULL; 7109 char filename[PATH_MAX]; 7110 bool defaultview; 7111 7112 REQUIRE(view != NULL); 7113 7114 /* See if we can re-use an existing keydata zone. */ 7115 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 7116 view->rdclass, &pview); 7117 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 7118 return result; 7119 } 7120 7121 if (pview != NULL) { 7122 if (pview->managed_keys != NULL) { 7123 dns_zone_attach(pview->managed_keys, 7124 &view->managed_keys); 7125 dns_zone_setview(pview->managed_keys, view); 7126 dns_zone_setviewcommit(pview->managed_keys); 7127 dns_view_detach(&pview); 7128 dns_zone_synckeyzone(view->managed_keys); 7129 return ISC_R_SUCCESS; 7130 } 7131 7132 dns_view_detach(&pview); 7133 } 7134 7135 /* No existing keydata zone was found; create one */ 7136 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 7137 CHECK(dns_zone_setorigin(zone, dns_rootname)); 7138 7139 defaultview = (strcmp(view->name, "_default") == 0); 7140 CHECK(isc_file_sanitize( 7141 directory, defaultview ? "managed-keys" : view->name, 7142 defaultview ? "bind" : "mkeys", filename, sizeof(filename))); 7143 CHECK(dns_zone_setfile(zone, filename, dns_masterformat_text, 7144 &dns_master_style_default)); 7145 7146 dns_zone_setview(zone, view); 7147 dns_zone_settype(zone, dns_zone_key); 7148 dns_zone_setclass(zone, view->rdclass); 7149 7150 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 7151 7152 CHECK(dns_acl_none(mctx, &none)); 7153 dns_zone_setqueryacl(zone, none); 7154 dns_zone_setqueryonacl(zone, none); 7155 dns_acl_detach(&none); 7156 7157 dns_zone_setdialup(zone, dns_dialuptype_no); 7158 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 7159 dns_zone_setnotifytype(zone, dns_notifytype_no); 7160 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 7161 dns_zone_setjournalsize(zone, 0); 7162 7163 dns_zone_setstats(zone, named_g_server->zonestats); 7164 setquerystats(zone, mctx, dns_zonestat_none); 7165 7166 if (view->managed_keys != NULL) { 7167 dns_zone_detach(&view->managed_keys); 7168 } 7169 dns_zone_attach(zone, &view->managed_keys); 7170 7171 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7172 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7173 "set up managed keys zone for view %s, file '%s'", 7174 view->name, filename); 7175 7176 cleanup: 7177 if (zone != NULL) { 7178 dns_zone_detach(&zone); 7179 } 7180 if (none != NULL) { 7181 dns_acl_detach(&none); 7182 } 7183 7184 return result; 7185 } 7186 7187 /* 7188 * Configure a single server quota. 7189 */ 7190 static void 7191 configure_server_quota(const cfg_obj_t **maps, const char *name, 7192 isc_quota_t *quota) { 7193 const cfg_obj_t *obj = NULL; 7194 isc_result_t result; 7195 7196 result = named_config_get(maps, name, &obj); 7197 INSIST(result == ISC_R_SUCCESS); 7198 isc_quota_max(quota, cfg_obj_asuint32(obj)); 7199 } 7200 7201 /* 7202 * This function is called as soon as the 'directory' statement has been 7203 * parsed. This can be extended to support other options if necessary. 7204 */ 7205 static isc_result_t 7206 directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { 7207 isc_result_t result; 7208 const char *directory; 7209 7210 REQUIRE(strcasecmp("directory", clausename) == 0); 7211 7212 UNUSED(arg); 7213 UNUSED(clausename); 7214 7215 /* 7216 * Change directory. 7217 */ 7218 directory = cfg_obj_asstring(obj); 7219 7220 if (!isc_file_ischdiridempotent(directory)) { 7221 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 7222 "option 'directory' contains relative path '%s'", 7223 directory); 7224 } 7225 7226 if (!isc_file_isdirwritable(directory)) { 7227 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7228 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7229 "directory '%s' is not writable", directory); 7230 return ISC_R_NOPERM; 7231 } 7232 7233 result = isc_dir_chdir(directory); 7234 if (result != ISC_R_SUCCESS) { 7235 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7236 "change directory to '%s' failed: %s", directory, 7237 isc_result_totext(result)); 7238 return result; 7239 } 7240 7241 char cwd[PATH_MAX]; 7242 if (getcwd(cwd, sizeof(cwd)) == cwd) { 7243 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7244 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7245 "the working directory is now '%s'", cwd); 7246 } 7247 7248 return ISC_R_SUCCESS; 7249 } 7250 7251 /* 7252 * This event callback is invoked to do periodic network interface 7253 * scanning. 7254 */ 7255 7256 static void 7257 interface_timer_tick(void *arg) { 7258 named_server_t *server = (named_server_t *)arg; 7259 7260 (void)ns_interfacemgr_scan(server->interfacemgr, false, false); 7261 } 7262 7263 static void 7264 heartbeat_timer_tick(void *arg) { 7265 named_server_t *server = (named_server_t *)arg; 7266 dns_view_t *view = NULL; 7267 7268 view = ISC_LIST_HEAD(server->viewlist); 7269 while (view != NULL) { 7270 dns_view_dialup(view); 7271 view = ISC_LIST_NEXT(view, link); 7272 } 7273 } 7274 7275 typedef struct { 7276 isc_mem_t *mctx; 7277 isc_loop_t *loop; 7278 dns_fetch_t *fetch; 7279 dns_view_t *view; 7280 dns_fixedname_t tatname; 7281 dns_fixedname_t keyname; 7282 dns_rdataset_t rdataset; 7283 dns_rdataset_t sigrdataset; 7284 } ns_tat_t; 7285 7286 static int 7287 cid(const void *a, const void *b) { 7288 const uint16_t ida = *(const uint16_t *)a; 7289 const uint16_t idb = *(const uint16_t *)b; 7290 if (ida < idb) { 7291 return -1; 7292 } else if (ida > idb) { 7293 return 1; 7294 } else { 7295 return 0; 7296 } 7297 } 7298 7299 static void 7300 tat_done(void *arg) { 7301 dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg; 7302 ns_tat_t *tat = NULL; 7303 7304 INSIST(resp != NULL); 7305 7306 tat = resp->arg; 7307 7308 INSIST(tat != NULL); 7309 7310 /* Free resources which are not of interest */ 7311 if (resp->node != NULL) { 7312 dns_db_detachnode(resp->db, &resp->node); 7313 } 7314 if (resp->db != NULL) { 7315 dns_db_detach(&resp->db); 7316 } 7317 7318 dns_resolver_freefresp(&resp); 7319 dns_resolver_destroyfetch(&tat->fetch); 7320 if (dns_rdataset_isassociated(&tat->rdataset)) { 7321 dns_rdataset_disassociate(&tat->rdataset); 7322 } 7323 if (dns_rdataset_isassociated(&tat->sigrdataset)) { 7324 dns_rdataset_disassociate(&tat->sigrdataset); 7325 } 7326 dns_view_detach(&tat->view); 7327 isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); 7328 } 7329 7330 struct dotat_arg { 7331 dns_view_t *view; 7332 isc_loop_t *loop; 7333 }; 7334 7335 /*% 7336 * Prepare the QNAME for the TAT query to be sent by processing the trust 7337 * anchors present at 'keynode' of 'keytable'. Store the result in 'dst' and 7338 * the domain name which 'keynode' is associated with in 'origin'. 7339 * 7340 * A maximum of 12 key IDs can be reported in a single TAT query due to the 7341 * 63-octet length limit for any single label in a domain name. If there are 7342 * more than 12 keys configured at 'keynode', only the first 12 will be 7343 * reported in the TAT query. 7344 */ 7345 static isc_result_t 7346 get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) { 7347 dns_rdataset_t dsset; 7348 unsigned int i, n = 0; 7349 uint16_t ids[12]; 7350 isc_textregion_t r; 7351 char label[64]; 7352 int m; 7353 7354 dns_rdataset_init(&dsset); 7355 if (dns_keynode_dsset(keynode, &dsset)) { 7356 isc_result_t result; 7357 7358 for (result = dns_rdataset_first(&dsset); 7359 result == ISC_R_SUCCESS; 7360 result = dns_rdataset_next(&dsset)) 7361 { 7362 dns_rdata_t rdata = DNS_RDATA_INIT; 7363 dns_rdata_ds_t ds; 7364 7365 dns_rdata_reset(&rdata); 7366 dns_rdataset_current(&dsset, &rdata); 7367 result = dns_rdata_tostruct(&rdata, &ds, NULL); 7368 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7369 if (n < (sizeof(ids) / sizeof(ids[0]))) { 7370 ids[n] = ds.key_tag; 7371 n++; 7372 } 7373 } 7374 dns_rdataset_disassociate(&dsset); 7375 } 7376 7377 if (n == 0) { 7378 return DNS_R_EMPTYNAME; 7379 } 7380 7381 if (n > 1) { 7382 qsort(ids, n, sizeof(ids[0]), cid); 7383 } 7384 7385 /* 7386 * Encoded as "_ta-xxxx\(-xxxx\)*" where xxxx is the hex version of 7387 * of the keyid. 7388 */ 7389 label[0] = 0; 7390 r.base = label; 7391 r.length = sizeof(label); 7392 m = snprintf(r.base, r.length, "_ta"); 7393 if (m < 0 || (unsigned int)m > r.length) { 7394 return ISC_R_FAILURE; 7395 } 7396 isc_textregion_consume(&r, m); 7397 for (i = 0; i < n; i++) { 7398 m = snprintf(r.base, r.length, "-%04x", ids[i]); 7399 if (m < 0 || (unsigned int)m > r.length) { 7400 return ISC_R_FAILURE; 7401 } 7402 isc_textregion_consume(&r, m); 7403 } 7404 7405 return dns_name_fromstring(target, label, keyname, 0, NULL); 7406 } 7407 7408 static void 7409 tat_send(void *arg) { 7410 ns_tat_t *tat = (ns_tat_t *)arg; 7411 char namebuf[DNS_NAME_FORMATSIZE]; 7412 dns_fixedname_t fdomain; 7413 dns_name_t *domain = NULL; 7414 dns_rdataset_t nameservers; 7415 isc_result_t result; 7416 dns_name_t *keyname = NULL; 7417 dns_name_t *tatname = NULL; 7418 7419 keyname = dns_fixedname_name(&tat->keyname); 7420 tatname = dns_fixedname_name(&tat->tatname); 7421 7422 dns_name_format(tatname, namebuf, sizeof(namebuf)); 7423 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7424 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7425 "%s: sending trust-anchor-telemetry query '%s/NULL'", 7426 tat->view->name, namebuf); 7427 7428 /* 7429 * TAT queries should be sent to the authoritative servers for a given 7430 * zone. If this function is called for a keytable node corresponding 7431 * to a locally served zone, calling dns_resolver_createfetch() with 7432 * NULL 'domain' and 'nameservers' arguments will cause 'tatname' to be 7433 * resolved locally, without sending any TAT queries upstream. 7434 * 7435 * Work around this issue by calling dns_view_findzonecut() first. If 7436 * the zone is served locally, the NS RRset for the given domain name 7437 * will be retrieved from local data; if it is not, the deepest zone 7438 * cut we have for it will be retrieved from cache. In either case, 7439 * passing the results to dns_resolver_createfetch() will prevent it 7440 * from returning NXDOMAIN for 'tatname' while still allowing it to 7441 * chase down any potential delegations returned by upstream servers in 7442 * order to eventually find the destination host to send the TAT query 7443 * to. 7444 * 7445 * After the dns_view_findzonecut() call, 'domain' will hold the 7446 * deepest zone cut we can find for 'keyname' while 'nameservers' will 7447 * hold the NS RRset at that zone cut. 7448 */ 7449 domain = dns_fixedname_initname(&fdomain); 7450 dns_rdataset_init(&nameservers); 7451 result = dns_view_findzonecut(tat->view, keyname, domain, NULL, 0, 0, 7452 true, true, &nameservers, NULL); 7453 if (result == ISC_R_SUCCESS) { 7454 result = dns_resolver_createfetch( 7455 tat->view->resolver, tatname, dns_rdatatype_null, 7456 domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, NULL, 7457 NULL, tat->loop, tat_done, tat, NULL, &tat->rdataset, 7458 &tat->sigrdataset, &tat->fetch); 7459 } 7460 7461 /* 7462 * 'domain' holds the dns_name_t pointer inside a dst_key_t structure. 7463 * dns_resolver_createfetch() creates its own copy of 'domain' if it 7464 * succeeds. Thus, 'domain' is not freed here. 7465 * 7466 * Even if dns_view_findzonecut() returned something else than 7467 * ISC_R_SUCCESS, it still could have associated 'nameservers'. 7468 * dns_resolver_createfetch() creates its own copy of 'nameservers' if 7469 * it succeeds. Thus, we need to check whether 'nameservers' is 7470 * associated and release it if it is. 7471 */ 7472 if (dns_rdataset_isassociated(&nameservers)) { 7473 dns_rdataset_disassociate(&nameservers); 7474 } 7475 7476 if (result != ISC_R_SUCCESS) { 7477 dns_view_detach(&tat->view); 7478 isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); 7479 } 7480 } 7481 7482 static void 7483 dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, dns_name_t *keyname, 7484 void *arg) { 7485 struct dotat_arg *dotat_arg = (struct dotat_arg *)arg; 7486 isc_result_t result; 7487 dns_view_t *view = NULL; 7488 ns_tat_t *tat = NULL; 7489 7490 REQUIRE(keytable != NULL); 7491 REQUIRE(keynode != NULL); 7492 REQUIRE(dotat_arg != NULL); 7493 7494 view = dotat_arg->view; 7495 7496 tat = isc_mem_get(view->mctx, sizeof(*tat)); 7497 *tat = (ns_tat_t){ 0 }; 7498 7499 dns_rdataset_init(&tat->rdataset); 7500 dns_rdataset_init(&tat->sigrdataset); 7501 dns_name_copy(keyname, dns_fixedname_initname(&tat->keyname)); 7502 result = get_tat_qname(dns_fixedname_initname(&tat->tatname), keyname, 7503 keynode); 7504 if (result != ISC_R_SUCCESS) { 7505 isc_mem_put(view->mctx, tat, sizeof(*tat)); 7506 return; 7507 } 7508 isc_mem_attach(view->mctx, &tat->mctx); 7509 tat->loop = dotat_arg->loop; 7510 dns_view_attach(view, &tat->view); 7511 7512 /* 7513 * We don't want to be holding the keytable lock when calling 7514 * dns_view_findzonecut() as it creates a lock order loop so 7515 * call dns_view_findzonecut() in a event handler. 7516 * 7517 * zone->lock (dns_zone_setviewcommit) while holding view->lock 7518 * (dns_view_setviewcommit) 7519 * 7520 * keytable->lock (dns_keytable_find) while holding zone->lock 7521 * (zone_asyncload) 7522 * 7523 * view->lock (dns_view_findzonecut) while holding keytable->lock 7524 * (dns_keytable_forall) 7525 */ 7526 isc_async_run(named_g_mainloop, tat_send, tat); 7527 } 7528 7529 static void 7530 tat_timer_tick(void *arg) { 7531 isc_result_t result; 7532 named_server_t *server = (named_server_t *)arg; 7533 struct dotat_arg dotat_arg = { 0 }; 7534 dns_view_t *view = NULL; 7535 dns_keytable_t *secroots = NULL; 7536 7537 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 7538 view = ISC_LIST_NEXT(view, link)) 7539 { 7540 if (!view->trust_anchor_telemetry || !view->enablevalidation) { 7541 continue; 7542 } 7543 7544 result = dns_view_getsecroots(view, &secroots); 7545 if (result != ISC_R_SUCCESS) { 7546 continue; 7547 } 7548 7549 dotat_arg.view = view; 7550 dotat_arg.loop = named_g_mainloop; 7551 dns_keytable_forall(secroots, dotat, &dotat_arg); 7552 dns_keytable_detach(&secroots); 7553 } 7554 } 7555 7556 static void 7557 pps_timer_tick(void *arg) { 7558 static unsigned int oldrequests = 0; 7559 unsigned int requests = atomic_load_relaxed(&ns_client_requests); 7560 7561 UNUSED(arg); 7562 7563 /* 7564 * Don't worry about wrapping as the overflow result will be right. 7565 */ 7566 dns_pps = (requests - oldrequests) / 1200; 7567 oldrequests = requests; 7568 } 7569 7570 /* 7571 * Replace the current value of '*field', a dynamically allocated 7572 * string or NULL, with a dynamically allocated copy of the 7573 * null-terminated string pointed to by 'value', or NULL. 7574 */ 7575 static void 7576 setstring(named_server_t *server, char **field, const char *value) { 7577 char *copy; 7578 7579 if (value != NULL) { 7580 copy = isc_mem_strdup(server->mctx, value); 7581 } else { 7582 copy = NULL; 7583 } 7584 7585 if (*field != NULL) { 7586 isc_mem_free(server->mctx, *field); 7587 } 7588 7589 *field = copy; 7590 } 7591 7592 /* 7593 * Replace the current value of '*field', a dynamically allocated 7594 * string or NULL, with another dynamically allocated string 7595 * or NULL if whether 'obj' is a string or void value, respectively. 7596 */ 7597 static void 7598 setoptstring(named_server_t *server, char **field, const cfg_obj_t *obj) { 7599 if (cfg_obj_isvoid(obj)) { 7600 setstring(server, field, NULL); 7601 } else { 7602 setstring(server, field, cfg_obj_asstring(obj)); 7603 } 7604 } 7605 7606 static void 7607 portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports, 7608 bool positive) { 7609 const cfg_listelt_t *element; 7610 7611 for (element = cfg_list_first(ports); element != NULL; 7612 element = cfg_list_next(element)) 7613 { 7614 const cfg_obj_t *obj = cfg_listelt_value(element); 7615 7616 if (cfg_obj_isuint32(obj)) { 7617 in_port_t port = (in_port_t)cfg_obj_asuint32(obj); 7618 7619 if (positive) { 7620 isc_portset_add(portset, port); 7621 } else { 7622 isc_portset_remove(portset, port); 7623 } 7624 } else { 7625 const cfg_obj_t *obj_loport, *obj_hiport; 7626 in_port_t loport, hiport; 7627 7628 obj_loport = cfg_tuple_get(obj, "loport"); 7629 loport = (in_port_t)cfg_obj_asuint32(obj_loport); 7630 obj_hiport = cfg_tuple_get(obj, "hiport"); 7631 hiport = (in_port_t)cfg_obj_asuint32(obj_hiport); 7632 7633 if (positive) { 7634 isc_portset_addrange(portset, loport, hiport); 7635 } else { 7636 isc_portset_removerange(portset, loport, 7637 hiport); 7638 } 7639 } 7640 } 7641 } 7642 7643 static isc_result_t 7644 removed(dns_zone_t *zone, void *uap) { 7645 if (dns_zone_getview(zone) != uap) { 7646 return ISC_R_SUCCESS; 7647 } 7648 7649 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", 7650 dns_zonetype_name(dns_zone_gettype(zone))); 7651 return ISC_R_SUCCESS; 7652 } 7653 7654 static void 7655 cleanup_session_key(named_server_t *server, isc_mem_t *mctx) { 7656 if (server->session_keyfile != NULL) { 7657 isc_file_remove(server->session_keyfile); 7658 isc_mem_free(mctx, server->session_keyfile); 7659 server->session_keyfile = NULL; 7660 } 7661 7662 if (server->session_keyname != NULL) { 7663 if (dns_name_dynamic(server->session_keyname)) { 7664 dns_name_free(server->session_keyname, mctx); 7665 } 7666 isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); 7667 server->session_keyname = NULL; 7668 } 7669 7670 if (server->sessionkey != NULL) { 7671 dst_key_free(&server->sessionkey); 7672 } 7673 7674 server->session_keyalg = DST_ALG_UNKNOWN; 7675 server->session_keybits = 0; 7676 } 7677 7678 static isc_result_t 7679 generate_session_key(const char *filename, const char *keynamestr, 7680 const dns_name_t *keyname, dst_algorithm_t alg, 7681 uint16_t bits, isc_mem_t *mctx, bool first_time, 7682 dst_key_t **keyp) { 7683 isc_result_t result = ISC_R_SUCCESS; 7684 dst_key_t *key = NULL; 7685 isc_buffer_t key_txtbuffer; 7686 isc_buffer_t key_rawbuffer; 7687 char key_txtsecret[256]; 7688 char key_rawsecret[64]; 7689 isc_region_t key_rawregion; 7690 FILE *fp = NULL; 7691 7692 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7693 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7694 "generating session key for dynamic DNS"); 7695 7696 /* generate key */ 7697 result = dst_key_generate(keyname, alg, bits, 1, 0, DNS_KEYPROTO_ANY, 7698 dns_rdataclass_in, NULL, mctx, &key, NULL); 7699 if (result != ISC_R_SUCCESS) { 7700 return result; 7701 } 7702 7703 /* 7704 * Dump the key to the buffer for later use. 7705 */ 7706 isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); 7707 CHECK(dst_key_tobuffer(key, &key_rawbuffer)); 7708 7709 isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); 7710 isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); 7711 CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); 7712 7713 /* Dump the key to the key file. */ 7714 fp = named_os_openfile(filename, S_IRUSR | S_IWUSR, first_time); 7715 if (fp == NULL) { 7716 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7717 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7718 "could not create %s", filename); 7719 result = ISC_R_NOPERM; 7720 goto cleanup; 7721 } 7722 7723 fprintf(fp, 7724 "key \"%s\" {\n" 7725 "\talgorithm %s;\n" 7726 "\tsecret \"%.*s\";\n};\n", 7727 keynamestr, dst_hmac_algorithm_totext(alg), 7728 (int)isc_buffer_usedlength(&key_txtbuffer), 7729 (char *)isc_buffer_base(&key_txtbuffer)); 7730 7731 CHECK(isc_stdio_flush(fp)); 7732 result = isc_stdio_close(fp); 7733 if (result != ISC_R_SUCCESS) { 7734 goto cleanup; 7735 } 7736 7737 *keyp = key; 7738 return ISC_R_SUCCESS; 7739 7740 cleanup: 7741 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7742 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7743 "failed to generate session key " 7744 "for dynamic DNS: %s", 7745 isc_result_totext(result)); 7746 if (fp != NULL) { 7747 (void)isc_stdio_close(fp); 7748 (void)isc_file_remove(filename); 7749 } 7750 if (key != NULL) { 7751 dst_key_free(&key); 7752 } 7753 7754 return result; 7755 } 7756 7757 static isc_result_t 7758 configure_session_key(const cfg_obj_t **maps, named_server_t *server, 7759 isc_mem_t *mctx, bool first_time) { 7760 const char *keyfile = NULL, *keynamestr = NULL, *algstr = NULL; 7761 unsigned int algtype; 7762 dns_fixedname_t fname; 7763 dns_name_t *keyname = NULL; 7764 isc_buffer_t buffer; 7765 uint16_t bits; 7766 const cfg_obj_t *obj = NULL; 7767 bool need_deleteold = false; 7768 bool need_createnew = false; 7769 isc_result_t result; 7770 7771 obj = NULL; 7772 result = named_config_get(maps, "session-keyfile", &obj); 7773 if (result == ISC_R_SUCCESS) { 7774 if (cfg_obj_isvoid(obj)) { 7775 keyfile = NULL; /* disable it */ 7776 } else { 7777 keyfile = cfg_obj_asstring(obj); 7778 } 7779 } else { 7780 keyfile = named_g_defaultsessionkeyfile; 7781 } 7782 7783 obj = NULL; 7784 result = named_config_get(maps, "session-keyname", &obj); 7785 INSIST(result == ISC_R_SUCCESS); 7786 keynamestr = cfg_obj_asstring(obj); 7787 isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr)); 7788 isc_buffer_add(&buffer, strlen(keynamestr)); 7789 keyname = dns_fixedname_initname(&fname); 7790 result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); 7791 if (result != ISC_R_SUCCESS) { 7792 return result; 7793 } 7794 7795 obj = NULL; 7796 result = named_config_get(maps, "session-keyalg", &obj); 7797 INSIST(result == ISC_R_SUCCESS); 7798 algstr = cfg_obj_asstring(obj); 7799 result = named_config_getkeyalgorithm(algstr, &algtype, &bits); 7800 if (result != ISC_R_SUCCESS) { 7801 const char *s = " (keeping current key)"; 7802 7803 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7804 "session-keyalg: " 7805 "unsupported or unknown algorithm '%s'%s", 7806 algstr, server->session_keyfile != NULL ? s : ""); 7807 return result; 7808 } 7809 7810 /* See if we need to (re)generate a new key. */ 7811 if (keyfile == NULL) { 7812 if (server->session_keyfile != NULL) { 7813 need_deleteold = true; 7814 } 7815 } else if (server->session_keyfile == NULL) { 7816 need_createnew = true; 7817 } else if (strcmp(keyfile, server->session_keyfile) != 0 || 7818 !dns_name_equal(server->session_keyname, keyname) || 7819 server->session_keyalg != algtype || 7820 server->session_keybits != bits) 7821 { 7822 need_deleteold = true; 7823 need_createnew = true; 7824 } 7825 7826 if (need_deleteold) { 7827 INSIST(server->session_keyfile != NULL); 7828 INSIST(server->session_keyname != NULL); 7829 INSIST(server->sessionkey != NULL); 7830 7831 cleanup_session_key(server, mctx); 7832 } 7833 7834 if (need_createnew) { 7835 INSIST(server->sessionkey == NULL); 7836 INSIST(server->session_keyfile == NULL); 7837 INSIST(server->session_keyname == NULL); 7838 INSIST(server->session_keyalg == DST_ALG_UNKNOWN); 7839 INSIST(server->session_keybits == 0); 7840 7841 server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); 7842 dns_name_init(server->session_keyname, NULL); 7843 dns_name_dup(keyname, mctx, server->session_keyname); 7844 7845 server->session_keyfile = isc_mem_strdup(mctx, keyfile); 7846 7847 server->session_keyalg = algtype; 7848 server->session_keybits = bits; 7849 7850 CHECK(generate_session_key(keyfile, keynamestr, keyname, 7851 algtype, bits, mctx, first_time, 7852 &server->sessionkey)); 7853 } 7854 7855 return result; 7856 7857 cleanup: 7858 cleanup_session_key(server, mctx); 7859 return result; 7860 } 7861 7862 static isc_result_t 7863 setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 7864 cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx) { 7865 isc_result_t result = ISC_R_SUCCESS; 7866 bool allow = false; 7867 ns_cfgctx_t *nzcfg = NULL; 7868 const cfg_obj_t *maps[4]; 7869 const cfg_obj_t *options = NULL, *voptions = NULL; 7870 const cfg_obj_t *nz = NULL; 7871 const cfg_obj_t *nzdir = NULL; 7872 const char *dir = NULL; 7873 const cfg_obj_t *obj = NULL; 7874 int i = 0; 7875 uint64_t mapsize = 0ULL; 7876 7877 REQUIRE(config != NULL); 7878 7879 if (vconfig != NULL) { 7880 voptions = cfg_tuple_get(vconfig, "options"); 7881 } 7882 if (voptions != NULL) { 7883 maps[i++] = voptions; 7884 } 7885 result = cfg_map_get(config, "options", &options); 7886 if (result == ISC_R_SUCCESS) { 7887 maps[i++] = options; 7888 } 7889 maps[i++] = named_g_defaults; 7890 maps[i] = NULL; 7891 7892 result = named_config_get(maps, "allow-new-zones", &nz); 7893 if (result == ISC_R_SUCCESS) { 7894 allow = cfg_obj_asboolean(nz); 7895 } 7896 result = named_config_get(maps, "new-zones-directory", &nzdir); 7897 if (result == ISC_R_SUCCESS) { 7898 dir = cfg_obj_asstring(nzdir); 7899 result = isc_file_isdirectory(dir); 7900 if (result != ISC_R_SUCCESS) { 7901 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 7902 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7903 "invalid new-zones-directory %s: %s", dir, 7904 isc_result_totext(result)); 7905 return result; 7906 } 7907 if (!isc_file_isdirwritable(dir)) { 7908 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7909 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7910 "new-zones-directory '%s' " 7911 "is not writable", 7912 dir); 7913 return ISC_R_NOPERM; 7914 } 7915 7916 dns_view_setnewzonedir(view, dir); 7917 } 7918 7919 #ifdef HAVE_LMDB 7920 result = named_config_get(maps, "lmdb-mapsize", &obj); 7921 if (result == ISC_R_SUCCESS && obj != NULL) { 7922 mapsize = cfg_obj_asuint64(obj); 7923 if (mapsize < (1ULL << 20)) { /* 1 megabyte */ 7924 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7925 "'lmdb-mapsize " 7926 "%" PRId64 "' " 7927 "is too small", 7928 mapsize); 7929 return ISC_R_FAILURE; 7930 } else if (mapsize > (1ULL << 40)) { /* 1 terabyte */ 7931 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7932 "'lmdb-mapsize " 7933 "%" PRId64 "' " 7934 "is too large", 7935 mapsize); 7936 return ISC_R_FAILURE; 7937 } 7938 } 7939 #else /* ifdef HAVE_LMDB */ 7940 UNUSED(obj); 7941 #endif /* HAVE_LMDB */ 7942 7943 /* 7944 * A non-empty catalog-zones statement implies allow-new-zones 7945 */ 7946 if (!allow) { 7947 const cfg_obj_t *cz = NULL; 7948 result = named_config_get(maps, "catalog-zones", &cz); 7949 if (result == ISC_R_SUCCESS) { 7950 const cfg_listelt_t *e = 7951 cfg_list_first(cfg_tuple_get(cz, "zone list")); 7952 if (e != NULL) { 7953 allow = true; 7954 } 7955 } 7956 } 7957 7958 if (!allow) { 7959 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 7960 return ISC_R_SUCCESS; 7961 } 7962 7963 nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg)); 7964 *nzcfg = (ns_cfgctx_t){ 0 }; 7965 7966 /* 7967 * We attach the parser that was used for config as well 7968 * as the one that will be used for added zones, to avoid 7969 * a shutdown race later. 7970 */ 7971 isc_mem_attach(view->mctx, &nzcfg->mctx); 7972 cfg_parser_attach(conf_parser, &nzcfg->conf_parser); 7973 cfg_parser_attach(named_g_addparser, &nzcfg->add_parser); 7974 cfg_aclconfctx_attach(actx, &nzcfg->actx); 7975 7976 result = dns_view_setnewzones(view, true, nzcfg, newzone_cfgctx_destroy, 7977 mapsize); 7978 if (result != ISC_R_SUCCESS) { 7979 cfg_aclconfctx_detach(&nzcfg->actx); 7980 cfg_parser_destroy(&nzcfg->add_parser); 7981 cfg_parser_destroy(&nzcfg->conf_parser); 7982 isc_mem_putanddetach(&nzcfg->mctx, nzcfg, sizeof(*nzcfg)); 7983 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 7984 return result; 7985 } 7986 7987 cfg_obj_attach(config, &nzcfg->config); 7988 if (vconfig != NULL) { 7989 cfg_obj_attach(vconfig, &nzcfg->vconfig); 7990 } 7991 7992 result = load_nzf(view, nzcfg); 7993 return result; 7994 } 7995 7996 static void 7997 configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, 7998 dns_view_t *view) { 7999 const char *zname; 8000 dns_fixedname_t fixorigin; 8001 dns_name_t *origin; 8002 isc_result_t result2; 8003 dns_view_t *pview = NULL; 8004 dns_zone_t *zone = NULL; 8005 8006 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 8007 origin = dns_fixedname_initname(&fixorigin); 8008 8009 result2 = dns_name_fromstring(origin, zname, dns_rootname, 0, NULL); 8010 if (result2 != ISC_R_SUCCESS) { 8011 return; 8012 } 8013 8014 result2 = dns_viewlist_find(&named_g_server->viewlist, view->name, 8015 view->rdclass, &pview); 8016 if (result2 != ISC_R_SUCCESS) { 8017 return; 8018 } 8019 8020 result2 = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, &zone); 8021 if (result2 != ISC_R_SUCCESS) { 8022 dns_view_detach(&pview); 8023 return; 8024 } 8025 8026 if (result == ISC_R_SUCCESS) { 8027 dns_zone_setviewcommit(zone); 8028 } else { 8029 dns_zone_setviewrevert(zone); 8030 } 8031 8032 dns_zone_detach(&zone); 8033 dns_view_detach(&pview); 8034 } 8035 8036 #ifndef HAVE_LMDB 8037 8038 static isc_result_t 8039 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 8040 cfg_aclconfctx_t *actx) { 8041 isc_result_t result; 8042 ns_cfgctx_t *nzctx; 8043 const cfg_obj_t *zonelist; 8044 const cfg_listelt_t *element; 8045 8046 nzctx = view->new_zone_config; 8047 if (nzctx == NULL || nzctx->nzf_config == NULL) { 8048 return ISC_R_SUCCESS; 8049 } 8050 8051 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8052 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8053 "loading additional zones for view '%s'", view->name); 8054 8055 zonelist = NULL; 8056 cfg_map_get(nzctx->nzf_config, "zone", &zonelist); 8057 8058 for (element = cfg_list_first(zonelist); element != NULL; 8059 element = cfg_list_next(element)) 8060 { 8061 const cfg_obj_t *zconfig = cfg_listelt_value(element); 8062 CHECK(configure_zone(config, zconfig, vconfig, view, 8063 &named_g_server->viewlist, 8064 &named_g_server->kasplist, 8065 &named_g_server->keystorelist, actx, true, 8066 false, false, false)); 8067 } 8068 8069 result = ISC_R_SUCCESS; 8070 8071 cleanup: 8072 for (element = cfg_list_first(zonelist); element != NULL; 8073 element = cfg_list_next(element)) 8074 { 8075 const cfg_obj_t *zconfig = cfg_listelt_value(element); 8076 configure_zone_setviewcommit(result, zconfig, view); 8077 } 8078 8079 return result; 8080 } 8081 8082 #else /* HAVE_LMDB */ 8083 8084 static isc_result_t 8085 data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, 8086 cfg_obj_t **zoneconfig) { 8087 isc_result_t result; 8088 const char *zone_name; 8089 size_t zone_name_len; 8090 const char *zone_config; 8091 size_t zone_config_len; 8092 cfg_obj_t *zoneconf = NULL; 8093 char bufname[DNS_NAME_FORMATSIZE]; 8094 8095 REQUIRE(view != NULL); 8096 REQUIRE(key != NULL); 8097 REQUIRE(data != NULL); 8098 REQUIRE(text != NULL); 8099 REQUIRE(zoneconfig != NULL && *zoneconfig == NULL); 8100 8101 if (*text == NULL) { 8102 isc_buffer_allocate(view->mctx, text, 256); 8103 } else { 8104 isc_buffer_clear(*text); 8105 } 8106 8107 zone_name = (const char *)key->mv_data; 8108 zone_name_len = key->mv_size; 8109 INSIST(zone_name != NULL && zone_name_len > 0); 8110 8111 zone_config = (const char *)data->mv_data; 8112 zone_config_len = data->mv_size; 8113 INSIST(zone_config != NULL && zone_config_len > 0); 8114 8115 /* zone zonename { config; }; */ 8116 result = isc_buffer_reserve(*text, 6 + zone_name_len + 2 + 8117 zone_config_len + 2); 8118 if (result != ISC_R_SUCCESS) { 8119 goto cleanup; 8120 } 8121 8122 CHECK(putstr(text, "zone \"")); 8123 CHECK(putmem(text, (const void *)zone_name, zone_name_len)); 8124 CHECK(putstr(text, "\" ")); 8125 CHECK(putmem(text, (const void *)zone_config, zone_config_len)); 8126 CHECK(putstr(text, ";\n")); 8127 8128 snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len, 8129 zone_name); 8130 8131 cfg_parser_reset(named_g_addparser); 8132 result = cfg_parse_buffer(named_g_addparser, *text, bufname, 0, 8133 &cfg_type_addzoneconf, 0, &zoneconf); 8134 if (result != ISC_R_SUCCESS) { 8135 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8136 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8137 "parsing config for zone '%.*s' in " 8138 "NZD database '%s' failed", 8139 (int)zone_name_len, zone_name, view->new_zone_db); 8140 goto cleanup; 8141 } 8142 8143 *zoneconfig = zoneconf; 8144 zoneconf = NULL; 8145 result = ISC_R_SUCCESS; 8146 8147 cleanup: 8148 if (zoneconf != NULL) { 8149 cfg_obj_destroy(named_g_addparser, &zoneconf); 8150 } 8151 8152 return result; 8153 } 8154 8155 /*% 8156 * Prototype for a callback which can be used with for_all_newzone_cfgs(). 8157 */ 8158 typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig, 8159 cfg_obj_t *config, cfg_obj_t *vconfig, 8160 dns_view_t *view, 8161 cfg_aclconfctx_t *actx); 8162 8163 /*% 8164 * For each zone found in a NZD opened by the caller, create an object 8165 * representing its configuration and invoke "callback" with the created 8166 * object, "config", "vconfig", "mctx", "view" and "actx" as arguments (all 8167 * these are non-global variables required to invoke configure_zone()). 8168 * Immediately interrupt processing if an error is encountered while 8169 * transforming NZD data into a zone configuration object or if "callback" 8170 * returns an error. 8171 * 8172 * Caller must hold 'view->new_zone_lock'. 8173 */ 8174 static isc_result_t 8175 for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config, 8176 cfg_obj_t *vconfig, dns_view_t *view, 8177 cfg_aclconfctx_t *actx, MDB_txn *txn, MDB_dbi dbi) { 8178 const cfg_obj_t *zconfig, *zlist; 8179 isc_result_t result = ISC_R_SUCCESS; 8180 cfg_obj_t *zconfigobj = NULL; 8181 isc_buffer_t *text = NULL; 8182 MDB_cursor *cursor = NULL; 8183 MDB_val data, key; 8184 int status; 8185 8186 status = mdb_cursor_open(txn, dbi, &cursor); 8187 if (status != MDB_SUCCESS) { 8188 return ISC_R_FAILURE; 8189 } 8190 8191 for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); 8192 status == MDB_SUCCESS; 8193 status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) 8194 { 8195 /* 8196 * Create a configuration object from data fetched from NZD. 8197 */ 8198 result = data_to_cfg(view, &key, &data, &text, &zconfigobj); 8199 if (result != ISC_R_SUCCESS) { 8200 break; 8201 } 8202 8203 /* 8204 * Extract zone configuration from configuration object. 8205 */ 8206 zlist = NULL; 8207 result = cfg_map_get(zconfigobj, "zone", &zlist); 8208 if (result != ISC_R_SUCCESS) { 8209 break; 8210 } else if (!cfg_obj_islist(zlist)) { 8211 result = ISC_R_FAILURE; 8212 break; 8213 } 8214 zconfig = cfg_listelt_value(cfg_list_first(zlist)); 8215 8216 /* 8217 * Invoke callback. 8218 */ 8219 result = callback(zconfig, config, vconfig, view, actx); 8220 if (result != ISC_R_SUCCESS) { 8221 break; 8222 } 8223 8224 /* 8225 * Destroy the configuration object created in this iteration. 8226 */ 8227 cfg_obj_destroy(named_g_addparser, &zconfigobj); 8228 } 8229 8230 if (text != NULL) { 8231 isc_buffer_free(&text); 8232 } 8233 if (zconfigobj != NULL) { 8234 cfg_obj_destroy(named_g_addparser, &zconfigobj); 8235 } 8236 mdb_cursor_close(cursor); 8237 8238 return result; 8239 } 8240 8241 /*% 8242 * Attempt to configure a zone found in NZD and return the result. 8243 */ 8244 static isc_result_t 8245 configure_newzone(const cfg_obj_t *zconfig, cfg_obj_t *config, 8246 cfg_obj_t *vconfig, dns_view_t *view, 8247 cfg_aclconfctx_t *actx) { 8248 return configure_zone( 8249 config, zconfig, vconfig, view, &named_g_server->viewlist, 8250 &named_g_server->kasplist, &named_g_server->keystorelist, actx, 8251 true, false, false, false); 8252 } 8253 8254 /*% 8255 * Revert new view assignment for a zone found in NZD. 8256 */ 8257 static isc_result_t 8258 configure_newzone_revert(const cfg_obj_t *zconfig, cfg_obj_t *config, 8259 cfg_obj_t *vconfig, dns_view_t *view, 8260 cfg_aclconfctx_t *actx) { 8261 UNUSED(config); 8262 UNUSED(vconfig); 8263 UNUSED(actx); 8264 8265 configure_zone_setviewcommit(ISC_R_FAILURE, zconfig, view); 8266 8267 return ISC_R_SUCCESS; 8268 } 8269 8270 static isc_result_t 8271 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 8272 cfg_aclconfctx_t *actx) { 8273 isc_result_t result; 8274 MDB_txn *txn = NULL; 8275 MDB_dbi dbi; 8276 8277 if (view->new_zone_config == NULL) { 8278 return ISC_R_SUCCESS; 8279 } 8280 8281 LOCK(&view->new_zone_lock); 8282 8283 result = nzd_open(view, MDB_RDONLY, &txn, &dbi); 8284 if (result != ISC_R_SUCCESS) { 8285 UNLOCK(&view->new_zone_lock); 8286 return ISC_R_SUCCESS; 8287 } 8288 8289 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8290 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8291 "loading NZD configs from '%s' " 8292 "for view '%s'", 8293 view->new_zone_db, view->name); 8294 8295 result = for_all_newzone_cfgs(configure_newzone, config, vconfig, view, 8296 actx, txn, dbi); 8297 if (result != ISC_R_SUCCESS) { 8298 /* 8299 * An error was encountered while attempting to configure zones 8300 * found in NZD. As this error may have been caused by a 8301 * configure_zone() failure, try restoring a sane configuration 8302 * by reattaching all zones found in NZD to the old view. If 8303 * this also fails, too bad, there is nothing more we can do in 8304 * terms of trying to make things right. 8305 */ 8306 (void)for_all_newzone_cfgs(configure_newzone_revert, config, 8307 vconfig, view, actx, txn, dbi); 8308 } 8309 8310 (void)nzd_close(&txn, false); 8311 8312 UNLOCK(&view->new_zone_lock); 8313 8314 return result; 8315 } 8316 8317 static isc_result_t 8318 get_newzone_config(dns_view_t *view, const char *zonename, 8319 cfg_obj_t **zoneconfig) { 8320 isc_result_t result; 8321 int status; 8322 cfg_obj_t *zoneconf = NULL; 8323 isc_buffer_t *text = NULL; 8324 MDB_txn *txn = NULL; 8325 MDB_dbi dbi; 8326 MDB_val key, data; 8327 char zname[DNS_NAME_FORMATSIZE]; 8328 dns_fixedname_t fname; 8329 dns_name_t *name; 8330 isc_buffer_t b; 8331 8332 INSIST(zoneconfig != NULL && *zoneconfig == NULL); 8333 8334 LOCK(&view->new_zone_lock); 8335 8336 CHECK(nzd_open(view, MDB_RDONLY, &txn, &dbi)); 8337 8338 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8339 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8340 "loading NZD config from '%s' " 8341 "for zone '%s'", 8342 view->new_zone_db, zonename); 8343 8344 /* Normalize zone name */ 8345 isc_buffer_constinit(&b, zonename, strlen(zonename)); 8346 isc_buffer_add(&b, strlen(zonename)); 8347 name = dns_fixedname_initname(&fname); 8348 CHECK(dns_name_fromtext(name, &b, dns_rootname, DNS_NAME_DOWNCASE, 8349 NULL)); 8350 dns_name_format(name, zname, sizeof(zname)); 8351 8352 key.mv_data = zname; 8353 key.mv_size = strlen(zname); 8354 8355 status = mdb_get(txn, dbi, &key, &data); 8356 if (status != MDB_SUCCESS) { 8357 CHECK(ISC_R_FAILURE); 8358 } 8359 8360 CHECK(data_to_cfg(view, &key, &data, &text, &zoneconf)); 8361 8362 *zoneconfig = zoneconf; 8363 zoneconf = NULL; 8364 result = ISC_R_SUCCESS; 8365 8366 cleanup: 8367 (void)nzd_close(&txn, false); 8368 8369 UNLOCK(&view->new_zone_lock); 8370 8371 if (zoneconf != NULL) { 8372 cfg_obj_destroy(named_g_addparser, &zoneconf); 8373 } 8374 if (text != NULL) { 8375 isc_buffer_free(&text); 8376 } 8377 8378 return result; 8379 } 8380 8381 #endif /* HAVE_LMDB */ 8382 8383 static isc_result_t 8384 load_configuration(const char *filename, named_server_t *server, 8385 bool first_time) { 8386 cfg_obj_t *config = NULL, *bindkeys = NULL; 8387 cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; 8388 const cfg_listelt_t *element; 8389 const cfg_obj_t *builtin_views; 8390 const cfg_obj_t *maps[3]; 8391 const cfg_obj_t *obj; 8392 const cfg_obj_t *options; 8393 const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; 8394 const cfg_obj_t *kasps; 8395 const cfg_obj_t *keystores; 8396 dns_kasp_t *kasp = NULL; 8397 dns_kasp_t *kasp_next = NULL; 8398 dns_kasp_t *default_kasp = NULL; 8399 dns_kasplist_t tmpkasplist, kasplist; 8400 unsigned int kaspopts = (ISCCFG_KASPCONF_CHECK_ALGORITHMS | 8401 ISCCFG_KASPCONF_CHECK_KEYLIST | 8402 ISCCFG_KASPCONF_LOG_ERRORS); 8403 dns_keystore_t *keystore = NULL; 8404 dns_keystore_t *keystore_next = NULL; 8405 dns_keystorelist_t tmpkeystorelist, keystorelist; 8406 const cfg_obj_t *views = NULL; 8407 dns_view_t *view_next = NULL; 8408 dns_viewlist_t tmpviewlist; 8409 dns_viewlist_t viewlist, builtin_viewlist; 8410 in_port_t listen_port, port_low, port_high; 8411 int i, backlog; 8412 isc_interval_t interval; 8413 isc_logconfig_t *logc = NULL; 8414 isc_portset_t *v4portset = NULL; 8415 isc_portset_t *v6portset = NULL; 8416 isc_result_t result; 8417 uint32_t heartbeat_interval; 8418 uint32_t interface_interval; 8419 uint32_t udpsize; 8420 uint32_t transfer_message_size; 8421 uint32_t recv_tcp_buffer_size; 8422 uint32_t send_tcp_buffer_size; 8423 uint32_t recv_udp_buffer_size; 8424 uint32_t send_udp_buffer_size; 8425 named_cache_t *nsc = NULL; 8426 named_cachelist_t cachelist, tmpcachelist; 8427 ns_altsecret_t *altsecret; 8428 ns_altsecretlist_t altsecrets, tmpaltsecrets; 8429 uint32_t softquota = 0; 8430 uint32_t max; 8431 uint64_t initial, idle, keepalive, advertised; 8432 bool loadbalancesockets; 8433 bool exclusive = true; 8434 dns_aclenv_t *env = 8435 ns_interfacemgr_getaclenv(named_g_server->interfacemgr); 8436 8437 /* 8438 * Require the reconfiguration to happen always on the main loop 8439 */ 8440 REQUIRE(isc_loop() == named_g_mainloop); 8441 8442 ISC_LIST_INIT(kasplist); 8443 ISC_LIST_INIT(keystorelist); 8444 ISC_LIST_INIT(viewlist); 8445 ISC_LIST_INIT(builtin_viewlist); 8446 ISC_LIST_INIT(cachelist); 8447 ISC_LIST_INIT(altsecrets); 8448 8449 /* Ensure exclusive access to configuration data. */ 8450 isc_loopmgr_pause(named_g_loopmgr); 8451 8452 /* Create the ACL configuration context */ 8453 if (named_g_aclconfctx != NULL) { 8454 cfg_aclconfctx_detach(&named_g_aclconfctx); 8455 } 8456 result = cfg_aclconfctx_create(named_g_mctx, &named_g_aclconfctx); 8457 if (result != ISC_R_SUCCESS) { 8458 goto cleanup_exclusive; 8459 } 8460 8461 /* 8462 * Shut down all dyndb instances. 8463 */ 8464 dns_dyndb_cleanup(false); 8465 8466 /* 8467 * Parse the global default pseudo-config file. 8468 */ 8469 if (first_time) { 8470 result = named_config_parsedefaults(named_g_parser, 8471 &named_g_config); 8472 if (result != ISC_R_SUCCESS) { 8473 named_main_earlyfatal("unable to load " 8474 "internal defaults: %s", 8475 isc_result_totext(result)); 8476 } 8477 RUNTIME_CHECK(cfg_map_get(named_g_config, "options", 8478 &named_g_defaults) == ISC_R_SUCCESS); 8479 } 8480 8481 /* 8482 * Log the current working directory. 8483 */ 8484 if (first_time) { 8485 char cwd[PATH_MAX]; 8486 if (getcwd(cwd, sizeof(cwd)) == cwd) { 8487 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8488 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8489 "the initial working directory is '%s'", 8490 cwd); 8491 } 8492 } 8493 8494 /* 8495 * Parse the configuration file using the new config code. 8496 */ 8497 config = NULL; 8498 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8499 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8500 "loading configuration from '%s'", filename); 8501 result = cfg_parser_create(named_g_mctx, named_g_lctx, &conf_parser); 8502 if (result != ISC_R_SUCCESS) { 8503 goto cleanup_exclusive; 8504 } 8505 8506 cfg_parser_setcallback(conf_parser, directory_callback, NULL); 8507 result = cfg_parse_file(conf_parser, filename, &cfg_type_namedconf, 8508 &config); 8509 if (result != ISC_R_SUCCESS) { 8510 goto cleanup_conf_parser; 8511 } 8512 8513 /* 8514 * Check the validity of the configuration. 8515 * 8516 * (Ignore plugin parameters for now; they will be 8517 * checked later when the modules are actually loaded and 8518 * registered.) 8519 */ 8520 result = isccfg_check_namedconf(config, BIND_CHECK_ALGORITHMS, 8521 named_g_lctx, named_g_mctx); 8522 if (result != ISC_R_SUCCESS) { 8523 goto cleanup_config; 8524 } 8525 8526 /* Let's recreate the TLS context cache */ 8527 if (server->tlsctx_server_cache != NULL) { 8528 isc_tlsctx_cache_detach(&server->tlsctx_server_cache); 8529 } 8530 8531 isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_server_cache); 8532 8533 if (server->tlsctx_client_cache != NULL) { 8534 isc_tlsctx_cache_detach(&server->tlsctx_client_cache); 8535 } 8536 8537 isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_client_cache); 8538 8539 dns_zonemgr_set_tlsctx_cache(server->zonemgr, 8540 server->tlsctx_client_cache); 8541 8542 /* 8543 * Fill in the maps array, used for resolving defaults. 8544 */ 8545 i = 0; 8546 options = NULL; 8547 result = cfg_map_get(config, "options", &options); 8548 if (result == ISC_R_SUCCESS) { 8549 maps[i++] = options; 8550 } 8551 maps[i++] = named_g_defaults; 8552 maps[i] = NULL; 8553 8554 #if HAVE_LIBNGHTTP2 8555 obj = NULL; 8556 result = named_config_get(maps, "http-port", &obj); 8557 INSIST(result == ISC_R_SUCCESS); 8558 named_g_httpport = (in_port_t)cfg_obj_asuint32(obj); 8559 8560 obj = NULL; 8561 result = named_config_get(maps, "https-port", &obj); 8562 INSIST(result == ISC_R_SUCCESS); 8563 named_g_httpsport = (in_port_t)cfg_obj_asuint32(obj); 8564 8565 obj = NULL; 8566 result = named_config_get(maps, "http-listener-clients", &obj); 8567 INSIST(result == ISC_R_SUCCESS); 8568 named_g_http_listener_clients = cfg_obj_asuint32(obj); 8569 8570 obj = NULL; 8571 result = named_config_get(maps, "http-streams-per-connection", &obj); 8572 INSIST(result == ISC_R_SUCCESS); 8573 named_g_http_streams_per_conn = cfg_obj_asuint32(obj); 8574 #endif 8575 8576 /* 8577 * If "dnssec-validation auto" is turned on, the root key 8578 * will be used as a default trust anchor. The root key 8579 * is built in, but if bindkeys-file is set, then it will 8580 * be overridden with the key in that file. 8581 */ 8582 obj = NULL; 8583 (void)named_config_get(maps, "bindkeys-file", &obj); 8584 if (obj != NULL) { 8585 setstring(server, &server->bindkeysfile, cfg_obj_asstring(obj)); 8586 INSIST(server->bindkeysfile != NULL); 8587 if (access(server->bindkeysfile, R_OK) != 0) { 8588 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8589 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8590 "unable to open '%s'; using built-in " 8591 "keys instead", 8592 server->bindkeysfile); 8593 } else { 8594 result = cfg_parser_create(named_g_mctx, named_g_lctx, 8595 &bindkeys_parser); 8596 if (result != ISC_R_SUCCESS) { 8597 goto cleanup_config; 8598 } 8599 8600 result = cfg_parse_file(bindkeys_parser, 8601 server->bindkeysfile, 8602 &cfg_type_bindkeys, &bindkeys); 8603 if (result != ISC_R_SUCCESS) { 8604 isc_log_write( 8605 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8606 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8607 "unable to parse '%s' " 8608 "error '%s'; using " 8609 "built-in keys instead", 8610 server->bindkeysfile, 8611 isc_result_totext(result)); 8612 } 8613 } 8614 } else { 8615 setstring(server, &server->bindkeysfile, NULL); 8616 } 8617 8618 #if defined(HAVE_GEOIP2) 8619 /* 8620 * Release any previously opened GeoIP2 databases. 8621 */ 8622 named_geoip_unload(); 8623 8624 /* 8625 * Initialize GeoIP databases from the configured location. 8626 * This should happen before configuring any ACLs, so that we 8627 * know what databases are available and can reject any GeoIP 8628 * ACLs that can't work. 8629 */ 8630 obj = NULL; 8631 result = named_config_get(maps, "geoip-directory", &obj); 8632 INSIST(result == ISC_R_SUCCESS); 8633 if (cfg_obj_isstring(obj)) { 8634 char *dir = UNCONST(cfg_obj_asstring(obj)); 8635 named_geoip_load(dir); 8636 } 8637 named_g_aclconfctx->geoip = named_g_geoip; 8638 #endif /* HAVE_GEOIP2 */ 8639 8640 /* 8641 * Configure various server options. 8642 */ 8643 configure_server_quota(maps, "transfers-out", 8644 &server->sctx->xfroutquota); 8645 configure_server_quota(maps, "tcp-clients", &server->sctx->tcpquota); 8646 configure_server_quota(maps, "recursive-clients", 8647 &server->sctx->recursionquota); 8648 configure_server_quota(maps, "update-quota", &server->sctx->updquota); 8649 configure_server_quota(maps, "sig0checks-quota", 8650 &server->sctx->sig0checksquota); 8651 8652 max = isc_quota_getmax(&server->sctx->recursionquota); 8653 if (max > 1000) { 8654 unsigned int margin = ISC_MAX(100, named_g_cpus + 1); 8655 if (margin + 100 > max) { 8656 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8657 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8658 "'recursive-clients %d' too low when " 8659 "running with %d worker threads", 8660 max, named_g_cpus); 8661 result = ISC_R_RANGE; 8662 8663 goto cleanup_bindkeys_parser; 8664 } 8665 softquota = max - margin; 8666 } else { 8667 softquota = (max * 90) / 100; 8668 } 8669 isc_quota_soft(&server->sctx->recursionquota, softquota); 8670 8671 obj = NULL; 8672 result = named_config_get(maps, "sig0checks-quota-exempt", &obj); 8673 if (result == ISC_R_SUCCESS) { 8674 result = cfg_acl_fromconfig( 8675 obj, config, named_g_lctx, named_g_aclconfctx, 8676 named_g_mctx, 0, &server->sctx->sig0checksquota_exempt); 8677 INSIST(result == ISC_R_SUCCESS); 8678 } 8679 8680 /* 8681 * Set "blackhole". Only legal at options level; there is 8682 * no default. 8683 */ 8684 result = configure_view_acl(NULL, config, NULL, "blackhole", NULL, 8685 named_g_aclconfctx, named_g_mctx, 8686 &server->sctx->blackholeacl); 8687 if (result != ISC_R_SUCCESS) { 8688 goto cleanup_bindkeys_parser; 8689 } 8690 8691 if (server->sctx->blackholeacl != NULL) { 8692 dns_dispatchmgr_setblackhole(named_g_dispatchmgr, 8693 server->sctx->blackholeacl); 8694 } 8695 8696 obj = NULL; 8697 result = named_config_get(maps, "match-mapped-addresses", &obj); 8698 INSIST(result == ISC_R_SUCCESS); 8699 env->match_mapped = cfg_obj_asboolean(obj); 8700 8701 /* 8702 * Configure the network manager 8703 */ 8704 obj = NULL; 8705 result = named_config_get(maps, "tcp-initial-timeout", &obj); 8706 INSIST(result == ISC_R_SUCCESS); 8707 initial = cfg_obj_asuint32(obj) * 100; 8708 if (initial > MAX_INITIAL_TIMEOUT) { 8709 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8710 "tcp-initial-timeout value is out of range: " 8711 "lowering to %" PRIu32, 8712 MAX_INITIAL_TIMEOUT / 100); 8713 initial = MAX_INITIAL_TIMEOUT; 8714 } else if (initial < MIN_INITIAL_TIMEOUT) { 8715 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8716 "tcp-initial-timeout value is out of range: " 8717 "raising to %" PRIu32, 8718 MIN_INITIAL_TIMEOUT / 100); 8719 initial = MIN_INITIAL_TIMEOUT; 8720 } 8721 8722 obj = NULL; 8723 result = named_config_get(maps, "tcp-idle-timeout", &obj); 8724 INSIST(result == ISC_R_SUCCESS); 8725 idle = cfg_obj_asuint32(obj) * 100; 8726 if (idle > MAX_IDLE_TIMEOUT) { 8727 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8728 "tcp-idle-timeout value is out of range: " 8729 "lowering to %" PRIu32, 8730 MAX_IDLE_TIMEOUT / 100); 8731 idle = MAX_IDLE_TIMEOUT; 8732 } else if (idle < MIN_IDLE_TIMEOUT) { 8733 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8734 "tcp-idle-timeout value is out of range: " 8735 "raising to %" PRIu32, 8736 MIN_IDLE_TIMEOUT / 100); 8737 idle = MIN_IDLE_TIMEOUT; 8738 } 8739 8740 obj = NULL; 8741 result = named_config_get(maps, "tcp-keepalive-timeout", &obj); 8742 INSIST(result == ISC_R_SUCCESS); 8743 keepalive = cfg_obj_asuint32(obj) * 100; 8744 if (keepalive > MAX_KEEPALIVE_TIMEOUT) { 8745 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8746 "tcp-keepalive-timeout value is out of range: " 8747 "lowering to %" PRIu32, 8748 MAX_KEEPALIVE_TIMEOUT / 100); 8749 keepalive = MAX_KEEPALIVE_TIMEOUT; 8750 } else if (keepalive < MIN_KEEPALIVE_TIMEOUT) { 8751 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8752 "tcp-keepalive-timeout value is out of range: " 8753 "raising to %" PRIu32, 8754 MIN_KEEPALIVE_TIMEOUT / 100); 8755 keepalive = MIN_KEEPALIVE_TIMEOUT; 8756 } 8757 8758 obj = NULL; 8759 result = named_config_get(maps, "tcp-advertised-timeout", &obj); 8760 INSIST(result == ISC_R_SUCCESS); 8761 advertised = cfg_obj_asuint32(obj) * 100; 8762 if (advertised > MAX_ADVERTISED_TIMEOUT) { 8763 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8764 "tcp-advertized-timeout value is out of range: " 8765 "lowering to %" PRIu32, 8766 MAX_ADVERTISED_TIMEOUT / 100); 8767 advertised = MAX_ADVERTISED_TIMEOUT; 8768 } 8769 8770 isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, 8771 advertised); 8772 8773 #define CAP_IF_NOT_ZERO(v, min, max) \ 8774 if (v > 0 && v < min) { \ 8775 v = min; \ 8776 } else if (v > max) { \ 8777 v = max; \ 8778 } 8779 8780 /* Set the kernel send and receive buffer sizes */ 8781 obj = NULL; 8782 result = named_config_get(maps, "tcp-receive-buffer", &obj); 8783 INSIST(result == ISC_R_SUCCESS); 8784 recv_tcp_buffer_size = cfg_obj_asuint32(obj); 8785 CAP_IF_NOT_ZERO(recv_tcp_buffer_size, 4096, INT32_MAX); 8786 8787 obj = NULL; 8788 result = named_config_get(maps, "tcp-send-buffer", &obj); 8789 INSIST(result == ISC_R_SUCCESS); 8790 send_tcp_buffer_size = cfg_obj_asuint32(obj); 8791 CAP_IF_NOT_ZERO(send_tcp_buffer_size, 4096, INT32_MAX); 8792 8793 obj = NULL; 8794 result = named_config_get(maps, "udp-receive-buffer", &obj); 8795 INSIST(result == ISC_R_SUCCESS); 8796 recv_udp_buffer_size = cfg_obj_asuint32(obj); 8797 CAP_IF_NOT_ZERO(recv_udp_buffer_size, 4096, INT32_MAX); 8798 8799 obj = NULL; 8800 result = named_config_get(maps, "udp-send-buffer", &obj); 8801 INSIST(result == ISC_R_SUCCESS); 8802 send_udp_buffer_size = cfg_obj_asuint32(obj); 8803 CAP_IF_NOT_ZERO(send_udp_buffer_size, 4096, INT32_MAX); 8804 8805 isc_nm_setnetbuffers(named_g_netmgr, recv_tcp_buffer_size, 8806 send_tcp_buffer_size, recv_udp_buffer_size, 8807 send_udp_buffer_size); 8808 8809 #undef CAP_IF_NOT_ZERO 8810 8811 /* 8812 * Configure sets of UDP query source ports. 8813 */ 8814 result = isc_portset_create(named_g_mctx, &v4portset); 8815 if (result != ISC_R_SUCCESS) { 8816 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8817 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8818 "creating UDP/IPv4 port set: %s", 8819 isc_result_totext(result)); 8820 goto cleanup_bindkeys_parser; 8821 } 8822 result = isc_portset_create(named_g_mctx, &v6portset); 8823 if (result != ISC_R_SUCCESS) { 8824 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8825 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8826 "creating UDP/IPv6 port set: %s", 8827 isc_result_totext(result)); 8828 goto cleanup_v4portset; 8829 } 8830 8831 usev4ports = NULL; 8832 usev6ports = NULL; 8833 avoidv4ports = NULL; 8834 avoidv6ports = NULL; 8835 8836 (void)named_config_get(maps, "use-v4-udp-ports", &usev4ports); 8837 if (usev4ports != NULL) { 8838 portset_fromconf(v4portset, usev4ports, true); 8839 } else { 8840 isc_net_getportrange(AF_INET, &port_low, &port_high); 8841 if (port_low == port_high) { 8842 isc_portset_add(v4portset, port_low); 8843 } else { 8844 isc_portset_addrange(v4portset, port_low, port_high); 8845 } 8846 if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE4)) { 8847 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8848 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8849 "using default UDP/IPv4 port range: " 8850 "[%d, %d]", 8851 port_low, port_high); 8852 } 8853 } 8854 (void)named_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports); 8855 if (avoidv4ports != NULL) { 8856 portset_fromconf(v4portset, avoidv4ports, false); 8857 } 8858 8859 (void)named_config_get(maps, "use-v6-udp-ports", &usev6ports); 8860 if (usev6ports != NULL) { 8861 portset_fromconf(v6portset, usev6ports, true); 8862 } else { 8863 isc_net_getportrange(AF_INET6, &port_low, &port_high); 8864 if (port_low == port_high) { 8865 isc_portset_add(v6portset, port_low); 8866 } else { 8867 isc_portset_addrange(v6portset, port_low, port_high); 8868 } 8869 if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE6)) { 8870 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8871 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8872 "using default UDP/IPv6 port range: " 8873 "[%d, %d]", 8874 port_low, port_high); 8875 } 8876 } 8877 (void)named_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports); 8878 if (avoidv6ports != NULL) { 8879 portset_fromconf(v6portset, avoidv6ports, false); 8880 } 8881 8882 dns_dispatchmgr_setavailports(named_g_dispatchmgr, v4portset, 8883 v6portset); 8884 8885 /* 8886 * Set the EDNS UDP size when we don't match a view. 8887 */ 8888 obj = NULL; 8889 result = named_config_get(maps, "edns-udp-size", &obj); 8890 INSIST(result == ISC_R_SUCCESS); 8891 udpsize = cfg_obj_asuint32(obj); 8892 if (udpsize < 512) { 8893 udpsize = 512; 8894 } 8895 if (udpsize > 4096) { 8896 udpsize = 4096; 8897 } 8898 server->sctx->udpsize = (uint16_t)udpsize; 8899 8900 /* Set the transfer message size for TCP */ 8901 obj = NULL; 8902 result = named_config_get(maps, "transfer-message-size", &obj); 8903 INSIST(result == ISC_R_SUCCESS); 8904 transfer_message_size = cfg_obj_asuint32(obj); 8905 if (transfer_message_size < 512) { 8906 transfer_message_size = 512; 8907 } else if (transfer_message_size > 65535) { 8908 transfer_message_size = 65535; 8909 } 8910 server->sctx->transfer_tcp_message_size = 8911 (uint16_t)transfer_message_size; 8912 8913 /* 8914 * Configure the zone manager. 8915 */ 8916 obj = NULL; 8917 result = named_config_get(maps, "transfers-in", &obj); 8918 INSIST(result == ISC_R_SUCCESS); 8919 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); 8920 8921 obj = NULL; 8922 result = named_config_get(maps, "transfers-per-ns", &obj); 8923 INSIST(result == ISC_R_SUCCESS); 8924 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); 8925 8926 obj = NULL; 8927 result = named_config_get(maps, "notify-rate", &obj); 8928 INSIST(result == ISC_R_SUCCESS); 8929 dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj)); 8930 8931 obj = NULL; 8932 result = named_config_get(maps, "startup-notify-rate", &obj); 8933 INSIST(result == ISC_R_SUCCESS); 8934 dns_zonemgr_setstartupnotifyrate(server->zonemgr, 8935 cfg_obj_asuint32(obj)); 8936 8937 obj = NULL; 8938 result = named_config_get(maps, "serial-query-rate", &obj); 8939 INSIST(result == ISC_R_SUCCESS); 8940 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); 8941 8942 /* 8943 * Determine which port to use for listening for incoming connections. 8944 */ 8945 if (named_g_port != 0) { 8946 listen_port = named_g_port; 8947 } else { 8948 result = named_config_getport(config, "port", &listen_port); 8949 if (result != ISC_R_SUCCESS) { 8950 goto cleanup_v6portset; 8951 } 8952 } 8953 8954 /* 8955 * Find the listen queue depth. 8956 */ 8957 obj = NULL; 8958 result = named_config_get(maps, "tcp-listen-queue", &obj); 8959 INSIST(result == ISC_R_SUCCESS); 8960 backlog = cfg_obj_asuint32(obj); 8961 if ((backlog > 0) && (backlog < 10)) { 8962 backlog = 10; 8963 } 8964 ns_interfacemgr_setbacklog(server->interfacemgr, backlog); 8965 8966 obj = NULL; 8967 result = named_config_get(maps, "reuseport", &obj); 8968 INSIST(result == ISC_R_SUCCESS); 8969 loadbalancesockets = cfg_obj_asboolean(obj); 8970 #if HAVE_SO_REUSEPORT_LB 8971 if (first_time) { 8972 isc_nm_setloadbalancesockets(named_g_netmgr, 8973 cfg_obj_asboolean(obj)); 8974 } else if (loadbalancesockets != 8975 isc_nm_getloadbalancesockets(named_g_netmgr)) 8976 { 8977 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8978 "changing reuseport value requires server restart"); 8979 } 8980 #else 8981 if (loadbalancesockets) { 8982 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8983 "reuseport has no effect on this system"); 8984 } 8985 #endif 8986 8987 /* 8988 * Configure the interface manager according to the "listen-on" 8989 * statement. 8990 */ 8991 { 8992 const cfg_obj_t *clistenon = NULL; 8993 ns_listenlist_t *listenon = NULL; 8994 8995 /* 8996 * Even though listen-on is present in the default 8997 * configuration, this way is easier. 8998 */ 8999 if (options != NULL) { 9000 (void)cfg_map_get(options, "listen-on", &clistenon); 9001 } 9002 if (clistenon != NULL) { 9003 result = listenlist_fromconfig( 9004 clistenon, config, named_g_aclconfctx, 9005 named_g_mctx, AF_INET, 9006 server->tlsctx_server_cache, &listenon); 9007 } else { 9008 /* 9009 * Not specified, use default. 9010 */ 9011 result = ns_listenlist_default(named_g_mctx, 9012 listen_port, true, 9013 AF_INET, &listenon); 9014 } 9015 if (result != ISC_R_SUCCESS) { 9016 goto cleanup_v6portset; 9017 } 9018 9019 if (listenon != NULL) { 9020 ns_interfacemgr_setlistenon4(server->interfacemgr, 9021 listenon); 9022 ns_listenlist_detach(&listenon); 9023 } 9024 } 9025 9026 /* 9027 * Ditto for IPv6. 9028 */ 9029 { 9030 const cfg_obj_t *clistenon = NULL; 9031 ns_listenlist_t *listenon = NULL; 9032 9033 if (options != NULL) { 9034 (void)cfg_map_get(options, "listen-on-v6", &clistenon); 9035 } 9036 if (clistenon != NULL) { 9037 result = listenlist_fromconfig( 9038 clistenon, config, named_g_aclconfctx, 9039 named_g_mctx, AF_INET6, 9040 server->tlsctx_server_cache, &listenon); 9041 } else { 9042 /* 9043 * Not specified, use default. 9044 */ 9045 result = ns_listenlist_default(named_g_mctx, 9046 listen_port, true, 9047 AF_INET6, &listenon); 9048 } 9049 if (result != ISC_R_SUCCESS) { 9050 goto cleanup_v6portset; 9051 } 9052 if (listenon != NULL) { 9053 ns_interfacemgr_setlistenon6(server->interfacemgr, 9054 listenon); 9055 ns_listenlist_detach(&listenon); 9056 } 9057 } 9058 9059 if (first_time) { 9060 /* 9061 * Rescan the interface list to pick up changes in the 9062 * listen-on option. This requires the loopmgr to be 9063 * temporarily resumed. 9064 */ 9065 isc_loopmgr_resume(named_g_loopmgr); 9066 result = ns_interfacemgr_scan(server->interfacemgr, true, true); 9067 isc_loopmgr_pause(named_g_loopmgr); 9068 9069 /* 9070 * Check that named is able to TCP listen on at least one 9071 * interface. Otherwise, another named process could be running 9072 * and we should fail. 9073 */ 9074 if (result == ISC_R_ADDRINUSE) { 9075 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9076 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9077 "unable to listen on any configured " 9078 "interfaces"); 9079 result = ISC_R_FAILURE; 9080 goto cleanup_v6portset; 9081 } 9082 } 9083 9084 /* 9085 * Arrange for further interface scanning to occur periodically 9086 * as specified by the "interface-interval" option. 9087 */ 9088 obj = NULL; 9089 result = named_config_get(maps, "interface-interval", &obj); 9090 INSIST(result == ISC_R_SUCCESS); 9091 interface_interval = cfg_obj_asduration(obj); 9092 server->interface_interval = interface_interval; 9093 9094 /* 9095 * Enable automatic interface scans. 9096 */ 9097 obj = NULL; 9098 result = named_config_get(maps, "automatic-interface-scan", &obj); 9099 INSIST(result == ISC_R_SUCCESS); 9100 server->sctx->interface_auto = cfg_obj_asboolean(obj); 9101 9102 if (server->sctx->interface_auto) { 9103 if (ns_interfacemgr_dynamic_updates_are_reliable() && 9104 server->interface_interval != 0) 9105 { 9106 /* 9107 * In some cases the user might expect a certain 9108 * behaviour from the rescan timer, let's try to deduce 9109 * that from the configuration options. 9110 */ 9111 isc_log_write( 9112 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9113 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9114 "Disabling periodic interface re-scans timer"); 9115 server->interface_interval = 0; 9116 } 9117 9118 ns_interfacemgr_routeconnect(server->interfacemgr); 9119 } else { 9120 ns_interfacemgr_routedisconnect(server->interfacemgr); 9121 } 9122 9123 if (server->interface_interval == 0) { 9124 isc_timer_stop(server->interface_timer); 9125 } else { 9126 isc_interval_set(&interval, interface_interval, 0); 9127 isc_timer_start(server->interface_timer, isc_timertype_ticker, 9128 &interval); 9129 } 9130 9131 /* 9132 * Configure the dialup heartbeat timer. 9133 */ 9134 obj = NULL; 9135 result = named_config_get(maps, "heartbeat-interval", &obj); 9136 INSIST(result == ISC_R_SUCCESS); 9137 heartbeat_interval = cfg_obj_asuint32(obj) * 60; 9138 if (heartbeat_interval == 0) { 9139 isc_timer_stop(server->heartbeat_timer); 9140 } else if (server->heartbeat_interval != heartbeat_interval) { 9141 isc_interval_set(&interval, heartbeat_interval, 0); 9142 isc_timer_start(server->heartbeat_timer, isc_timertype_ticker, 9143 &interval); 9144 } 9145 server->heartbeat_interval = heartbeat_interval; 9146 9147 isc_interval_set(&interval, 1200, 0); 9148 isc_timer_start(server->pps_timer, isc_timertype_ticker, &interval); 9149 9150 isc_interval_set(&interval, named_g_tat_interval, 0); 9151 isc_timer_start(server->tat_timer, isc_timertype_ticker, &interval); 9152 9153 /* 9154 * Write the PID file. 9155 */ 9156 obj = NULL; 9157 if (named_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) { 9158 if (cfg_obj_isvoid(obj)) { 9159 named_os_writepidfile(NULL, first_time); 9160 } else { 9161 named_os_writepidfile(cfg_obj_asstring(obj), 9162 first_time); 9163 } 9164 } else { 9165 named_os_writepidfile(named_g_defaultpidfile, first_time); 9166 } 9167 9168 /* 9169 * Configure the server-wide session key. This must be done before 9170 * configure views because zone configuration may need to know 9171 * session-keyname. 9172 * 9173 * Failure of session key generation isn't fatal at this time; if it 9174 * turns out that a session key is really needed but doesn't exist, 9175 * we'll treat it as a fatal error then. 9176 */ 9177 (void)configure_session_key(maps, server, named_g_mctx, first_time); 9178 9179 /* 9180 * Create the built-in key store ("key-directory"). 9181 */ 9182 result = cfg_keystore_fromconfig(NULL, named_g_mctx, named_g_lctx, 9183 named_g_engine, &keystorelist, NULL); 9184 if (result != ISC_R_SUCCESS) { 9185 goto cleanup_keystorelist; 9186 } 9187 9188 /* 9189 * Create the DNSSEC key stores. 9190 */ 9191 keystores = NULL; 9192 (void)cfg_map_get(config, "key-store", &keystores); 9193 for (element = cfg_list_first(keystores); element != NULL; 9194 element = cfg_list_next(element)) 9195 { 9196 cfg_obj_t *kconfig = cfg_listelt_value(element); 9197 keystore = NULL; 9198 result = cfg_keystore_fromconfig(kconfig, named_g_mctx, 9199 named_g_lctx, named_g_engine, 9200 &keystorelist, NULL); 9201 if (result != ISC_R_SUCCESS) { 9202 goto cleanup_keystorelist; 9203 } 9204 } 9205 9206 /* 9207 * Create the built-in kasp policies ("default", "insecure"). 9208 */ 9209 kasps = NULL; 9210 (void)cfg_map_get(named_g_config, "dnssec-policy", &kasps); 9211 for (element = cfg_list_first(kasps); element != NULL; 9212 element = cfg_list_next(element)) 9213 { 9214 cfg_obj_t *kconfig = cfg_listelt_value(element); 9215 9216 kasp = NULL; 9217 result = cfg_kasp_fromconfig(kconfig, default_kasp, kaspopts, 9218 named_g_mctx, named_g_lctx, 9219 &keystorelist, &kasplist, &kasp); 9220 if (result != ISC_R_SUCCESS) { 9221 goto cleanup_kasplist; 9222 } 9223 INSIST(kasp != NULL); 9224 dns_kasp_freeze(kasp); 9225 9226 /* Insist that the first built-in policy is the default one. */ 9227 if (default_kasp == NULL) { 9228 INSIST(strcmp(dns_kasp_getname(kasp), "default") == 0); 9229 dns_kasp_attach(kasp, &default_kasp); 9230 } 9231 9232 dns_kasp_detach(&kasp); 9233 } 9234 INSIST(default_kasp != NULL); 9235 9236 /* 9237 * Create the DNSSEC key and signing policies (KASP). 9238 */ 9239 kasps = NULL; 9240 (void)cfg_map_get(config, "dnssec-policy", &kasps); 9241 for (element = cfg_list_first(kasps); element != NULL; 9242 element = cfg_list_next(element)) 9243 { 9244 cfg_obj_t *kconfig = cfg_listelt_value(element); 9245 kasp = NULL; 9246 result = cfg_kasp_fromconfig(kconfig, default_kasp, kaspopts, 9247 named_g_mctx, named_g_lctx, 9248 &keystorelist, &kasplist, &kasp); 9249 if (result != ISC_R_SUCCESS) { 9250 goto cleanup_kasplist; 9251 } 9252 INSIST(kasp != NULL); 9253 dns_kasp_freeze(kasp); 9254 dns_kasp_detach(&kasp); 9255 } 9256 dns_kasp_detach(&default_kasp); 9257 9258 /* 9259 * Save keystore list and kasp list. 9260 */ 9261 tmpkeystorelist = server->keystorelist; 9262 server->keystorelist = keystorelist; 9263 keystorelist = tmpkeystorelist; 9264 9265 tmpkasplist = server->kasplist; 9266 server->kasplist = kasplist; 9267 kasplist = tmpkasplist; 9268 9269 #ifdef USE_DNSRPS 9270 /* 9271 * Find the path to the DNSRPS implementation library. 9272 */ 9273 obj = NULL; 9274 if (named_config_get(maps, "dnsrps-library", &obj) == ISC_R_SUCCESS) { 9275 if (server->dnsrpslib != NULL) { 9276 dns_dnsrps_server_destroy(); 9277 isc_mem_free(server->mctx, server->dnsrpslib); 9278 server->dnsrpslib = NULL; 9279 } 9280 setstring(server, &server->dnsrpslib, cfg_obj_asstring(obj)); 9281 result = dns_dnsrps_server_create(server->dnsrpslib); 9282 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9283 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9284 "initializing DNSRPS RPZ provider '%s': %s", 9285 server->dnsrpslib, isc_result_totext(result)); 9286 /* 9287 * It's okay if librpz isn't available. We'll complain 9288 * later if it turns out to be needed for a view with 9289 * "dnsrps-enable yes". 9290 */ 9291 if (result == ISC_R_FILENOTFOUND) { 9292 result = ISC_R_SUCCESS; 9293 } 9294 CHECKFATAL(result, "initializing RPZ service interface"); 9295 } 9296 #endif /* ifdef USE_DNSRPS */ 9297 9298 /* 9299 * Configure the views. 9300 */ 9301 views = NULL; 9302 (void)cfg_map_get(config, "view", &views); 9303 9304 /* 9305 * Create the views. 9306 */ 9307 for (element = cfg_list_first(views); element != NULL; 9308 element = cfg_list_next(element)) 9309 { 9310 cfg_obj_t *vconfig = cfg_listelt_value(element); 9311 dns_view_t *view = NULL; 9312 9313 result = create_view(vconfig, &viewlist, &view); 9314 if (result != ISC_R_SUCCESS) { 9315 goto cleanup_viewlist; 9316 } 9317 INSIST(view != NULL); 9318 9319 result = setup_newzones(view, config, vconfig, conf_parser, 9320 named_g_aclconfctx); 9321 dns_view_detach(&view); 9322 9323 if (result != ISC_R_SUCCESS) { 9324 goto cleanup_viewlist; 9325 } 9326 } 9327 9328 /* 9329 * If there were no explicit views then we do the default 9330 * view here. 9331 */ 9332 if (views == NULL) { 9333 dns_view_t *view = NULL; 9334 9335 result = create_view(NULL, &viewlist, &view); 9336 if (result != ISC_R_SUCCESS) { 9337 goto cleanup_viewlist; 9338 } 9339 INSIST(view != NULL); 9340 9341 result = setup_newzones(view, config, NULL, conf_parser, 9342 named_g_aclconfctx); 9343 9344 dns_view_detach(&view); 9345 if (result != ISC_R_SUCCESS) { 9346 goto cleanup_viewlist; 9347 } 9348 } 9349 9350 /* 9351 * Configure and freeze all explicit views. Explicit 9352 * views that have zones were already created at parsing 9353 * time, but views with no zones must be created here. 9354 */ 9355 for (element = cfg_list_first(views); element != NULL; 9356 element = cfg_list_next(element)) 9357 { 9358 cfg_obj_t *vconfig = cfg_listelt_value(element); 9359 dns_view_t *view = NULL; 9360 9361 view = NULL; 9362 result = find_view(vconfig, &viewlist, &view); 9363 if (result != ISC_R_SUCCESS) { 9364 goto cleanup_cachelist; 9365 } 9366 9367 result = configure_view( 9368 view, &viewlist, config, vconfig, &cachelist, 9369 &server->cachelist, &server->kasplist, 9370 &server->keystorelist, bindkeys, named_g_mctx, 9371 named_g_aclconfctx, true, first_time); 9372 if (result != ISC_R_SUCCESS) { 9373 dns_view_detach(&view); 9374 goto cleanup_cachelist; 9375 } 9376 dns_view_freeze(view); 9377 dns_view_detach(&view); 9378 } 9379 9380 /* 9381 * Make sure we have a default view if and only if there 9382 * were no explicit views. 9383 */ 9384 if (views == NULL) { 9385 dns_view_t *view = NULL; 9386 result = find_view(NULL, &viewlist, &view); 9387 if (result != ISC_R_SUCCESS) { 9388 goto cleanup_cachelist; 9389 } 9390 result = configure_view( 9391 view, &viewlist, config, NULL, &cachelist, 9392 &server->cachelist, &server->kasplist, 9393 &server->keystorelist, bindkeys, named_g_mctx, 9394 named_g_aclconfctx, true, first_time); 9395 if (result != ISC_R_SUCCESS) { 9396 dns_view_detach(&view); 9397 goto cleanup_cachelist; 9398 } 9399 dns_view_freeze(view); 9400 dns_view_detach(&view); 9401 } 9402 9403 /* 9404 * Create (or recreate) the built-in views. 9405 */ 9406 builtin_views = NULL; 9407 RUNTIME_CHECK(cfg_map_get(named_g_config, "view", &builtin_views) == 9408 ISC_R_SUCCESS); 9409 for (element = cfg_list_first(builtin_views); element != NULL; 9410 element = cfg_list_next(element)) 9411 { 9412 cfg_obj_t *vconfig = cfg_listelt_value(element); 9413 dns_view_t *view = NULL; 9414 9415 result = create_view(vconfig, &builtin_viewlist, &view); 9416 if (result != ISC_R_SUCCESS) { 9417 goto cleanup_cachelist; 9418 } 9419 9420 result = configure_view( 9421 view, &viewlist, config, vconfig, &cachelist, 9422 &server->cachelist, &server->kasplist, 9423 &server->keystorelist, bindkeys, named_g_mctx, 9424 named_g_aclconfctx, false, first_time); 9425 if (result != ISC_R_SUCCESS) { 9426 dns_view_detach(&view); 9427 goto cleanup_cachelist; 9428 } 9429 dns_view_freeze(view); 9430 dns_view_detach(&view); 9431 } 9432 9433 /* Now combine the two viewlists into one */ 9434 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 9435 9436 /* 9437 * Commit any dns_zone_setview() calls on all zones in the new 9438 * view. 9439 */ 9440 for (dns_view_t *view = ISC_LIST_HEAD(viewlist); view != NULL; 9441 view = ISC_LIST_NEXT(view, link)) 9442 { 9443 dns_view_setviewcommit(view); 9444 } 9445 9446 /* Swap our new view list with the production one. */ 9447 tmpviewlist = server->viewlist; 9448 server->viewlist = viewlist; 9449 viewlist = tmpviewlist; 9450 9451 /* Make the view list available to each of the views */ 9452 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9453 view = ISC_LIST_NEXT(view, link)) 9454 { 9455 view->viewlist = &server->viewlist; 9456 } 9457 9458 /* Swap our new cache list with the production one. */ 9459 tmpcachelist = server->cachelist; 9460 server->cachelist = cachelist; 9461 cachelist = tmpcachelist; 9462 9463 /* Load the TKEY information from the configuration. */ 9464 if (options != NULL) { 9465 dns_tkeyctx_t *tkeyctx = NULL; 9466 9467 result = named_tkeyctx_fromconfig(options, named_g_mctx, 9468 &tkeyctx); 9469 if (result != ISC_R_SUCCESS) { 9470 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9471 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9472 "configuring TKEY: %s", 9473 isc_result_totext(result)); 9474 goto cleanup_cachelist; 9475 } 9476 if (server->sctx->tkeyctx != NULL) { 9477 dns_tkeyctx_destroy(&server->sctx->tkeyctx); 9478 } 9479 server->sctx->tkeyctx = tkeyctx; 9480 } 9481 9482 #ifdef HAVE_LMDB 9483 /* 9484 * If we're using LMDB, we may have created newzones databases 9485 * as root, making it impossible to reopen them later after 9486 * switching to a new userid. We close them now, and reopen 9487 * after relinquishing privileges them. 9488 */ 9489 if (first_time) { 9490 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); 9491 view != NULL; view = ISC_LIST_NEXT(view, link)) 9492 { 9493 nzd_env_close(view); 9494 } 9495 } 9496 #endif /* HAVE_LMDB */ 9497 9498 /* 9499 * Switch to the effective UID for setting up files. 9500 * Later, after configuring all the listening ports, 9501 * we'll relinquish root privileges permanently. 9502 */ 9503 if (first_time) { 9504 named_os_changeuser(false); 9505 } 9506 9507 /* 9508 * Check that the working directory is writable. 9509 */ 9510 if (!isc_file_isdirwritable(".")) { 9511 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9512 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9513 "the working directory is not writable"); 9514 result = ISC_R_NOPERM; 9515 goto cleanup_cachelist; 9516 } 9517 9518 #ifdef HAVE_LMDB 9519 /* 9520 * Reopen NZD databases. 9521 */ 9522 if (first_time) { 9523 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); 9524 view != NULL; view = ISC_LIST_NEXT(view, link)) 9525 { 9526 nzd_env_reopen(view); 9527 } 9528 } 9529 #endif /* HAVE_LMDB */ 9530 9531 /* 9532 * Configure the logging system. 9533 * 9534 * Do this after changing UID to make sure that any log 9535 * files specified in named.conf get created by the 9536 * unprivileged user, not root. 9537 */ 9538 if (named_g_logstderr) { 9539 const cfg_obj_t *logobj = NULL; 9540 9541 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9542 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9543 "not using config file logging " 9544 "statement for logging due to " 9545 "-g option"); 9546 9547 (void)cfg_map_get(config, "logging", &logobj); 9548 if (logobj != NULL) { 9549 result = named_logconfig(NULL, logobj); 9550 if (result != ISC_R_SUCCESS) { 9551 isc_log_write( 9552 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9553 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9554 "checking logging configuration " 9555 "failed: %s", 9556 isc_result_totext(result)); 9557 goto cleanup_cachelist; 9558 } 9559 } 9560 } else { 9561 const cfg_obj_t *logobj = NULL; 9562 9563 isc_logconfig_create(named_g_lctx, &logc); 9564 9565 logobj = NULL; 9566 (void)cfg_map_get(config, "logging", &logobj); 9567 if (logobj != NULL) { 9568 result = named_logconfig(logc, logobj); 9569 if (result != ISC_R_SUCCESS) { 9570 isc_log_write( 9571 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9572 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9573 "configuring logging: %s", 9574 isc_result_totext(result)); 9575 goto cleanup_logc; 9576 } 9577 } else { 9578 named_log_setdefaultchannels(logc); 9579 named_log_setdefaultsslkeylogfile(logc); 9580 result = named_log_setunmatchedcategory(logc); 9581 if (result != ISC_R_SUCCESS) { 9582 isc_log_write( 9583 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9584 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9585 "setting up default 'category " 9586 "unmatched': %s", 9587 isc_result_totext(result)); 9588 goto cleanup_logc; 9589 } 9590 result = named_log_setdefaultcategory(logc); 9591 if (result != ISC_R_SUCCESS) { 9592 isc_log_write( 9593 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9594 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9595 "setting up default 'category " 9596 "default': %s", 9597 isc_result_totext(result)); 9598 goto cleanup_logc; 9599 } 9600 } 9601 9602 isc_logconfig_use(named_g_lctx, logc); 9603 logc = NULL; 9604 9605 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9606 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9607 "now using logging configuration from " 9608 "config file"); 9609 } 9610 9611 /* 9612 * Set the default value of the query logging flag depending 9613 * whether a "queries" category has been defined. This is 9614 * a disgusting hack, but we need to do this for BIND 8 9615 * compatibility. 9616 */ 9617 if (first_time) { 9618 const cfg_obj_t *logobj = NULL; 9619 const cfg_obj_t *categories = NULL; 9620 9621 obj = NULL; 9622 if (named_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { 9623 ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES, 9624 cfg_obj_asboolean(obj)); 9625 } else { 9626 (void)cfg_map_get(config, "logging", &logobj); 9627 if (logobj != NULL) { 9628 (void)cfg_map_get(logobj, "category", 9629 &categories); 9630 } 9631 if (categories != NULL) { 9632 for (element = cfg_list_first(categories); 9633 element != NULL; 9634 element = cfg_list_next(element)) 9635 { 9636 const cfg_obj_t *catobj; 9637 const char *str; 9638 9639 obj = cfg_listelt_value(element); 9640 catobj = cfg_tuple_get(obj, "name"); 9641 str = cfg_obj_asstring(catobj); 9642 if (strcasecmp(str, "queries") == 0) { 9643 ns_server_setoption( 9644 server->sctx, 9645 NS_SERVER_LOGQUERIES, 9646 true); 9647 } 9648 } 9649 } 9650 } 9651 obj = NULL; 9652 result = named_config_get(maps, "responselog", &obj); 9653 if (result == ISC_R_SUCCESS) { 9654 ns_server_setoption(server->sctx, 9655 NS_SERVER_LOGRESPONSES, 9656 cfg_obj_asboolean(obj)); 9657 } 9658 } 9659 9660 obj = NULL; 9661 if (options != NULL && 9662 cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS) 9663 { 9664 named_g_memstatistics = cfg_obj_asboolean(obj); 9665 } else { 9666 named_g_memstatistics = 9667 ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0); 9668 } 9669 9670 obj = NULL; 9671 if (named_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS) 9672 { 9673 named_main_setmemstats(cfg_obj_asstring(obj)); 9674 } else if (named_g_memstatistics) { 9675 named_main_setmemstats("named.memstats"); 9676 } else { 9677 named_main_setmemstats(NULL); 9678 } 9679 9680 obj = NULL; 9681 result = named_config_get(maps, "statistics-file", &obj); 9682 INSIST(result == ISC_R_SUCCESS); 9683 setstring(server, &server->statsfile, cfg_obj_asstring(obj)); 9684 9685 obj = NULL; 9686 result = named_config_get(maps, "dump-file", &obj); 9687 INSIST(result == ISC_R_SUCCESS); 9688 setstring(server, &server->dumpfile, cfg_obj_asstring(obj)); 9689 9690 obj = NULL; 9691 result = named_config_get(maps, "secroots-file", &obj); 9692 INSIST(result == ISC_R_SUCCESS); 9693 setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)); 9694 9695 obj = NULL; 9696 result = named_config_get(maps, "recursing-file", &obj); 9697 INSIST(result == ISC_R_SUCCESS); 9698 setstring(server, &server->recfile, cfg_obj_asstring(obj)); 9699 9700 obj = NULL; 9701 result = named_config_get(maps, "version", &obj); 9702 if (result == ISC_R_SUCCESS) { 9703 setoptstring(server, &server->version, obj); 9704 server->version_set = true; 9705 } else { 9706 server->version_set = false; 9707 } 9708 9709 obj = NULL; 9710 result = named_config_get(maps, "hostname", &obj); 9711 if (result == ISC_R_SUCCESS) { 9712 setoptstring(server, &server->hostname, obj); 9713 server->hostname_set = true; 9714 } else { 9715 server->hostname_set = false; 9716 } 9717 9718 obj = NULL; 9719 result = named_config_get(maps, "server-id", &obj); 9720 server->sctx->usehostname = false; 9721 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 9722 /* The parser translates "hostname" to true */ 9723 server->sctx->usehostname = true; 9724 result = ns_server_setserverid(server->sctx, NULL); 9725 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 9726 /* Found a quoted string */ 9727 result = ns_server_setserverid(server->sctx, 9728 cfg_obj_asstring(obj)); 9729 } else { 9730 result = ns_server_setserverid(server->sctx, NULL); 9731 } 9732 RUNTIME_CHECK(result == ISC_R_SUCCESS); 9733 9734 obj = NULL; 9735 result = named_config_get(maps, "flush-zones-on-shutdown", &obj); 9736 if (result == ISC_R_SUCCESS) { 9737 server->flushonshutdown = cfg_obj_asboolean(obj); 9738 } else { 9739 server->flushonshutdown = false; 9740 } 9741 9742 obj = NULL; 9743 result = named_config_get(maps, "answer-cookie", &obj); 9744 INSIST(result == ISC_R_SUCCESS); 9745 server->sctx->answercookie = cfg_obj_asboolean(obj); 9746 9747 obj = NULL; 9748 result = named_config_get(maps, "cookie-algorithm", &obj); 9749 INSIST(result == ISC_R_SUCCESS); 9750 if (strcasecmp(cfg_obj_asstring(obj), "siphash24") == 0) { 9751 server->sctx->cookiealg = ns_cookiealg_siphash24; 9752 } else { 9753 UNREACHABLE(); 9754 } 9755 9756 obj = NULL; 9757 result = named_config_get(maps, "cookie-secret", &obj); 9758 if (result == ISC_R_SUCCESS) { 9759 const char *str; 9760 bool first = true; 9761 isc_buffer_t b; 9762 unsigned int usedlength; 9763 unsigned int expectedlength; 9764 9765 for (element = cfg_list_first(obj); element != NULL; 9766 element = cfg_list_next(element)) 9767 { 9768 obj = cfg_listelt_value(element); 9769 str = cfg_obj_asstring(obj); 9770 9771 if (first) { 9772 memset(server->sctx->secret, 0, 9773 sizeof(server->sctx->secret)); 9774 isc_buffer_init(&b, server->sctx->secret, 9775 sizeof(server->sctx->secret)); 9776 result = isc_hex_decodestring(str, &b); 9777 if (result != ISC_R_SUCCESS && 9778 result != ISC_R_NOSPACE) 9779 { 9780 goto cleanup_altsecrets; 9781 } 9782 first = false; 9783 } else { 9784 altsecret = isc_mem_get(server->sctx->mctx, 9785 sizeof(*altsecret)); 9786 isc_buffer_init(&b, altsecret->secret, 9787 sizeof(altsecret->secret)); 9788 result = isc_hex_decodestring(str, &b); 9789 if (result != ISC_R_SUCCESS && 9790 result != ISC_R_NOSPACE) 9791 { 9792 isc_mem_put(server->sctx->mctx, 9793 altsecret, 9794 sizeof(*altsecret)); 9795 goto cleanup_altsecrets; 9796 } 9797 ISC_LIST_INITANDAPPEND(altsecrets, altsecret, 9798 link); 9799 } 9800 9801 usedlength = isc_buffer_usedlength(&b); 9802 switch (server->sctx->cookiealg) { 9803 case ns_cookiealg_siphash24: 9804 expectedlength = ISC_SIPHASH24_KEY_LENGTH; 9805 if (usedlength != expectedlength) { 9806 result = ISC_R_RANGE; 9807 isc_log_write( 9808 named_g_lctx, 9809 NAMED_LOGCATEGORY_GENERAL, 9810 NAMED_LOGMODULE_SERVER, 9811 ISC_LOG_ERROR, 9812 "SipHash-2-4 cookie-secret " 9813 "must be 128 bits: %s", 9814 isc_result_totext(result)); 9815 goto cleanup_altsecrets; 9816 } 9817 break; 9818 } 9819 } 9820 } else { 9821 isc_nonce_buf(server->sctx->secret, 9822 sizeof(server->sctx->secret)); 9823 } 9824 9825 /* 9826 * Swap altsecrets lists. 9827 */ 9828 tmpaltsecrets = server->sctx->altsecrets; 9829 server->sctx->altsecrets = altsecrets; 9830 altsecrets = tmpaltsecrets; 9831 9832 (void)named_server_loadnta(server); 9833 9834 #ifdef USE_DNSRPS 9835 /* 9836 * Start and connect to the DNS Response Policy Service 9837 * daemon, dnsrpzd, for each view that uses DNSRPS. 9838 */ 9839 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9840 view = ISC_LIST_NEXT(view, link)) 9841 { 9842 result = dns_dnsrps_connect(view->rpzs); 9843 if (result != ISC_R_SUCCESS) { 9844 view = NULL; 9845 goto cleanup_altsecrets; 9846 } 9847 } 9848 #endif /* ifdef USE_DNSRPS */ 9849 9850 /* 9851 * Record the time of most recent configuration 9852 */ 9853 named_g_configtime = isc_time_now(); 9854 9855 isc_loopmgr_resume(named_g_loopmgr); 9856 exclusive = false; 9857 9858 /* Take back root privileges temporarily */ 9859 if (first_time) { 9860 named_os_restoreuser(); 9861 } 9862 9863 /* Configure the statistics channel(s) */ 9864 result = named_statschannels_configure(named_g_server, config, 9865 named_g_aclconfctx); 9866 if (result != ISC_R_SUCCESS) { 9867 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9868 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9869 "configuring statistics server(s): %s", 9870 isc_result_totext(result)); 9871 goto cleanup_altsecrets; 9872 } 9873 9874 /* 9875 * Bind the control port(s). 9876 */ 9877 result = named_controls_configure(named_g_server->controls, config, 9878 named_g_aclconfctx); 9879 if (result != ISC_R_SUCCESS) { 9880 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9881 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9882 "binding control channel(s): %s", 9883 isc_result_totext(result)); 9884 goto cleanup_altsecrets; 9885 } 9886 9887 (void)ns_interfacemgr_scan(server->interfacemgr, true, true); 9888 9889 /* 9890 * Permanently drop root privileges now. 9891 */ 9892 if (first_time) { 9893 named_os_changeuser(true); 9894 } 9895 9896 /* 9897 * These cleans up either the old production view list 9898 * or our temporary list depending on whether they 9899 * were swapped above or not. 9900 */ 9901 cleanup_altsecrets: 9902 while ((altsecret = ISC_LIST_HEAD(altsecrets)) != NULL) { 9903 ISC_LIST_UNLINK(altsecrets, altsecret, link); 9904 isc_mem_put(server->sctx->mctx, altsecret, sizeof(*altsecret)); 9905 } 9906 9907 cleanup_logc: 9908 if (logc != NULL) { 9909 isc_logconfig_destroy(&logc); 9910 } 9911 9912 cleanup_cachelist: 9913 while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { 9914 ISC_LIST_UNLINK(cachelist, nsc, link); 9915 dns_cache_detach(&nsc->cache); 9916 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 9917 } 9918 9919 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 9920 9921 cleanup_viewlist: 9922 for (dns_view_t *view = ISC_LIST_HEAD(viewlist); view != NULL; 9923 view = view_next) 9924 { 9925 view_next = ISC_LIST_NEXT(view, link); 9926 ISC_LIST_UNLINK(viewlist, view, link); 9927 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) 9928 { 9929 dns_view_setviewrevert(view); 9930 (void)dns_view_apply(view, false, NULL, removed, view); 9931 } 9932 dns_view_detach(&view); 9933 } 9934 9935 cleanup_kasplist: 9936 for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) { 9937 kasp_next = ISC_LIST_NEXT(kasp, link); 9938 ISC_LIST_UNLINK(kasplist, kasp, link); 9939 dns_kasp_detach(&kasp); 9940 } 9941 9942 cleanup_keystorelist: 9943 for (keystore = ISC_LIST_HEAD(keystorelist); keystore != NULL; 9944 keystore = keystore_next) 9945 { 9946 keystore_next = ISC_LIST_NEXT(keystore, link); 9947 ISC_LIST_UNLINK(keystorelist, keystore, link); 9948 dns_keystore_detach(&keystore); 9949 } 9950 9951 cleanup_v6portset: 9952 isc_portset_destroy(named_g_mctx, &v6portset); 9953 9954 cleanup_v4portset: 9955 isc_portset_destroy(named_g_mctx, &v4portset); 9956 9957 cleanup_bindkeys_parser: 9958 9959 if (bindkeys_parser != NULL) { 9960 if (bindkeys != NULL) { 9961 cfg_obj_destroy(bindkeys_parser, &bindkeys); 9962 } 9963 cfg_parser_destroy(&bindkeys_parser); 9964 } 9965 9966 cleanup_config: 9967 cfg_obj_destroy(conf_parser, &config); 9968 9969 cleanup_conf_parser: 9970 cfg_parser_destroy(&conf_parser); 9971 9972 cleanup_exclusive: 9973 if (exclusive) { 9974 isc_loopmgr_resume(named_g_loopmgr); 9975 } 9976 9977 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9978 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9979 "load_configuration: %s", isc_result_totext(result)); 9980 9981 return result; 9982 } 9983 9984 static isc_result_t 9985 view_loaded(void *arg) { 9986 isc_result_t result; 9987 ns_zoneload_t *zl = (ns_zoneload_t *)arg; 9988 9989 /* 9990 * Force zone maintenance. Do this after loading 9991 * so that we know when we need to force AXFR of 9992 * secondary zones whose master files are missing. 9993 * 9994 * We use the zoneload reference counter to let us 9995 * know when all views are finished. 9996 */ 9997 if (isc_refcount_decrement(&zl->refs) == 1) { 9998 named_server_t *server = zl->server; 9999 bool reconfig = zl->reconfig; 10000 dns_view_t *view = NULL; 10001 10002 isc_refcount_destroy(&zl->refs); 10003 isc_mem_put(server->mctx, zl, sizeof(*zl)); 10004 10005 /* 10006 * To maintain compatibility with log parsing tools that might 10007 * be looking for this string after "rndc reconfig", we keep it 10008 * as it is 10009 */ 10010 if (reconfig) { 10011 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10012 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10013 "any newly configured zones are now " 10014 "loaded"); 10015 } else { 10016 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10017 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10018 "all zones loaded"); 10019 } 10020 10021 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10022 view = ISC_LIST_NEXT(view, link)) 10023 { 10024 if (view->managed_keys != NULL) { 10025 result = dns_zone_synckeyzone( 10026 view->managed_keys); 10027 if (result != ISC_R_SUCCESS) { 10028 isc_log_write( 10029 named_g_lctx, 10030 DNS_LOGCATEGORY_DNSSEC, 10031 DNS_LOGMODULE_DNSSEC, 10032 ISC_LOG_ERROR, 10033 "failed to initialize " 10034 "managed-keys for view %s " 10035 "(%s): DNSSEC validation is " 10036 "at risk", 10037 view->name, 10038 isc_result_totext(result)); 10039 } 10040 } 10041 } 10042 10043 CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr), 10044 "forcing zone maintenance"); 10045 10046 named_os_started(); 10047 10048 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10049 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10050 "FIPS mode is %s", 10051 isc_fips_mode() ? "enabled" : "disabled"); 10052 10053 named_os_notify_systemd("READY=1\n" 10054 "STATUS=running\n" 10055 "MAINPID=%" PRId64 "\n", 10056 (int64_t)getpid()); 10057 10058 atomic_store(&server->reload_status, NAMED_RELOAD_DONE); 10059 10060 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10061 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10062 "running"); 10063 } 10064 10065 return ISC_R_SUCCESS; 10066 } 10067 10068 static isc_result_t 10069 load_zones(named_server_t *server, bool reconfig) { 10070 isc_result_t result = ISC_R_SUCCESS; 10071 ns_zoneload_t *zl = NULL; 10072 dns_view_t *view = NULL; 10073 10074 zl = isc_mem_get(server->mctx, sizeof(*zl)); 10075 zl->server = server; 10076 zl->reconfig = reconfig; 10077 10078 isc_loopmgr_pause(named_g_loopmgr); 10079 10080 isc_refcount_init(&zl->refs, 1); 10081 10082 /* 10083 * Schedule zones to be loaded from disk. 10084 */ 10085 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10086 view = ISC_LIST_NEXT(view, link)) 10087 { 10088 if (view->managed_keys != NULL) { 10089 result = dns_zone_load(view->managed_keys, false); 10090 if (result != ISC_R_SUCCESS && 10091 result != DNS_R_UPTODATE && 10092 result != DNS_R_CONTINUE) 10093 { 10094 goto cleanup; 10095 } 10096 } 10097 if (view->redirect != NULL) { 10098 result = dns_zone_load(view->redirect, false); 10099 if (result != ISC_R_SUCCESS && 10100 result != DNS_R_UPTODATE && 10101 result != DNS_R_CONTINUE) 10102 { 10103 goto cleanup; 10104 } 10105 } 10106 10107 /* 10108 * 'dns_view_asyncload' calls view_loaded if there are no 10109 * zones. 10110 */ 10111 isc_refcount_increment(&zl->refs); 10112 result = dns_view_asyncload(view, reconfig, view_loaded, zl); 10113 if (result != ISC_R_SUCCESS) { 10114 isc_refcount_decrement1(&zl->refs); 10115 goto cleanup; 10116 } 10117 } 10118 10119 cleanup: 10120 if (isc_refcount_decrement(&zl->refs) == 1) { 10121 isc_refcount_destroy(&zl->refs); 10122 isc_mem_put(server->mctx, zl, sizeof(*zl)); 10123 } 10124 10125 isc_loopmgr_resume(named_g_loopmgr); 10126 10127 return result; 10128 } 10129 10130 static void 10131 run_server(void *arg) { 10132 isc_result_t result; 10133 named_server_t *server = (named_server_t *)arg; 10134 dns_geoip_databases_t *geoip = NULL; 10135 10136 dns_zonemgr_create(named_g_mctx, named_g_netmgr, &server->zonemgr); 10137 10138 CHECKFATAL(dns_dispatchmgr_create(named_g_mctx, named_g_loopmgr, 10139 named_g_netmgr, &named_g_dispatchmgr), 10140 "creating dispatch manager"); 10141 10142 dns_dispatchmgr_setstats(named_g_dispatchmgr, server->resolverstats); 10143 10144 #if defined(HAVE_GEOIP2) 10145 geoip = named_g_geoip; 10146 #else /* if defined(HAVE_GEOIP2) */ 10147 geoip = NULL; 10148 #endif /* if defined(HAVE_GEOIP2) */ 10149 10150 CHECKFATAL(ns_interfacemgr_create(named_g_mctx, server->sctx, 10151 named_g_loopmgr, named_g_netmgr, 10152 named_g_dispatchmgr, geoip, 10153 &server->interfacemgr), 10154 "creating interface manager"); 10155 10156 isc_timer_create(named_g_mainloop, interface_timer_tick, server, 10157 &server->interface_timer); 10158 10159 isc_timer_create(named_g_mainloop, heartbeat_timer_tick, server, 10160 &server->heartbeat_timer); 10161 10162 isc_timer_create(named_g_mainloop, tat_timer_tick, server, 10163 &server->tat_timer); 10164 10165 isc_timer_create(named_g_mainloop, pps_timer_tick, server, 10166 &server->pps_timer); 10167 10168 CHECKFATAL( 10169 cfg_parser_create(named_g_mctx, named_g_lctx, &named_g_parser), 10170 "creating default configuration parser"); 10171 10172 CHECKFATAL(cfg_parser_create(named_g_mctx, named_g_lctx, 10173 &named_g_addparser), 10174 "creating additional configuration parser"); 10175 10176 CHECKFATAL(load_configuration(named_g_conffile, server, true), 10177 "loading configuration"); 10178 10179 CHECKFATAL(load_zones(server, false), "loading zones"); 10180 #ifdef ENABLE_AFL 10181 named_g_run_done = true; 10182 #endif /* ifdef ENABLE_AFL */ 10183 } 10184 10185 void 10186 named_server_flushonshutdown(named_server_t *server, bool flush) { 10187 REQUIRE(NAMED_SERVER_VALID(server)); 10188 10189 server->flushonshutdown = flush; 10190 } 10191 10192 static void 10193 shutdown_server(void *arg) { 10194 named_server_t *server = (named_server_t *)arg; 10195 dns_view_t *view = NULL, *view_next = NULL; 10196 dns_kasp_t *kasp = NULL, *kasp_next = NULL; 10197 dns_keystore_t *keystore = NULL, *keystore_next = NULL; 10198 bool flush = server->flushonshutdown; 10199 named_cache_t *nsc = NULL; 10200 10201 named_os_notify_systemd("STOPPING=1\n"); 10202 named_os_notify_close(); 10203 10204 isc_signal_stop(server->sighup); 10205 isc_signal_destroy(&server->sighup); 10206 10207 /* 10208 * We need to shutdown the interface before going 10209 * exclusive (which would pause the netmgr). 10210 */ 10211 ns_interfacemgr_shutdown(server->interfacemgr); 10212 10213 named_controls_shutdown(server->controls); 10214 10215 named_statschannels_shutdown(server); 10216 10217 isc_loopmgr_pause(named_g_loopmgr); 10218 10219 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10220 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "shutting down%s", 10221 flush ? ": flushing changes" : ""); 10222 10223 cleanup_session_key(server, server->mctx); 10224 10225 if (named_g_aclconfctx != NULL) { 10226 cfg_aclconfctx_detach(&named_g_aclconfctx); 10227 } 10228 10229 cfg_obj_destroy(named_g_parser, &named_g_config); 10230 cfg_parser_destroy(&named_g_parser); 10231 cfg_parser_destroy(&named_g_addparser); 10232 10233 (void)named_server_saventa(server); 10234 10235 for (kasp = ISC_LIST_HEAD(server->kasplist); kasp != NULL; 10236 kasp = kasp_next) 10237 { 10238 kasp_next = ISC_LIST_NEXT(kasp, link); 10239 ISC_LIST_UNLINK(server->kasplist, kasp, link); 10240 dns_kasp_detach(&kasp); 10241 } 10242 10243 for (keystore = ISC_LIST_HEAD(server->keystorelist); keystore != NULL; 10244 keystore = keystore_next) 10245 { 10246 keystore_next = ISC_LIST_NEXT(keystore, link); 10247 ISC_LIST_UNLINK(server->keystorelist, keystore, link); 10248 dns_keystore_detach(&keystore); 10249 } 10250 10251 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10252 view = view_next) 10253 { 10254 view_next = ISC_LIST_NEXT(view, link); 10255 ISC_LIST_UNLINK(server->viewlist, view, link); 10256 dns_view_flushonshutdown(view, flush); 10257 dns_view_detach(&view); 10258 } 10259 10260 /* 10261 * Shut down all dyndb instances. 10262 */ 10263 dns_dyndb_cleanup(true); 10264 10265 while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { 10266 ISC_LIST_UNLINK(server->cachelist, nsc, link); 10267 dns_cache_detach(&nsc->cache); 10268 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 10269 } 10270 10271 isc_timer_destroy(&server->interface_timer); 10272 isc_timer_destroy(&server->heartbeat_timer); 10273 isc_timer_destroy(&server->pps_timer); 10274 isc_timer_destroy(&server->tat_timer); 10275 10276 ns_interfacemgr_detach(&server->interfacemgr); 10277 10278 dns_dispatchmgr_detach(&named_g_dispatchmgr); 10279 10280 dns_zonemgr_shutdown(server->zonemgr); 10281 10282 #if defined(HAVE_GEOIP2) 10283 named_geoip_shutdown(); 10284 #endif /* HAVE_GEOIP2 */ 10285 10286 dns_db_detach(&server->in_roothints); 10287 10288 isc_loopmgr_resume(named_g_loopmgr); 10289 } 10290 10291 static isc_result_t 10292 get_matching_view_sync(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, 10293 dns_message_t *message, dns_aclenv_t *env, 10294 isc_result_t *sigresult, dns_view_t **viewp) { 10295 dns_view_t *view; 10296 10297 /* 10298 * We should not be running synchronous view matching if signature 10299 * checking involves SIG(0). TSIG has priority of SIG(0), so if TSIG 10300 * is set then we proceed anyway. 10301 */ 10302 INSIST(message->tsigkey != NULL || message->tsig != NULL || 10303 message->sig0 == NULL); 10304 10305 for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL; 10306 view = ISC_LIST_NEXT(view, link)) 10307 { 10308 if (message->rdclass == view->rdclass || 10309 message->rdclass == dns_rdataclass_any) 10310 { 10311 const dns_name_t *tsig = NULL; 10312 10313 dns_message_resetsig(message); 10314 *sigresult = dns_message_checksig(message, view); 10315 if (*sigresult == ISC_R_SUCCESS) { 10316 tsig = dns_tsigkey_identity(message->tsigkey); 10317 } 10318 10319 if (dns_acl_allowed(srcaddr, tsig, view->matchclients, 10320 env) && 10321 dns_acl_allowed(destaddr, tsig, 10322 view->matchdestinations, env) && 10323 !(view->matchrecursiveonly && 10324 (message->flags & DNS_MESSAGEFLAG_RD) == 0)) 10325 { 10326 dns_view_attach(view, viewp); 10327 return ISC_R_SUCCESS; 10328 } 10329 } 10330 } 10331 10332 return ISC_R_NOTFOUND; 10333 } 10334 10335 static void 10336 get_matching_view_done(void *cbarg) { 10337 matching_view_ctx_t *mvctx = cbarg; 10338 dns_message_t *message = mvctx->message; 10339 10340 if (*mvctx->viewmatchresult == ISC_R_SUCCESS) { 10341 INSIST(mvctx->view != NULL); 10342 dns_view_attach(mvctx->view, mvctx->viewp); 10343 } 10344 10345 mvctx->cb(mvctx->cbarg); 10346 10347 dns_aclenv_detach(&mvctx->aclenv); 10348 10349 if (mvctx->quota_result == ISC_R_SUCCESS) { 10350 isc_quota_release(&mvctx->sctx->sig0checksquota); 10351 } 10352 if (mvctx->view != NULL) { 10353 dns_view_detach(&mvctx->view); 10354 } 10355 isc_loop_detach(&mvctx->loop); 10356 ns_server_detach(&mvctx->sctx); 10357 isc_mem_put(message->mctx, mvctx, sizeof(*mvctx)); 10358 dns_message_detach(&message); 10359 } 10360 10361 static dns_view_t * 10362 get_matching_view_next(dns_view_t *view, dns_rdataclass_t rdclass) { 10363 if (view == NULL) { 10364 view = ISC_LIST_HEAD(named_g_server->viewlist); 10365 } else { 10366 view = ISC_LIST_NEXT(view, link); 10367 } 10368 while (true) { 10369 if (view == NULL || rdclass == view->rdclass || 10370 rdclass == dns_rdataclass_any) 10371 { 10372 return view; 10373 } 10374 view = ISC_LIST_NEXT(view, link); 10375 }; 10376 } 10377 10378 static void 10379 get_matching_view_continue(void *cbarg, isc_result_t result) { 10380 matching_view_ctx_t *mvctx = cbarg; 10381 dns_view_t *view = NULL; 10382 const dns_name_t *tsig = NULL; 10383 10384 *mvctx->sigresult = result; 10385 10386 if (result == ISC_R_SUCCESS) { 10387 tsig = dns_tsigkey_identity(mvctx->message->tsigkey); 10388 } 10389 10390 if (dns_acl_allowed(&mvctx->srcaddr, tsig, mvctx->view->matchclients, 10391 mvctx->aclenv) && 10392 dns_acl_allowed(&mvctx->destaddr, tsig, 10393 mvctx->view->matchdestinations, mvctx->aclenv) && 10394 !(mvctx->view->matchrecursiveonly && 10395 (mvctx->message->flags & DNS_MESSAGEFLAG_RD) == 0)) 10396 { 10397 /* 10398 * A matching view is found. 10399 */ 10400 *mvctx->viewmatchresult = ISC_R_SUCCESS; 10401 get_matching_view_done(cbarg); 10402 return; 10403 } 10404 10405 dns_message_resetsig(mvctx->message); 10406 10407 view = get_matching_view_next(mvctx->view, mvctx->message->rdclass); 10408 dns_view_detach(&mvctx->view); 10409 if (view != NULL) { 10410 /* 10411 * Try the next view. 10412 */ 10413 dns_view_attach(view, &mvctx->view); 10414 result = dns_message_checksig_async( 10415 mvctx->message, view, mvctx->loop, 10416 get_matching_view_continue, mvctx); 10417 INSIST(result == DNS_R_WAIT); 10418 return; 10419 } 10420 10421 /* 10422 * No matching view is found. 10423 */ 10424 *mvctx->viewmatchresult = ISC_R_NOTFOUND; 10425 get_matching_view_done(cbarg); 10426 } 10427 10428 /*% 10429 * Find a view that matches the source and destination addresses of a query. 10430 */ 10431 static isc_result_t 10432 get_matching_view(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, 10433 dns_message_t *message, dns_aclenv_t *env, ns_server_t *sctx, 10434 isc_loop_t *loop, isc_job_cb cb, void *cbarg, 10435 isc_result_t *sigresult, isc_result_t *viewmatchresult, 10436 dns_view_t **viewp) { 10437 dns_view_t *view = NULL; 10438 isc_result_t result; 10439 10440 REQUIRE(message != NULL); 10441 REQUIRE(sctx != NULL); 10442 REQUIRE(loop == NULL || cb != NULL); 10443 REQUIRE(sigresult != NULL); 10444 REQUIRE(viewmatchresult != NULL); 10445 REQUIRE(viewp != NULL && *viewp == NULL); 10446 10447 /* No offloading is requested if the loop is unset. */ 10448 if (loop == NULL) { 10449 *viewmatchresult = get_matching_view_sync( 10450 srcaddr, destaddr, message, env, sigresult, viewp); 10451 return *viewmatchresult; 10452 } 10453 10454 /* Also no offloading when there is no view at all to match against. */ 10455 view = get_matching_view_next(NULL, message->rdclass); 10456 if (view == NULL) { 10457 *viewmatchresult = ISC_R_NOTFOUND; 10458 return *viewmatchresult; 10459 } 10460 10461 dns_message_resetsig(message); 10462 10463 matching_view_ctx_t *mvctx = isc_mem_get(message->mctx, sizeof(*mvctx)); 10464 *mvctx = (matching_view_ctx_t){ 10465 .srcaddr = *srcaddr, 10466 .destaddr = *destaddr, 10467 .aclenv = dns_aclenv_ref(env), 10468 .cb = cb, 10469 .cbarg = cbarg, 10470 .sigresult = sigresult, 10471 .viewmatchresult = viewmatchresult, 10472 .quota_result = ISC_R_UNSET, 10473 .viewp = viewp, 10474 }; 10475 ns_server_attach(sctx, &mvctx->sctx); 10476 isc_loop_attach(loop, &mvctx->loop); 10477 dns_message_attach(message, &mvctx->message); 10478 10479 /* 10480 * If the message has a SIG0 signature which we are going to 10481 * check, and the client is not exempt from the SIG(0) quota, 10482 * then acquire a quota. TSIG has priority over SIG(0), so if 10483 * TSIG is set then we don't care. 10484 */ 10485 if (message->tsigkey == NULL && message->tsig == NULL && 10486 message->sig0 != NULL) 10487 { 10488 if (sctx->sig0checksquota_exempt != NULL) { 10489 int exempt_match; 10490 10491 result = dns_acl_match(srcaddr, NULL, 10492 sctx->sig0checksquota_exempt, 10493 env, &exempt_match, NULL); 10494 if (result == ISC_R_SUCCESS && exempt_match > 0) { 10495 mvctx->quota_result = ISC_R_EXISTS; 10496 } 10497 } 10498 if (mvctx->quota_result == ISC_R_UNSET) { 10499 mvctx->quota_result = 10500 isc_quota_acquire(&sctx->sig0checksquota); 10501 } 10502 if (mvctx->quota_result == ISC_R_SOFTQUOTA) { 10503 isc_quota_release(&sctx->sig0checksquota); 10504 } 10505 if (mvctx->quota_result != ISC_R_SUCCESS && 10506 mvctx->quota_result != ISC_R_EXISTS) 10507 { 10508 *mvctx->viewmatchresult = ISC_R_QUOTA; 10509 isc_async_run(loop, get_matching_view_done, mvctx); 10510 return DNS_R_WAIT; 10511 } 10512 } 10513 10514 dns_view_attach(view, &mvctx->view); 10515 result = dns_message_checksig_async(message, view, loop, 10516 get_matching_view_continue, mvctx); 10517 INSIST(result == DNS_R_WAIT); 10518 10519 return DNS_R_WAIT; 10520 } 10521 10522 void 10523 named_server_create(isc_mem_t *mctx, named_server_t **serverp) { 10524 isc_result_t result; 10525 named_server_t *server = isc_mem_get(mctx, sizeof(*server)); 10526 10527 *server = (named_server_t){ 10528 .mctx = mctx, 10529 .statsfile = isc_mem_strdup(mctx, "named.stats"), 10530 .dumpfile = isc_mem_strdup(mctx, "named_dump.db"), 10531 .secrootsfile = isc_mem_strdup(mctx, "named.secroots"), 10532 .recfile = isc_mem_strdup(mctx, "named.recursing"), 10533 }; 10534 10535 /* Initialize server data structures. */ 10536 ISC_LIST_INIT(server->kasplist); 10537 ISC_LIST_INIT(server->keystorelist); 10538 ISC_LIST_INIT(server->viewlist); 10539 10540 /* Must be first. */ 10541 CHECKFATAL(dst_lib_init(named_g_mctx, named_g_engine), 10542 "initializing DST"); 10543 10544 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, 10545 &server->in_roothints), 10546 "setting up root hints"); 10547 10548 atomic_init(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 10549 10550 ns_server_create(mctx, get_matching_view, &server->sctx); 10551 10552 #if defined(HAVE_GEOIP2) 10553 /* 10554 * GeoIP must be initialized before the interface 10555 * manager (which includes the ACL environment) 10556 * is created. 10557 */ 10558 named_geoip_init(); 10559 #endif /* HAVE_GEOIP2 */ 10560 10561 #ifdef ENABLE_AFL 10562 server->sctx->fuzztype = named_g_fuzz_type; 10563 server->sctx->fuzznotify = named_fuzz_notify; 10564 #endif /* ifdef ENABLE_AFL */ 10565 10566 named_g_mainloop = isc_loop_main(named_g_loopmgr); 10567 10568 isc_loop_setup(named_g_mainloop, run_server, server); 10569 isc_loop_teardown(named_g_mainloop, shutdown_server, server); 10570 10571 /* Add SIGHUP reload handler */ 10572 server->sighup = isc_signal_new( 10573 named_g_loopmgr, named_server_reloadwanted, server, SIGHUP); 10574 10575 isc_stats_create(server->mctx, &server->sockstats, 10576 isc_sockstatscounter_max); 10577 isc_nm_setstats(named_g_netmgr, server->sockstats); 10578 10579 isc_stats_create(named_g_mctx, &server->zonestats, 10580 dns_zonestatscounter_max); 10581 10582 isc_stats_create(named_g_mctx, &server->resolverstats, 10583 dns_resstatscounter_max); 10584 10585 CHECKFATAL(named_controls_create(server, &server->controls), 10586 "named_controls_create"); 10587 10588 ISC_LIST_INIT(server->statschannels); 10589 10590 ISC_LIST_INIT(server->cachelist); 10591 10592 server->magic = NAMED_SERVER_MAGIC; 10593 10594 *serverp = server; 10595 } 10596 10597 void 10598 named_server_destroy(named_server_t **serverp) { 10599 named_server_t *server = *serverp; 10600 REQUIRE(NAMED_SERVER_VALID(server)); 10601 10602 #ifdef HAVE_DNSTAP 10603 if (server->dtenv != NULL) { 10604 dns_dtenv_detach(&server->dtenv); 10605 } 10606 #endif /* HAVE_DNSTAP */ 10607 10608 #ifdef USE_DNSRPS 10609 dns_dnsrps_server_destroy(); 10610 isc_mem_free(server->mctx, server->dnsrpslib); 10611 #endif /* ifdef USE_DNSRPS */ 10612 10613 named_controls_destroy(&server->controls); 10614 10615 isc_stats_detach(&server->zonestats); 10616 isc_stats_detach(&server->sockstats); 10617 isc_stats_detach(&server->resolverstats); 10618 10619 if (server->sctx != NULL) { 10620 ns_server_detach(&server->sctx); 10621 } 10622 10623 isc_mem_free(server->mctx, server->statsfile); 10624 isc_mem_free(server->mctx, server->dumpfile); 10625 isc_mem_free(server->mctx, server->secrootsfile); 10626 isc_mem_free(server->mctx, server->recfile); 10627 10628 if (server->bindkeysfile != NULL) { 10629 isc_mem_free(server->mctx, server->bindkeysfile); 10630 } 10631 10632 if (server->version != NULL) { 10633 isc_mem_free(server->mctx, server->version); 10634 } 10635 if (server->hostname != NULL) { 10636 isc_mem_free(server->mctx, server->hostname); 10637 } 10638 10639 if (server->zonemgr != NULL) { 10640 dns_zonemgr_detach(&server->zonemgr); 10641 } 10642 10643 dst_lib_destroy(); 10644 10645 INSIST(ISC_LIST_EMPTY(server->kasplist)); 10646 INSIST(ISC_LIST_EMPTY(server->keystorelist)); 10647 INSIST(ISC_LIST_EMPTY(server->viewlist)); 10648 INSIST(ISC_LIST_EMPTY(server->cachelist)); 10649 10650 if (server->tlsctx_server_cache != NULL) { 10651 isc_tlsctx_cache_detach(&server->tlsctx_server_cache); 10652 } 10653 10654 if (server->tlsctx_client_cache != NULL) { 10655 isc_tlsctx_cache_detach(&server->tlsctx_client_cache); 10656 } 10657 10658 server->magic = 0; 10659 isc_mem_put(server->mctx, server, sizeof(*server)); 10660 *serverp = NULL; 10661 } 10662 10663 static void 10664 fatal(const char *msg, isc_result_t result) { 10665 if (named_g_loopmgr_running) { 10666 isc_loopmgr_pause(named_g_loopmgr); 10667 } 10668 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10669 NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "%s: %s", msg, 10670 isc_result_totext(result)); 10671 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10672 NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, 10673 "exiting (due to fatal error)"); 10674 named_os_shutdown(); 10675 _exit(EXIT_FAILURE); 10676 } 10677 10678 static isc_result_t 10679 loadconfig(named_server_t *server) { 10680 isc_result_t result; 10681 result = load_configuration(named_g_conffile, server, false); 10682 if (result == ISC_R_SUCCESS) { 10683 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10684 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10685 "reloading configuration succeeded"); 10686 } else { 10687 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10688 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 10689 "reloading configuration failed: %s", 10690 isc_result_totext(result)); 10691 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 10692 } 10693 10694 return result; 10695 } 10696 10697 static isc_result_t 10698 reload(named_server_t *server) { 10699 isc_result_t result; 10700 10701 atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 10702 10703 named_os_notify_systemd("RELOADING=1\n" 10704 "MONOTONIC_USEC=%" PRIu64 "\n" 10705 "STATUS=reload command received\n", 10706 (uint64_t)isc_time_monotonic() / NS_PER_US); 10707 10708 CHECK(loadconfig(server)); 10709 10710 result = load_zones(server, false); 10711 if (result == ISC_R_SUCCESS) { 10712 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10713 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10714 "reloading zones succeeded"); 10715 } else { 10716 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10717 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 10718 "reloading zones failed: %s", 10719 isc_result_totext(result)); 10720 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 10721 } 10722 cleanup: 10723 named_os_notify_systemd("READY=1\n" 10724 "STATUS=reload command finished: %s\n", 10725 isc_result_totext(result)); 10726 10727 return result; 10728 } 10729 10730 /* 10731 * Handle a reload event (from SIGHUP). 10732 */ 10733 static void 10734 named_server_reload(void *arg) { 10735 named_server_t *server = (named_server_t *)arg; 10736 10737 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10738 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10739 "received SIGHUP signal to reload zones"); 10740 (void)reload(server); 10741 } 10742 10743 void 10744 named_server_reloadwanted(void *arg, int signum) { 10745 named_server_t *server = (named_server_t *)arg; 10746 10747 REQUIRE(signum == SIGHUP); 10748 10749 isc_async_run(named_g_mainloop, named_server_reload, server); 10750 } 10751 10752 #ifdef JEMALLOC_API_SUPPORTED 10753 static isc_result_t 10754 memprof_toggle(bool active) { 10755 if (mallctl("prof.active", NULL, NULL, &active, sizeof(active)) != 0) { 10756 return ISC_R_FAILURE; 10757 } 10758 10759 return ISC_R_SUCCESS; 10760 } 10761 10762 static isc_result_t 10763 memprof_dump(void) { 10764 if (mallctl("prof.dump", NULL, NULL, NULL, 0) != 0) { 10765 return ISC_R_FAILURE; 10766 } 10767 10768 return ISC_R_SUCCESS; 10769 } 10770 #else 10771 static isc_result_t 10772 memprof_toggle(bool active) { 10773 UNUSED(active); 10774 10775 return ISC_R_NOTIMPLEMENTED; 10776 } 10777 10778 static isc_result_t 10779 memprof_dump(void) { 10780 return ISC_R_NOTIMPLEMENTED; 10781 } 10782 10783 #endif /* JEMALLOC_API_SUPPORTED */ 10784 10785 void 10786 named_server_scan_interfaces(named_server_t *server) { 10787 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10788 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 10789 "automatic interface rescan"); 10790 10791 ns_interfacemgr_scan(server->interfacemgr, true, false); 10792 } 10793 10794 /* 10795 * Get the next token from lexer 'lex'. 10796 * 10797 * NOTE: the token value for string tokens always uses the same pointer 10798 * value. Multiple calls to this function on the same lexer will always 10799 * return either that value (lex->data) or NULL. It is necessary to copy 10800 * the token into local storage if it needs to be referenced after the next 10801 * call to next_token(). 10802 */ 10803 static char * 10804 next_token(isc_lex_t *lex, isc_buffer_t **text) { 10805 isc_result_t result; 10806 isc_token_t token; 10807 10808 token.type = isc_tokentype_unknown; 10809 result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF | ISC_LEXOPT_QSTRING, 10810 &token); 10811 10812 switch (result) { 10813 case ISC_R_NOMORE: 10814 (void)isc_lex_close(lex); 10815 break; 10816 case ISC_R_SUCCESS: 10817 if (token.type == isc_tokentype_eof) { 10818 (void)isc_lex_close(lex); 10819 } 10820 break; 10821 case ISC_R_NOSPACE: 10822 if (text != NULL) { 10823 (void)putstr(text, "token too large"); 10824 (void)putnull(text); 10825 } 10826 return NULL; 10827 default: 10828 if (text != NULL) { 10829 (void)putstr(text, isc_result_totext(result)); 10830 (void)putnull(text); 10831 } 10832 return NULL; 10833 } 10834 10835 if (token.type == isc_tokentype_string || 10836 token.type == isc_tokentype_qstring) 10837 { 10838 return token.value.as_textregion.base; 10839 } 10840 10841 return NULL; 10842 } 10843 10844 /* 10845 * Find the zone specified in the control channel command, if any. 10846 * If a zone is specified, point '*zonep' at it, otherwise 10847 * set '*zonep' to NULL, and f 'zonename' is not NULL, copy 10848 * the zone name into it (N.B. 'zonename' must have space to hold 10849 * a full DNS name). 10850 * 10851 * If 'zonetxt' is set, the caller has already pulled a token 10852 * off the command line that is to be used as the zone name. (This 10853 * is sometimes done when it's necessary to check for an optional 10854 * argument before the zone name, as in "rndc sync [-clean] zone".) 10855 */ 10856 static isc_result_t 10857 zone_from_args(named_server_t *server, isc_lex_t *lex, const char *zonetxt, 10858 dns_zone_t **zonep, char *zonename, isc_buffer_t **text, 10859 bool skip) { 10860 char *ptr; 10861 char *classtxt; 10862 const char *viewtxt = NULL; 10863 dns_fixedname_t fname; 10864 dns_name_t *name; 10865 isc_result_t result; 10866 dns_view_t *view = NULL; 10867 dns_rdataclass_t rdclass; 10868 char problem[DNS_NAME_FORMATSIZE + 500] = ""; 10869 char zonebuf[DNS_NAME_FORMATSIZE]; 10870 bool redirect = false; 10871 10872 REQUIRE(zonep != NULL && *zonep == NULL); 10873 10874 if (skip) { 10875 /* Skip the command name. */ 10876 ptr = next_token(lex, text); 10877 if (ptr == NULL) { 10878 return ISC_R_UNEXPECTEDEND; 10879 } 10880 } 10881 10882 /* Look for the zone name. */ 10883 if (zonetxt == NULL) { 10884 zonetxt = next_token(lex, text); 10885 } 10886 if (zonetxt == NULL) { 10887 return ISC_R_SUCCESS; 10888 } 10889 10890 /* Copy zonetxt because it'll be overwritten by next_token() */ 10891 /* To locate a zone named "-redirect" use "-redirect." */ 10892 if (strcmp(zonetxt, "-redirect") == 0) { 10893 redirect = true; 10894 strlcpy(zonebuf, ".", DNS_NAME_FORMATSIZE); 10895 } else { 10896 strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE); 10897 } 10898 if (zonename != NULL) { 10899 strlcpy(zonename, redirect ? "." : zonetxt, 10900 DNS_NAME_FORMATSIZE); 10901 } 10902 10903 name = dns_fixedname_initname(&fname); 10904 CHECK(dns_name_fromstring(name, zonebuf, dns_rootname, 0, NULL)); 10905 10906 /* Look for the optional class name. */ 10907 classtxt = next_token(lex, text); 10908 if (classtxt != NULL) { 10909 isc_textregion_t r; 10910 r.base = classtxt; 10911 r.length = strlen(classtxt); 10912 CHECK(dns_rdataclass_fromtext(&rdclass, &r)); 10913 10914 /* Look for the optional view name. */ 10915 viewtxt = next_token(lex, text); 10916 } else { 10917 rdclass = dns_rdataclass_in; 10918 } 10919 10920 if (viewtxt == NULL) { 10921 if (redirect) { 10922 result = dns_viewlist_find(&server->viewlist, 10923 "_default", 10924 dns_rdataclass_in, &view); 10925 if (result != ISC_R_SUCCESS || view->redirect == NULL) { 10926 result = ISC_R_NOTFOUND; 10927 snprintf(problem, sizeof(problem), 10928 "redirect zone not found in " 10929 "_default view"); 10930 } else { 10931 dns_zone_attach(view->redirect, zonep); 10932 result = ISC_R_SUCCESS; 10933 } 10934 } else { 10935 result = dns_viewlist_findzone(&server->viewlist, name, 10936 classtxt == NULL, 10937 rdclass, zonep); 10938 if (result == ISC_R_NOTFOUND) { 10939 snprintf(problem, sizeof(problem), 10940 "no matching zone '%s' in any view", 10941 zonebuf); 10942 } else if (result == ISC_R_MULTIPLE) { 10943 snprintf(problem, sizeof(problem), 10944 "zone '%s' was found in multiple " 10945 "views", 10946 zonebuf); 10947 } 10948 } 10949 } else { 10950 result = dns_viewlist_find(&server->viewlist, viewtxt, rdclass, 10951 &view); 10952 if (result != ISC_R_SUCCESS) { 10953 snprintf(problem, sizeof(problem), 10954 "no matching view '%s'", viewtxt); 10955 goto report; 10956 } 10957 10958 if (redirect) { 10959 if (view->redirect != NULL) { 10960 dns_zone_attach(view->redirect, zonep); 10961 result = ISC_R_SUCCESS; 10962 } else { 10963 result = ISC_R_NOTFOUND; 10964 } 10965 } else { 10966 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 10967 zonep); 10968 } 10969 if (result != ISC_R_SUCCESS) { 10970 snprintf(problem, sizeof(problem), 10971 "no matching zone '%s' in view '%s'", zonebuf, 10972 viewtxt); 10973 } 10974 } 10975 10976 /* Partial match? */ 10977 if (result != ISC_R_SUCCESS && *zonep != NULL) { 10978 dns_zone_detach(zonep); 10979 } 10980 if (result == DNS_R_PARTIALMATCH) { 10981 result = ISC_R_NOTFOUND; 10982 } 10983 report: 10984 if (result != ISC_R_SUCCESS) { 10985 isc_result_t tresult; 10986 10987 tresult = putstr(text, problem); 10988 if (tresult == ISC_R_SUCCESS) { 10989 (void)putnull(text); 10990 } 10991 } 10992 10993 cleanup: 10994 if (view != NULL) { 10995 dns_view_detach(&view); 10996 } 10997 10998 return result; 10999 } 11000 11001 /* 11002 * Act on a "retransfer" command from the command channel. 11003 */ 11004 isc_result_t 11005 named_server_retransfercommand(named_server_t *server, isc_lex_t *lex, 11006 isc_buffer_t **text) { 11007 isc_result_t result; 11008 const char *arg = NULL; 11009 dns_zone_t *zone = NULL; 11010 dns_zone_t *raw = NULL; 11011 dns_zonetype_t type; 11012 bool force = false; 11013 11014 REQUIRE(text != NULL); 11015 11016 /* Skip the command name. */ 11017 (void)next_token(lex, text); 11018 11019 arg = next_token(lex, text); 11020 if (arg != NULL && (strcmp(arg, "-force") == 0)) { 11021 force = true; 11022 arg = next_token(lex, text); 11023 } 11024 11025 result = zone_from_args(server, lex, arg, &zone, NULL, text, false); 11026 if (result != ISC_R_SUCCESS) { 11027 return result; 11028 } 11029 if (zone == NULL) { 11030 return ISC_R_UNEXPECTEDEND; 11031 } 11032 dns_zone_getraw(zone, &raw); 11033 if (raw != NULL) { 11034 dns_zone_detach(&zone); 11035 dns_zone_attach(raw, &zone); 11036 dns_zone_detach(&raw); 11037 } 11038 type = dns_zone_gettype(zone); 11039 if (type == dns_zone_secondary || type == dns_zone_mirror || 11040 type == dns_zone_stub || 11041 (type == dns_zone_redirect && 11042 dns_zone_getredirecttype(zone) == dns_zone_secondary)) 11043 { 11044 if (force) { 11045 dns_zone_stopxfr(zone); 11046 } 11047 dns_zone_forcexfr(zone); 11048 } else { 11049 (void)putstr(text, "retransfer: inappropriate zone type: "); 11050 (void)putstr(text, dns_zonetype_name(type)); 11051 if (type == dns_zone_redirect) { 11052 type = dns_zone_getredirecttype(zone); 11053 (void)putstr(text, "("); 11054 (void)putstr(text, dns_zonetype_name(type)); 11055 (void)putstr(text, ")"); 11056 } 11057 (void)putnull(text); 11058 result = ISC_R_FAILURE; 11059 } 11060 dns_zone_detach(&zone); 11061 return result; 11062 } 11063 11064 /* 11065 * Act on a "reload" command from the command channel. 11066 */ 11067 isc_result_t 11068 named_server_reloadcommand(named_server_t *server, isc_lex_t *lex, 11069 isc_buffer_t **text) { 11070 isc_result_t result; 11071 dns_zone_t *zone = NULL; 11072 dns_zonetype_t type; 11073 const char *msg = NULL; 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 result = reload(server); 11083 if (result == ISC_R_SUCCESS) { 11084 msg = "server reload successful"; 11085 } 11086 } else { 11087 type = dns_zone_gettype(zone); 11088 if (type == dns_zone_secondary || type == dns_zone_mirror || 11089 type == dns_zone_stub) 11090 { 11091 dns_zone_refresh(zone); 11092 dns_zone_detach(&zone); 11093 msg = "zone refresh queued"; 11094 } else { 11095 result = dns_zone_load(zone, false); 11096 dns_zone_detach(&zone); 11097 switch (result) { 11098 case ISC_R_SUCCESS: 11099 msg = "zone reload successful"; 11100 break; 11101 case DNS_R_CONTINUE: 11102 msg = "zone reload queued"; 11103 result = ISC_R_SUCCESS; 11104 break; 11105 case DNS_R_UPTODATE: 11106 msg = "zone reload up-to-date"; 11107 result = ISC_R_SUCCESS; 11108 break; 11109 default: 11110 /* failure message will be generated by rndc */ 11111 break; 11112 } 11113 } 11114 } 11115 if (msg != NULL) { 11116 (void)putstr(text, msg); 11117 (void)putnull(text); 11118 } 11119 return result; 11120 } 11121 11122 /* 11123 * Act on a "reset-stats" command from the command channel. 11124 */ 11125 isc_result_t 11126 named_server_resetstatscommand(named_server_t *server, isc_lex_t *lex, 11127 isc_buffer_t **text) { 11128 const char *arg = NULL; 11129 bool recursive_high_water = false; 11130 bool tcp_high_water = false; 11131 11132 REQUIRE(text != NULL); 11133 11134 /* Skip the command name. */ 11135 (void)next_token(lex, text); 11136 11137 arg = next_token(lex, text); 11138 if (arg == NULL) { 11139 (void)putstr(text, "reset-stats: argument expected"); 11140 (void)putnull(text); 11141 return ISC_R_UNEXPECTEDEND; 11142 } 11143 while (arg != NULL) { 11144 if (strcmp(arg, "recursive-high-water") == 0) { 11145 recursive_high_water = true; 11146 } else if (strcmp(arg, "tcp-high-water") == 0) { 11147 tcp_high_water = true; 11148 } else { 11149 (void)putstr(text, "reset-stats: " 11150 "unrecognized argument: "); 11151 (void)putstr(text, arg); 11152 (void)putnull(text); 11153 return ISC_R_FAILURE; 11154 } 11155 arg = next_token(lex, text); 11156 } 11157 11158 if (recursive_high_water) { 11159 isc_stats_set(ns_stats_get(server->sctx->nsstats), 0, 11160 ns_statscounter_recurshighwater); 11161 } 11162 if (tcp_high_water) { 11163 isc_stats_set(ns_stats_get(server->sctx->nsstats), 0, 11164 ns_statscounter_tcphighwater); 11165 } 11166 11167 return ISC_R_SUCCESS; 11168 } 11169 11170 /* 11171 * Act on a "reconfig" command from the command channel. 11172 */ 11173 isc_result_t 11174 named_server_reconfigcommand(named_server_t *server) { 11175 isc_result_t result; 11176 atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 11177 11178 named_os_notify_systemd("RELOADING=1\n" 11179 "MONOTONIC_USEC=%" PRIu64 "\n" 11180 "STATUS=reconfig command received\n", 11181 (uint64_t)isc_time_monotonic() / NS_PER_US); 11182 11183 CHECK(loadconfig(server)); 11184 11185 result = load_zones(server, true); 11186 if (result == ISC_R_SUCCESS) { 11187 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11188 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11189 "scheduled loading new zones"); 11190 } else { 11191 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11192 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11193 "loading new zones failed: %s", 11194 isc_result_totext(result)); 11195 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 11196 } 11197 cleanup: 11198 named_os_notify_systemd("READY=1\n" 11199 "STATUS=reconfig command finished: %s\n", 11200 isc_result_totext(result)); 11201 11202 return result; 11203 } 11204 11205 /* 11206 * Act on a "notify" command from the command channel. 11207 */ 11208 isc_result_t 11209 named_server_notifycommand(named_server_t *server, isc_lex_t *lex, 11210 isc_buffer_t **text) { 11211 isc_result_t result; 11212 dns_zone_t *zone = NULL; 11213 const char msg[] = "zone notify queued"; 11214 11215 REQUIRE(text != NULL); 11216 11217 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11218 if (result != ISC_R_SUCCESS) { 11219 return result; 11220 } 11221 if (zone == NULL) { 11222 return ISC_R_UNEXPECTEDEND; 11223 } 11224 11225 dns_zone_notify(zone, true); 11226 dns_zone_detach(&zone); 11227 (void)putstr(text, msg); 11228 (void)putnull(text); 11229 11230 return ISC_R_SUCCESS; 11231 } 11232 11233 /* 11234 * Act on a "refresh" command from the command channel. 11235 */ 11236 isc_result_t 11237 named_server_refreshcommand(named_server_t *server, isc_lex_t *lex, 11238 isc_buffer_t **text) { 11239 isc_result_t result; 11240 dns_zone_t *zone = NULL, *raw = NULL; 11241 const char msg1[] = "zone refresh queued"; 11242 const char msg2[] = "not a secondary, mirror, or stub zone"; 11243 dns_zonetype_t type; 11244 11245 REQUIRE(text != NULL); 11246 11247 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11248 if (result != ISC_R_SUCCESS) { 11249 return result; 11250 } 11251 if (zone == NULL) { 11252 return ISC_R_UNEXPECTEDEND; 11253 } 11254 11255 dns_zone_getraw(zone, &raw); 11256 if (raw != NULL) { 11257 dns_zone_detach(&zone); 11258 dns_zone_attach(raw, &zone); 11259 dns_zone_detach(&raw); 11260 } 11261 11262 type = dns_zone_gettype(zone); 11263 if (type == dns_zone_secondary || type == dns_zone_mirror || 11264 type == dns_zone_stub) 11265 { 11266 dns_zone_refresh(zone); 11267 dns_zone_detach(&zone); 11268 (void)putstr(text, msg1); 11269 (void)putnull(text); 11270 return ISC_R_SUCCESS; 11271 } 11272 11273 dns_zone_detach(&zone); 11274 (void)putstr(text, msg2); 11275 (void)putnull(text); 11276 return ISC_R_FAILURE; 11277 } 11278 11279 isc_result_t 11280 named_server_setortoggle(named_server_t *server, const char *optname, 11281 unsigned int option, isc_lex_t *lex) { 11282 bool prev, value; 11283 char *ptr = NULL; 11284 11285 /* Skip the command name. */ 11286 ptr = next_token(lex, NULL); 11287 if (ptr == NULL) { 11288 return ISC_R_UNEXPECTEDEND; 11289 } 11290 11291 prev = ns_server_getoption(server->sctx, option); 11292 11293 ptr = next_token(lex, NULL); 11294 if (ptr == NULL) { 11295 value = !prev; 11296 } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 11297 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 11298 { 11299 value = true; 11300 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 11301 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 11302 { 11303 value = false; 11304 } else { 11305 return DNS_R_SYNTAX; 11306 } 11307 11308 if (value == prev) { 11309 return ISC_R_SUCCESS; 11310 } 11311 11312 ns_server_setoption(server->sctx, option, value); 11313 11314 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11315 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "%s is now %s", 11316 optname, value ? "on" : "off"); 11317 return ISC_R_SUCCESS; 11318 } 11319 11320 static isc_result_t 11321 listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 11322 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 11323 isc_tlsctx_cache_t *tlsctx_cache, 11324 ns_listenlist_t **target) { 11325 isc_result_t result; 11326 const cfg_listelt_t *element; 11327 ns_listenlist_t *dlist = NULL; 11328 11329 REQUIRE(target != NULL && *target == NULL); 11330 11331 result = ns_listenlist_create(mctx, &dlist); 11332 if (result != ISC_R_SUCCESS) { 11333 return result; 11334 } 11335 11336 for (element = cfg_list_first(listenlist); element != NULL; 11337 element = cfg_list_next(element)) 11338 { 11339 ns_listenelt_t *delt = NULL; 11340 const cfg_obj_t *listener = cfg_listelt_value(element); 11341 result = listenelt_fromconfig(listener, config, actx, mctx, 11342 family, tlsctx_cache, &delt); 11343 if (result != ISC_R_SUCCESS) { 11344 goto cleanup; 11345 } 11346 ISC_LIST_APPEND(dlist->elts, delt, link); 11347 } 11348 *target = dlist; 11349 return ISC_R_SUCCESS; 11350 11351 cleanup: 11352 ns_listenlist_detach(&dlist); 11353 return result; 11354 } 11355 11356 static const cfg_obj_t * 11357 find_maplist(const cfg_obj_t *config, const char *listname, const char *name) { 11358 isc_result_t result; 11359 const cfg_obj_t *maplist = NULL; 11360 const cfg_listelt_t *elt = NULL; 11361 11362 REQUIRE(config != NULL); 11363 REQUIRE(name != NULL); 11364 11365 result = cfg_map_get(config, listname, &maplist); 11366 if (result != ISC_R_SUCCESS) { 11367 return NULL; 11368 } 11369 11370 for (elt = cfg_list_first(maplist); elt != NULL; 11371 elt = cfg_list_next(elt)) 11372 { 11373 const cfg_obj_t *map = cfg_listelt_value(elt); 11374 if (strcasecmp(cfg_obj_asstring(cfg_map_getname(map)), name) == 11375 0) 11376 { 11377 return map; 11378 } 11379 } 11380 11381 return NULL; 11382 } 11383 11384 /* 11385 * Create a listen list from the corresponding configuration 11386 * data structure. 11387 */ 11388 static isc_result_t 11389 listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 11390 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 11391 isc_tlsctx_cache_t *tlsctx_cache, 11392 ns_listenelt_t **target) { 11393 isc_result_t result; 11394 const cfg_obj_t *ltup = NULL; 11395 const cfg_obj_t *tlsobj = NULL, *httpobj = NULL; 11396 const cfg_obj_t *portobj = NULL; 11397 const cfg_obj_t *http_server = NULL; 11398 const cfg_obj_t *proxyobj = NULL; 11399 in_port_t port = 0; 11400 const char *key = NULL, *cert = NULL, *ca_file = NULL, 11401 *dhparam_file = NULL, *ciphers = NULL, *cipher_suites = NULL; 11402 bool tls_prefer_server_ciphers = false, 11403 tls_prefer_server_ciphers_set = false; 11404 bool tls_session_tickets = false, tls_session_tickets_set = false; 11405 bool do_tls = false, no_tls = false, http = false; 11406 ns_listenelt_t *delt = NULL; 11407 uint32_t tls_protos = 0; 11408 ns_listen_tls_params_t tls_params = { 0 }; 11409 const char *tlsname = NULL; 11410 isc_nm_proxy_type_t proxy = ISC_NM_PROXY_NONE; 11411 11412 REQUIRE(target != NULL && *target == NULL); 11413 11414 ltup = cfg_tuple_get(listener, "tuple"); 11415 RUNTIME_CHECK(ltup != NULL); 11416 11417 tlsobj = cfg_tuple_get(ltup, "tls"); 11418 if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) { 11419 tlsname = cfg_obj_asstring(tlsobj); 11420 11421 if (strcasecmp(tlsname, "none") == 0) { 11422 no_tls = true; 11423 } else if (strcasecmp(tlsname, "ephemeral") == 0) { 11424 do_tls = true; 11425 } else { 11426 const cfg_obj_t *keyobj = NULL, *certobj = NULL, 11427 *ca_obj = NULL, *dhparam_obj = NULL; 11428 const cfg_obj_t *tlsmap = NULL; 11429 const cfg_obj_t *tls_proto_list = NULL; 11430 const cfg_obj_t *ciphers_obj = NULL; 11431 const cfg_obj_t *cipher_suites_obj = NULL; 11432 const cfg_obj_t *prefer_server_ciphers_obj = NULL; 11433 const cfg_obj_t *session_tickets_obj = NULL; 11434 11435 do_tls = true; 11436 11437 tlsmap = find_maplist(config, "tls", tlsname); 11438 if (tlsmap == NULL) { 11439 cfg_obj_log(tlsobj, named_g_lctx, ISC_LOG_ERROR, 11440 "tls '%s' is not defined", 11441 cfg_obj_asstring(tlsobj)); 11442 return ISC_R_FAILURE; 11443 } 11444 11445 CHECK(cfg_map_get(tlsmap, "key-file", &keyobj)); 11446 key = cfg_obj_asstring(keyobj); 11447 11448 CHECK(cfg_map_get(tlsmap, "cert-file", &certobj)); 11449 cert = cfg_obj_asstring(certobj); 11450 11451 if (cfg_map_get(tlsmap, "ca-file", &ca_obj) == 11452 ISC_R_SUCCESS) 11453 { 11454 ca_file = cfg_obj_asstring(ca_obj); 11455 } 11456 11457 if (cfg_map_get(tlsmap, "protocols", &tls_proto_list) == 11458 ISC_R_SUCCESS) 11459 { 11460 const cfg_listelt_t *proto = NULL; 11461 INSIST(tls_proto_list != NULL); 11462 for (proto = cfg_list_first(tls_proto_list); 11463 proto != 0; proto = cfg_list_next(proto)) 11464 { 11465 const cfg_obj_t *tls_proto_obj = 11466 cfg_listelt_value(proto); 11467 const char *tls_sver = 11468 cfg_obj_asstring(tls_proto_obj); 11469 const isc_tls_protocol_version_t ver = 11470 isc_tls_protocol_name_to_version( 11471 tls_sver); 11472 11473 INSIST(ver != 11474 ISC_TLS_PROTO_VER_UNDEFINED); 11475 INSIST(isc_tls_protocol_supported(ver)); 11476 tls_protos |= ver; 11477 } 11478 } 11479 11480 if (cfg_map_get(tlsmap, "dhparam-file", &dhparam_obj) == 11481 ISC_R_SUCCESS) 11482 { 11483 dhparam_file = cfg_obj_asstring(dhparam_obj); 11484 } 11485 11486 if (cfg_map_get(tlsmap, "ciphers", &ciphers_obj) == 11487 ISC_R_SUCCESS) 11488 { 11489 ciphers = cfg_obj_asstring(ciphers_obj); 11490 } 11491 11492 if (cfg_map_get(tlsmap, "cipher-suites", 11493 &cipher_suites_obj) == ISC_R_SUCCESS) 11494 { 11495 cipher_suites = 11496 cfg_obj_asstring(cipher_suites_obj); 11497 } 11498 11499 if (cfg_map_get(tlsmap, "prefer-server-ciphers", 11500 &prefer_server_ciphers_obj) == 11501 ISC_R_SUCCESS) 11502 { 11503 tls_prefer_server_ciphers = cfg_obj_asboolean( 11504 prefer_server_ciphers_obj); 11505 tls_prefer_server_ciphers_set = true; 11506 } 11507 11508 if (cfg_map_get(tlsmap, "session-tickets", 11509 &session_tickets_obj) == ISC_R_SUCCESS) 11510 { 11511 tls_session_tickets = 11512 cfg_obj_asboolean(session_tickets_obj); 11513 tls_session_tickets_set = true; 11514 } 11515 } 11516 } 11517 11518 tls_params = (ns_listen_tls_params_t){ 11519 .name = tlsname, 11520 .key = key, 11521 .cert = cert, 11522 .ca_file = ca_file, 11523 .protocols = tls_protos, 11524 .dhparam_file = dhparam_file, 11525 .ciphers = ciphers, 11526 .cipher_suites = cipher_suites, 11527 .prefer_server_ciphers = tls_prefer_server_ciphers, 11528 .prefer_server_ciphers_set = tls_prefer_server_ciphers_set, 11529 .session_tickets = tls_session_tickets, 11530 .session_tickets_set = tls_session_tickets_set 11531 }; 11532 11533 httpobj = cfg_tuple_get(ltup, "http"); 11534 if (httpobj != NULL && cfg_obj_isstring(httpobj)) { 11535 const char *httpname = cfg_obj_asstring(httpobj); 11536 11537 if (!do_tls && !no_tls) { 11538 return ISC_R_FAILURE; 11539 } 11540 11541 http_server = find_maplist(config, "http", httpname); 11542 if (http_server == NULL && strcasecmp(httpname, "default") != 0) 11543 { 11544 cfg_obj_log(httpobj, named_g_lctx, ISC_LOG_ERROR, 11545 "http '%s' is not defined", 11546 cfg_obj_asstring(httpobj)); 11547 return ISC_R_FAILURE; 11548 } 11549 11550 http = true; 11551 } 11552 11553 portobj = cfg_tuple_get(ltup, "port"); 11554 if (!cfg_obj_isuint32(portobj)) { 11555 if (http && do_tls) { 11556 if (named_g_httpsport != 0) { 11557 port = named_g_httpsport; 11558 } else { 11559 result = named_config_getport( 11560 config, "https-port", &port); 11561 if (result != ISC_R_SUCCESS) { 11562 return result; 11563 } 11564 } 11565 } else if (http && !do_tls) { 11566 if (named_g_httpport != 0) { 11567 port = named_g_httpport; 11568 } else { 11569 result = named_config_getport( 11570 config, "http-port", &port); 11571 if (result != ISC_R_SUCCESS) { 11572 return result; 11573 } 11574 } 11575 } else if (do_tls) { 11576 if (named_g_tlsport != 0) { 11577 port = named_g_tlsport; 11578 } else { 11579 result = named_config_getport( 11580 config, "tls-port", &port); 11581 if (result != ISC_R_SUCCESS) { 11582 return result; 11583 } 11584 } 11585 } else { 11586 if (named_g_port != 0) { 11587 port = named_g_port; 11588 } else { 11589 result = named_config_getport(config, "port", 11590 &port); 11591 if (result != ISC_R_SUCCESS) { 11592 return result; 11593 } 11594 } 11595 } 11596 } else { 11597 if (cfg_obj_asuint32(portobj) >= UINT16_MAX) { 11598 return ISC_R_RANGE; 11599 } 11600 port = (in_port_t)cfg_obj_asuint32(portobj); 11601 } 11602 11603 proxyobj = cfg_tuple_get(ltup, "proxy"); 11604 if (proxyobj != NULL && cfg_obj_isstring(proxyobj)) { 11605 const char *proxyval = cfg_obj_asstring(proxyobj); 11606 11607 if (strcasecmp(proxyval, "encrypted") == 0) { 11608 INSIST(do_tls == true); 11609 proxy = ISC_NM_PROXY_ENCRYPTED; 11610 } else if (strcasecmp(proxyval, "plain") == 0) { 11611 proxy = ISC_NM_PROXY_PLAIN; 11612 } else { 11613 UNREACHABLE(); 11614 } 11615 } 11616 11617 #ifdef HAVE_LIBNGHTTP2 11618 if (http) { 11619 CHECK(listenelt_http(http_server, family, do_tls, &tls_params, 11620 tlsctx_cache, port, mctx, proxy, &delt)); 11621 } 11622 #endif /* HAVE_LIBNGHTTP2 */ 11623 11624 if (!http) { 11625 CHECK(ns_listenelt_create(mctx, port, NULL, family, do_tls, 11626 &tls_params, tlsctx_cache, proxy, 11627 &delt)); 11628 } 11629 11630 result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"), config, 11631 named_g_lctx, actx, mctx, family, 11632 &delt->acl); 11633 if (result != ISC_R_SUCCESS) { 11634 ns_listenelt_destroy(delt); 11635 return result; 11636 } 11637 *target = delt; 11638 11639 cleanup: 11640 return result; 11641 } 11642 11643 #ifdef HAVE_LIBNGHTTP2 11644 static isc_result_t 11645 listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, 11646 const ns_listen_tls_params_t *tls_params, 11647 isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, 11648 isc_mem_t *mctx, isc_nm_proxy_type_t proxy, 11649 ns_listenelt_t **target) { 11650 isc_result_t result = ISC_R_SUCCESS; 11651 ns_listenelt_t *delt = NULL; 11652 char **endpoints = NULL; 11653 const cfg_obj_t *eplist = NULL; 11654 const cfg_listelt_t *elt = NULL; 11655 size_t len = 1, i = 0; 11656 uint32_t max_clients = named_g_http_listener_clients; 11657 uint32_t max_streams = named_g_http_streams_per_conn; 11658 11659 REQUIRE(target != NULL && *target == NULL); 11660 11661 if (tls) { 11662 INSIST(tls_params != NULL); 11663 INSIST((tls_params->key == NULL) == (tls_params->cert == NULL)); 11664 } 11665 11666 if (port == 0) { 11667 port = tls ? named_g_httpsport : named_g_httpport; 11668 } 11669 11670 /* 11671 * If "default" was used, we set up the default endpoint 11672 * of "/dns-query". 11673 */ 11674 if (http != NULL) { 11675 const cfg_obj_t *cfg_max_clients = NULL; 11676 const cfg_obj_t *cfg_max_streams = NULL; 11677 11678 if (cfg_map_get(http, "endpoints", &eplist) == ISC_R_SUCCESS) { 11679 INSIST(eplist != NULL); 11680 len = cfg_list_length(eplist, false); 11681 } 11682 11683 if (cfg_map_get(http, "listener-clients", &cfg_max_clients) == 11684 ISC_R_SUCCESS) 11685 { 11686 INSIST(cfg_max_clients != NULL); 11687 max_clients = cfg_obj_asuint32(cfg_max_clients); 11688 } 11689 11690 if (cfg_map_get(http, "streams-per-connection", 11691 &cfg_max_streams) == ISC_R_SUCCESS) 11692 { 11693 INSIST(cfg_max_streams != NULL); 11694 max_streams = cfg_obj_asuint32(cfg_max_streams); 11695 } 11696 } 11697 11698 endpoints = isc_mem_allocate(mctx, sizeof(endpoints[0]) * len); 11699 11700 if (http != NULL && eplist != NULL) { 11701 for (elt = cfg_list_first(eplist); elt != NULL; 11702 elt = cfg_list_next(elt)) 11703 { 11704 const cfg_obj_t *ep = cfg_listelt_value(elt); 11705 const char *path = cfg_obj_asstring(ep); 11706 endpoints[i++] = isc_mem_strdup(mctx, path); 11707 } 11708 } else { 11709 endpoints[i++] = isc_mem_strdup(mctx, ISC_NM_HTTP_DEFAULT_PATH); 11710 } 11711 11712 INSIST(i == len); 11713 11714 result = ns_listenelt_create_http( 11715 mctx, port, NULL, family, tls, tls_params, tlsctx_cache, proxy, 11716 endpoints, len, max_clients, max_streams, &delt); 11717 if (result != ISC_R_SUCCESS) { 11718 goto error; 11719 } 11720 11721 *target = delt; 11722 11723 return result; 11724 error: 11725 if (delt != NULL) { 11726 ns_listenelt_destroy(delt); 11727 } 11728 return result; 11729 } 11730 #endif /* HAVE_LIBNGHTTP2 */ 11731 11732 isc_result_t 11733 named_server_dumpstats(named_server_t *server) { 11734 isc_result_t result; 11735 FILE *fp = NULL; 11736 11737 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), 11738 "could not open statistics dump file", server->statsfile); 11739 11740 result = named_stats_dump(server, fp); 11741 11742 cleanup: 11743 if (fp != NULL) { 11744 (void)isc_stdio_close(fp); 11745 } 11746 if (result == ISC_R_SUCCESS) { 11747 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11748 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11749 "dumpstats complete"); 11750 } else { 11751 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11752 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11753 "dumpstats failed: %s", 11754 isc_result_totext(result)); 11755 } 11756 return result; 11757 } 11758 11759 static isc_result_t 11760 add_zone_tolist(dns_zone_t *zone, void *uap) { 11761 struct dumpcontext *dctx = uap; 11762 struct zonelistentry *zle; 11763 11764 zle = isc_mem_get(dctx->mctx, sizeof *zle); 11765 zle->zone = NULL; 11766 dns_zone_attach(zone, &zle->zone); 11767 ISC_LINK_INIT(zle, link); 11768 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); 11769 return ISC_R_SUCCESS; 11770 } 11771 11772 static isc_result_t 11773 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { 11774 struct viewlistentry *vle; 11775 isc_result_t result = ISC_R_SUCCESS; 11776 11777 /* 11778 * Prevent duplicate views. 11779 */ 11780 for (vle = ISC_LIST_HEAD(dctx->viewlist); vle != NULL; 11781 vle = ISC_LIST_NEXT(vle, link)) 11782 { 11783 if (vle->view == view) { 11784 return ISC_R_SUCCESS; 11785 } 11786 } 11787 11788 vle = isc_mem_get(dctx->mctx, sizeof *vle); 11789 vle->view = NULL; 11790 dns_view_attach(view, &vle->view); 11791 ISC_LINK_INIT(vle, link); 11792 ISC_LIST_INIT(vle->zonelist); 11793 ISC_LIST_APPEND(dctx->viewlist, vle, link); 11794 if (dctx->dumpzones) { 11795 result = dns_view_apply(view, true, NULL, add_zone_tolist, 11796 dctx); 11797 } 11798 return result; 11799 } 11800 11801 static void 11802 dumpcontext_destroy(struct dumpcontext *dctx) { 11803 struct viewlistentry *vle; 11804 struct zonelistentry *zle; 11805 11806 vle = ISC_LIST_HEAD(dctx->viewlist); 11807 while (vle != NULL) { 11808 ISC_LIST_UNLINK(dctx->viewlist, vle, link); 11809 zle = ISC_LIST_HEAD(vle->zonelist); 11810 while (zle != NULL) { 11811 ISC_LIST_UNLINK(vle->zonelist, zle, link); 11812 dns_zone_detach(&zle->zone); 11813 isc_mem_put(dctx->mctx, zle, sizeof *zle); 11814 zle = ISC_LIST_HEAD(vle->zonelist); 11815 } 11816 dns_view_detach(&vle->view); 11817 isc_mem_put(dctx->mctx, vle, sizeof *vle); 11818 vle = ISC_LIST_HEAD(dctx->viewlist); 11819 } 11820 if (dctx->version != NULL) { 11821 dns_db_closeversion(dctx->db, &dctx->version, false); 11822 } 11823 if (dctx->db != NULL) { 11824 dns_db_detach(&dctx->db); 11825 } 11826 if (dctx->cache != NULL) { 11827 dns_db_detach(&dctx->cache); 11828 } 11829 if (dctx->fp != NULL) { 11830 (void)isc_stdio_close(dctx->fp); 11831 } 11832 if (dctx->mdctx != NULL) { 11833 dns_dumpctx_detach(&dctx->mdctx); 11834 } 11835 isc_mem_put(dctx->mctx, dctx, sizeof *dctx); 11836 } 11837 11838 static void 11839 dumpdone(void *arg, isc_result_t result) { 11840 struct dumpcontext *dctx = arg; 11841 char buf[1024 + 32]; 11842 const dns_master_style_t *style; 11843 11844 if (result != ISC_R_SUCCESS) { 11845 goto cleanup; 11846 } 11847 if (dctx->mdctx != NULL) { 11848 dns_dumpctx_detach(&dctx->mdctx); 11849 } 11850 if (dctx->view == NULL) { 11851 dctx->view = ISC_LIST_HEAD(dctx->viewlist); 11852 if (dctx->view == NULL) { 11853 goto done; 11854 } 11855 INSIST(dctx->zone == NULL); 11856 } else { 11857 goto resume; 11858 } 11859 nextview: 11860 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); 11861 resume: 11862 if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { 11863 fprintf(dctx->fp, ";\n; Cache of view '%s' is shared as '%s'\n", 11864 dctx->view->view->name, 11865 dns_cache_getname(dctx->view->view->cache)); 11866 } else if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) 11867 { 11868 if (dctx->dumpexpired) { 11869 style = &dns_master_style_cache_with_expired; 11870 } else { 11871 style = &dns_master_style_cache; 11872 } 11873 /* start cache dump */ 11874 if (dctx->view->view->cachedb != NULL) { 11875 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 11876 } 11877 if (dctx->cache != NULL) { 11878 fprintf(dctx->fp, 11879 ";\n; Cache dump of view '%s' (cache %s)\n;\n", 11880 dctx->view->view->name, 11881 dns_cache_getname(dctx->view->view->cache)); 11882 result = dns_master_dumptostreamasync( 11883 dctx->mctx, dctx->cache, NULL, style, dctx->fp, 11884 named_g_mainloop, dumpdone, dctx, &dctx->mdctx); 11885 if (result == ISC_R_SUCCESS) { 11886 return; 11887 } 11888 if (result == ISC_R_NOTIMPLEMENTED) { 11889 fprintf(dctx->fp, "; %s\n", 11890 isc_result_totext(result)); 11891 } else if (result != ISC_R_SUCCESS) { 11892 goto cleanup; 11893 } 11894 } 11895 } 11896 11897 if ((dctx->dumpadb || dctx->dumpfail) && dctx->cache == NULL && 11898 dctx->view->view->cachedb != NULL) 11899 { 11900 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 11901 } 11902 11903 if (dctx->cache != NULL) { 11904 if (dctx->dumpadb) { 11905 dns_adb_t *adb = NULL; 11906 dns_view_getadb(dctx->view->view, &adb); 11907 if (adb != NULL) { 11908 dns_adb_dump(adb, dctx->fp); 11909 dns_adb_detach(&adb); 11910 } 11911 } 11912 if (dctx->dumpfail) { 11913 dns_badcache_print(dctx->view->view->failcache, 11914 "SERVFAIL cache", dctx->fp); 11915 } 11916 dns_db_detach(&dctx->cache); 11917 } 11918 if (dctx->dumpzones) { 11919 style = &dns_master_style_full; 11920 nextzone: 11921 if (dctx->version != NULL) { 11922 dns_db_closeversion(dctx->db, &dctx->version, false); 11923 } 11924 if (dctx->db != NULL) { 11925 dns_db_detach(&dctx->db); 11926 } 11927 if (dctx->zone == NULL) { 11928 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); 11929 } else { 11930 dctx->zone = ISC_LIST_NEXT(dctx->zone, link); 11931 } 11932 if (dctx->zone != NULL) { 11933 /* start zone dump */ 11934 dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); 11935 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); 11936 result = dns_zone_getdb(dctx->zone->zone, &dctx->db); 11937 if (result != ISC_R_SUCCESS) { 11938 fprintf(dctx->fp, "; %s\n", 11939 isc_result_totext(result)); 11940 goto nextzone; 11941 } 11942 dns_db_currentversion(dctx->db, &dctx->version); 11943 result = dns_master_dumptostreamasync( 11944 dctx->mctx, dctx->db, dctx->version, style, 11945 dctx->fp, dns_zone_getloop(dctx->zone->zone), 11946 dumpdone, dctx, &dctx->mdctx); 11947 if (result == ISC_R_SUCCESS) { 11948 return; 11949 } 11950 if (result == ISC_R_NOTIMPLEMENTED) { 11951 fprintf(dctx->fp, "; %s\n", 11952 isc_result_totext(result)); 11953 result = ISC_R_SUCCESS; 11954 POST(result); 11955 goto nextzone; 11956 } 11957 if (result != ISC_R_SUCCESS) { 11958 goto cleanup; 11959 } 11960 } 11961 } 11962 if (dctx->view != NULL) { 11963 dctx->view = ISC_LIST_NEXT(dctx->view, link); 11964 if (dctx->view != NULL) { 11965 goto nextview; 11966 } 11967 } 11968 done: 11969 fprintf(dctx->fp, "; Dump complete\n"); 11970 result = isc_stdio_flush(dctx->fp); 11971 if (result == ISC_R_SUCCESS) { 11972 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11973 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11974 "dumpdb complete"); 11975 } 11976 cleanup: 11977 if (result != ISC_R_SUCCESS) { 11978 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11979 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11980 "dumpdb failed: %s", isc_result_totext(result)); 11981 } 11982 dumpcontext_destroy(dctx); 11983 } 11984 11985 isc_result_t 11986 named_server_dumpdb(named_server_t *server, isc_lex_t *lex, 11987 isc_buffer_t **text) { 11988 struct dumpcontext *dctx = NULL; 11989 dns_view_t *view; 11990 isc_result_t result; 11991 char *ptr; 11992 const char *sep; 11993 bool found; 11994 11995 REQUIRE(text != NULL); 11996 11997 /* Skip the command name. */ 11998 ptr = next_token(lex, NULL); 11999 if (ptr == NULL) { 12000 return ISC_R_UNEXPECTEDEND; 12001 } 12002 12003 dctx = isc_mem_get(server->mctx, sizeof(*dctx)); 12004 *dctx = (struct dumpcontext){ 12005 .mctx = server->mctx, 12006 .dumpcache = true, 12007 .dumpadb = true, 12008 .dumpfail = true, 12009 .viewlist = ISC_LIST_INITIALIZER, 12010 }; 12011 12012 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), 12013 "could not open dump file", server->dumpfile); 12014 12015 ptr = next_token(lex, NULL); 12016 sep = (ptr == NULL) ? "" : ": "; 12017 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12018 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12019 "dumpdb started%s%s", sep, (ptr != NULL) ? ptr : ""); 12020 12021 if (ptr != NULL && strcmp(ptr, "-all") == 0) { 12022 /* also dump zones */ 12023 dctx->dumpzones = true; 12024 ptr = next_token(lex, NULL); 12025 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { 12026 /* this is the default */ 12027 ptr = next_token(lex, NULL); 12028 } else if (ptr != NULL && strcmp(ptr, "-expired") == 0) { 12029 /* this is the same as -cache but includes expired data */ 12030 dctx->dumpexpired = true; 12031 ptr = next_token(lex, NULL); 12032 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { 12033 /* only dump zones, suppress caches */ 12034 dctx->dumpadb = false; 12035 dctx->dumpcache = false; 12036 dctx->dumpfail = false; 12037 dctx->dumpzones = true; 12038 ptr = next_token(lex, NULL); 12039 } else if (ptr != NULL && strcmp(ptr, "-adb") == 0) { 12040 /* only dump adb, suppress other caches */ 12041 dctx->dumpcache = false; 12042 dctx->dumpfail = false; 12043 ptr = next_token(lex, NULL); 12044 } else if (ptr != NULL && strcmp(ptr, "-bad") == 0) { 12045 /* only dump badcache, suppress other caches */ 12046 dctx->dumpadb = false; 12047 dctx->dumpcache = false; 12048 dctx->dumpfail = false; 12049 ptr = next_token(lex, NULL); 12050 } else if (ptr != NULL && strcmp(ptr, "-fail") == 0) { 12051 /* only dump servfail cache, suppress other caches */ 12052 dctx->dumpadb = false; 12053 dctx->dumpcache = false; 12054 ptr = next_token(lex, NULL); 12055 } 12056 12057 nextview: 12058 found = false; 12059 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12060 view = ISC_LIST_NEXT(view, link)) 12061 { 12062 if (ptr != NULL && strcmp(view->name, ptr) != 0) { 12063 continue; 12064 } 12065 found = true; 12066 CHECK(add_view_tolist(dctx, view)); 12067 } 12068 if (ptr != NULL) { 12069 if (!found) { 12070 CHECK(putstr(text, "view '")); 12071 CHECK(putstr(text, ptr)); 12072 CHECK(putstr(text, "' not found")); 12073 CHECK(putnull(text)); 12074 result = ISC_R_NOTFOUND; 12075 dumpdone(dctx, result); 12076 return result; 12077 } 12078 ptr = next_token(lex, NULL); 12079 if (ptr != NULL) { 12080 goto nextview; 12081 } 12082 } 12083 dumpdone(dctx, ISC_R_SUCCESS); 12084 return ISC_R_SUCCESS; 12085 12086 cleanup: 12087 dumpcontext_destroy(dctx); 12088 return result; 12089 } 12090 12091 isc_result_t 12092 named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex, 12093 isc_buffer_t **text) { 12094 dns_view_t *view; 12095 dns_keytable_t *secroots = NULL; 12096 dns_ntatable_t *ntatable = NULL; 12097 isc_result_t result; 12098 char *ptr; 12099 FILE *fp = NULL; 12100 isc_time_t now; 12101 char tbuf[64]; 12102 unsigned int used = isc_buffer_usedlength(*text); 12103 bool first = true; 12104 12105 REQUIRE(text != NULL); 12106 12107 /* Skip the command name. */ 12108 ptr = next_token(lex, text); 12109 if (ptr == NULL) { 12110 return ISC_R_UNEXPECTEDEND; 12111 } 12112 12113 /* "-" here means print the output instead of dumping to file */ 12114 ptr = next_token(lex, text); 12115 if (ptr != NULL && strcmp(ptr, "-") == 0) { 12116 ptr = next_token(lex, text); 12117 } else { 12118 result = isc_stdio_open(server->secrootsfile, "w", &fp); 12119 if (result != ISC_R_SUCCESS) { 12120 (void)putstr(text, "could not open "); 12121 (void)putstr(text, server->secrootsfile); 12122 CHECKMF(result, "could not open secroots dump file", 12123 server->secrootsfile); 12124 } 12125 } 12126 12127 now = isc_time_now(); 12128 isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); 12129 CHECK(putstr(text, "secure roots as of ")); 12130 CHECK(putstr(text, tbuf)); 12131 CHECK(putstr(text, ":\n")); 12132 used = isc_buffer_usedlength(*text); 12133 12134 do { 12135 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12136 view = ISC_LIST_NEXT(view, link)) 12137 { 12138 if (ptr != NULL && strcmp(view->name, ptr) != 0) { 12139 continue; 12140 } 12141 if (secroots != NULL) { 12142 dns_keytable_detach(&secroots); 12143 } 12144 result = dns_view_getsecroots(view, &secroots); 12145 if (result == ISC_R_NOTFOUND) { 12146 result = ISC_R_SUCCESS; 12147 continue; 12148 } 12149 if (first || used != isc_buffer_usedlength(*text)) { 12150 CHECK(putstr(text, "\n")); 12151 first = false; 12152 } 12153 CHECK(putstr(text, " Start view ")); 12154 CHECK(putstr(text, view->name)); 12155 CHECK(putstr(text, "\n Secure roots:\n\n")); 12156 used = isc_buffer_usedlength(*text); 12157 CHECK(dns_keytable_totext(secroots, text)); 12158 12159 if (ntatable != NULL) { 12160 dns_ntatable_detach(&ntatable); 12161 } 12162 result = dns_view_getntatable(view, &ntatable); 12163 if (result == ISC_R_NOTFOUND) { 12164 result = ISC_R_SUCCESS; 12165 continue; 12166 } 12167 if (used != isc_buffer_usedlength(*text)) { 12168 CHECK(putstr(text, "\n")); 12169 } 12170 CHECK(putstr(text, " Negative trust anchors:\n\n")); 12171 used = isc_buffer_usedlength(*text); 12172 CHECK(dns_ntatable_totext(ntatable, NULL, text)); 12173 } 12174 12175 if (ptr != NULL) { 12176 ptr = next_token(lex, text); 12177 } 12178 } while (ptr != NULL); 12179 12180 cleanup: 12181 if (secroots != NULL) { 12182 dns_keytable_detach(&secroots); 12183 } 12184 if (ntatable != NULL) { 12185 dns_ntatable_detach(&ntatable); 12186 } 12187 12188 if (fp != NULL) { 12189 if (used != isc_buffer_usedlength(*text)) { 12190 (void)putstr(text, "\n"); 12191 } 12192 fprintf(fp, "%.*s", (int)isc_buffer_usedlength(*text), 12193 (char *)isc_buffer_base(*text)); 12194 isc_buffer_clear(*text); 12195 (void)isc_stdio_close(fp); 12196 } else if (isc_buffer_usedlength(*text) > 0) { 12197 (void)putnull(text); 12198 } 12199 12200 if (result == ISC_R_SUCCESS) { 12201 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12202 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12203 "dumpsecroots complete"); 12204 } else { 12205 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12206 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12207 "dumpsecroots failed: %s", 12208 isc_result_totext(result)); 12209 } 12210 return result; 12211 } 12212 12213 isc_result_t 12214 named_server_dumprecursing(named_server_t *server) { 12215 FILE *fp = NULL; 12216 dns_view_t *view; 12217 isc_result_t result; 12218 12219 CHECKMF(isc_stdio_open(server->recfile, "w", &fp), 12220 "could not open dump file", server->recfile); 12221 fprintf(fp, ";\n; Recursing Queries\n;\n"); 12222 ns_interfacemgr_dumprecursing(fp, server->interfacemgr); 12223 12224 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12225 view = ISC_LIST_NEXT(view, link)) 12226 { 12227 fprintf(fp, ";\n; Active fetch domains [view: %s]\n;\n", 12228 view->name); 12229 dns_resolver_dumpfetches(view->resolver, isc_statsformat_file, 12230 fp); 12231 } 12232 12233 fprintf(fp, "; Dump complete\n"); 12234 12235 cleanup: 12236 if (fp != NULL) { 12237 result = isc_stdio_close(fp); 12238 } 12239 if (result == ISC_R_SUCCESS) { 12240 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12241 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12242 "dumprecursing complete"); 12243 } else { 12244 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12245 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12246 "dumprecursing failed: %s", 12247 isc_result_totext(result)); 12248 } 12249 return result; 12250 } 12251 12252 isc_result_t 12253 named_server_setdebuglevel(named_server_t *server, isc_lex_t *lex) { 12254 char *ptr; 12255 char *endp; 12256 long newlevel; 12257 12258 UNUSED(server); 12259 12260 /* Skip the command name. */ 12261 ptr = next_token(lex, NULL); 12262 if (ptr == NULL) { 12263 return ISC_R_UNEXPECTEDEND; 12264 } 12265 12266 /* Look for the new level name. */ 12267 ptr = next_token(lex, NULL); 12268 if (ptr == NULL) { 12269 if (named_g_debuglevel < 99) { 12270 named_g_debuglevel++; 12271 } 12272 } else { 12273 newlevel = strtol(ptr, &endp, 10); 12274 if (*endp != '\0' || newlevel < 0 || newlevel > 99) { 12275 return ISC_R_RANGE; 12276 } 12277 named_g_debuglevel = (unsigned int)newlevel; 12278 } 12279 isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel); 12280 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12281 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12282 "debug level is now %u", named_g_debuglevel); 12283 return ISC_R_SUCCESS; 12284 } 12285 12286 isc_result_t 12287 named_server_validation(named_server_t *server, isc_lex_t *lex, 12288 isc_buffer_t **text) { 12289 char *ptr; 12290 dns_view_t *view; 12291 bool changed = false; 12292 isc_result_t result; 12293 bool enable = true, set = true, first = true; 12294 12295 REQUIRE(text != NULL); 12296 12297 /* Skip the command name. */ 12298 ptr = next_token(lex, text); 12299 if (ptr == NULL) { 12300 return ISC_R_UNEXPECTEDEND; 12301 } 12302 12303 /* Find out what we are to do. */ 12304 ptr = next_token(lex, text); 12305 if (ptr == NULL) { 12306 return ISC_R_UNEXPECTEDEND; 12307 } 12308 12309 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 12310 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 12311 { 12312 enable = true; 12313 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 12314 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 12315 { 12316 enable = false; 12317 } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { 12318 set = false; 12319 } else { 12320 return DNS_R_SYNTAX; 12321 } 12322 12323 /* Look for the view name. */ 12324 ptr = next_token(lex, text); 12325 12326 isc_loopmgr_pause(named_g_loopmgr); 12327 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12328 view = ISC_LIST_NEXT(view, link)) 12329 { 12330 if ((ptr != NULL && strcasecmp(ptr, view->name) != 0) || 12331 strcasecmp("_bind", view->name) == 0) 12332 { 12333 continue; 12334 } 12335 12336 if (set) { 12337 CHECK(dns_view_flushcache(view, false)); 12338 view->enablevalidation = enable; 12339 changed = true; 12340 } else { 12341 if (!first) { 12342 CHECK(putstr(text, "\n")); 12343 } 12344 CHECK(putstr(text, "DNSSEC validation is ")); 12345 CHECK(putstr(text, view->enablevalidation 12346 ? "enabled" 12347 : "disabled")); 12348 CHECK(putstr(text, " (view ")); 12349 CHECK(putstr(text, view->name)); 12350 CHECK(putstr(text, ")")); 12351 first = false; 12352 } 12353 } 12354 CHECK(putnull(text)); 12355 12356 if (!set) { 12357 result = ISC_R_SUCCESS; 12358 } else if (changed) { 12359 result = ISC_R_SUCCESS; 12360 } else { 12361 result = ISC_R_FAILURE; 12362 } 12363 cleanup: 12364 isc_loopmgr_resume(named_g_loopmgr); 12365 return result; 12366 } 12367 12368 isc_result_t 12369 named_server_flushcache(named_server_t *server, isc_lex_t *lex) { 12370 char *ptr; 12371 dns_view_t *view; 12372 bool flushed; 12373 bool found; 12374 isc_result_t result; 12375 named_cache_t *nsc; 12376 12377 /* Skip the command name. */ 12378 ptr = next_token(lex, NULL); 12379 if (ptr == NULL) { 12380 return ISC_R_UNEXPECTEDEND; 12381 } 12382 12383 /* Look for the view name. */ 12384 ptr = next_token(lex, NULL); 12385 12386 isc_loopmgr_pause(named_g_loopmgr); 12387 flushed = true; 12388 found = false; 12389 12390 /* 12391 * Flushing a cache is tricky when caches are shared by multiple views. 12392 * We first identify which caches should be flushed in the local cache 12393 * list, flush these caches, and then update other views that refer to 12394 * the flushed cache DB. 12395 */ 12396 if (ptr != NULL) { 12397 /* 12398 * Mark caches that need to be flushed. This is an O(#view^2) 12399 * operation in the very worst case, but should be normally 12400 * much more lightweight because only a few (most typically just 12401 * one) views will match. 12402 */ 12403 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12404 view = ISC_LIST_NEXT(view, link)) 12405 { 12406 if (strcasecmp(ptr, view->name) != 0) { 12407 continue; 12408 } 12409 found = true; 12410 for (nsc = ISC_LIST_HEAD(server->cachelist); 12411 nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) 12412 { 12413 if (nsc->cache == view->cache) { 12414 break; 12415 } 12416 } 12417 INSIST(nsc != NULL); 12418 nsc->needflush = true; 12419 } 12420 } else { 12421 found = true; 12422 } 12423 12424 /* Perform flush */ 12425 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12426 nsc = ISC_LIST_NEXT(nsc, link)) 12427 { 12428 if (ptr != NULL && !nsc->needflush) { 12429 continue; 12430 } 12431 nsc->needflush = true; 12432 result = dns_view_flushcache(nsc->primaryview, false); 12433 if (result != ISC_R_SUCCESS) { 12434 flushed = false; 12435 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12436 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12437 "flushing cache in view '%s' failed: %s", 12438 nsc->primaryview->name, 12439 isc_result_totext(result)); 12440 } 12441 } 12442 12443 /* 12444 * Fix up views that share a flushed cache: let the views update the 12445 * cache DB they're referring to. This could also be an expensive 12446 * operation, but should typically be marginal: the inner loop is only 12447 * necessary for views that share a cache, and if there are many such 12448 * views the number of shared cache should normally be small. 12449 * A worst case is that we have n views and n/2 caches, each shared by 12450 * two views. Then this will be a O(n^2/4) operation. 12451 */ 12452 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12453 view = ISC_LIST_NEXT(view, link)) 12454 { 12455 if (!dns_view_iscacheshared(view)) { 12456 continue; 12457 } 12458 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12459 nsc = ISC_LIST_NEXT(nsc, link)) 12460 { 12461 if (!nsc->needflush || nsc->cache != view->cache) { 12462 continue; 12463 } 12464 result = dns_view_flushcache(view, true); 12465 if (result != ISC_R_SUCCESS) { 12466 flushed = false; 12467 isc_log_write( 12468 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12469 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12470 "fixing cache in view '%s' " 12471 "failed: %s", 12472 view->name, isc_result_totext(result)); 12473 } 12474 } 12475 } 12476 12477 /* Cleanup the cache list. */ 12478 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12479 nsc = ISC_LIST_NEXT(nsc, link)) 12480 { 12481 nsc->needflush = false; 12482 } 12483 12484 if (flushed && found) { 12485 if (ptr != NULL) { 12486 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12487 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12488 "flushing cache in view '%s' succeeded", 12489 ptr); 12490 } else { 12491 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12492 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12493 "flushing caches in all views succeeded"); 12494 } 12495 result = ISC_R_SUCCESS; 12496 } else { 12497 if (!found) { 12498 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12499 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12500 "flushing cache in view '%s' failed: " 12501 "view not found", 12502 ptr); 12503 result = ISC_R_NOTFOUND; 12504 } else { 12505 result = ISC_R_FAILURE; 12506 } 12507 } 12508 isc_loopmgr_resume(named_g_loopmgr); 12509 return result; 12510 } 12511 12512 isc_result_t 12513 named_server_flushnode(named_server_t *server, isc_lex_t *lex, bool tree) { 12514 char *ptr, *viewname; 12515 char target[DNS_NAME_FORMATSIZE]; 12516 dns_view_t *view; 12517 bool flushed; 12518 bool found; 12519 isc_result_t result; 12520 isc_buffer_t b; 12521 dns_fixedname_t fixed; 12522 dns_name_t *name; 12523 12524 /* Skip the command name. */ 12525 ptr = next_token(lex, NULL); 12526 if (ptr == NULL) { 12527 return ISC_R_UNEXPECTEDEND; 12528 } 12529 12530 /* Find the domain name to flush. */ 12531 ptr = next_token(lex, NULL); 12532 if (ptr == NULL) { 12533 return ISC_R_UNEXPECTEDEND; 12534 } 12535 12536 strlcpy(target, ptr, DNS_NAME_FORMATSIZE); 12537 isc_buffer_constinit(&b, target, strlen(target)); 12538 isc_buffer_add(&b, strlen(target)); 12539 name = dns_fixedname_initname(&fixed); 12540 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 12541 if (result != ISC_R_SUCCESS) { 12542 return result; 12543 } 12544 12545 /* Look for the view name. */ 12546 viewname = next_token(lex, NULL); 12547 12548 isc_loopmgr_pause(named_g_loopmgr); 12549 flushed = true; 12550 found = false; 12551 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12552 view = ISC_LIST_NEXT(view, link)) 12553 { 12554 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) { 12555 continue; 12556 } 12557 found = true; 12558 /* 12559 * It's a little inefficient to try flushing name for all views 12560 * if some of the views share a single cache. But since the 12561 * operation is lightweight we prefer simplicity here. 12562 */ 12563 result = dns_view_flushnode(view, name, tree); 12564 if (result != ISC_R_SUCCESS) { 12565 flushed = false; 12566 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12567 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12568 "flushing %s '%s' in cache view '%s' " 12569 "failed: %s", 12570 tree ? "tree" : "name", target, 12571 view->name, isc_result_totext(result)); 12572 } 12573 } 12574 if (flushed && found) { 12575 if (viewname != NULL) { 12576 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12577 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12578 "flushing %s '%s' in cache view '%s' " 12579 "succeeded", 12580 tree ? "tree" : "name", target, viewname); 12581 } else { 12582 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12583 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12584 "flushing %s '%s' in all cache views " 12585 "succeeded", 12586 tree ? "tree" : "name", target); 12587 } 12588 result = ISC_R_SUCCESS; 12589 } else { 12590 if (!found) { 12591 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12592 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12593 "flushing %s '%s' in cache view '%s' " 12594 "failed: view not found", 12595 tree ? "tree" : "name", target, viewname); 12596 } 12597 result = ISC_R_FAILURE; 12598 } 12599 isc_loopmgr_resume(named_g_loopmgr); 12600 return result; 12601 } 12602 12603 isc_result_t 12604 named_server_status(named_server_t *server, isc_buffer_t **text) { 12605 isc_result_t result; 12606 unsigned int zonecount, xferrunning, xferdeferred, xferfirstrefresh; 12607 unsigned int soaqueries, automatic; 12608 const char *ob = "", *cb = "", *alt = ""; 12609 char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE]; 12610 char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE]; 12611 char line[1024], hostname[256]; 12612 named_reload_t reload_status; 12613 12614 REQUIRE(text != NULL); 12615 12616 if (named_g_server->version_set) { 12617 ob = " ("; 12618 cb = ")"; 12619 if (named_g_server->version == NULL) { 12620 alt = "version.bind/txt/ch disabled"; 12621 } else { 12622 alt = named_g_server->version; 12623 } 12624 } 12625 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); 12626 xferrunning = dns_zonemgr_getcount(server->zonemgr, 12627 DNS_ZONESTATE_XFERRUNNING); 12628 xferdeferred = dns_zonemgr_getcount(server->zonemgr, 12629 DNS_ZONESTATE_XFERDEFERRED); 12630 xferfirstrefresh = dns_zonemgr_getcount(server->zonemgr, 12631 DNS_ZONESTATE_XFERFIRSTREFRESH); 12632 soaqueries = dns_zonemgr_getcount(server->zonemgr, 12633 DNS_ZONESTATE_SOAQUERY); 12634 automatic = dns_zonemgr_getcount(server->zonemgr, 12635 DNS_ZONESTATE_AUTOMATIC); 12636 12637 isc_time_formathttptimestamp(&named_g_boottime, boottime, 12638 sizeof(boottime)); 12639 isc_time_formathttptimestamp(&named_g_configtime, configtime, 12640 sizeof(configtime)); 12641 12642 snprintf(line, sizeof(line), "version: %s%s <id:%s>%s%s%s\n", 12643 PACKAGE_STRING, PACKAGE_DESCRIPTION, PACKAGE_SRCID, ob, alt, 12644 cb); 12645 CHECK(putstr(text, line)); 12646 12647 if (gethostname(hostname, sizeof(hostname)) != 0) { 12648 strlcpy(hostname, "localhost", sizeof(hostname)); 12649 } 12650 snprintf(line, sizeof(line), "running on %s: %s\n", hostname, 12651 named_os_uname()); 12652 CHECK(putstr(text, line)); 12653 12654 snprintf(line, sizeof(line), "boot time: %s\n", boottime); 12655 CHECK(putstr(text, line)); 12656 12657 snprintf(line, sizeof(line), "last configured: %s\n", configtime); 12658 CHECK(putstr(text, line)); 12659 12660 if (named_g_chrootdir != NULL) { 12661 snprintf(line, sizeof(line), "configuration file: %s (%s%s)\n", 12662 named_g_conffile, named_g_chrootdir, named_g_conffile); 12663 } else { 12664 snprintf(line, sizeof(line), "configuration file: %s\n", 12665 named_g_conffile); 12666 } 12667 CHECK(putstr(text, line)); 12668 12669 snprintf(line, sizeof(line), "CPUs found: %u\n", named_g_cpus_detected); 12670 CHECK(putstr(text, line)); 12671 12672 snprintf(line, sizeof(line), "worker threads: %u\n", named_g_cpus); 12673 CHECK(putstr(text, line)); 12674 12675 snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n", 12676 zonecount, automatic); 12677 CHECK(putstr(text, line)); 12678 12679 snprintf(line, sizeof(line), "debug level: %u\n", named_g_debuglevel); 12680 CHECK(putstr(text, line)); 12681 12682 snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning); 12683 CHECK(putstr(text, line)); 12684 12685 snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred); 12686 CHECK(putstr(text, line)); 12687 12688 snprintf(line, sizeof(line), "xfers first refresh: %u\n", 12689 xferfirstrefresh); 12690 CHECK(putstr(text, line)); 12691 12692 snprintf(line, sizeof(line), "soa queries in progress: %u\n", 12693 soaqueries); 12694 CHECK(putstr(text, line)); 12695 12696 snprintf(line, sizeof(line), "query logging is %s\n", 12697 ns_server_getoption(server->sctx, NS_SERVER_LOGQUERIES) 12698 ? "ON" 12699 : "OFF"); 12700 CHECK(putstr(text, line)); 12701 12702 snprintf(line, sizeof(line), "response logging is %s\n", 12703 ns_server_getoption(server->sctx, NS_SERVER_LOGRESPONSES) 12704 ? "ON" 12705 : "OFF"); 12706 CHECK(putstr(text, line)); 12707 12708 snprintf(line, sizeof(line), "memory profiling is %s\n", 12709 named_server_getmemprof()); 12710 CHECK(putstr(text, line)); 12711 12712 snprintf(line, sizeof(line), "recursive clients: %u/%u/%u\n", 12713 isc_quota_getused(&server->sctx->recursionquota), 12714 isc_quota_getsoft(&server->sctx->recursionquota), 12715 isc_quota_getmax(&server->sctx->recursionquota)); 12716 CHECK(putstr(text, line)); 12717 12718 snprintf(line, sizeof(line), "recursive high-water: %u\n", 12719 (unsigned int)ns_stats_get_counter( 12720 server->sctx->nsstats, 12721 ns_statscounter_recurshighwater)); 12722 CHECK(putstr(text, line)); 12723 12724 snprintf(line, sizeof(line), "tcp clients: %u/%u\n", 12725 isc_quota_getused(&server->sctx->tcpquota), 12726 isc_quota_getmax(&server->sctx->tcpquota)); 12727 CHECK(putstr(text, line)); 12728 12729 snprintf(line, sizeof(line), "TCP high-water: %u\n", 12730 (unsigned int)ns_stats_get_counter( 12731 server->sctx->nsstats, ns_statscounter_tcphighwater)); 12732 CHECK(putstr(text, line)); 12733 12734 reload_status = atomic_load(&server->reload_status); 12735 if (reload_status != NAMED_RELOAD_DONE) { 12736 snprintf(line, sizeof(line), "reload/reconfig %s\n", 12737 reload_status == NAMED_RELOAD_FAILED ? "failed" 12738 : "in progress"); 12739 CHECK(putstr(text, line)); 12740 } 12741 12742 CHECK(putstr(text, "server is up and running")); 12743 CHECK(putnull(text)); 12744 12745 return ISC_R_SUCCESS; 12746 cleanup: 12747 return result; 12748 } 12749 12750 isc_result_t 12751 named_server_testgen(isc_lex_t *lex, isc_buffer_t **text) { 12752 isc_result_t result; 12753 char *ptr; 12754 unsigned long count; 12755 unsigned long i; 12756 const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; 12757 12758 REQUIRE(text != NULL); 12759 12760 /* Skip the command name. */ 12761 ptr = next_token(lex, text); 12762 if (ptr == NULL) { 12763 return ISC_R_UNEXPECTEDEND; 12764 } 12765 12766 ptr = next_token(lex, text); 12767 if (ptr == NULL) { 12768 count = 26; 12769 } else { 12770 count = strtoul(ptr, NULL, 10); 12771 } 12772 12773 CHECK(isc_buffer_reserve(*text, count)); 12774 for (i = 0; i < count; i++) { 12775 CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)])); 12776 } 12777 12778 CHECK(putnull(text)); 12779 12780 cleanup: 12781 return result; 12782 } 12783 12784 /* 12785 * Act on a "sign" or "loadkeys" command from the command channel. 12786 */ 12787 isc_result_t 12788 named_server_rekey(named_server_t *server, isc_lex_t *lex, 12789 isc_buffer_t **text) { 12790 isc_result_t result; 12791 dns_zone_t *zone = NULL; 12792 dns_zonetype_t type; 12793 uint16_t keyopts; 12794 bool fullsign = false; 12795 char *ptr; 12796 12797 REQUIRE(text != NULL); 12798 12799 ptr = next_token(lex, text); 12800 if (ptr == NULL) { 12801 return ISC_R_UNEXPECTEDEND; 12802 } 12803 12804 if (strcasecmp(ptr, NAMED_COMMAND_SIGN) == 0) { 12805 fullsign = true; 12806 } 12807 12808 REQUIRE(text != NULL); 12809 12810 result = zone_from_args(server, lex, NULL, &zone, NULL, text, false); 12811 if (result != ISC_R_SUCCESS) { 12812 return result; 12813 } 12814 if (zone == NULL) { 12815 return ISC_R_UNEXPECTEDEND; /* XXX: or do all zones? */ 12816 } 12817 12818 type = dns_zone_gettype(zone); 12819 if (type != dns_zone_primary) { 12820 dns_zone_detach(&zone); 12821 return DNS_R_NOTPRIMARY; 12822 } 12823 12824 keyopts = dns_zone_getkeyopts(zone); 12825 12826 /* 12827 * "rndc loadkeys" requires a "dnssec-policy". 12828 */ 12829 if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) { 12830 result = ISC_R_NOPERM; 12831 } else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) { 12832 result = ISC_R_NOPERM; 12833 } else { 12834 dns_zone_rekey(zone, fullsign, false); 12835 } 12836 12837 dns_zone_detach(&zone); 12838 return result; 12839 } 12840 12841 /* 12842 * Act on a "sync" command from the command channel. 12843 */ 12844 static isc_result_t 12845 synczone(dns_zone_t *zone, void *uap) { 12846 bool cleanup = *(bool *)uap; 12847 isc_result_t result; 12848 dns_zone_t *raw = NULL; 12849 char *journal; 12850 12851 dns_zone_getraw(zone, &raw); 12852 if (raw != NULL) { 12853 synczone(raw, uap); 12854 dns_zone_detach(&raw); 12855 } 12856 12857 result = dns_zone_flush(zone); 12858 if (result != ISC_R_SUCCESS) { 12859 cleanup = false; 12860 } 12861 if (cleanup) { 12862 journal = dns_zone_getjournal(zone); 12863 if (journal != NULL) { 12864 (void)isc_file_remove(journal); 12865 } 12866 } 12867 12868 return result; 12869 } 12870 12871 isc_result_t 12872 named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { 12873 isc_result_t result, tresult; 12874 dns_view_t *view = NULL; 12875 dns_zone_t *zone = NULL; 12876 char classstr[DNS_RDATACLASS_FORMATSIZE]; 12877 char zonename[DNS_NAME_FORMATSIZE]; 12878 const char *vname = NULL, *sep = NULL, *arg = NULL; 12879 bool cleanup = false; 12880 12881 REQUIRE(text != NULL); 12882 12883 (void)next_token(lex, text); 12884 12885 arg = next_token(lex, text); 12886 if (arg != NULL && 12887 (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) 12888 { 12889 cleanup = true; 12890 arg = next_token(lex, text); 12891 } 12892 12893 REQUIRE(text != NULL); 12894 12895 result = zone_from_args(server, lex, arg, &zone, NULL, text, false); 12896 if (result != ISC_R_SUCCESS) { 12897 return result; 12898 } 12899 12900 if (zone == NULL) { 12901 isc_loopmgr_pause(named_g_loopmgr); 12902 tresult = ISC_R_SUCCESS; 12903 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12904 view = ISC_LIST_NEXT(view, link)) 12905 { 12906 result = dns_view_apply(view, false, NULL, synczone, 12907 &cleanup); 12908 if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) 12909 { 12910 tresult = result; 12911 } 12912 } 12913 isc_loopmgr_resume(named_g_loopmgr); 12914 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12915 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12916 "dumping all zones%s: %s", 12917 cleanup ? ", removing journal files" : "", 12918 isc_result_totext(result)); 12919 return tresult; 12920 } 12921 12922 isc_loopmgr_pause(named_g_loopmgr); 12923 result = synczone(zone, &cleanup); 12924 isc_loopmgr_resume(named_g_loopmgr); 12925 12926 view = dns_zone_getview(zone); 12927 if (strcmp(view->name, "_default") == 0 || 12928 strcmp(view->name, "_bind") == 0) 12929 { 12930 vname = ""; 12931 sep = ""; 12932 } else { 12933 vname = view->name; 12934 sep = " "; 12935 } 12936 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 12937 sizeof(classstr)); 12938 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 12939 isc_log_write( 12940 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, 12941 ISC_LOG_INFO, "sync: dumping zone '%s/%s'%s%s%s: %s", zonename, 12942 classstr, sep, vname, cleanup ? ", removing journal file" : "", 12943 isc_result_totext(result)); 12944 dns_zone_detach(&zone); 12945 return result; 12946 } 12947 12948 /* 12949 * Act on a "freeze" or "thaw" command from the command channel. 12950 */ 12951 isc_result_t 12952 named_server_freeze(named_server_t *server, bool freeze, isc_lex_t *lex, 12953 isc_buffer_t **text) { 12954 isc_result_t result, tresult; 12955 dns_zone_t *mayberaw = NULL, *raw = NULL; 12956 dns_zonetype_t type; 12957 char classstr[DNS_RDATACLASS_FORMATSIZE]; 12958 char zonename[DNS_NAME_FORMATSIZE]; 12959 dns_view_t *view; 12960 const char *vname, *sep; 12961 bool frozen; 12962 const char *msg = NULL; 12963 12964 REQUIRE(text != NULL); 12965 12966 result = zone_from_args(server, lex, NULL, &mayberaw, NULL, text, true); 12967 if (result != ISC_R_SUCCESS) { 12968 return result; 12969 } 12970 if (mayberaw == NULL) { 12971 isc_loopmgr_pause(named_g_loopmgr); 12972 tresult = ISC_R_SUCCESS; 12973 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12974 view = ISC_LIST_NEXT(view, link)) 12975 { 12976 result = dns_view_freezezones(view, freeze); 12977 if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) 12978 { 12979 tresult = result; 12980 } 12981 } 12982 isc_loopmgr_resume(named_g_loopmgr); 12983 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12984 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12985 "%s all zones: %s", 12986 freeze ? "freezing" : "thawing", 12987 isc_result_totext(tresult)); 12988 return tresult; 12989 } 12990 dns_zone_getraw(mayberaw, &raw); 12991 if (raw != NULL) { 12992 dns_zone_detach(&mayberaw); 12993 dns_zone_attach(raw, &mayberaw); 12994 dns_zone_detach(&raw); 12995 } 12996 type = dns_zone_gettype(mayberaw); 12997 if (type != dns_zone_primary) { 12998 dns_zone_detach(&mayberaw); 12999 return DNS_R_NOTPRIMARY; 13000 } 13001 13002 if (freeze && !dns_zone_isdynamic(mayberaw, true)) { 13003 dns_zone_detach(&mayberaw); 13004 return DNS_R_NOTDYNAMIC; 13005 } 13006 13007 isc_loopmgr_pause(named_g_loopmgr); 13008 frozen = dns_zone_getupdatedisabled(mayberaw); 13009 if (freeze) { 13010 if (frozen) { 13011 msg = "WARNING: The zone was already frozen.\n" 13012 "Someone else may be editing it or " 13013 "it may still be re-loading."; 13014 result = DNS_R_FROZEN; 13015 } 13016 if (result == ISC_R_SUCCESS) { 13017 result = dns_zone_flush(mayberaw); 13018 if (result != ISC_R_SUCCESS) { 13019 msg = "Flushing the zone updates to " 13020 "disk failed."; 13021 } 13022 } 13023 if (result == ISC_R_SUCCESS) { 13024 dns_zone_setupdatedisabled(mayberaw, freeze); 13025 } 13026 } else { 13027 if (frozen) { 13028 result = dns_zone_loadandthaw(mayberaw); 13029 switch (result) { 13030 case ISC_R_SUCCESS: 13031 case DNS_R_UPTODATE: 13032 msg = "The zone reload and thaw was " 13033 "successful."; 13034 result = ISC_R_SUCCESS; 13035 break; 13036 case DNS_R_CONTINUE: 13037 msg = "A zone reload and thaw was started.\n" 13038 "Check the logs to see the result."; 13039 result = ISC_R_SUCCESS; 13040 break; 13041 default: 13042 break; 13043 } 13044 } 13045 } 13046 isc_loopmgr_resume(named_g_loopmgr); 13047 13048 if (msg != NULL) { 13049 (void)putstr(text, msg); 13050 (void)putnull(text); 13051 } 13052 13053 view = dns_zone_getview(mayberaw); 13054 if (strcmp(view->name, "_default") == 0 || 13055 strcmp(view->name, "_bind") == 0) 13056 { 13057 vname = ""; 13058 sep = ""; 13059 } else { 13060 vname = view->name; 13061 sep = " "; 13062 } 13063 dns_rdataclass_format(dns_zone_getclass(mayberaw), classstr, 13064 sizeof(classstr)); 13065 dns_name_format(dns_zone_getorigin(mayberaw), zonename, 13066 sizeof(zonename)); 13067 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13068 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13069 "%s zone '%s/%s'%s%s: %s", 13070 freeze ? "freezing" : "thawing", zonename, classstr, sep, 13071 vname, isc_result_totext(result)); 13072 dns_zone_detach(&mayberaw); 13073 return result; 13074 } 13075 13076 #ifdef HAVE_LIBSCF 13077 /* 13078 * This function adds a message for rndc to echo if named 13079 * is managed by smf and is also running chroot. 13080 */ 13081 isc_result_t 13082 named_smf_add_message(isc_buffer_t **text) { 13083 REQUIRE(text != NULL); 13084 13085 return putstr(text, "use svcadm(1M) to manage named"); 13086 } 13087 #endif /* HAVE_LIBSCF */ 13088 13089 #ifndef HAVE_LMDB 13090 13091 /* 13092 * Emit a comment at the top of the nzf file containing the viewname 13093 * Expects the fp to already be open for writing 13094 */ 13095 #define HEADER1 "# New zone file for view: " 13096 #define HEADER2 \ 13097 "\n# This file contains configuration for zones added by\n" \ 13098 "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n" 13099 static isc_result_t 13100 add_comment(FILE *fp, const char *viewname) { 13101 isc_result_t result; 13102 CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL)); 13103 CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL)); 13104 CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL)); 13105 cleanup: 13106 return result; 13107 } 13108 13109 static void 13110 dumpzone(void *arg, const char *buf, int len) { 13111 FILE *fp = arg; 13112 13113 (void)isc_stdio_write(buf, len, 1, fp, NULL); 13114 } 13115 13116 static isc_result_t 13117 nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) { 13118 isc_result_t result; 13119 off_t offset; 13120 FILE *fp = NULL; 13121 bool offsetok = false; 13122 13123 LOCK(&view->new_zone_lock); 13124 13125 CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); 13126 CHECK(isc_stdio_seek(fp, 0, SEEK_END)); 13127 13128 CHECK(isc_stdio_tell(fp, &offset)); 13129 offsetok = true; 13130 if (offset == 0) { 13131 CHECK(add_comment(fp, view->name)); 13132 } 13133 13134 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 13135 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); 13136 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); 13137 CHECK(isc_stdio_flush(fp)); 13138 result = isc_stdio_close(fp); 13139 fp = NULL; 13140 13141 cleanup: 13142 if (fp != NULL) { 13143 (void)isc_stdio_close(fp); 13144 if (offsetok) { 13145 isc_result_t result2; 13146 13147 result2 = isc_file_truncate(view->new_zone_file, 13148 offset); 13149 if (result2 != ISC_R_SUCCESS) { 13150 isc_log_write( 13151 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13152 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13153 "Error truncating NZF file '%s' " 13154 "during rollback from append: " 13155 "%s", 13156 view->new_zone_file, 13157 isc_result_totext(result2)); 13158 } 13159 } 13160 } 13161 UNLOCK(&view->new_zone_lock); 13162 return result; 13163 } 13164 13165 static isc_result_t 13166 nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { 13167 const cfg_obj_t *zl = NULL; 13168 cfg_list_t *list; 13169 const cfg_listelt_t *elt; 13170 13171 FILE *fp = NULL; 13172 char tmp[1024]; 13173 isc_result_t result; 13174 13175 result = isc_file_template(view->new_zone_file, "nzf-XXXXXXXX", tmp, 13176 sizeof(tmp)); 13177 if (result == ISC_R_SUCCESS) { 13178 result = isc_file_openunique(tmp, &fp); 13179 } 13180 if (result != ISC_R_SUCCESS) { 13181 return result; 13182 } 13183 13184 cfg_map_get(config, "zone", &zl); 13185 if (!cfg_obj_islist(zl)) { 13186 CHECK(ISC_R_FAILURE); 13187 } 13188 13189 list = UNCONST(&zl->value.list); 13190 13191 CHECK(add_comment(fp, view->name)); /* force a comment */ 13192 13193 for (elt = ISC_LIST_HEAD(*list); elt != NULL; 13194 elt = ISC_LIST_NEXT(elt, link)) 13195 { 13196 const cfg_obj_t *zconfig = cfg_listelt_value(elt); 13197 13198 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 13199 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); 13200 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); 13201 } 13202 13203 CHECK(isc_stdio_flush(fp)); 13204 result = isc_stdio_close(fp); 13205 fp = NULL; 13206 if (result != ISC_R_SUCCESS) { 13207 goto cleanup; 13208 } 13209 CHECK(isc_file_rename(tmp, view->new_zone_file)); 13210 return result; 13211 13212 cleanup: 13213 if (fp != NULL) { 13214 (void)isc_stdio_close(fp); 13215 } 13216 (void)isc_file_remove(tmp); 13217 return result; 13218 } 13219 13220 static isc_result_t 13221 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { 13222 isc_result_t result; 13223 13224 /* The new zone file may not exist. That is OK. */ 13225 if (!isc_file_exists(view->new_zone_file)) { 13226 return ISC_R_SUCCESS; 13227 } 13228 13229 /* 13230 * Parse the configuration in the NZF file. This may be called in 13231 * multiple views, so we reset the parser each time. 13232 */ 13233 cfg_parser_reset(named_g_addparser); 13234 result = cfg_parse_file(named_g_addparser, view->new_zone_file, 13235 &cfg_type_addzoneconf, &nzcfg->nzf_config); 13236 if (result != ISC_R_SUCCESS) { 13237 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13238 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13239 "Error parsing NZF file '%s': %s", 13240 view->new_zone_file, isc_result_totext(result)); 13241 } 13242 13243 return result; 13244 } 13245 #else /* HAVE_LMDB */ 13246 13247 static void 13248 nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) { 13249 dns_fixedname_t fixed; 13250 13251 dns_fixedname_init(&fixed); 13252 dns_name_downcase(name, dns_fixedname_name(&fixed), NULL); 13253 dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen); 13254 13255 key->mv_data = namebuf; 13256 key->mv_size = strlen(namebuf); 13257 } 13258 13259 static void 13260 dumpzone(void *arg, const char *buf, int len) { 13261 ns_dzarg_t *dzarg = arg; 13262 isc_result_t result; 13263 13264 REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); 13265 13266 result = putmem(dzarg->text, buf, len); 13267 if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { 13268 dzarg->result = result; 13269 } 13270 } 13271 13272 static isc_result_t 13273 nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone, 13274 const cfg_obj_t *zconfig) { 13275 isc_result_t result; 13276 int status; 13277 dns_view_t *view; 13278 bool commit = false; 13279 isc_buffer_t *text = NULL; 13280 char namebuf[1024]; 13281 MDB_val key, data; 13282 ns_dzarg_t dzarg; 13283 13284 view = dns_zone_getview(zone); 13285 13286 nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf)); 13287 13288 if (zconfig == NULL) { 13289 /* We're deleting the zone from the database */ 13290 status = mdb_del(*txnp, dbi, &key, NULL); 13291 if (status != MDB_SUCCESS && status != MDB_NOTFOUND) { 13292 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13293 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13294 "Error deleting zone %s " 13295 "from NZD database: %s", 13296 namebuf, mdb_strerror(status)); 13297 result = ISC_R_FAILURE; 13298 goto cleanup; 13299 } else if (status != MDB_NOTFOUND) { 13300 commit = true; 13301 } 13302 } else { 13303 /* We're creating or overwriting the zone */ 13304 const cfg_obj_t *zoptions; 13305 13306 isc_buffer_allocate(view->mctx, &text, 256); 13307 13308 zoptions = cfg_tuple_get(zconfig, "options"); 13309 if (zoptions == NULL) { 13310 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13311 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13312 "Unable to get options from config in " 13313 "nzd_save()"); 13314 result = ISC_R_FAILURE; 13315 goto cleanup; 13316 } 13317 13318 dzarg.magic = DZARG_MAGIC; 13319 dzarg.text = &text; 13320 dzarg.result = ISC_R_SUCCESS; 13321 cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); 13322 if (dzarg.result != ISC_R_SUCCESS) { 13323 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13324 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13325 "Error writing zone config to " 13326 "buffer in nzd_save(): %s", 13327 isc_result_totext(dzarg.result)); 13328 result = dzarg.result; 13329 goto cleanup; 13330 } 13331 13332 data.mv_data = isc_buffer_base(text); 13333 data.mv_size = isc_buffer_usedlength(text); 13334 13335 status = mdb_put(*txnp, dbi, &key, &data, 0); 13336 if (status != MDB_SUCCESS) { 13337 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13338 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13339 "Error inserting zone in " 13340 "NZD database: %s", 13341 mdb_strerror(status)); 13342 result = ISC_R_FAILURE; 13343 goto cleanup; 13344 } 13345 13346 commit = true; 13347 } 13348 13349 result = ISC_R_SUCCESS; 13350 13351 cleanup: 13352 if (!commit || result != ISC_R_SUCCESS) { 13353 (void)mdb_txn_abort(*txnp); 13354 } else { 13355 status = mdb_txn_commit(*txnp); 13356 if (status != MDB_SUCCESS) { 13357 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13358 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13359 "Error committing " 13360 "NZD database: %s", 13361 mdb_strerror(status)); 13362 result = ISC_R_FAILURE; 13363 } 13364 } 13365 *txnp = NULL; 13366 13367 if (text != NULL) { 13368 isc_buffer_free(&text); 13369 } 13370 13371 return result; 13372 } 13373 13374 /* 13375 * Check whether the new zone database for 'view' can be opened for writing. 13376 * 13377 * Caller must hold 'view->new_zone_lock'. 13378 */ 13379 static isc_result_t 13380 nzd_writable(dns_view_t *view) { 13381 isc_result_t result = ISC_R_SUCCESS; 13382 int status; 13383 MDB_dbi dbi; 13384 MDB_txn *txn = NULL; 13385 13386 REQUIRE(view != NULL); 13387 13388 status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, 0, &txn); 13389 if (status != MDB_SUCCESS) { 13390 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13391 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13392 "mdb_txn_begin: %s", mdb_strerror(status)); 13393 return ISC_R_FAILURE; 13394 } 13395 13396 status = mdb_dbi_open(txn, NULL, 0, &dbi); 13397 if (status != MDB_SUCCESS) { 13398 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13399 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13400 "mdb_dbi_open: %s", mdb_strerror(status)); 13401 result = ISC_R_FAILURE; 13402 } 13403 13404 mdb_txn_abort(txn); 13405 return result; 13406 } 13407 13408 /* 13409 * Open the new zone database for 'view' and start a transaction for it. 13410 * 13411 * Caller must hold 'view->new_zone_lock'. 13412 */ 13413 static isc_result_t 13414 nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { 13415 int status; 13416 MDB_txn *txn = NULL; 13417 13418 REQUIRE(view != NULL); 13419 REQUIRE(txnp != NULL && *txnp == NULL); 13420 REQUIRE(dbi != NULL); 13421 13422 status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, flags, &txn); 13423 if (status != MDB_SUCCESS) { 13424 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13425 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13426 "mdb_txn_begin: %s", mdb_strerror(status)); 13427 goto cleanup; 13428 } 13429 13430 status = mdb_dbi_open(txn, NULL, 0, dbi); 13431 if (status != MDB_SUCCESS) { 13432 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13433 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13434 "mdb_dbi_open: %s", mdb_strerror(status)); 13435 goto cleanup; 13436 } 13437 13438 *txnp = txn; 13439 13440 cleanup: 13441 if (status != MDB_SUCCESS) { 13442 if (txn != NULL) { 13443 mdb_txn_abort(txn); 13444 } 13445 return ISC_R_FAILURE; 13446 } 13447 13448 return ISC_R_SUCCESS; 13449 } 13450 13451 /* 13452 * nzd_env_close() and nzd_env_reopen are a kluge to address the 13453 * problem of an NZD file possibly being created before we drop 13454 * root privileges. 13455 */ 13456 static void 13457 nzd_env_close(dns_view_t *view) { 13458 const char *dbpath = NULL; 13459 char dbpath_copy[PATH_MAX]; 13460 char lockpath[PATH_MAX]; 13461 int status, ret; 13462 13463 if (view->new_zone_dbenv == NULL) { 13464 return; 13465 } 13466 13467 status = mdb_env_get_path(view->new_zone_dbenv, &dbpath); 13468 INSIST(status == MDB_SUCCESS); 13469 snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath); 13470 strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy)); 13471 mdb_env_close((MDB_env *)view->new_zone_dbenv); 13472 13473 /* 13474 * Database files must be owned by the eventual user, not by root. 13475 */ 13476 ret = chown(dbpath_copy, named_os_uid(), -1); 13477 UNUSED(ret); 13478 13479 /* 13480 * Some platforms need the lockfile not to exist when we reopen the 13481 * environment. 13482 */ 13483 (void)isc_file_remove(lockpath); 13484 13485 view->new_zone_dbenv = NULL; 13486 } 13487 13488 static isc_result_t 13489 nzd_env_reopen(dns_view_t *view) { 13490 isc_result_t result; 13491 MDB_env *env = NULL; 13492 int status; 13493 13494 if (view->new_zone_db == NULL) { 13495 return ISC_R_SUCCESS; 13496 } 13497 13498 nzd_env_close(view); 13499 13500 status = mdb_env_create(&env); 13501 if (status != MDB_SUCCESS) { 13502 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13503 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13504 "mdb_env_create failed: %s", 13505 mdb_strerror(status)); 13506 CHECK(ISC_R_FAILURE); 13507 } 13508 13509 if (view->new_zone_mapsize != 0ULL) { 13510 status = mdb_env_set_mapsize(env, view->new_zone_mapsize); 13511 if (status != MDB_SUCCESS) { 13512 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13513 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13514 "mdb_env_set_mapsize failed: %s", 13515 mdb_strerror(status)); 13516 CHECK(ISC_R_FAILURE); 13517 } 13518 } 13519 13520 status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); 13521 if (status != MDB_SUCCESS) { 13522 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13523 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13524 "mdb_env_open of '%s' failed: %s", 13525 view->new_zone_db, mdb_strerror(status)); 13526 CHECK(ISC_R_FAILURE); 13527 } 13528 13529 view->new_zone_dbenv = env; 13530 env = NULL; 13531 result = ISC_R_SUCCESS; 13532 13533 cleanup: 13534 if (env != NULL) { 13535 mdb_env_close(env); 13536 } 13537 return result; 13538 } 13539 13540 /* 13541 * If 'commit' is true, commit the new zone database transaction pointed to by 13542 * 'txnp'; otherwise, abort that transaction. 13543 * 13544 * Caller must hold 'view->new_zone_lock' for the view that the transaction 13545 * pointed to by 'txnp' was started for. 13546 */ 13547 static isc_result_t 13548 nzd_close(MDB_txn **txnp, bool commit) { 13549 isc_result_t result = ISC_R_SUCCESS; 13550 int status; 13551 13552 REQUIRE(txnp != NULL); 13553 13554 if (*txnp != NULL) { 13555 if (commit) { 13556 status = mdb_txn_commit(*txnp); 13557 if (status != MDB_SUCCESS) { 13558 result = ISC_R_FAILURE; 13559 } 13560 } else { 13561 mdb_txn_abort(*txnp); 13562 } 13563 *txnp = NULL; 13564 } 13565 13566 return result; 13567 } 13568 13569 /* 13570 * If there's an existing NZF file, load it and migrate its data 13571 * to the NZD. 13572 * 13573 * Caller must hold view->new_zone_lock. 13574 */ 13575 static isc_result_t 13576 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { 13577 isc_result_t result; 13578 cfg_obj_t *nzf_config = NULL; 13579 int status; 13580 isc_buffer_t *text = NULL; 13581 bool commit = false; 13582 const cfg_obj_t *zonelist; 13583 const cfg_listelt_t *element; 13584 char tempname[PATH_MAX]; 13585 MDB_txn *txn = NULL; 13586 MDB_dbi dbi; 13587 MDB_val key, data; 13588 ns_dzarg_t dzarg; 13589 13590 UNUSED(nzcfg); 13591 13592 /* 13593 * If NZF file doesn't exist, or NZD DB exists and already 13594 * has data, return without attempting migration. 13595 */ 13596 if (!isc_file_exists(view->new_zone_file)) { 13597 result = ISC_R_SUCCESS; 13598 goto cleanup; 13599 } 13600 13601 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13602 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13603 "Migrating zones from NZF file '%s' to " 13604 "NZD database '%s'", 13605 view->new_zone_file, view->new_zone_db); 13606 /* 13607 * Instead of blindly copying lines, we parse the NZF file using 13608 * the configuration parser, because it validates it against the 13609 * config type, giving us a guarantee that valid configuration 13610 * will be written to DB. 13611 */ 13612 cfg_parser_reset(named_g_addparser); 13613 result = cfg_parse_file(named_g_addparser, view->new_zone_file, 13614 &cfg_type_addzoneconf, &nzf_config); 13615 if (result != ISC_R_SUCCESS) { 13616 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13617 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13618 "Error parsing NZF file '%s': %s", 13619 view->new_zone_file, isc_result_totext(result)); 13620 goto cleanup; 13621 } 13622 13623 zonelist = NULL; 13624 CHECK(cfg_map_get(nzf_config, "zone", &zonelist)); 13625 if (!cfg_obj_islist(zonelist)) { 13626 CHECK(ISC_R_FAILURE); 13627 } 13628 13629 CHECK(nzd_open(view, 0, &txn, &dbi)); 13630 13631 isc_buffer_allocate(view->mctx, &text, 256); 13632 13633 for (element = cfg_list_first(zonelist); element != NULL; 13634 element = cfg_list_next(element)) 13635 { 13636 const cfg_obj_t *zconfig; 13637 const cfg_obj_t *zoptions; 13638 char zname[DNS_NAME_FORMATSIZE]; 13639 dns_fixedname_t fname; 13640 dns_name_t *name; 13641 const char *origin; 13642 isc_buffer_t b; 13643 13644 zconfig = cfg_listelt_value(element); 13645 13646 origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 13647 if (origin == NULL) { 13648 result = ISC_R_FAILURE; 13649 goto cleanup; 13650 } 13651 13652 /* Normalize zone name */ 13653 isc_buffer_constinit(&b, origin, strlen(origin)); 13654 isc_buffer_add(&b, strlen(origin)); 13655 name = dns_fixedname_initname(&fname); 13656 CHECK(dns_name_fromtext(name, &b, dns_rootname, 13657 DNS_NAME_DOWNCASE, NULL)); 13658 dns_name_format(name, zname, sizeof(zname)); 13659 13660 key.mv_data = zname; 13661 key.mv_size = strlen(zname); 13662 13663 zoptions = cfg_tuple_get(zconfig, "options"); 13664 if (zoptions == NULL) { 13665 result = ISC_R_FAILURE; 13666 goto cleanup; 13667 } 13668 13669 isc_buffer_clear(text); 13670 dzarg.magic = DZARG_MAGIC; 13671 dzarg.text = &text; 13672 dzarg.result = ISC_R_SUCCESS; 13673 cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); 13674 if (dzarg.result != ISC_R_SUCCESS) { 13675 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13676 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13677 "Error writing zone config to " 13678 "buffer in load_nzf(): %s", 13679 isc_result_totext(result)); 13680 result = dzarg.result; 13681 goto cleanup; 13682 } 13683 13684 data.mv_data = isc_buffer_base(text); 13685 data.mv_size = isc_buffer_usedlength(text); 13686 13687 status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE); 13688 if (status != MDB_SUCCESS) { 13689 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13690 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13691 "Error inserting zone in " 13692 "NZD database: %s", 13693 mdb_strerror(status)); 13694 result = ISC_R_FAILURE; 13695 goto cleanup; 13696 } 13697 13698 commit = true; 13699 } 13700 13701 result = ISC_R_SUCCESS; 13702 13703 /* 13704 * Leaving the NZF file in place is harmless as we won't use it 13705 * if an NZD database is found for the view. But we rename NZF file 13706 * to a backup name here. 13707 */ 13708 strlcpy(tempname, view->new_zone_file, sizeof(tempname)); 13709 if (strlen(tempname) < sizeof(tempname) - 1) { 13710 strlcat(tempname, "~", sizeof(tempname)); 13711 isc_file_rename(view->new_zone_file, tempname); 13712 } 13713 13714 cleanup: 13715 if (result != ISC_R_SUCCESS) { 13716 (void)nzd_close(&txn, false); 13717 } else { 13718 result = nzd_close(&txn, commit); 13719 } 13720 13721 if (text != NULL) { 13722 isc_buffer_free(&text); 13723 } 13724 13725 if (nzf_config != NULL) { 13726 cfg_obj_destroy(named_g_addparser, &nzf_config); 13727 } 13728 13729 return result; 13730 } 13731 #endif /* HAVE_LMDB */ 13732 13733 static isc_result_t 13734 newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, 13735 cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp, 13736 bool *redirectp, isc_buffer_t **text) { 13737 isc_result_t result; 13738 isc_buffer_t argbuf; 13739 bool redirect = false; 13740 cfg_obj_t *zoneconf = NULL; 13741 const cfg_obj_t *zlist = NULL; 13742 const cfg_obj_t *zoneobj = NULL; 13743 const cfg_obj_t *zoptions = NULL; 13744 const cfg_obj_t *obj = NULL; 13745 const char *viewname = NULL; 13746 dns_rdataclass_t rdclass; 13747 dns_view_t *view = NULL; 13748 const char *bn = NULL; 13749 13750 REQUIRE(viewp != NULL && *viewp == NULL); 13751 REQUIRE(zoneobjp != NULL && *zoneobjp == NULL); 13752 REQUIRE(zoneconfp != NULL && *zoneconfp == NULL); 13753 REQUIRE(redirectp != NULL); 13754 13755 /* Try to parse the argument string */ 13756 isc_buffer_init(&argbuf, command, (unsigned int)strlen(command)); 13757 isc_buffer_add(&argbuf, strlen(command)); 13758 13759 if (strncasecmp(command, "add", 3) == 0) { 13760 bn = "addzone"; 13761 } else if (strncasecmp(command, "mod", 3) == 0) { 13762 bn = "modzone"; 13763 } else { 13764 UNREACHABLE(); 13765 } 13766 13767 /* 13768 * Convert the "addzone" or "modzone" to just "zone", for 13769 * the benefit of the parser 13770 */ 13771 isc_buffer_forward(&argbuf, 3); 13772 13773 cfg_parser_reset(named_g_addparser); 13774 CHECK(cfg_parse_buffer(named_g_addparser, &argbuf, bn, 0, 13775 &cfg_type_addzoneconf, 0, &zoneconf)); 13776 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 13777 if (!cfg_obj_islist(zlist)) { 13778 CHECK(ISC_R_FAILURE); 13779 } 13780 13781 /* For now we only support adding one zone at a time */ 13782 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 13783 13784 /* Check the zone type for ones that are not supported by addzone. */ 13785 zoptions = cfg_tuple_get(zoneobj, "options"); 13786 13787 obj = NULL; 13788 (void)cfg_map_get(zoptions, "type", &obj); 13789 if (obj == NULL) { 13790 (void)cfg_map_get(zoptions, "in-view", &obj); 13791 if (obj != NULL) { 13792 (void)putstr(text, "'in-view' zones not supported by "); 13793 (void)putstr(text, bn); 13794 } else { 13795 (void)putstr(text, "zone type not specified"); 13796 } 13797 CHECK(ISC_R_FAILURE); 13798 } 13799 13800 if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 || 13801 strcasecmp(cfg_obj_asstring(obj), "forward") == 0) 13802 { 13803 (void)putstr(text, "'"); 13804 (void)putstr(text, cfg_obj_asstring(obj)); 13805 (void)putstr(text, "' zones not supported by "); 13806 (void)putstr(text, bn); 13807 CHECK(ISC_R_FAILURE); 13808 } 13809 13810 if (strcasecmp(cfg_obj_asstring(obj), "redirect") == 0) { 13811 redirect = true; 13812 } 13813 13814 /* Make sense of optional class argument */ 13815 obj = cfg_tuple_get(zoneobj, "class"); 13816 CHECK(named_config_getclass(obj, dns_rdataclass_in, &rdclass)); 13817 13818 /* Make sense of optional view argument */ 13819 obj = cfg_tuple_get(zoneobj, "view"); 13820 if (obj && cfg_obj_isstring(obj)) { 13821 viewname = cfg_obj_asstring(obj); 13822 } 13823 if (viewname == NULL || *viewname == '\0') { 13824 viewname = "_default"; 13825 } 13826 result = dns_viewlist_find(&server->viewlist, viewname, rdclass, &view); 13827 if (result == ISC_R_NOTFOUND) { 13828 (void)putstr(text, "no matching view found for '"); 13829 (void)putstr(text, viewname); 13830 (void)putstr(text, "'"); 13831 goto cleanup; 13832 } else if (result != ISC_R_SUCCESS) { 13833 goto cleanup; 13834 } 13835 13836 *viewp = view; 13837 *zoneobjp = zoneobj; 13838 *zoneconfp = zoneconf; 13839 *redirectp = redirect; 13840 13841 return ISC_R_SUCCESS; 13842 13843 cleanup: 13844 if (zoneconf != NULL) { 13845 cfg_obj_destroy(named_g_addparser, &zoneconf); 13846 } 13847 if (view != NULL) { 13848 dns_view_detach(&view); 13849 } 13850 13851 return result; 13852 } 13853 13854 static isc_result_t 13855 delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config, 13856 const dns_name_t *zname, nzfwriter_t nzfwriter, bool locked) { 13857 isc_result_t result = ISC_R_NOTFOUND; 13858 const cfg_listelt_t *elt = NULL; 13859 const cfg_obj_t *zl = NULL; 13860 cfg_list_t *list; 13861 dns_fixedname_t myfixed; 13862 dns_name_t *myname; 13863 13864 REQUIRE(view != NULL); 13865 REQUIRE(pctx != NULL); 13866 REQUIRE(config != NULL); 13867 REQUIRE(zname != NULL); 13868 13869 if (!locked) { 13870 LOCK(&view->new_zone_lock); 13871 } 13872 13873 cfg_map_get(config, "zone", &zl); 13874 13875 if (!cfg_obj_islist(zl)) { 13876 CHECK(ISC_R_FAILURE); 13877 } 13878 13879 list = UNCONST(&zl->value.list); 13880 13881 myname = dns_fixedname_initname(&myfixed); 13882 13883 for (elt = ISC_LIST_HEAD(*list); elt != NULL; 13884 elt = ISC_LIST_NEXT(elt, link)) 13885 { 13886 const cfg_obj_t *zconf = cfg_listelt_value(elt); 13887 const char *zn; 13888 cfg_listelt_t *e; 13889 13890 zn = cfg_obj_asstring(cfg_tuple_get(zconf, "name")); 13891 result = dns_name_fromstring(myname, zn, dns_rootname, 0, NULL); 13892 if (result != ISC_R_SUCCESS || !dns_name_equal(zname, myname)) { 13893 continue; 13894 } 13895 13896 e = UNCONST(elt); 13897 ISC_LIST_UNLINK(*list, e, link); 13898 cfg_obj_destroy(pctx, &e->obj); 13899 isc_mem_put(pctx->mctx, e, sizeof(*e)); 13900 result = ISC_R_SUCCESS; 13901 break; 13902 } 13903 13904 /* 13905 * Write config to NZF file if appropriate 13906 */ 13907 if (nzfwriter != NULL && view->new_zone_file != NULL) { 13908 result = nzfwriter(config, view); 13909 } 13910 13911 cleanup: 13912 if (!locked) { 13913 UNLOCK(&view->new_zone_lock); 13914 } 13915 return result; 13916 } 13917 13918 static isc_result_t 13919 do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, 13920 dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj, 13921 bool redirect, isc_buffer_t **text) { 13922 isc_result_t result, tresult; 13923 dns_zone_t *zone = NULL; 13924 bool locked = false; 13925 #ifndef HAVE_LMDB 13926 FILE *fp = NULL; 13927 bool cleanup_config = false; 13928 #else /* HAVE_LMDB */ 13929 MDB_txn *txn = NULL; 13930 MDB_dbi dbi; 13931 13932 UNUSED(zoneconf); 13933 #endif 13934 13935 /* Zone shouldn't already exist */ 13936 if (redirect) { 13937 result = (view->redirect == NULL) ? ISC_R_NOTFOUND 13938 : ISC_R_EXISTS; 13939 } else { 13940 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 13941 if (result == ISC_R_SUCCESS) { 13942 result = ISC_R_EXISTS; 13943 } 13944 } 13945 if (result != ISC_R_NOTFOUND) { 13946 goto cleanup; 13947 } 13948 13949 isc_loopmgr_pause(named_g_loopmgr); 13950 13951 #ifndef HAVE_LMDB 13952 /* 13953 * Make sure we can open the configuration save file 13954 */ 13955 result = isc_stdio_open(view->new_zone_file, "a", &fp); 13956 if (result != ISC_R_SUCCESS) { 13957 isc_loopmgr_resume(named_g_loopmgr); 13958 TCHECK(putstr(text, "unable to create '")); 13959 TCHECK(putstr(text, view->new_zone_file)); 13960 TCHECK(putstr(text, "': ")); 13961 TCHECK(putstr(text, isc_result_totext(result))); 13962 goto cleanup; 13963 } 13964 13965 (void)isc_stdio_close(fp); 13966 fp = NULL; 13967 #else /* HAVE_LMDB */ 13968 LOCK(&view->new_zone_lock); 13969 locked = true; 13970 /* Make sure we can open the NZD database */ 13971 result = nzd_writable(view); 13972 if (result != ISC_R_SUCCESS) { 13973 isc_loopmgr_resume(named_g_loopmgr); 13974 TCHECK(putstr(text, "unable to open NZD database for '")); 13975 TCHECK(putstr(text, view->new_zone_db)); 13976 TCHECK(putstr(text, "'")); 13977 result = ISC_R_FAILURE; 13978 goto cleanup; 13979 } 13980 #endif /* HAVE_LMDB */ 13981 13982 /* Mark view unfrozen and configure zone */ 13983 dns_view_thaw(view); 13984 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, 13985 &server->viewlist, &server->kasplist, 13986 &server->keystorelist, cfg->actx, true, false, 13987 false, false); 13988 dns_view_freeze(view); 13989 13990 isc_loopmgr_resume(named_g_loopmgr); 13991 13992 if (result != ISC_R_SUCCESS) { 13993 TCHECK(putstr(text, "configure_zone failed: ")); 13994 TCHECK(putstr(text, isc_result_totext(result))); 13995 goto cleanup; 13996 } 13997 13998 /* Is it there yet? */ 13999 if (redirect) { 14000 if (view->redirect == NULL) { 14001 CHECK(ISC_R_NOTFOUND); 14002 } 14003 dns_zone_attach(view->redirect, &zone); 14004 } else { 14005 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 14006 if (result != ISC_R_SUCCESS) { 14007 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14008 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14009 "added new zone was not found: %s", 14010 isc_result_totext(result)); 14011 goto cleanup; 14012 } 14013 } 14014 14015 #ifndef HAVE_LMDB 14016 /* 14017 * If there wasn't a previous newzone config, just save the one 14018 * we've created. If there was a previous one, merge the new 14019 * zone into it. 14020 */ 14021 if (cfg->nzf_config == NULL) { 14022 cfg_obj_attach(zoneconf, &cfg->nzf_config); 14023 } else { 14024 cfg_obj_t *z = UNCONST(zoneobj); 14025 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, 14026 "zone")); 14027 } 14028 cleanup_config = true; 14029 #endif /* HAVE_LMDB */ 14030 14031 /* 14032 * Load the zone from the master file. If this fails, we'll 14033 * need to undo the configuration we've done already. 14034 */ 14035 result = dns_zone_load(zone, true); 14036 if (result != ISC_R_SUCCESS) { 14037 dns_db_t *dbp = NULL; 14038 14039 TCHECK(putstr(text, "dns_zone_loadnew failed: ")); 14040 TCHECK(putstr(text, isc_result_totext(result))); 14041 14042 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14043 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14044 "addzone failed; reverting."); 14045 14046 /* If the zone loaded partially, unload it */ 14047 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14048 dns_db_detach(&dbp); 14049 dns_zone_unload(zone); 14050 } 14051 14052 /* Remove the zone from the zone table */ 14053 dns_view_delzone(view, zone); 14054 goto cleanup; 14055 } 14056 14057 /* Flag the zone as having been added at runtime */ 14058 dns_zone_setadded(zone, true); 14059 14060 #ifdef HAVE_LMDB 14061 /* Save the new zone configuration into the NZD */ 14062 CHECK(nzd_open(view, 0, &txn, &dbi)); 14063 CHECK(nzd_save(&txn, dbi, zone, zoneobj)); 14064 #else /* ifdef HAVE_LMDB */ 14065 /* Append the zone configuration to the NZF */ 14066 result = nzf_append(view, zoneobj); 14067 #endif /* HAVE_LMDB */ 14068 14069 cleanup: 14070 14071 #ifndef HAVE_LMDB 14072 if (fp != NULL) { 14073 (void)isc_stdio_close(fp); 14074 } 14075 if (result != ISC_R_SUCCESS && cleanup_config) { 14076 tresult = delete_zoneconf(view, cfg->add_parser, 14077 cfg->nzf_config, name, NULL, locked); 14078 RUNTIME_CHECK(tresult == ISC_R_SUCCESS); 14079 } 14080 #else /* HAVE_LMDB */ 14081 if (txn != NULL) { 14082 (void)nzd_close(&txn, false); 14083 } 14084 if (locked) { 14085 UNLOCK(&view->new_zone_lock); 14086 } 14087 #endif /* HAVE_LMDB */ 14088 14089 if (zone != NULL) { 14090 dns_zone_detach(&zone); 14091 } 14092 14093 return result; 14094 } 14095 14096 static isc_result_t 14097 do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, 14098 dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj, 14099 bool redirect, isc_buffer_t **text) { 14100 isc_result_t result, tresult; 14101 dns_zone_t *zone = NULL; 14102 bool added; 14103 bool locked = false; 14104 const cfg_obj_t *options = NULL; 14105 #ifndef HAVE_LMDB 14106 FILE *fp = NULL; 14107 cfg_obj_t *z; 14108 #else /* HAVE_LMDB */ 14109 MDB_txn *txn = NULL; 14110 MDB_dbi dbi; 14111 #endif /* HAVE_LMDB */ 14112 14113 /* Zone must already exist */ 14114 if (redirect) { 14115 if (view->redirect != NULL) { 14116 dns_zone_attach(view->redirect, &zone); 14117 result = ISC_R_SUCCESS; 14118 } else { 14119 result = ISC_R_NOTFOUND; 14120 } 14121 } else { 14122 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 14123 } 14124 if (result != ISC_R_SUCCESS) { 14125 goto cleanup; 14126 } 14127 14128 added = dns_zone_getadded(zone); 14129 dns_zone_detach(&zone); 14130 14131 #ifndef HAVE_LMDB 14132 cfg = (ns_cfgctx_t *)view->new_zone_config; 14133 if (cfg == NULL) { 14134 TCHECK(putstr(text, "new zone config is not set")); 14135 CHECK(ISC_R_FAILURE); 14136 } 14137 #endif /* ifndef HAVE_LMDB */ 14138 14139 isc_loopmgr_pause(named_g_loopmgr); 14140 14141 #ifndef HAVE_LMDB 14142 /* Make sure we can open the configuration save file */ 14143 result = isc_stdio_open(view->new_zone_file, "a", &fp); 14144 if (result != ISC_R_SUCCESS) { 14145 TCHECK(putstr(text, "unable to open '")); 14146 TCHECK(putstr(text, view->new_zone_file)); 14147 TCHECK(putstr(text, "': ")); 14148 TCHECK(putstr(text, isc_result_totext(result))); 14149 isc_loopmgr_resume(named_g_loopmgr); 14150 goto cleanup; 14151 } 14152 (void)isc_stdio_close(fp); 14153 fp = NULL; 14154 #else /* HAVE_LMDB */ 14155 LOCK(&view->new_zone_lock); 14156 locked = true; 14157 /* Make sure we can open the NZD database */ 14158 result = nzd_writable(view); 14159 if (result != ISC_R_SUCCESS) { 14160 TCHECK(putstr(text, "unable to open NZD database for '")); 14161 TCHECK(putstr(text, view->new_zone_db)); 14162 TCHECK(putstr(text, "'")); 14163 result = ISC_R_FAILURE; 14164 isc_loopmgr_resume(named_g_loopmgr); 14165 goto cleanup; 14166 } 14167 #endif /* HAVE_LMDB */ 14168 14169 /* Reconfigure the zone */ 14170 dns_view_thaw(view); 14171 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, 14172 &server->viewlist, &server->kasplist, 14173 &server->keystorelist, cfg->actx, false, false, 14174 false, true); 14175 dns_view_freeze(view); 14176 14177 isc_loopmgr_resume(named_g_loopmgr); 14178 14179 if (result != ISC_R_SUCCESS) { 14180 TCHECK(putstr(text, "configure_zone failed: ")); 14181 TCHECK(putstr(text, isc_result_totext(result))); 14182 goto cleanup; 14183 } 14184 14185 /* Is it there yet? */ 14186 if (redirect) { 14187 if (view->redirect == NULL) { 14188 CHECK(ISC_R_NOTFOUND); 14189 } 14190 dns_zone_attach(view->redirect, &zone); 14191 } else { 14192 CHECK(dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone)); 14193 } 14194 14195 #ifndef HAVE_LMDB 14196 /* Remove old zone from configuration (and NZF file if applicable) */ 14197 if (added) { 14198 result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, 14199 dns_zone_getorigin(zone), 14200 nzf_writeconf, locked); 14201 if (result != ISC_R_SUCCESS) { 14202 TCHECK(putstr(text, "former zone configuration " 14203 "not deleted: ")); 14204 TCHECK(putstr(text, isc_result_totext(result))); 14205 goto cleanup; 14206 } 14207 } 14208 #endif /* HAVE_LMDB */ 14209 14210 if (!added) { 14211 if (cfg->vconfig == NULL) { 14212 options = cfg->config; 14213 } else { 14214 options = cfg_tuple_get(cfg->vconfig, "options"); 14215 } 14216 result = delete_zoneconf(view, cfg->conf_parser, options, 14217 dns_zone_getorigin(zone), NULL, 14218 locked); 14219 if (result != ISC_R_SUCCESS) { 14220 TCHECK(putstr(text, "former zone configuration " 14221 "not deleted: ")); 14222 TCHECK(putstr(text, isc_result_totext(result))); 14223 goto cleanup; 14224 } 14225 } 14226 14227 /* Load the zone from the master file if it needs reloading. */ 14228 result = dns_zone_load(zone, true); 14229 14230 /* 14231 * Dynamic zones need no reloading, so we can pass this result. 14232 */ 14233 if (result == DNS_R_DYNAMIC) { 14234 result = ISC_R_SUCCESS; 14235 } 14236 14237 if (result != ISC_R_SUCCESS) { 14238 dns_db_t *dbp = NULL; 14239 14240 TCHECK(putstr(text, "failed to load zone '")); 14241 TCHECK(putstr(text, zname)); 14242 TCHECK(putstr(text, "': ")); 14243 TCHECK(putstr(text, isc_result_totext(result))); 14244 TCHECK(putstr(text, "\nThe zone is no longer being served. ")); 14245 TCHECK(putstr(text, "Use 'rndc addzone' to correct\n")); 14246 TCHECK(putstr(text, "the problem and restore service.")); 14247 14248 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14249 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14250 "modzone failed; removing zone."); 14251 14252 /* If the zone loaded partially, unload it */ 14253 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14254 dns_db_detach(&dbp); 14255 dns_zone_unload(zone); 14256 } 14257 14258 /* Remove the zone from the zone table */ 14259 dns_view_delzone(view, zone); 14260 goto cleanup; 14261 } 14262 14263 #ifndef HAVE_LMDB 14264 /* Store the new zone configuration; also in NZF if applicable */ 14265 if (cfg->nzf_config != NULL) { 14266 z = UNCONST(zoneobj); 14267 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, 14268 "zone")); 14269 } 14270 #endif /* HAVE_LMDB */ 14271 14272 if (added) { 14273 #ifdef HAVE_LMDB 14274 CHECK(nzd_open(view, 0, &txn, &dbi)); 14275 CHECK(nzd_save(&txn, dbi, zone, zoneobj)); 14276 #else /* ifdef HAVE_LMDB */ 14277 result = nzf_append(view, zoneobj); 14278 if (result != ISC_R_SUCCESS) { 14279 TCHECK(putstr(text, "\nNew zone config not saved: ")); 14280 TCHECK(putstr(text, isc_result_totext(result))); 14281 goto cleanup; 14282 } 14283 #endif /* HAVE_LMDB */ 14284 14285 TCHECK(putstr(text, "zone '")); 14286 TCHECK(putstr(text, zname)); 14287 TCHECK(putstr(text, "' reconfigured.")); 14288 } else { 14289 CHECK(cfg_parser_mapadd(cfg->conf_parser, UNCONST(options), 14290 UNCONST(zoneobj), "zone")); 14291 14292 TCHECK(putstr(text, "zone '")); 14293 TCHECK(putstr(text, zname)); 14294 TCHECK(putstr(text, "' must also be reconfigured in\n")); 14295 TCHECK(putstr(text, "named.conf to make changes permanent.")); 14296 } 14297 14298 cleanup: 14299 14300 #ifndef HAVE_LMDB 14301 if (fp != NULL) { 14302 (void)isc_stdio_close(fp); 14303 } 14304 #else /* HAVE_LMDB */ 14305 if (txn != NULL) { 14306 (void)nzd_close(&txn, false); 14307 } 14308 if (locked) { 14309 UNLOCK(&view->new_zone_lock); 14310 } 14311 #endif /* HAVE_LMDB */ 14312 14313 if (zone != NULL) { 14314 dns_zone_detach(&zone); 14315 } 14316 14317 return result; 14318 } 14319 14320 /* 14321 * Act on an "addzone" or "modzone" command from the command channel. 14322 */ 14323 isc_result_t 14324 named_server_changezone(named_server_t *server, char *command, 14325 isc_buffer_t **text) { 14326 isc_result_t result; 14327 bool addzone; 14328 bool redirect = false; 14329 ns_cfgctx_t *cfg = NULL; 14330 cfg_obj_t *zoneconf = NULL; 14331 const cfg_obj_t *zoneobj = NULL; 14332 const char *zonename; 14333 dns_view_t *view = NULL; 14334 isc_buffer_t buf; 14335 dns_fixedname_t fname; 14336 dns_name_t *dnsname; 14337 14338 REQUIRE(text != NULL); 14339 14340 if (strncasecmp(command, "add", 3) == 0) { 14341 addzone = true; 14342 } else { 14343 INSIST(strncasecmp(command, "mod", 3) == 0); 14344 addzone = false; 14345 } 14346 14347 CHECK(newzone_parse(server, command, &view, &zoneconf, &zoneobj, 14348 &redirect, text)); 14349 14350 /* Are we accepting new zones in this view? */ 14351 #ifdef HAVE_LMDB 14352 if (view->new_zone_db == NULL) 14353 #else /* ifdef HAVE_LMDB */ 14354 if (view->new_zone_file == NULL) 14355 #endif /* HAVE_LMDB */ 14356 { 14357 (void)putstr(text, "Not allowing new zones in view '"); 14358 (void)putstr(text, view->name); 14359 (void)putstr(text, "'"); 14360 result = ISC_R_NOPERM; 14361 goto cleanup; 14362 } 14363 14364 cfg = (ns_cfgctx_t *)view->new_zone_config; 14365 if (cfg == NULL) { 14366 result = ISC_R_FAILURE; 14367 goto cleanup; 14368 } 14369 14370 zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name")); 14371 isc_buffer_constinit(&buf, zonename, strlen(zonename)); 14372 isc_buffer_add(&buf, strlen(zonename)); 14373 14374 dnsname = dns_fixedname_initname(&fname); 14375 CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, 0, NULL)); 14376 14377 if (redirect) { 14378 if (!dns_name_equal(dnsname, dns_rootname)) { 14379 (void)putstr(text, "redirect zones must be called " 14380 "\".\""); 14381 CHECK(ISC_R_FAILURE); 14382 } 14383 } 14384 14385 if (addzone) { 14386 CHECK(do_addzone(server, cfg, view, dnsname, zoneconf, zoneobj, 14387 redirect, text)); 14388 } else { 14389 CHECK(do_modzone(server, cfg, view, dnsname, zonename, zoneobj, 14390 redirect, text)); 14391 } 14392 14393 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14394 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14395 "%s zone %s in view %s via %s", 14396 addzone ? "added" : "updated", zonename, view->name, 14397 addzone ? NAMED_COMMAND_ADDZONE : NAMED_COMMAND_MODZONE); 14398 14399 /* Changing a zone counts as reconfiguration */ 14400 named_g_configtime = isc_time_now(); 14401 14402 cleanup: 14403 if (isc_buffer_usedlength(*text) > 0) { 14404 (void)putnull(text); 14405 } 14406 if (zoneconf != NULL) { 14407 cfg_obj_destroy(named_g_addparser, &zoneconf); 14408 } 14409 if (view != NULL) { 14410 dns_view_detach(&view); 14411 } 14412 14413 return result; 14414 } 14415 14416 static bool 14417 inuse(const char *file, bool first, isc_buffer_t **text) { 14418 if (file != NULL && isc_file_exists(file)) { 14419 if (first) { 14420 (void)putstr(text, "The following files were in use " 14421 "and may now be removed:\n"); 14422 } else { 14423 (void)putstr(text, "\n"); 14424 } 14425 (void)putstr(text, file); 14426 (void)putnull(text); 14427 return false; 14428 } 14429 return first; 14430 } 14431 14432 typedef struct { 14433 dns_zone_t *zone; 14434 bool cleanup; 14435 } ns_dzctx_t; 14436 14437 /* 14438 * Carry out a zone deletion scheduled by named_server_delzone(). 14439 */ 14440 static void 14441 rmzone(void *arg) { 14442 ns_dzctx_t *dz = (ns_dzctx_t *)arg; 14443 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; 14444 dns_catz_zone_t *catz = NULL; 14445 char zonename[DNS_NAME_FORMATSIZE]; 14446 dns_view_t *view = NULL; 14447 ns_cfgctx_t *cfg = NULL; 14448 dns_db_t *dbp = NULL; 14449 bool added; 14450 isc_result_t result; 14451 #ifdef HAVE_LMDB 14452 MDB_txn *txn = NULL; 14453 MDB_dbi dbi; 14454 #endif /* ifdef HAVE_LMDB */ 14455 14456 REQUIRE(dz != NULL); 14457 14458 /* Dig out configuration for this zone */ 14459 zone = dz->zone; 14460 view = dns_zone_getview(zone); 14461 cfg = (ns_cfgctx_t *)view->new_zone_config; 14462 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 14463 14464 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14465 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14466 "deleting zone %s in view %s via delzone", zonename, 14467 view->name); 14468 14469 /* 14470 * Remove the zone from configuration (and NZF file if applicable) 14471 * (If this is a catalog zone member then nzf_config can be NULL) 14472 */ 14473 added = dns_zone_getadded(zone); 14474 catz = dns_zone_get_parentcatz(zone); 14475 14476 if (added && catz == NULL && cfg != NULL) { 14477 #ifdef HAVE_LMDB 14478 /* Make sure we can open the NZD database */ 14479 LOCK(&view->new_zone_lock); 14480 result = nzd_open(view, 0, &txn, &dbi); 14481 if (result != ISC_R_SUCCESS) { 14482 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14483 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14484 "unable to open NZD database for '%s'", 14485 view->new_zone_db); 14486 } else { 14487 result = nzd_save(&txn, dbi, zone, NULL); 14488 } 14489 14490 if (result != ISC_R_SUCCESS) { 14491 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14492 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14493 "unable to delete zone configuration: %s", 14494 isc_result_totext(result)); 14495 } 14496 14497 if (txn != NULL) { 14498 (void)nzd_close(&txn, false); 14499 } 14500 UNLOCK(&view->new_zone_lock); 14501 #else /* ifdef HAVE_LMDB */ 14502 result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, 14503 dns_zone_getorigin(zone), 14504 nzf_writeconf, false); 14505 if (result != ISC_R_SUCCESS) { 14506 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14507 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14508 "unable to delete zone configuration: %s", 14509 isc_result_totext(result)); 14510 } 14511 #endif /* HAVE_LMDB */ 14512 } 14513 14514 if (!added && cfg != NULL) { 14515 if (cfg->vconfig != NULL) { 14516 const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, 14517 "options"); 14518 result = delete_zoneconf( 14519 view, cfg->conf_parser, voptions, 14520 dns_zone_getorigin(zone), NULL, false); 14521 } else { 14522 result = delete_zoneconf( 14523 view, cfg->conf_parser, cfg->config, 14524 dns_zone_getorigin(zone), NULL, false); 14525 } 14526 if (result != ISC_R_SUCCESS) { 14527 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14528 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14529 "unable to delete zone configuration: %s", 14530 isc_result_totext(result)); 14531 } 14532 } 14533 14534 /* Unload zone database */ 14535 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14536 dns_db_detach(&dbp); 14537 dns_zone_unload(zone); 14538 } 14539 14540 /* Clean up stub/secondary zone files if requested to do so */ 14541 dns_zone_getraw(zone, &raw); 14542 mayberaw = (raw != NULL) ? raw : zone; 14543 14544 if (added && dz->cleanup) { 14545 const char *file; 14546 14547 file = dns_zone_getfile(mayberaw); 14548 result = isc_file_remove(file); 14549 if (result != ISC_R_SUCCESS) { 14550 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14551 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14552 "file %s not removed: %s", file, 14553 isc_result_totext(result)); 14554 } 14555 14556 file = dns_zone_getjournal(mayberaw); 14557 result = isc_file_remove(file); 14558 if (result != ISC_R_SUCCESS) { 14559 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14560 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14561 "file %s not removed: %s", file, 14562 isc_result_totext(result)); 14563 } 14564 14565 if (zone != mayberaw) { 14566 file = dns_zone_getfile(zone); 14567 result = isc_file_remove(file); 14568 if (result != ISC_R_SUCCESS) { 14569 isc_log_write( 14570 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14571 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14572 "file %s not removed: %s", file, 14573 isc_result_totext(result)); 14574 } 14575 14576 file = dns_zone_getjournal(zone); 14577 result = isc_file_remove(file); 14578 if (result != ISC_R_SUCCESS) { 14579 isc_log_write( 14580 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14581 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14582 "file %s not removed: %s", file, 14583 isc_result_totext(result)); 14584 } 14585 } 14586 } 14587 14588 if (raw != NULL) { 14589 dns_zone_detach(&raw); 14590 } 14591 dns_zone_detach(&zone); 14592 isc_mem_put(named_g_mctx, dz, sizeof(*dz)); 14593 } 14594 14595 /* 14596 * Act on a "delzone" command from the command channel. 14597 */ 14598 isc_result_t 14599 named_server_delzone(named_server_t *server, isc_lex_t *lex, 14600 isc_buffer_t **text) { 14601 isc_result_t result, tresult; 14602 dns_zone_t *zone = NULL; 14603 dns_zone_t *raw = NULL; 14604 dns_zone_t *mayberaw; 14605 dns_view_t *view = NULL; 14606 char zonename[DNS_NAME_FORMATSIZE]; 14607 bool cleanup = false; 14608 const char *ptr; 14609 bool added; 14610 ns_dzctx_t *dz = NULL; 14611 14612 REQUIRE(text != NULL); 14613 14614 /* Skip the command name. */ 14615 ptr = next_token(lex, text); 14616 if (ptr == NULL) { 14617 return ISC_R_UNEXPECTEDEND; 14618 } 14619 14620 /* Find out what we are to do. */ 14621 ptr = next_token(lex, text); 14622 if (ptr == NULL) { 14623 return ISC_R_UNEXPECTEDEND; 14624 } 14625 14626 if (strcmp(ptr, "-clean") == 0 || strcmp(ptr, "-clear") == 0) { 14627 cleanup = true; 14628 ptr = next_token(lex, text); 14629 } 14630 14631 CHECK(zone_from_args(server, lex, ptr, &zone, zonename, text, false)); 14632 if (zone == NULL) { 14633 result = ISC_R_UNEXPECTEDEND; 14634 goto cleanup; 14635 } 14636 14637 INSIST(zonename != NULL); 14638 14639 /* Is this a policy zone? */ 14640 if (dns_zone_get_rpz_num(zone) != DNS_RPZ_INVALID_NUM) { 14641 TCHECK(putstr(text, "zone '")); 14642 TCHECK(putstr(text, zonename)); 14643 TCHECK(putstr(text, 14644 "' cannot be deleted: response-policy zone.")); 14645 result = ISC_R_FAILURE; 14646 goto cleanup; 14647 } 14648 14649 view = dns_zone_getview(zone); 14650 if (dns_zone_gettype(zone) == dns_zone_redirect) { 14651 dns_zone_detach(&view->redirect); 14652 } else { 14653 CHECK(dns_view_delzone(view, zone)); 14654 } 14655 14656 /* Send cleanup event */ 14657 dz = isc_mem_get(named_g_mctx, sizeof(*dz)); 14658 *dz = (ns_dzctx_t){ 14659 .cleanup = cleanup, 14660 }; 14661 dns_zone_attach(zone, &dz->zone); 14662 isc_async_run(dns_zone_getloop(zone), rmzone, dz); 14663 14664 /* Inform user about cleaning up stub/secondary zone files */ 14665 dns_zone_getraw(zone, &raw); 14666 mayberaw = (raw != NULL) ? raw : zone; 14667 14668 added = dns_zone_getadded(zone); 14669 if (!added) { 14670 TCHECK(putstr(text, "zone '")); 14671 TCHECK(putstr(text, zonename)); 14672 TCHECK(putstr(text, "' is no longer active and will be " 14673 "deleted.\n")); 14674 TCHECK(putstr(text, "To keep it from returning ")); 14675 TCHECK(putstr(text, "when the server is restarted, it\n")); 14676 TCHECK(putstr(text, "must also be removed from named.conf.")); 14677 } else if (cleanup) { 14678 TCHECK(putstr(text, "zone '")); 14679 TCHECK(putstr(text, zonename)); 14680 TCHECK(putstr(text, "' and associated files will be deleted.")); 14681 } else if (dns_zone_gettype(mayberaw) == dns_zone_secondary || 14682 dns_zone_gettype(mayberaw) == dns_zone_mirror || 14683 dns_zone_gettype(mayberaw) == dns_zone_stub) 14684 { 14685 bool first; 14686 const char *file; 14687 14688 TCHECK(putstr(text, "zone '")); 14689 TCHECK(putstr(text, zonename)); 14690 TCHECK(putstr(text, "' will be deleted.")); 14691 14692 file = dns_zone_getfile(mayberaw); 14693 first = inuse(file, true, text); 14694 14695 file = dns_zone_getjournal(mayberaw); 14696 first = inuse(file, first, text); 14697 14698 if (zone != mayberaw) { 14699 file = dns_zone_getfile(zone); 14700 first = inuse(file, first, text); 14701 14702 file = dns_zone_getjournal(zone); 14703 (void)inuse(file, first, text); 14704 } 14705 } 14706 14707 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14708 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14709 "zone %s scheduled for removal via delzone", zonename); 14710 14711 /* Removing a zone counts as reconfiguration */ 14712 named_g_configtime = isc_time_now(); 14713 14714 result = ISC_R_SUCCESS; 14715 14716 cleanup: 14717 if (isc_buffer_usedlength(*text) > 0) { 14718 (void)putnull(text); 14719 } 14720 if (raw != NULL) { 14721 dns_zone_detach(&raw); 14722 } 14723 if (zone != NULL) { 14724 dns_zone_detach(&zone); 14725 } 14726 14727 return result; 14728 } 14729 14730 static const cfg_obj_t * 14731 find_name_in_list_from_map(const cfg_obj_t *config, 14732 const char *map_key_for_list, const char *name, 14733 bool redirect) { 14734 const cfg_obj_t *list = NULL; 14735 const cfg_listelt_t *element; 14736 const cfg_obj_t *obj = NULL; 14737 dns_fixedname_t fixed1, fixed2; 14738 dns_name_t *name1 = NULL, *name2 = NULL; 14739 isc_result_t result; 14740 14741 if (strcmp(map_key_for_list, "zone") == 0) { 14742 name1 = dns_fixedname_initname(&fixed1); 14743 name2 = dns_fixedname_initname(&fixed2); 14744 result = dns_name_fromstring(name1, name, dns_rootname, 0, 14745 NULL); 14746 RUNTIME_CHECK(result == ISC_R_SUCCESS); 14747 } 14748 14749 cfg_map_get(config, map_key_for_list, &list); 14750 for (element = cfg_list_first(list); element != NULL; 14751 element = cfg_list_next(element)) 14752 { 14753 const char *vname; 14754 14755 obj = cfg_listelt_value(element); 14756 INSIST(obj != NULL); 14757 vname = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 14758 if (vname == NULL) { 14759 obj = NULL; 14760 continue; 14761 } 14762 14763 if (name1 != NULL) { 14764 result = dns_name_fromstring(name2, vname, dns_rootname, 14765 0, NULL); 14766 if (result == ISC_R_SUCCESS && 14767 dns_name_equal(name1, name2)) 14768 { 14769 const cfg_obj_t *zoptions; 14770 const cfg_obj_t *typeobj = NULL; 14771 zoptions = cfg_tuple_get(obj, "options"); 14772 14773 if (zoptions != NULL) { 14774 cfg_map_get(zoptions, "type", &typeobj); 14775 } 14776 if (redirect && typeobj != NULL && 14777 strcasecmp(cfg_obj_asstring(typeobj), 14778 "redirect") == 0) 14779 { 14780 break; 14781 } else if (!redirect) { 14782 break; 14783 } 14784 } 14785 } else if (strcasecmp(vname, name) == 0) { 14786 break; 14787 } 14788 14789 obj = NULL; 14790 } 14791 14792 return obj; 14793 } 14794 14795 static void 14796 emitzone(void *arg, const char *buf, int len) { 14797 ns_dzarg_t *dzarg = arg; 14798 isc_result_t result; 14799 14800 REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); 14801 result = putmem(dzarg->text, buf, len); 14802 if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { 14803 dzarg->result = result; 14804 } 14805 } 14806 14807 /* 14808 * Act on a "showzone" command from the command channel. 14809 */ 14810 isc_result_t 14811 named_server_showzone(named_server_t *server, isc_lex_t *lex, 14812 isc_buffer_t **text) { 14813 isc_result_t result; 14814 const cfg_obj_t *vconfig = NULL, *zconfig = NULL; 14815 char zonename[DNS_NAME_FORMATSIZE]; 14816 const cfg_obj_t *map; 14817 dns_view_t *view = NULL; 14818 dns_zone_t *zone = NULL; 14819 ns_cfgctx_t *cfg = NULL; 14820 #ifdef HAVE_LMDB 14821 cfg_obj_t *nzconfig = NULL; 14822 #endif /* HAVE_LMDB */ 14823 bool added, redirect; 14824 ns_dzarg_t dzarg; 14825 14826 REQUIRE(text != NULL); 14827 14828 /* Parse parameters */ 14829 CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); 14830 if (zone == NULL) { 14831 result = ISC_R_UNEXPECTEDEND; 14832 goto cleanup; 14833 } 14834 14835 redirect = dns_zone_gettype(zone) == dns_zone_redirect; 14836 added = dns_zone_getadded(zone); 14837 view = dns_zone_getview(zone); 14838 dns_zone_detach(&zone); 14839 14840 cfg = (ns_cfgctx_t *)view->new_zone_config; 14841 if (cfg == NULL) { 14842 result = ISC_R_FAILURE; 14843 goto cleanup; 14844 } 14845 14846 if (!added) { 14847 /* Find the view statement */ 14848 vconfig = find_name_in_list_from_map(cfg->config, "view", 14849 view->name, false); 14850 14851 /* Find the zone statement */ 14852 if (vconfig != NULL) { 14853 map = cfg_tuple_get(vconfig, "options"); 14854 } else { 14855 map = cfg->config; 14856 } 14857 14858 zconfig = find_name_in_list_from_map(map, "zone", zonename, 14859 redirect); 14860 } 14861 14862 #ifndef HAVE_LMDB 14863 if (zconfig == NULL && cfg->nzf_config != NULL) { 14864 zconfig = find_name_in_list_from_map(cfg->nzf_config, "zone", 14865 zonename, redirect); 14866 } 14867 #else /* HAVE_LMDB */ 14868 if (zconfig == NULL) { 14869 const cfg_obj_t *zlist = NULL; 14870 CHECK(get_newzone_config(view, zonename, &nzconfig)); 14871 CHECK(cfg_map_get(nzconfig, "zone", &zlist)); 14872 if (!cfg_obj_islist(zlist)) { 14873 CHECK(ISC_R_FAILURE); 14874 } 14875 14876 zconfig = cfg_listelt_value(cfg_list_first(zlist)); 14877 } 14878 #endif /* HAVE_LMDB */ 14879 14880 if (zconfig == NULL) { 14881 CHECK(ISC_R_NOTFOUND); 14882 } 14883 14884 CHECK(putstr(text, "zone ")); 14885 dzarg.magic = DZARG_MAGIC; 14886 dzarg.text = text; 14887 dzarg.result = ISC_R_SUCCESS; 14888 cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, &dzarg); 14889 CHECK(dzarg.result); 14890 14891 CHECK(putstr(text, ";")); 14892 14893 result = ISC_R_SUCCESS; 14894 14895 cleanup: 14896 #ifdef HAVE_LMDB 14897 if (nzconfig != NULL) { 14898 cfg_obj_destroy(named_g_addparser, &nzconfig); 14899 } 14900 #endif /* HAVE_LMDB */ 14901 if (isc_buffer_usedlength(*text) > 0) { 14902 (void)putnull(text); 14903 } 14904 14905 return result; 14906 } 14907 14908 static void 14909 newzone_cfgctx_destroy(void **cfgp) { 14910 ns_cfgctx_t *cfg; 14911 14912 REQUIRE(cfgp != NULL && *cfgp != NULL); 14913 14914 cfg = *cfgp; 14915 14916 if (cfg->conf_parser != NULL) { 14917 if (cfg->config != NULL) { 14918 cfg_obj_destroy(cfg->conf_parser, &cfg->config); 14919 } 14920 if (cfg->vconfig != NULL) { 14921 cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig); 14922 } 14923 cfg_parser_destroy(&cfg->conf_parser); 14924 } 14925 if (cfg->add_parser != NULL) { 14926 if (cfg->nzf_config != NULL) { 14927 cfg_obj_destroy(cfg->add_parser, &cfg->nzf_config); 14928 } 14929 cfg_parser_destroy(&cfg->add_parser); 14930 } 14931 14932 if (cfg->actx != NULL) { 14933 cfg_aclconfctx_detach(&cfg->actx); 14934 } 14935 14936 isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); 14937 *cfgp = NULL; 14938 } 14939 14940 isc_result_t 14941 named_server_signing(named_server_t *server, isc_lex_t *lex, 14942 isc_buffer_t **text) { 14943 isc_result_t result = ISC_R_SUCCESS; 14944 dns_zone_t *zone = NULL; 14945 dns_name_t *origin; 14946 dns_db_t *db = NULL; 14947 dns_dbnode_t *node = NULL; 14948 dns_dbversion_t *version = NULL; 14949 dns_rdatatype_t privatetype; 14950 dns_rdataset_t privset; 14951 bool first = true; 14952 bool list = false, clear = false; 14953 bool chain = false; 14954 bool setserial = false; 14955 bool resalt = false; 14956 uint32_t serial = 0; 14957 char keystr[DNS_SECALG_FORMATSIZE + 7]; /* <5-digit keyid>/<alg> */ 14958 unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0; 14959 unsigned char salt[255]; 14960 const char *ptr; 14961 size_t n; 14962 bool kasp = false; 14963 14964 REQUIRE(text != NULL); 14965 14966 dns_rdataset_init(&privset); 14967 14968 /* Skip the command name. */ 14969 ptr = next_token(lex, text); 14970 if (ptr == NULL) { 14971 return ISC_R_UNEXPECTEDEND; 14972 } 14973 14974 /* Find out what we are to do. */ 14975 ptr = next_token(lex, text); 14976 if (ptr == NULL) { 14977 return ISC_R_UNEXPECTEDEND; 14978 } 14979 14980 if (strcasecmp(ptr, "-list") == 0) { 14981 list = true; 14982 } else if ((strcasecmp(ptr, "-clear") == 0) || 14983 (strcasecmp(ptr, "-clean") == 0)) 14984 { 14985 clear = true; 14986 ptr = next_token(lex, text); 14987 if (ptr == NULL) { 14988 return ISC_R_UNEXPECTEDEND; 14989 } 14990 strlcpy(keystr, ptr, sizeof(keystr)); 14991 } else if (strcasecmp(ptr, "-nsec3param") == 0) { 14992 char hashbuf[64], flagbuf[64], iterbuf[64]; 14993 char nbuf[256]; 14994 14995 chain = true; 14996 ptr = next_token(lex, text); 14997 if (ptr == NULL) { 14998 return ISC_R_UNEXPECTEDEND; 14999 } 15000 15001 if (strcasecmp(ptr, "none") == 0) { 15002 hash = 0; 15003 } else { 15004 strlcpy(hashbuf, ptr, sizeof(hashbuf)); 15005 15006 ptr = next_token(lex, text); 15007 if (ptr == NULL) { 15008 return ISC_R_UNEXPECTEDEND; 15009 } 15010 strlcpy(flagbuf, ptr, sizeof(flagbuf)); 15011 15012 ptr = next_token(lex, text); 15013 if (ptr == NULL) { 15014 return ISC_R_UNEXPECTEDEND; 15015 } 15016 strlcpy(iterbuf, ptr, sizeof(iterbuf)); 15017 n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", hashbuf, 15018 flagbuf, iterbuf); 15019 if (n == sizeof(nbuf)) { 15020 return ISC_R_NOSPACE; 15021 } 15022 n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); 15023 if (n != 3U) { 15024 return ISC_R_BADNUMBER; 15025 } 15026 15027 if (hash > 0xffU || flags > 0xffU || 15028 iter > dns_nsec3_maxiterations()) 15029 { 15030 return ISC_R_RANGE; 15031 } 15032 15033 ptr = next_token(lex, text); 15034 if (ptr == NULL) { 15035 return ISC_R_UNEXPECTEDEND; 15036 } else if (strcasecmp(ptr, "auto") == 0) { 15037 /* Auto-generate a random salt. 15038 * XXXMUKS: This currently uses the 15039 * minimum recommended length by RFC 15040 * 5155 (64 bits). It should be made 15041 * configurable. 15042 */ 15043 saltlen = 8; 15044 resalt = true; 15045 } else if (strcmp(ptr, "-") != 0) { 15046 isc_buffer_t buf; 15047 15048 isc_buffer_init(&buf, salt, sizeof(salt)); 15049 CHECK(isc_hex_decodestring(ptr, &buf)); 15050 saltlen = isc_buffer_usedlength(&buf); 15051 } 15052 } 15053 } else if (strcasecmp(ptr, "-serial") == 0) { 15054 ptr = next_token(lex, text); 15055 if (ptr == NULL) { 15056 return ISC_R_UNEXPECTEDEND; 15057 } 15058 CHECK(isc_parse_uint32(&serial, ptr, 10)); 15059 setserial = true; 15060 } else { 15061 CHECK(DNS_R_SYNTAX); 15062 } 15063 15064 CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); 15065 if (zone == NULL) { 15066 CHECK(ISC_R_UNEXPECTEDEND); 15067 } 15068 15069 if (dns_zone_getkasp(zone) != NULL) { 15070 kasp = true; 15071 } 15072 15073 if (clear) { 15074 CHECK(dns_zone_keydone(zone, keystr)); 15075 (void)putstr(text, "request queued"); 15076 (void)putnull(text); 15077 } else if (chain && !kasp) { 15078 CHECK(dns_zone_setnsec3param( 15079 zone, (uint8_t)hash, (uint8_t)flags, iter, 15080 (uint8_t)saltlen, salt, true, resalt)); 15081 (void)putstr(text, "nsec3param request queued"); 15082 (void)putnull(text); 15083 } else if (setserial) { 15084 CHECK(dns_zone_setserial(zone, serial)); 15085 (void)putstr(text, "serial request queued"); 15086 (void)putnull(text); 15087 } else if (list) { 15088 privatetype = dns_zone_getprivatetype(zone); 15089 origin = dns_zone_getorigin(zone); 15090 CHECK(dns_zone_getdb(zone, &db)); 15091 CHECK(dns_db_findnode(db, origin, false, &node)); 15092 dns_db_currentversion(db, &version); 15093 15094 result = dns_db_findrdataset(db, node, version, privatetype, 15095 dns_rdatatype_none, 0, &privset, 15096 NULL); 15097 if (result == ISC_R_NOTFOUND) { 15098 (void)putstr(text, "No signing records found"); 15099 (void)putnull(text); 15100 result = ISC_R_SUCCESS; 15101 goto cleanup; 15102 } 15103 15104 for (result = dns_rdataset_first(&privset); 15105 result == ISC_R_SUCCESS; 15106 result = dns_rdataset_next(&privset)) 15107 { 15108 dns_rdata_t priv = DNS_RDATA_INIT; 15109 /* 15110 * In theory, the output buffer could hold a full RDATA 15111 * record which is 16-bit and then some text around 15112 * it 15113 */ 15114 char output[UINT16_MAX + BUFSIZ]; 15115 isc_buffer_t buf; 15116 15117 dns_rdataset_current(&privset, &priv); 15118 15119 isc_buffer_init(&buf, output, sizeof(output)); 15120 CHECK(dns_private_totext(&priv, &buf)); 15121 if (!first) { 15122 CHECK(putstr(text, "\n")); 15123 } 15124 CHECK(putstr(text, output)); 15125 first = false; 15126 } 15127 if (!first) { 15128 CHECK(putnull(text)); 15129 } 15130 15131 if (result == ISC_R_NOMORE) { 15132 result = ISC_R_SUCCESS; 15133 } 15134 } else if (kasp) { 15135 (void)putstr(text, "zone uses dnssec-policy, use rndc dnssec " 15136 "command instead"); 15137 (void)putnull(text); 15138 } 15139 15140 cleanup: 15141 if (dns_rdataset_isassociated(&privset)) { 15142 dns_rdataset_disassociate(&privset); 15143 } 15144 if (node != NULL) { 15145 dns_db_detachnode(db, &node); 15146 } 15147 if (version != NULL) { 15148 dns_db_closeversion(db, &version, false); 15149 } 15150 if (db != NULL) { 15151 dns_db_detach(&db); 15152 } 15153 if (zone != NULL) { 15154 dns_zone_detach(&zone); 15155 } 15156 15157 return result; 15158 } 15159 15160 static bool 15161 argcheck(char *cmd, const char *full) { 15162 size_t l; 15163 15164 if (cmd == NULL || cmd[0] != '-') { 15165 return false; 15166 } 15167 15168 cmd++; 15169 l = strlen(cmd); 15170 if (l > strlen(full) || strncasecmp(cmd, full, l) != 0) { 15171 return false; 15172 } 15173 15174 return true; 15175 } 15176 15177 isc_result_t 15178 named_server_dnssec(named_server_t *server, isc_lex_t *lex, 15179 isc_buffer_t **text) { 15180 isc_result_t result = ISC_R_SUCCESS; 15181 dns_zone_t *zone = NULL; 15182 dns_kasp_t *kasp = NULL; 15183 dns_dnsseckeylist_t keys; 15184 dns_dnsseckey_t *key; 15185 char *ptr, *zonetext = NULL; 15186 const char *msg = NULL; 15187 /* variables for -step */ 15188 bool forcestep = false; 15189 /* variables for -checkds */ 15190 bool checkds = false, dspublish = false; 15191 /* variables for -rollover */ 15192 bool rollover = false; 15193 /* variables for -key */ 15194 bool use_keyid = false; 15195 dns_keytag_t keyid = 0; 15196 uint8_t algorithm = 0; 15197 /* variables for -status */ 15198 bool status = false; 15199 char output[4096]; 15200 isc_stdtime_t now, when; 15201 isc_time_t timenow, timewhen; 15202 dns_db_t *db = NULL; 15203 dns_dbversion_t *version = NULL; 15204 15205 REQUIRE(text != NULL); 15206 15207 /* Skip the command name. */ 15208 ptr = next_token(lex, text); 15209 if (ptr == NULL) { 15210 return ISC_R_UNEXPECTEDEND; 15211 } 15212 15213 /* Find out what we are to do. */ 15214 ptr = next_token(lex, text); 15215 if (ptr == NULL) { 15216 return ISC_R_UNEXPECTEDEND; 15217 } 15218 15219 /* Initialize current time and key list. */ 15220 timenow = isc_time_now(); 15221 now = isc_time_seconds(&timenow); 15222 when = now; 15223 15224 ISC_LIST_INIT(keys); 15225 15226 if (strcasecmp(ptr, "-status") == 0) { 15227 status = true; 15228 } else if (strcasecmp(ptr, "-rollover") == 0) { 15229 rollover = true; 15230 } else if (strcasecmp(ptr, "-checkds") == 0) { 15231 checkds = true; 15232 } else if (strcasecmp(ptr, "-step") == 0) { 15233 forcestep = true; 15234 } else { 15235 CHECK(DNS_R_SYNTAX); 15236 } 15237 15238 if (rollover || checkds) { 15239 /* Check for options */ 15240 for (;;) { 15241 ptr = next_token(lex, text); 15242 if (ptr == NULL) { 15243 msg = "Bad format"; 15244 CHECK(ISC_R_UNEXPECTEDEND); 15245 } else if (argcheck(ptr, "alg")) { 15246 isc_consttextregion_t alg; 15247 ptr = next_token(lex, text); 15248 if (ptr == NULL) { 15249 msg = "No key algorithm specified"; 15250 CHECK(ISC_R_UNEXPECTEDEND); 15251 } 15252 alg.base = ptr; 15253 alg.length = strlen(alg.base); 15254 result = dns_secalg_fromtext( 15255 &algorithm, (isc_textregion_t *)&alg); 15256 if (result != ISC_R_SUCCESS) { 15257 msg = "Bad algorithm"; 15258 CHECK(DNS_R_SYNTAX); 15259 } 15260 continue; 15261 } else if (argcheck(ptr, "key")) { 15262 uint16_t id; 15263 ptr = next_token(lex, text); 15264 if (ptr == NULL) { 15265 msg = "No key identifier specified"; 15266 CHECK(ISC_R_UNEXPECTEDEND); 15267 } 15268 CHECK(isc_parse_uint16(&id, ptr, 10)); 15269 keyid = (dns_keytag_t)id; 15270 use_keyid = true; 15271 continue; 15272 } else if (argcheck(ptr, "when")) { 15273 uint32_t tw; 15274 ptr = next_token(lex, text); 15275 if (ptr == NULL) { 15276 msg = "No time specified"; 15277 CHECK(ISC_R_UNEXPECTEDEND); 15278 } 15279 CHECK(dns_time32_fromtext(ptr, &tw)); 15280 when = (isc_stdtime_t)tw; 15281 continue; 15282 } else if (ptr[0] == '-') { 15283 msg = "Unknown option"; 15284 CHECK(DNS_R_SYNTAX); 15285 } else if (checkds) { 15286 /* 15287 * No arguments provided, so we must be 15288 * parsing "published|withdrawn". 15289 */ 15290 if (strcasecmp(ptr, "published") == 0) { 15291 dspublish = true; 15292 } else if (strcasecmp(ptr, "withdrawn") != 0) { 15293 CHECK(DNS_R_SYNTAX); 15294 } 15295 } else if (rollover) { 15296 /* 15297 * No arguments provided, so we must be 15298 * parsing the zone. 15299 */ 15300 zonetext = ptr; 15301 } 15302 break; 15303 } 15304 15305 if (rollover && !use_keyid) { 15306 msg = "Key id is required when scheduling rollover"; 15307 CHECK(DNS_R_SYNTAX); 15308 } 15309 15310 if (algorithm > 0 && !use_keyid) { 15311 msg = "Key id is required when setting algorithm"; 15312 CHECK(DNS_R_SYNTAX); 15313 } 15314 } 15315 15316 /* Get zone. */ 15317 CHECK(zone_from_args(server, lex, zonetext, &zone, NULL, text, false)); 15318 if (zone == NULL) { 15319 msg = "Zone not found"; 15320 CHECK(ISC_R_UNEXPECTEDEND); 15321 } 15322 15323 /* Trailing garbage? */ 15324 ptr = next_token(lex, text); 15325 if (ptr != NULL) { 15326 msg = "Too many arguments"; 15327 CHECK(DNS_R_SYNTAX); 15328 } 15329 15330 /* Get dnssec-policy. */ 15331 kasp = dns_zone_getkasp(zone); 15332 if (kasp == NULL) { 15333 msg = "Zone does not have dnssec-policy"; 15334 goto cleanup; 15335 } 15336 15337 /* Get DNSSEC keys. */ 15338 CHECK(dns_zone_getdb(zone, &db)); 15339 dns_db_currentversion(db, &version); 15340 LOCK(&kasp->lock); 15341 result = dns_zone_getdnsseckeys(zone, db, version, now, &keys); 15342 UNLOCK(&kasp->lock); 15343 if (result != ISC_R_SUCCESS) { 15344 if (result != ISC_R_NOTFOUND) { 15345 goto cleanup; 15346 } 15347 } 15348 15349 if (status) { 15350 /* 15351 * Output the DNSSEC status of the key and signing policy. 15352 */ 15353 isc_result_t r; 15354 LOCK(&kasp->lock); 15355 r = dns_keymgr_status(kasp, &keys, now, &output[0], 15356 sizeof(output)); 15357 UNLOCK(&kasp->lock); 15358 CHECK(putstr(text, output)); 15359 if (r != ISC_R_SUCCESS) { 15360 CHECK(putstr(text, 15361 "\n\nStatus output is truncated...")); 15362 } 15363 } else if (checkds) { 15364 /* 15365 * Mark DS record has been seen, so it may move to the 15366 * rumoured state. 15367 */ 15368 char whenbuf[80]; 15369 isc_time_set(&timewhen, when, 0); 15370 isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); 15371 isc_result_t ret; 15372 15373 LOCK(&kasp->lock); 15374 if (use_keyid) { 15375 result = dns_keymgr_checkds_id(kasp, &keys, now, when, 15376 dspublish, keyid, 15377 (unsigned int)algorithm); 15378 } else { 15379 result = dns_keymgr_checkds(kasp, &keys, now, when, 15380 dspublish); 15381 } 15382 UNLOCK(&kasp->lock); 15383 15384 switch (result) { 15385 case ISC_R_SUCCESS: 15386 /* 15387 * Rekey after checkds command because the next key 15388 * event may have changed. 15389 */ 15390 dns_zone_rekey(zone, false, false); 15391 15392 if (use_keyid) { 15393 char tagbuf[6]; 15394 snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); 15395 CHECK(putstr(text, "KSK ")); 15396 CHECK(putstr(text, tagbuf)); 15397 CHECK(putstr(text, ": ")); 15398 } 15399 CHECK(putstr(text, "Marked DS as ")); 15400 if (dspublish) { 15401 CHECK(putstr(text, "published ")); 15402 } else { 15403 CHECK(putstr(text, "withdrawn ")); 15404 } 15405 CHECK(putstr(text, "since ")); 15406 CHECK(putstr(text, whenbuf)); 15407 break; 15408 case DNS_R_TOOMANYKEYS: 15409 CHECK(putstr(text, 15410 "Error: multiple possible keys found, " 15411 "retry command with -key id")); 15412 break; 15413 default: 15414 ret = result; 15415 CHECK(putstr(text, 15416 "Error executing checkds command: ")); 15417 CHECK(putstr(text, isc_result_totext(ret))); 15418 break; 15419 } 15420 } else if (rollover) { 15421 /* 15422 * Manually rollover a key. 15423 */ 15424 char whenbuf[80]; 15425 isc_time_set(&timewhen, when, 0); 15426 isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); 15427 isc_result_t ret; 15428 15429 LOCK(&kasp->lock); 15430 result = dns_keymgr_rollover(kasp, &keys, now, when, keyid, 15431 (unsigned int)algorithm); 15432 UNLOCK(&kasp->lock); 15433 15434 switch (result) { 15435 case ISC_R_SUCCESS: 15436 /* 15437 * Rekey after rollover command because the next key 15438 * event may have changed. 15439 */ 15440 dns_zone_rekey(zone, false, false); 15441 15442 if (use_keyid) { 15443 char tagbuf[6]; 15444 snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); 15445 CHECK(putstr(text, "Key ")); 15446 CHECK(putstr(text, tagbuf)); 15447 CHECK(putstr(text, ": ")); 15448 } 15449 CHECK(putstr(text, "Rollover scheduled on ")); 15450 CHECK(putstr(text, whenbuf)); 15451 break; 15452 case DNS_R_TOOMANYKEYS: 15453 CHECK(putstr(text, 15454 "Error: multiple possible keys found, " 15455 "retry command with -alg algorithm")); 15456 break; 15457 default: 15458 ret = result; 15459 CHECK(putstr(text, 15460 "Error executing rollover command: ")); 15461 CHECK(putstr(text, isc_result_totext(ret))); 15462 break; 15463 } 15464 } else if (forcestep) { 15465 dns_zone_rekey(zone, false, true); 15466 } 15467 15468 CHECK(putnull(text)); 15469 15470 cleanup: 15471 if (msg != NULL) { 15472 (void)putstr(text, msg); 15473 (void)putnull(text); 15474 } 15475 15476 if (version != NULL) { 15477 dns_db_closeversion(db, &version, false); 15478 } 15479 if (db != NULL) { 15480 dns_db_detach(&db); 15481 } 15482 15483 while (!ISC_LIST_EMPTY(keys)) { 15484 key = ISC_LIST_HEAD(keys); 15485 ISC_LIST_UNLINK(keys, key, link); 15486 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key); 15487 } 15488 15489 if (zone != NULL) { 15490 dns_zone_detach(&zone); 15491 } 15492 15493 return result; 15494 } 15495 15496 static isc_result_t 15497 putmem(isc_buffer_t **b, const char *str, size_t len) { 15498 isc_result_t result; 15499 15500 result = isc_buffer_reserve(*b, (unsigned int)len); 15501 if (result != ISC_R_SUCCESS) { 15502 return ISC_R_NOSPACE; 15503 } 15504 15505 isc_buffer_putmem(*b, (const unsigned char *)str, (unsigned int)len); 15506 return ISC_R_SUCCESS; 15507 } 15508 15509 static isc_result_t 15510 putstr(isc_buffer_t **b, const char *str) { 15511 return putmem(b, str, strlen(str)); 15512 } 15513 15514 static isc_result_t 15515 putuint8(isc_buffer_t **b, uint8_t val) { 15516 isc_result_t result; 15517 15518 result = isc_buffer_reserve(*b, 1); 15519 if (result != ISC_R_SUCCESS) { 15520 return ISC_R_NOSPACE; 15521 } 15522 15523 isc_buffer_putuint8(*b, val); 15524 return ISC_R_SUCCESS; 15525 } 15526 15527 static isc_result_t 15528 putnull(isc_buffer_t **b) { 15529 return putuint8(b, 0); 15530 } 15531 15532 isc_result_t 15533 named_server_zonestatus(named_server_t *server, isc_lex_t *lex, 15534 isc_buffer_t **text) { 15535 isc_result_t result = ISC_R_SUCCESS; 15536 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; 15537 const char *type, *file; 15538 char zonename[DNS_NAME_FORMATSIZE]; 15539 uint32_t serial, signed_serial, nodes; 15540 char serbuf[16], sserbuf[16], nodebuf[16]; 15541 char resignbuf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 2]; 15542 char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15543 char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15544 char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15545 char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15546 char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15547 isc_time_t loadtime, expiretime, refreshtime; 15548 isc_time_t refreshkeytime, resigntime; 15549 dns_zonetype_t zonetype; 15550 bool dynamic = false, frozen = false; 15551 bool hasraw = false; 15552 bool secure, maintain, allow; 15553 dns_db_t *db = NULL, *rawdb = NULL; 15554 char **incfiles = NULL; 15555 int nfiles = 0; 15556 15557 REQUIRE(text != NULL); 15558 15559 isc_time_settoepoch(&loadtime); 15560 isc_time_settoepoch(&refreshtime); 15561 isc_time_settoepoch(&expiretime); 15562 isc_time_settoepoch(&refreshkeytime); 15563 isc_time_settoepoch(&resigntime); 15564 15565 CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); 15566 if (zone == NULL) { 15567 result = ISC_R_UNEXPECTEDEND; 15568 goto cleanup; 15569 } 15570 15571 /* Inline signing? */ 15572 CHECK(dns_zone_getdb(zone, &db)); 15573 dns_zone_getraw(zone, &raw); 15574 hasraw = (raw != NULL); 15575 if (hasraw) { 15576 mayberaw = raw; 15577 zonetype = dns_zone_gettype(raw); 15578 CHECK(dns_zone_getdb(raw, &rawdb)); 15579 } else { 15580 mayberaw = zone; 15581 zonetype = dns_zone_gettype(zone); 15582 } 15583 15584 type = dns_zonetype_name(zonetype); 15585 15586 /* Serial number */ 15587 result = dns_zone_getserial(mayberaw, &serial); 15588 15589 /* This is to mirror old behavior with dns_zone_getserial */ 15590 if (result != ISC_R_SUCCESS) { 15591 serial = 0; 15592 } 15593 15594 snprintf(serbuf, sizeof(serbuf), "%u", serial); 15595 if (hasraw) { 15596 result = dns_zone_getserial(zone, &signed_serial); 15597 if (result != ISC_R_SUCCESS) { 15598 serial = 0; 15599 } 15600 snprintf(sserbuf, sizeof(sserbuf), "%u", signed_serial); 15601 } 15602 15603 /* Database node count */ 15604 nodes = dns_db_nodecount(hasraw ? rawdb : db, dns_dbtree_main); 15605 snprintf(nodebuf, sizeof(nodebuf), "%u", nodes); 15606 15607 /* Security */ 15608 secure = dns_db_issecure(db); 15609 allow = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW) != 0); 15610 maintain = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0); 15611 15612 /* Master files */ 15613 file = dns_zone_getfile(mayberaw); 15614 nfiles = dns_zone_getincludes(mayberaw, &incfiles); 15615 15616 /* Load time */ 15617 dns_zone_getloadtime(zone, &loadtime); 15618 isc_time_formathttptimestamp(&loadtime, lbuf, sizeof(lbuf)); 15619 15620 /* Refresh/expire times */ 15621 if (zonetype == dns_zone_secondary || zonetype == dns_zone_mirror || 15622 zonetype == dns_zone_stub || zonetype == dns_zone_redirect) 15623 { 15624 dns_zone_getexpiretime(mayberaw, &expiretime); 15625 isc_time_formathttptimestamp(&expiretime, xbuf, sizeof(xbuf)); 15626 dns_zone_getrefreshtime(mayberaw, &refreshtime); 15627 isc_time_formathttptimestamp(&refreshtime, rbuf, sizeof(rbuf)); 15628 } 15629 15630 /* Key refresh time */ 15631 if (zonetype == dns_zone_primary || 15632 (zonetype == dns_zone_secondary && hasraw)) 15633 { 15634 dns_zone_getrefreshkeytime(zone, &refreshkeytime); 15635 isc_time_formathttptimestamp(&refreshkeytime, kbuf, 15636 sizeof(kbuf)); 15637 } 15638 15639 /* Dynamic? */ 15640 if (zonetype == dns_zone_primary) { 15641 dynamic = dns_zone_isdynamic(mayberaw, true); 15642 frozen = dynamic && !dns_zone_isdynamic(mayberaw, false); 15643 } 15644 15645 /* Next resign event */ 15646 if (secure && (zonetype == dns_zone_primary || 15647 (zonetype == dns_zone_secondary && hasraw))) 15648 { 15649 dns_name_t *name; 15650 dns_fixedname_t fixed; 15651 isc_stdtime_t resign; 15652 dns_typepair_t typepair; 15653 15654 name = dns_fixedname_initname(&fixed); 15655 15656 result = dns_db_getsigningtime(db, &resign, name, &typepair); 15657 if (result == ISC_R_SUCCESS) { 15658 char namebuf[DNS_NAME_FORMATSIZE]; 15659 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 15660 15661 resign -= dns_zone_getsigresigninginterval(zone); 15662 15663 dns_name_format(name, namebuf, sizeof(namebuf)); 15664 dns_rdatatype_format(DNS_TYPEPAIR_COVERS(typepair), 15665 typebuf, sizeof(typebuf)); 15666 snprintf(resignbuf, sizeof(resignbuf), "%s/%s", namebuf, 15667 typebuf); 15668 isc_time_set(&resigntime, resign, 0); 15669 isc_time_formathttptimestamp(&resigntime, rtbuf, 15670 sizeof(rtbuf)); 15671 } 15672 } 15673 15674 /* Create text */ 15675 CHECK(putstr(text, "name: ")); 15676 CHECK(putstr(text, zonename)); 15677 15678 CHECK(putstr(text, "\ntype: ")); 15679 CHECK(putstr(text, type)); 15680 15681 if (file != NULL) { 15682 int i; 15683 CHECK(putstr(text, "\nfiles: ")); 15684 CHECK(putstr(text, file)); 15685 for (i = 0; i < nfiles; i++) { 15686 CHECK(putstr(text, ", ")); 15687 if (incfiles[i] != NULL) { 15688 CHECK(putstr(text, incfiles[i])); 15689 } 15690 } 15691 } 15692 15693 CHECK(putstr(text, "\nserial: ")); 15694 CHECK(putstr(text, serbuf)); 15695 if (hasraw) { 15696 CHECK(putstr(text, "\nsigned serial: ")); 15697 CHECK(putstr(text, sserbuf)); 15698 } 15699 15700 CHECK(putstr(text, "\nnodes: ")); 15701 CHECK(putstr(text, nodebuf)); 15702 15703 if (!isc_time_isepoch(&loadtime)) { 15704 CHECK(putstr(text, "\nlast loaded: ")); 15705 CHECK(putstr(text, lbuf)); 15706 } 15707 15708 if (!isc_time_isepoch(&refreshtime)) { 15709 CHECK(putstr(text, "\nnext refresh: ")); 15710 CHECK(putstr(text, rbuf)); 15711 } 15712 15713 if (!isc_time_isepoch(&expiretime)) { 15714 CHECK(putstr(text, "\nexpires: ")); 15715 CHECK(putstr(text, xbuf)); 15716 } 15717 15718 if (secure) { 15719 CHECK(putstr(text, "\nsecure: yes")); 15720 if (hasraw) { 15721 CHECK(putstr(text, "\ninline signing: yes")); 15722 } else { 15723 CHECK(putstr(text, "\ninline signing: no")); 15724 } 15725 } else { 15726 CHECK(putstr(text, "\nsecure: no")); 15727 } 15728 15729 if (maintain) { 15730 CHECK(putstr(text, "\nkey maintenance: automatic")); 15731 if (!isc_time_isepoch(&refreshkeytime)) { 15732 CHECK(putstr(text, "\nnext key event: ")); 15733 CHECK(putstr(text, kbuf)); 15734 } 15735 } else if (allow) { 15736 CHECK(putstr(text, "\nkey maintenance: on command")); 15737 } else if (secure || hasraw) { 15738 CHECK(putstr(text, "\nkey maintenance: none")); 15739 } 15740 15741 if (!isc_time_isepoch(&resigntime)) { 15742 CHECK(putstr(text, "\nnext resign node: ")); 15743 CHECK(putstr(text, resignbuf)); 15744 CHECK(putstr(text, "\nnext resign time: ")); 15745 CHECK(putstr(text, rtbuf)); 15746 } 15747 15748 if (dynamic) { 15749 CHECK(putstr(text, "\ndynamic: yes")); 15750 if (frozen) { 15751 CHECK(putstr(text, "\nfrozen: yes")); 15752 } else { 15753 CHECK(putstr(text, "\nfrozen: no")); 15754 } 15755 } else { 15756 CHECK(putstr(text, "\ndynamic: no")); 15757 } 15758 15759 CHECK(putstr(text, "\nreconfigurable via modzone: ")); 15760 CHECK(putstr(text, dns_zone_getadded(zone) ? "yes" : "no")); 15761 15762 cleanup: 15763 /* Indicate truncated output if possible. */ 15764 if (result == ISC_R_NOSPACE) { 15765 (void)putstr(text, "\n..."); 15766 } 15767 if (result == ISC_R_SUCCESS || result == ISC_R_NOSPACE) { 15768 (void)putnull(text); 15769 } 15770 15771 if (db != NULL) { 15772 dns_db_detach(&db); 15773 } 15774 if (rawdb != NULL) { 15775 dns_db_detach(&rawdb); 15776 } 15777 if (incfiles != NULL && mayberaw != NULL) { 15778 int i; 15779 isc_mem_t *mctx = dns_zone_getmctx(mayberaw); 15780 15781 for (i = 0; i < nfiles; i++) { 15782 if (incfiles[i] != NULL) { 15783 isc_mem_free(mctx, incfiles[i]); 15784 } 15785 } 15786 isc_mem_free(mctx, incfiles); 15787 } 15788 if (raw != NULL) { 15789 dns_zone_detach(&raw); 15790 } 15791 if (zone != NULL) { 15792 dns_zone_detach(&zone); 15793 } 15794 return result; 15795 } 15796 15797 isc_result_t 15798 named_server_nta(named_server_t *server, isc_lex_t *lex, bool readonly, 15799 isc_buffer_t **text) { 15800 dns_view_t *view; 15801 dns_ntatable_t *ntatable = NULL; 15802 isc_result_t result = ISC_R_SUCCESS; 15803 char *ptr, *nametext = NULL, *viewname; 15804 char namebuf[DNS_NAME_FORMATSIZE]; 15805 char viewbuf[DNS_NAME_FORMATSIZE]; 15806 isc_stdtime_t now, when; 15807 isc_time_t t; 15808 char tbuf[64]; 15809 const char *msg = NULL; 15810 bool dump = false, force = false; 15811 dns_fixedname_t fn; 15812 const dns_name_t *ntaname; 15813 dns_name_t *fname; 15814 dns_ttl_t ntattl; 15815 bool ttlset = false, viewfound = false; 15816 dns_rdataclass_t rdclass = dns_rdataclass_in; 15817 bool first = true; 15818 15819 REQUIRE(text != NULL); 15820 15821 UNUSED(force); 15822 15823 fname = dns_fixedname_initname(&fn); 15824 15825 /* Skip the command name. */ 15826 ptr = next_token(lex, text); 15827 if (ptr == NULL) { 15828 return ISC_R_UNEXPECTEDEND; 15829 } 15830 15831 for (;;) { 15832 /* Check for options */ 15833 ptr = next_token(lex, text); 15834 if (ptr == NULL) { 15835 return ISC_R_UNEXPECTEDEND; 15836 } 15837 15838 if (strcmp(ptr, "--") == 0) { 15839 break; 15840 } else if (argcheck(ptr, "dump")) { 15841 dump = true; 15842 } else if (argcheck(ptr, "remove")) { 15843 ntattl = 0; 15844 ttlset = true; 15845 } else if (argcheck(ptr, "force")) { 15846 force = true; 15847 continue; 15848 } else if (argcheck(ptr, "lifetime")) { 15849 isc_textregion_t tr; 15850 15851 ptr = next_token(lex, text); 15852 if (ptr == NULL) { 15853 msg = "No lifetime specified"; 15854 CHECK(ISC_R_UNEXPECTEDEND); 15855 } 15856 15857 tr.base = ptr; 15858 tr.length = strlen(ptr); 15859 result = dns_ttl_fromtext(&tr, &ntattl); 15860 if (result != ISC_R_SUCCESS) { 15861 msg = "could not parse NTA lifetime"; 15862 CHECK(result); 15863 } 15864 15865 if (ntattl > 604800) { 15866 msg = "NTA lifetime cannot exceed one week"; 15867 CHECK(ISC_R_RANGE); 15868 } 15869 15870 ttlset = true; 15871 continue; 15872 } else if (argcheck(ptr, "class")) { 15873 isc_textregion_t tr; 15874 15875 ptr = next_token(lex, text); 15876 if (ptr == NULL) { 15877 msg = "No class specified"; 15878 CHECK(ISC_R_UNEXPECTEDEND); 15879 } 15880 15881 tr.base = ptr; 15882 tr.length = strlen(ptr); 15883 CHECK(dns_rdataclass_fromtext(&rdclass, &tr)); 15884 continue; 15885 } else if (ptr[0] == '-') { 15886 msg = "Unknown option"; 15887 CHECK(DNS_R_SYNTAX); 15888 } else { 15889 nametext = ptr; 15890 } 15891 15892 break; 15893 } 15894 15895 /* 15896 * If -dump was specified, list NTA's and return 15897 */ 15898 if (dump) { 15899 size_t last = 0; 15900 15901 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15902 view = ISC_LIST_NEXT(view, link)) 15903 { 15904 if (ntatable != NULL) { 15905 dns_ntatable_detach(&ntatable); 15906 } 15907 result = dns_view_getntatable(view, &ntatable); 15908 if (result == ISC_R_NOTFOUND) { 15909 continue; 15910 } 15911 15912 if (last != isc_buffer_usedlength(*text)) { 15913 CHECK(putstr(text, "\n")); 15914 } 15915 15916 last = isc_buffer_usedlength(*text); 15917 15918 CHECK(dns_ntatable_totext(ntatable, view->name, text)); 15919 } 15920 CHECK(putnull(text)); 15921 15922 goto cleanup; 15923 } 15924 15925 if (readonly) { 15926 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15927 NAMED_LOGMODULE_CONTROL, ISC_LOG_INFO, 15928 "rejecting restricted control channel " 15929 "NTA command"); 15930 CHECK(ISC_R_FAILURE); 15931 } 15932 15933 /* Get the NTA name if not found above. */ 15934 if (nametext == NULL) { 15935 nametext = next_token(lex, text); 15936 } 15937 if (nametext == NULL) { 15938 return ISC_R_UNEXPECTEDEND; 15939 } 15940 15941 /* Copy nametext as it'll be overwritten by next_token() */ 15942 strlcpy(namebuf, nametext, DNS_NAME_FORMATSIZE); 15943 15944 if (strcmp(namebuf, ".") == 0) { 15945 ntaname = dns_rootname; 15946 } else { 15947 isc_buffer_t b; 15948 isc_buffer_init(&b, namebuf, strlen(namebuf)); 15949 isc_buffer_add(&b, strlen(namebuf)); 15950 CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0, NULL)); 15951 ntaname = fname; 15952 } 15953 15954 /* Look for the view name. */ 15955 viewname = next_token(lex, text); 15956 if (viewname != NULL) { 15957 strlcpy(viewbuf, viewname, DNS_NAME_FORMATSIZE); 15958 viewname = viewbuf; 15959 } 15960 15961 if (next_token(lex, text) != NULL) { 15962 CHECK(DNS_R_SYNTAX); 15963 } 15964 15965 now = isc_stdtime_now(); 15966 15967 isc_loopmgr_pause(named_g_loopmgr); 15968 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15969 view = ISC_LIST_NEXT(view, link)) 15970 { 15971 if (viewname != NULL && strcmp(view->name, viewname) != 0) { 15972 continue; 15973 } 15974 viewfound = true; 15975 15976 if (view->rdclass != rdclass && rdclass != dns_rdataclass_any) { 15977 continue; 15978 } 15979 15980 if (view->nta_lifetime == 0) { 15981 continue; 15982 } 15983 15984 if (!ttlset) { 15985 ntattl = view->nta_lifetime; 15986 } 15987 15988 if (ntatable != NULL) { 15989 dns_ntatable_detach(&ntatable); 15990 } 15991 15992 result = dns_view_getntatable(view, &ntatable); 15993 if (result == ISC_R_NOTFOUND) { 15994 result = ISC_R_SUCCESS; 15995 continue; 15996 } 15997 15998 result = dns_view_flushnode(view, ntaname, true); 15999 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16000 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16001 "flush tree '%s' in cache view '%s': %s", namebuf, 16002 view->name, isc_result_totext(result)); 16003 16004 if (ntattl != 0) { 16005 CHECK(dns_ntatable_add(ntatable, ntaname, force, now, 16006 ntattl)); 16007 16008 when = now + ntattl; 16009 isc_time_set(&t, when, 0); 16010 isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); 16011 16012 if (!first) { 16013 CHECK(putstr(text, "\n")); 16014 } 16015 first = false; 16016 16017 CHECK(putstr(text, "Negative trust anchor added: ")); 16018 CHECK(putstr(text, namebuf)); 16019 CHECK(putstr(text, "/")); 16020 CHECK(putstr(text, view->name)); 16021 CHECK(putstr(text, ", expires ")); 16022 CHECK(putstr(text, tbuf)); 16023 16024 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16025 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16026 "added NTA '%s' (%d sec) in view '%s'", 16027 namebuf, ntattl, view->name); 16028 } else { 16029 bool wasremoved; 16030 16031 result = dns_ntatable_delete(ntatable, ntaname); 16032 if (result == ISC_R_SUCCESS) { 16033 wasremoved = true; 16034 } else if (result == ISC_R_NOTFOUND) { 16035 wasremoved = false; 16036 } else { 16037 goto cleanup_exclusive; 16038 } 16039 16040 if (!first) { 16041 CHECK(putstr(text, "\n")); 16042 } 16043 first = false; 16044 16045 CHECK(putstr(text, "Negative trust anchor ")); 16046 CHECK(putstr(text, 16047 wasremoved ? "removed: " : "not found: ")); 16048 CHECK(putstr(text, namebuf)); 16049 CHECK(putstr(text, "/")); 16050 CHECK(putstr(text, view->name)); 16051 16052 if (wasremoved) { 16053 isc_log_write( 16054 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16055 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16056 "removed NTA '%s' in view %s", namebuf, 16057 view->name); 16058 } 16059 } 16060 16061 result = dns_view_saventa(view); 16062 if (result != ISC_R_SUCCESS) { 16063 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16064 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16065 "error writing NTA file " 16066 "for view '%s': %s", 16067 view->name, isc_result_totext(result)); 16068 } 16069 } 16070 16071 if (!viewfound) { 16072 msg = "No such view"; 16073 result = ISC_R_NOTFOUND; 16074 } else { 16075 (void)putnull(text); 16076 } 16077 16078 cleanup_exclusive: 16079 isc_loopmgr_resume(named_g_loopmgr); 16080 16081 cleanup: 16082 16083 if (msg != NULL) { 16084 (void)putstr(text, msg); 16085 (void)putnull(text); 16086 } 16087 16088 if (ntatable != NULL) { 16089 dns_ntatable_detach(&ntatable); 16090 } 16091 return result; 16092 } 16093 16094 isc_result_t 16095 named_server_saventa(named_server_t *server) { 16096 dns_view_t *view; 16097 16098 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16099 view = ISC_LIST_NEXT(view, link)) 16100 { 16101 isc_result_t result = dns_view_saventa(view); 16102 16103 if (result != ISC_R_SUCCESS) { 16104 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16105 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16106 "error writing NTA file " 16107 "for view '%s': %s", 16108 view->name, isc_result_totext(result)); 16109 } 16110 } 16111 16112 return ISC_R_SUCCESS; 16113 } 16114 16115 isc_result_t 16116 named_server_loadnta(named_server_t *server) { 16117 dns_view_t *view; 16118 16119 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16120 view = ISC_LIST_NEXT(view, link)) 16121 { 16122 isc_result_t result = dns_view_loadnta(view); 16123 16124 if ((result != ISC_R_SUCCESS) && 16125 (result != ISC_R_FILENOTFOUND) && 16126 (result != ISC_R_NOTFOUND)) 16127 { 16128 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16129 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16130 "error loading NTA file " 16131 "for view '%s': %s", 16132 view->name, isc_result_totext(result)); 16133 } 16134 } 16135 16136 return ISC_R_SUCCESS; 16137 } 16138 16139 static isc_result_t 16140 mkey_refresh(dns_view_t *view, isc_buffer_t **text) { 16141 isc_result_t result; 16142 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16143 16144 snprintf(msg, sizeof(msg), "refreshing managed keys for '%s'", 16145 view->name); 16146 CHECK(putstr(text, msg)); 16147 CHECK(dns_zone_synckeyzone(view->managed_keys)); 16148 16149 cleanup: 16150 return result; 16151 } 16152 16153 static isc_result_t 16154 mkey_destroy(dns_view_t *view, isc_buffer_t **text) { 16155 isc_result_t result; 16156 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16157 const char *file = NULL; 16158 dns_db_t *dbp = NULL; 16159 dns_zone_t *mkzone = NULL; 16160 bool removed_a_file = false; 16161 16162 if (view->managed_keys == NULL) { 16163 CHECK(ISC_R_NOTFOUND); 16164 } 16165 16166 snprintf(msg, sizeof(msg), "destroying managed-keys database for '%s'", 16167 view->name); 16168 CHECK(putstr(text, msg)); 16169 16170 isc_loopmgr_pause(named_g_loopmgr); 16171 16172 /* Remove and clean up managed keys zone from view */ 16173 mkzone = view->managed_keys; 16174 view->managed_keys = NULL; 16175 (void)dns_zone_flush(mkzone); 16176 16177 /* Unload zone database */ 16178 if (dns_zone_getdb(mkzone, &dbp) == ISC_R_SUCCESS) { 16179 dns_db_detach(&dbp); 16180 dns_zone_unload(mkzone); 16181 } 16182 16183 /* Delete files */ 16184 file = dns_zone_getfile(mkzone); 16185 result = isc_file_remove(file); 16186 if (result == ISC_R_SUCCESS) { 16187 removed_a_file = true; 16188 } else { 16189 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16190 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 16191 "file %s not removed: %s", file, 16192 isc_result_totext(result)); 16193 } 16194 16195 file = dns_zone_getjournal(mkzone); 16196 result = isc_file_remove(file); 16197 if (result == ISC_R_SUCCESS) { 16198 removed_a_file = true; 16199 } else { 16200 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16201 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 16202 "file %s not removed: %s", file, 16203 isc_result_totext(result)); 16204 } 16205 16206 if (!removed_a_file) { 16207 CHECK(putstr(text, "error: no files could be removed")); 16208 CHECK(ISC_R_FAILURE); 16209 } 16210 16211 dns_zone_detach(&mkzone); 16212 result = ISC_R_SUCCESS; 16213 16214 cleanup: 16215 isc_loopmgr_resume(named_g_loopmgr); 16216 return result; 16217 } 16218 16219 static isc_result_t 16220 mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) { 16221 isc_result_t result; 16222 dns_db_t *db = NULL; 16223 dns_dbversion_t *ver = NULL; 16224 dns_rriterator_t rrit; 16225 isc_stdtime_t now = isc_stdtime_now(); 16226 dns_name_t *prevname = NULL; 16227 16228 CHECK(dns_zone_getdb(view->managed_keys, &db)); 16229 dns_db_currentversion(db, &ver); 16230 dns_rriterator_init(&rrit, db, ver, 0); 16231 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS; 16232 result = dns_rriterator_nextrrset(&rrit)) 16233 { 16234 char buf[DNS_NAME_FORMATSIZE + 500]; 16235 dns_name_t *name = NULL; 16236 dns_rdataset_t *kdset = NULL; 16237 dns_rdata_t rdata = DNS_RDATA_INIT; 16238 dns_rdata_keydata_t kd; 16239 uint32_t ttl; 16240 16241 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL); 16242 if (kdset == NULL || kdset->type != dns_rdatatype_keydata || 16243 !dns_rdataset_isassociated(kdset)) 16244 { 16245 continue; 16246 } 16247 16248 if (name != prevname) { 16249 char nbuf[DNS_NAME_FORMATSIZE]; 16250 dns_name_format(name, nbuf, sizeof(nbuf)); 16251 snprintf(buf, sizeof(buf), "\n\n name: %s", nbuf); 16252 CHECK(putstr(text, buf)); 16253 } 16254 16255 for (result = dns_rdataset_first(kdset); 16256 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset)) 16257 { 16258 char alg[DNS_SECALG_FORMATSIZE]; 16259 char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 16260 dns_keytag_t keyid; 16261 isc_region_t r; 16262 isc_time_t t; 16263 bool revoked; 16264 16265 dns_rdata_reset(&rdata); 16266 dns_rdataset_current(kdset, &rdata); 16267 result = dns_rdata_tostruct(&rdata, &kd, NULL); 16268 RUNTIME_CHECK(result == ISC_R_SUCCESS); 16269 16270 dns_rdata_toregion(&rdata, &r); 16271 isc_region_consume(&r, 12); 16272 keyid = dst_region_computeid(&r); 16273 16274 snprintf(buf, sizeof(buf), "\n keyid: %u", keyid); 16275 CHECK(putstr(text, buf)); 16276 16277 dns_secalg_format(kd.algorithm, alg, sizeof(alg)); 16278 snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg); 16279 CHECK(putstr(text, buf)); 16280 16281 revoked = ((kd.flags & DNS_KEYFLAG_REVOKE) != 0); 16282 snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s", 16283 revoked ? " REVOKE" : "", 16284 ((kd.flags & DNS_KEYFLAG_KSK) != 0) ? " SEP" 16285 : "", 16286 (kd.flags == 0) ? " (none)" : ""); 16287 CHECK(putstr(text, buf)); 16288 16289 isc_time_set(&t, kd.refresh, 0); 16290 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); 16291 snprintf(buf, sizeof(buf), "\n\tnext refresh: %s", 16292 tbuf); 16293 CHECK(putstr(text, buf)); 16294 16295 if (kd.removehd != 0) { 16296 isc_time_set(&t, kd.removehd, 0); 16297 isc_time_formathttptimestamp(&t, tbuf, 16298 sizeof(tbuf)); 16299 snprintf(buf, sizeof(buf), "\n\tremove at: %s", 16300 tbuf); 16301 CHECK(putstr(text, buf)); 16302 } 16303 16304 isc_time_set(&t, kd.addhd, 0); 16305 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); 16306 if (kd.addhd == 0) { 16307 snprintf(buf, sizeof(buf), "\n\tno trust"); 16308 } else if (revoked) { 16309 snprintf(buf, sizeof(buf), "\n\ttrust revoked"); 16310 } else if (kd.addhd <= now) { 16311 snprintf(buf, sizeof(buf), 16312 "\n\ttrusted since: %s", tbuf); 16313 } else if (kd.addhd > now) { 16314 snprintf(buf, sizeof(buf), 16315 "\n\ttrust pending: %s", tbuf); 16316 } 16317 CHECK(putstr(text, buf)); 16318 } 16319 } 16320 16321 if (result == ISC_R_NOMORE) { 16322 result = ISC_R_SUCCESS; 16323 } 16324 16325 cleanup: 16326 if (ver != NULL) { 16327 dns_rriterator_destroy(&rrit); 16328 dns_db_closeversion(db, &ver, false); 16329 } 16330 if (db != NULL) { 16331 dns_db_detach(&db); 16332 } 16333 16334 return result; 16335 } 16336 16337 static isc_result_t 16338 mkey_status(dns_view_t *view, isc_buffer_t **text) { 16339 isc_result_t result; 16340 char msg[ISC_FORMATHTTPTIMESTAMP_SIZE]; 16341 isc_time_t t; 16342 16343 CHECK(putstr(text, "view: ")); 16344 CHECK(putstr(text, view->name)); 16345 16346 CHECK(putstr(text, "\nnext scheduled event: ")); 16347 16348 dns_zone_getrefreshkeytime(view->managed_keys, &t); 16349 if (isc_time_isepoch(&t)) { 16350 CHECK(putstr(text, "never")); 16351 } else { 16352 isc_time_formathttptimestamp(&t, msg, sizeof(msg)); 16353 CHECK(putstr(text, msg)); 16354 } 16355 16356 CHECK(mkey_dumpzone(view, text)); 16357 16358 cleanup: 16359 return result; 16360 } 16361 16362 isc_result_t 16363 named_server_mkeys(named_server_t *server, isc_lex_t *lex, 16364 isc_buffer_t **text) { 16365 char *cmd, *classtxt, *viewtxt = NULL; 16366 isc_result_t result = ISC_R_SUCCESS; 16367 dns_view_t *view = NULL; 16368 dns_rdataclass_t rdclass; 16369 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16370 enum { NONE, STAT, REFRESH, SYNC, DESTROY } opt = NONE; 16371 bool found = false; 16372 bool first = true; 16373 16374 REQUIRE(text != NULL); 16375 16376 /* Skip rndc command name */ 16377 cmd = next_token(lex, text); 16378 if (cmd == NULL) { 16379 return ISC_R_UNEXPECTEDEND; 16380 } 16381 16382 /* Get managed-keys subcommand */ 16383 cmd = next_token(lex, text); 16384 if (cmd == NULL) { 16385 return ISC_R_UNEXPECTEDEND; 16386 } 16387 16388 if (strcasecmp(cmd, "status") == 0) { 16389 opt = STAT; 16390 } else if (strcasecmp(cmd, "refresh") == 0) { 16391 opt = REFRESH; 16392 } else if (strcasecmp(cmd, "sync") == 0) { 16393 opt = SYNC; 16394 } else if (strcasecmp(cmd, "destroy") == 0) { 16395 opt = DESTROY; 16396 } else { 16397 snprintf(msg, sizeof(msg), "unknown command '%s'", cmd); 16398 (void)putstr(text, msg); 16399 result = ISC_R_UNEXPECTED; 16400 goto cleanup; 16401 } 16402 16403 /* Look for the optional class name. */ 16404 classtxt = next_token(lex, text); 16405 if (classtxt != NULL) { 16406 isc_textregion_t r; 16407 r.base = classtxt; 16408 r.length = strlen(classtxt); 16409 result = dns_rdataclass_fromtext(&rdclass, &r); 16410 if (result != ISC_R_SUCCESS) { 16411 snprintf(msg, sizeof(msg), "unknown class '%s'", 16412 classtxt); 16413 (void)putstr(text, msg); 16414 goto cleanup; 16415 } 16416 viewtxt = next_token(lex, text); 16417 } 16418 16419 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16420 view = ISC_LIST_NEXT(view, link)) 16421 { 16422 if (viewtxt != NULL && (rdclass != view->rdclass || 16423 strcmp(view->name, viewtxt) != 0)) 16424 { 16425 continue; 16426 } 16427 16428 if (view->managed_keys == NULL) { 16429 if (viewtxt != NULL) { 16430 snprintf(msg, sizeof(msg), 16431 "view '%s': no managed keys", viewtxt); 16432 CHECK(putstr(text, msg)); 16433 goto cleanup; 16434 } else { 16435 continue; 16436 } 16437 } 16438 16439 found = true; 16440 16441 switch (opt) { 16442 case REFRESH: 16443 if (!first) { 16444 CHECK(putstr(text, "\n")); 16445 } 16446 CHECK(mkey_refresh(view, text)); 16447 break; 16448 case STAT: 16449 if (!first) { 16450 CHECK(putstr(text, "\n\n")); 16451 } 16452 CHECK(mkey_status(view, text)); 16453 break; 16454 case SYNC: 16455 CHECK(dns_zone_flush(view->managed_keys)); 16456 break; 16457 case DESTROY: 16458 if (!first) { 16459 CHECK(putstr(text, "\n")); 16460 } 16461 CHECK(mkey_destroy(view, text)); 16462 break; 16463 default: 16464 UNREACHABLE(); 16465 } 16466 16467 if (viewtxt != NULL) { 16468 break; 16469 } 16470 first = false; 16471 } 16472 16473 if (!found) { 16474 CHECK(putstr(text, "no views with managed keys")); 16475 } 16476 16477 cleanup: 16478 if (isc_buffer_usedlength(*text) > 0) { 16479 (void)putnull(text); 16480 } 16481 16482 return result; 16483 } 16484 16485 isc_result_t 16486 named_server_dnstap(named_server_t *server, isc_lex_t *lex, 16487 isc_buffer_t **text) { 16488 #ifdef HAVE_DNSTAP 16489 char *ptr; 16490 isc_result_t result; 16491 bool reopen = false; 16492 int backups = 0; 16493 16494 REQUIRE(text != NULL); 16495 16496 if (server->dtenv == NULL) { 16497 return ISC_R_NOTFOUND; 16498 } 16499 16500 /* Check the command name. */ 16501 ptr = next_token(lex, text); 16502 if (ptr == NULL) { 16503 return ISC_R_UNEXPECTEDEND; 16504 } 16505 16506 /* "dnstap-reopen" was used in 9.11.0b1 */ 16507 if (strcasecmp(ptr, "dnstap-reopen") == 0) { 16508 reopen = true; 16509 } else { 16510 ptr = next_token(lex, text); 16511 if (ptr == NULL) { 16512 return ISC_R_UNEXPECTEDEND; 16513 } 16514 } 16515 16516 if (reopen || strcasecmp(ptr, "-reopen") == 0) { 16517 backups = ISC_LOG_ROLLNEVER; 16518 } else if (strcasecmp(ptr, "-roll") == 0) { 16519 unsigned int n; 16520 ptr = next_token(lex, text); 16521 if (ptr != NULL) { 16522 unsigned int u; 16523 n = sscanf(ptr, "%u", &u); 16524 if (n != 1U || u > INT_MAX) { 16525 return ISC_R_BADNUMBER; 16526 } 16527 backups = u; 16528 } else { 16529 backups = ISC_LOG_ROLLINFINITE; 16530 } 16531 } else { 16532 return DNS_R_SYNTAX; 16533 } 16534 16535 result = dns_dt_reopen(server->dtenv, backups); 16536 return result; 16537 #else /* ifdef HAVE_DNSTAP */ 16538 UNUSED(server); 16539 UNUSED(lex); 16540 UNUSED(text); 16541 return ISC_R_NOTIMPLEMENTED; 16542 #endif /* ifdef HAVE_DNSTAP */ 16543 } 16544 16545 isc_result_t 16546 named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) { 16547 char *ptr; 16548 isc_result_t result = ISC_R_SUCCESS; 16549 uint32_t initial, idle, keepalive, advertised; 16550 char msg[128]; 16551 16552 /* Skip the command name. */ 16553 ptr = next_token(lex, text); 16554 if (ptr == NULL) { 16555 return ISC_R_UNEXPECTEDEND; 16556 } 16557 16558 isc_nm_gettimeouts(named_g_netmgr, &initial, &idle, &keepalive, 16559 &advertised); 16560 16561 /* Look for optional arguments. */ 16562 ptr = next_token(lex, NULL); 16563 if (ptr != NULL) { 16564 CHECK(isc_parse_uint32(&initial, ptr, 10)); 16565 initial *= 100; 16566 if (initial > MAX_INITIAL_TIMEOUT) { 16567 CHECK(ISC_R_RANGE); 16568 } 16569 if (initial < MIN_INITIAL_TIMEOUT) { 16570 CHECK(ISC_R_RANGE); 16571 } 16572 16573 ptr = next_token(lex, text); 16574 if (ptr == NULL) { 16575 return ISC_R_UNEXPECTEDEND; 16576 } 16577 CHECK(isc_parse_uint32(&idle, ptr, 10)); 16578 idle *= 100; 16579 if (idle > MAX_IDLE_TIMEOUT) { 16580 CHECK(ISC_R_RANGE); 16581 } 16582 if (idle < MIN_IDLE_TIMEOUT) { 16583 CHECK(ISC_R_RANGE); 16584 } 16585 16586 ptr = next_token(lex, text); 16587 if (ptr == NULL) { 16588 return ISC_R_UNEXPECTEDEND; 16589 } 16590 CHECK(isc_parse_uint32(&keepalive, ptr, 10)); 16591 keepalive *= 100; 16592 if (keepalive > MAX_KEEPALIVE_TIMEOUT) { 16593 CHECK(ISC_R_RANGE); 16594 } 16595 if (keepalive < MIN_KEEPALIVE_TIMEOUT) { 16596 CHECK(ISC_R_RANGE); 16597 } 16598 16599 ptr = next_token(lex, text); 16600 if (ptr == NULL) { 16601 return ISC_R_UNEXPECTEDEND; 16602 } 16603 CHECK(isc_parse_uint32(&advertised, ptr, 10)); 16604 advertised *= 100; 16605 if (advertised > MAX_ADVERTISED_TIMEOUT) { 16606 CHECK(ISC_R_RANGE); 16607 } 16608 16609 isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, 16610 advertised); 16611 } 16612 16613 snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial / 100); 16614 CHECK(putstr(text, msg)); 16615 snprintf(msg, sizeof(msg), "tcp-idle-timeout=%u\n", idle / 100); 16616 CHECK(putstr(text, msg)); 16617 snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n", 16618 keepalive / 100); 16619 CHECK(putstr(text, msg)); 16620 snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u", 16621 advertised / 100); 16622 CHECK(putstr(text, msg)); 16623 16624 cleanup: 16625 if (isc_buffer_usedlength(*text) > 0) { 16626 (void)putnull(text); 16627 } 16628 16629 return result; 16630 } 16631 16632 isc_result_t 16633 named_server_servestale(named_server_t *server, isc_lex_t *lex, 16634 isc_buffer_t **text) { 16635 char *ptr, *classtxt, *viewtxt = NULL; 16636 char msg[128]; 16637 dns_rdataclass_t rdclass = dns_rdataclass_in; 16638 dns_view_t *view; 16639 bool found = false; 16640 dns_stale_answer_t staleanswersok = dns_stale_answer_conf; 16641 bool wantstatus = false; 16642 isc_result_t result = ISC_R_SUCCESS; 16643 16644 REQUIRE(text != NULL); 16645 16646 /* Skip the command name. */ 16647 ptr = next_token(lex, text); 16648 if (ptr == NULL) { 16649 return ISC_R_UNEXPECTEDEND; 16650 } 16651 16652 ptr = next_token(lex, NULL); 16653 if (ptr == NULL) { 16654 return ISC_R_UNEXPECTEDEND; 16655 } 16656 16657 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 16658 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 16659 { 16660 staleanswersok = dns_stale_answer_yes; 16661 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 16662 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 16663 { 16664 staleanswersok = dns_stale_answer_no; 16665 } else if (strcasecmp(ptr, "reset") == 0) { 16666 staleanswersok = dns_stale_answer_conf; 16667 } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { 16668 wantstatus = true; 16669 } else { 16670 return DNS_R_SYNTAX; 16671 } 16672 16673 /* Look for the optional class name. */ 16674 classtxt = next_token(lex, text); 16675 if (classtxt != NULL) { 16676 isc_textregion_t r; 16677 16678 /* Look for the optional view name. */ 16679 viewtxt = next_token(lex, text); 16680 16681 /* 16682 * If 'classtext' is not a valid class then it us a view name. 16683 */ 16684 r.base = classtxt; 16685 r.length = strlen(classtxt); 16686 result = dns_rdataclass_fromtext(&rdclass, &r); 16687 if (result != ISC_R_SUCCESS) { 16688 if (viewtxt != NULL) { 16689 snprintf(msg, sizeof(msg), "unknown class '%s'", 16690 classtxt); 16691 (void)putstr(text, msg); 16692 goto cleanup; 16693 } 16694 16695 viewtxt = classtxt; 16696 classtxt = NULL; 16697 } 16698 } 16699 16700 isc_loopmgr_pause(named_g_loopmgr); 16701 16702 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16703 view = ISC_LIST_NEXT(view, link)) 16704 { 16705 dns_ttl_t stale_ttl = 0; 16706 uint32_t stale_refresh = 0; 16707 dns_db_t *db = NULL; 16708 16709 if (classtxt != NULL && rdclass != view->rdclass) { 16710 continue; 16711 } 16712 16713 if (viewtxt != NULL && strcmp(view->name, viewtxt) != 0) { 16714 continue; 16715 } 16716 16717 if (!wantstatus) { 16718 view->staleanswersok = staleanswersok; 16719 found = true; 16720 continue; 16721 } 16722 16723 db = NULL; 16724 dns_db_attach(view->cachedb, &db); 16725 (void)dns_db_getservestalettl(db, &stale_ttl); 16726 (void)dns_db_getservestalerefresh(db, &stale_refresh); 16727 dns_db_detach(&db); 16728 if (found) { 16729 CHECK(putstr(text, "\n")); 16730 } 16731 CHECK(putstr(text, view->name)); 16732 CHECK(putstr(text, ": ")); 16733 switch (view->staleanswersok) { 16734 case dns_stale_answer_yes: 16735 if (stale_ttl > 0) { 16736 CHECK(putstr(text, "stale cache " 16737 "enabled; stale " 16738 "answers enabled")); 16739 } else { 16740 CHECK(putstr(text, "stale cache disabled; " 16741 "stale " 16742 "answers unavailable")); 16743 } 16744 break; 16745 case dns_stale_answer_no: 16746 if (stale_ttl > 0) { 16747 CHECK(putstr(text, "stale cache " 16748 "enabled; stale " 16749 "answers disabled")); 16750 } else { 16751 CHECK(putstr(text, "stale cache disabled; " 16752 "stale " 16753 "answers unavailable")); 16754 } 16755 break; 16756 case dns_stale_answer_conf: 16757 if (view->staleanswersenable && stale_ttl > 0) { 16758 CHECK(putstr(text, "stale cache " 16759 "enabled; stale " 16760 "answers enabled")); 16761 } else if (stale_ttl > 0) { 16762 CHECK(putstr(text, "stale cache " 16763 "enabled; stale " 16764 "answers disabled")); 16765 } else { 16766 CHECK(putstr(text, "stale cache disabled; " 16767 "stale " 16768 "answers unavailable")); 16769 } 16770 break; 16771 } 16772 if (stale_ttl > 0) { 16773 snprintf(msg, sizeof(msg), 16774 " (stale-answer-ttl=%u " 16775 "max-stale-ttl=%u " 16776 "stale-refresh-time=%u)", 16777 view->staleanswerttl, stale_ttl, 16778 stale_refresh); 16779 CHECK(putstr(text, msg)); 16780 } 16781 found = true; 16782 } 16783 16784 if (!found) { 16785 result = ISC_R_NOTFOUND; 16786 } 16787 16788 cleanup: 16789 isc_loopmgr_resume(named_g_loopmgr); 16790 16791 if (isc_buffer_usedlength(*text) > 0) { 16792 (void)putnull(text); 16793 } 16794 16795 return result; 16796 } 16797 16798 isc_result_t 16799 named_server_fetchlimit(named_server_t *server, isc_lex_t *lex, 16800 isc_buffer_t **text) { 16801 isc_result_t result = ISC_R_SUCCESS; 16802 dns_view_t *view = NULL; 16803 char *ptr = NULL, *viewname = NULL; 16804 bool first = true; 16805 dns_adb_t *adb = NULL; 16806 16807 REQUIRE(text != NULL); 16808 16809 /* Skip the command name. */ 16810 ptr = next_token(lex, text); 16811 if (ptr == NULL) { 16812 return ISC_R_UNEXPECTEDEND; 16813 } 16814 16815 /* Look for the view name. */ 16816 viewname = next_token(lex, text); 16817 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16818 view = ISC_LIST_NEXT(view, link)) 16819 { 16820 char tbuf[100]; 16821 unsigned int used; 16822 uint32_t val; 16823 int s; 16824 16825 if (view->rdclass != dns_rdataclass_in) { 16826 continue; 16827 } 16828 16829 if (viewname != NULL && strcasecmp(view->name, viewname) != 0) { 16830 continue; 16831 } 16832 16833 dns_view_getadb(view, &adb); 16834 if (adb == NULL) { 16835 continue; 16836 } 16837 16838 if (!first) { 16839 CHECK(putstr(text, "\n")); 16840 } 16841 CHECK(putstr(text, "Rate limited servers, view ")); 16842 CHECK(putstr(text, view->name)); 16843 16844 dns_adb_getquota(adb, &val, NULL, NULL, NULL, NULL); 16845 s = snprintf(tbuf, sizeof(tbuf), 16846 " (fetches-per-server %u):", val); 16847 if (s < 0 || (unsigned int)s > sizeof(tbuf)) { 16848 CHECK(ISC_R_NOSPACE); 16849 } 16850 first = false; 16851 CHECK(putstr(text, tbuf)); 16852 used = isc_buffer_usedlength(*text); 16853 CHECK(dns_adb_dumpquota(adb, text)); 16854 if (used == isc_buffer_usedlength(*text)) { 16855 CHECK(putstr(text, "\n None.")); 16856 } 16857 16858 CHECK(putstr(text, "\nRate limited servers, view ")); 16859 CHECK(putstr(text, view->name)); 16860 val = dns_resolver_getfetchesperzone(view->resolver); 16861 s = snprintf(tbuf, sizeof(tbuf), 16862 " (fetches-per-zone %u):", val); 16863 if (s < 0 || (unsigned int)s > sizeof(tbuf)) { 16864 CHECK(ISC_R_NOSPACE); 16865 } 16866 CHECK(putstr(text, tbuf)); 16867 used = isc_buffer_usedlength(*text); 16868 CHECK(dns_resolver_dumpquota(view->resolver, text)); 16869 if (used == isc_buffer_usedlength(*text)) { 16870 CHECK(putstr(text, "\n None.")); 16871 } 16872 dns_adb_detach(&adb); 16873 } 16874 cleanup: 16875 if (adb != NULL) { 16876 dns_adb_detach(&adb); 16877 } 16878 if (isc_buffer_usedlength(*text) > 0) { 16879 (void)putnull(text); 16880 } 16881 16882 return result; 16883 } 16884 16885 isc_result_t 16886 named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { 16887 isc_result_t result = ISC_R_SUCCESS; 16888 dns_zone_t *zone = NULL; 16889 dns_kasp_t *kasp = NULL; 16890 const char *ptr; 16891 char skrfile[PATH_MAX]; 16892 16893 /* Skip the command name. */ 16894 ptr = next_token(lex, text); 16895 if (ptr == NULL) { 16896 return ISC_R_UNEXPECTEDEND; 16897 } 16898 16899 /* Find out what we are to do. */ 16900 ptr = next_token(lex, text); 16901 if (ptr == NULL) { 16902 return ISC_R_UNEXPECTEDEND; 16903 } 16904 16905 if (strcasecmp(ptr, "-import") != 0) { 16906 CHECK(DNS_R_SYNTAX); 16907 } 16908 16909 ptr = next_token(lex, NULL); 16910 if (ptr == NULL) { 16911 return ISC_R_UNEXPECTEDEND; 16912 } 16913 (void)snprintf(skrfile, sizeof(skrfile), "%s", ptr); 16914 16915 CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); 16916 if (zone == NULL) { 16917 CHECK(ISC_R_UNEXPECTEDEND); 16918 } 16919 kasp = dns_zone_getkasp(zone); 16920 if (kasp == NULL) { 16921 CHECK(putstr(text, "zone does not have a dnssec-policy")); 16922 CHECK(putnull(text)); 16923 goto cleanup; 16924 } 16925 16926 if (!dns_kasp_offlineksk(kasp)) { 16927 CHECK(putstr(text, "zone does not have offline-ksk enabled")); 16928 CHECK(putnull(text)); 16929 goto cleanup; 16930 } 16931 16932 result = dns_zone_import_skr(zone, skrfile); 16933 if (result != ISC_R_SUCCESS) { 16934 CHECK(putstr(text, "import failed: ")); 16935 CHECK(putstr(text, isc_result_totext(result))); 16936 CHECK(putnull(text)); 16937 } else { 16938 /* Schedule a rekey */ 16939 dns_zone_rekey(zone, false, false); 16940 } 16941 16942 cleanup: 16943 if (zone != NULL) { 16944 dns_zone_detach(&zone); 16945 } 16946 16947 return result; 16948 } 16949 16950 isc_result_t 16951 named_server_togglememprof(isc_lex_t *lex) { 16952 isc_result_t result = ISC_R_FAILURE; 16953 bool active; 16954 char *ptr; 16955 16956 /* Skip the command name. */ 16957 ptr = next_token(lex, NULL); 16958 if (ptr == NULL) { 16959 return ISC_R_UNEXPECTEDEND; 16960 } 16961 16962 ptr = next_token(lex, NULL); 16963 if (ptr == NULL) { 16964 return ISC_R_UNEXPECTEDEND; 16965 } else if (!strcasecmp(ptr, "dump")) { 16966 result = memprof_dump(); 16967 if (result != ISC_R_SUCCESS) { 16968 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16969 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16970 "failed to dump memory profile"); 16971 16972 } else { 16973 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16974 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16975 "memory profile dumped"); 16976 } 16977 16978 goto done; 16979 } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 16980 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 16981 { 16982 active = true; 16983 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 16984 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 16985 { 16986 active = false; 16987 } else { 16988 return DNS_R_SYNTAX; 16989 } 16990 16991 result = memprof_toggle(active); 16992 if (result != ISC_R_SUCCESS) { 16993 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16994 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16995 "failed to toggle memory profiling"); 16996 } else { 16997 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16998 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16999 "memory profiling %s", 17000 active ? "enabled" : "disabled"); 17001 } 17002 17003 done: 17004 return result; 17005 } 17006 17007 #ifdef JEMALLOC_API_SUPPORTED 17008 const char * 17009 named_server_getmemprof(void) { 17010 memprof_status status = MEMPROF_ON; 17011 bool is_enabled; 17012 size_t len = sizeof(is_enabled); 17013 17014 if (mallctl("config.prof", &is_enabled, &len, NULL, 0) != 0) { 17015 status = MEMPROF_FAILING; 17016 goto done; 17017 } 17018 17019 INSIST(len == sizeof(is_enabled)); 17020 17021 if (!is_enabled) { 17022 status = MEMPROF_UNSUPPORTED; 17023 goto done; 17024 } 17025 17026 if (mallctl("opt.prof", &is_enabled, &len, NULL, 0) != 0) { 17027 status = MEMPROF_FAILING; 17028 goto done; 17029 } 17030 17031 INSIST(len == sizeof(is_enabled)); 17032 17033 if (!is_enabled) { 17034 status = MEMPROF_INACTIVE; 17035 goto done; 17036 } 17037 17038 len = sizeof(is_enabled); 17039 if (mallctl("prof.active", &is_enabled, &len, NULL, 0) != 0) { 17040 status = MEMPROF_FAILING; 17041 goto done; 17042 } 17043 17044 INSIST(len == sizeof(is_enabled)); 17045 17046 if (!is_enabled) { 17047 status = MEMPROF_OFF; 17048 } 17049 17050 done: 17051 return memprof_status_text[status]; 17052 } 17053 17054 #else /* JEMALLOC_API_SUPPORTED */ 17055 const char * 17056 named_server_getmemprof(void) { 17057 return memprof_status_text[MEMPROF_UNSUPPORTED]; 17058 } 17059 #endif /* JEMALLOC_API_SUPPORTED */ 17060