1 /* $NetBSD: server.c,v 1.26 2026/01/29 18:36:27 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #include <ctype.h> 19 #include <inttypes.h> 20 #include <limits.h> 21 #include <signal.h> 22 #include <stdbool.h> 23 #include <stdint.h> 24 #include <stdlib.h> 25 #include <sys/stat.h> 26 #include <sys/types.h> 27 #include <unistd.h> 28 29 #ifdef HAVE_DNSTAP 30 #include <fstrm.h> 31 #endif 32 33 #include <isc/async.h> 34 #include <isc/attributes.h> 35 #include <isc/base64.h> 36 #include <isc/commandline.h> 37 #include <isc/dir.h> 38 #include <isc/file.h> 39 #include <isc/fips.h> 40 #include <isc/hash.h> 41 #include <isc/hex.h> 42 #include <isc/hmac.h> 43 #include <isc/httpd.h> 44 #include <isc/job.h> 45 #include <isc/lex.h> 46 #include <isc/loop.h> 47 #include <isc/meminfo.h> 48 #include <isc/netmgr.h> 49 #include <isc/nonce.h> 50 #include <isc/parseint.h> 51 #include <isc/portset.h> 52 #include <isc/refcount.h> 53 #include <isc/result.h> 54 #include <isc/signal.h> 55 #include <isc/siphash.h> 56 #include <isc/stats.h> 57 #include <isc/stdio.h> 58 #include <isc/string.h> 59 #include <isc/time.h> 60 #include <isc/timer.h> 61 #include <isc/util.h> 62 63 #include <dns/adb.h> 64 #include <dns/badcache.h> 65 #include <dns/cache.h> 66 #include <dns/catz.h> 67 #include <dns/db.h> 68 #include <dns/dispatch.h> 69 #include <dns/dlz.h> 70 #include <dns/dns64.h> 71 #include <dns/dnsrps.h> 72 #include <dns/dnssec.h> 73 #include <dns/dyndb.h> 74 #include <dns/fixedname.h> 75 #include <dns/forward.h> 76 #include <dns/geoip.h> 77 #include <dns/journal.h> 78 #include <dns/kasp.h> 79 #include <dns/keymgr.h> 80 #include <dns/keystore.h> 81 #include <dns/keytable.h> 82 #include <dns/keyvalues.h> 83 #include <dns/master.h> 84 #include <dns/masterdump.h> 85 #include <dns/nametree.h> 86 #include <dns/nsec3.h> 87 #include <dns/nta.h> 88 #include <dns/order.h> 89 #include <dns/peer.h> 90 #include <dns/private.h> 91 #include <dns/rbt.h> 92 #include <dns/rdataclass.h> 93 #include <dns/rdatalist.h> 94 #include <dns/rdataset.h> 95 #include <dns/rdatastruct.h> 96 #include <dns/resolver.h> 97 #include <dns/rootns.h> 98 #include <dns/rriterator.h> 99 #include <dns/secalg.h> 100 #include <dns/soa.h> 101 #include <dns/stats.h> 102 #include <dns/time.h> 103 #include <dns/tkey.h> 104 #include <dns/tsig.h> 105 #include <dns/ttl.h> 106 #include <dns/view.h> 107 #include <dns/zone.h> 108 #include <dns/zt.h> 109 110 #include <dst/dst.h> 111 112 #include <isccfg/check.h> 113 #include <isccfg/grammar.h> 114 #include <isccfg/kaspconf.h> 115 #include <isccfg/namedconf.h> 116 117 #include <ns/client.h> 118 #include <ns/hooks.h> 119 #include <ns/interfacemgr.h> 120 #include <ns/listenlist.h> 121 122 #include <named/config.h> 123 #include <named/control.h> 124 #if defined(HAVE_GEOIP2) 125 #include <named/geoip.h> 126 #endif /* HAVE_GEOIP2 */ 127 #include <named/log.h> 128 #include <named/logconf.h> 129 #include <named/main.h> 130 #include <named/os.h> 131 #include <named/server.h> 132 #include <named/statschannel.h> 133 #include <named/tkeyconf.h> 134 #include <named/transportconf.h> 135 #include <named/tsigconf.h> 136 #include <named/zoneconf.h> 137 #ifdef HAVE_LIBSCF 138 #include <stdlib.h> 139 140 #include <named/smf_globals.h> 141 #endif /* ifdef HAVE_LIBSCF */ 142 143 /* On DragonFly BSD the header does not provide jemalloc API */ 144 #if defined(HAVE_MALLOC_NP_H) && !defined(__DragonFly__) 145 #include <malloc_np.h> 146 #define JEMALLOC_API_SUPPORTED 1 147 #elif defined(HAVE_JEMALLOC) 148 #include <jemalloc/jemalloc.h> 149 #define JEMALLOC_API_SUPPORTED 1 150 #endif 151 152 #ifdef HAVE_LMDB 153 #include <lmdb.h> 154 #define configure_newzones configure_newzones_db 155 #define dumpzone dumpzone_db 156 #else /* HAVE_LMDB */ 157 #define configure_newzones configure_newzones_file 158 #define dumpzone dumpzone_file 159 #endif /* HAVE_LMDB */ 160 161 #ifndef SIZE_MAX 162 #define SIZE_MAX ((size_t)-1) 163 #endif /* ifndef SIZE_MAX */ 164 165 #ifndef SIZE_AS_PERCENT 166 #define SIZE_AS_PERCENT ((size_t)-2) 167 #endif /* ifndef SIZE_AS_PERCENT */ 168 169 /* RFC7828 defines timeout as 16-bit value specified in units of 100 170 * milliseconds, so the maximum and minimum advertised and keepalive 171 * timeouts are capped by the data type (it's ~109 minutes) 172 */ 173 #define MIN_INITIAL_TIMEOUT UINT32_C(2500) /* 2.5 seconds */ 174 #define MAX_INITIAL_TIMEOUT UINT32_C(120000) /* 2 minutes */ 175 #define MIN_IDLE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ 176 #define MAX_IDLE_TIMEOUT UINT32_C(120000) /* 2 minutes */ 177 #define MIN_KEEPALIVE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ 178 #define MAX_KEEPALIVE_TIMEOUT UINT32_C(UINT16_MAX * 100) 179 #define MIN_ADVERTISED_TIMEOUT UINT32_C(0) /* No minimum */ 180 #define MAX_ADVERTISED_TIMEOUT UINT32_C(UINT16_MAX * 100) 181 182 /*% 183 * Check an operation for failure. Assumes that the function 184 * using it has a 'result' variable and a 'cleanup' label. 185 */ 186 #define TCHECK(op) \ 187 do { \ 188 tresult = (op); \ 189 if (tresult != ISC_R_SUCCESS) { \ 190 isc_buffer_clear(*text); \ 191 goto cleanup; \ 192 } \ 193 } while (0) 194 195 #define CHECKM(op, msg) \ 196 do { \ 197 result = (op); \ 198 if (result != ISC_R_SUCCESS) { \ 199 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ 200 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \ 201 "%s: %s", msg, \ 202 isc_result_totext(result)); \ 203 goto cleanup; \ 204 } \ 205 } while (0) 206 207 #define CHECKMF(op, msg, file) \ 208 do { \ 209 result = (op); \ 210 if (result != ISC_R_SUCCESS) { \ 211 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ 212 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \ 213 "%s '%s': %s", msg, file, \ 214 isc_result_totext(result)); \ 215 goto cleanup; \ 216 } \ 217 } while (0) 218 219 #define CHECKFATAL(op, msg) \ 220 { \ 221 result = (op); \ 222 if (result != ISC_R_SUCCESS) { \ 223 fatal(msg, result); \ 224 } \ 225 } 226 227 /*% 228 * Maximum ADB size for views that share a cache. Use this limit to suppress 229 * the total of memory footprint, which should be the main reason for sharing 230 * a cache. Only effective when a finite max-cache-size is specified. 231 * This is currently defined to be 8MB. 232 */ 233 #define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U 234 235 struct named_dispatch { 236 isc_sockaddr_t addr; 237 unsigned int dispatchgen; 238 dns_dispatch_t *dispatch; 239 ISC_LINK(struct named_dispatch) link; 240 }; 241 242 struct named_cache { 243 dns_cache_t *cache; 244 dns_view_t *primaryview; 245 bool needflush; 246 bool adbsizeadjusted; 247 dns_rdataclass_t rdclass; 248 ISC_LINK(named_cache_t) link; 249 }; 250 251 struct dumpcontext { 252 isc_mem_t *mctx; 253 bool dumpcache; 254 bool dumpzones; 255 bool dumpadb; 256 bool dumpexpired; 257 bool dumpfail; 258 FILE *fp; 259 ISC_LIST(struct viewlistentry) viewlist; 260 struct viewlistentry *view; 261 struct zonelistentry *zone; 262 dns_dumpctx_t *mdctx; 263 dns_db_t *db; 264 dns_db_t *cache; 265 isc_loop_t *loop; 266 dns_dbversion_t *version; 267 }; 268 269 struct viewlistentry { 270 dns_view_t *view; 271 ISC_LINK(struct viewlistentry) link; 272 ISC_LIST(struct zonelistentry) zonelist; 273 }; 274 275 struct zonelistentry { 276 dns_zone_t *zone; 277 ISC_LINK(struct zonelistentry) link; 278 }; 279 280 /*% 281 * Message-to-view matching context to run message signature validation 282 * asynchronously. 283 */ 284 typedef struct matching_view_ctx { 285 isc_netaddr_t *srcaddr; 286 isc_netaddr_t *destaddr; 287 dns_message_t *message; 288 dns_aclenv_t *env; 289 ns_server_t *sctx; 290 isc_loop_t *loop; 291 isc_job_cb cb; 292 void *cbarg; 293 isc_result_t *sigresult; 294 isc_result_t *viewmatchresult; 295 isc_result_t quota_result; 296 dns_view_t **viewp; 297 dns_view_t *view; 298 } matching_view_ctx_t; 299 300 /*% 301 * Configuration context to retain for each view that allows 302 * new zones to be added at runtime. 303 */ 304 typedef struct ns_cfgctx { 305 isc_mem_t *mctx; 306 cfg_parser_t *conf_parser; 307 cfg_parser_t *add_parser; 308 cfg_obj_t *config; 309 cfg_obj_t *vconfig; 310 cfg_obj_t *nzf_config; 311 cfg_aclconfctx_t *actx; 312 } ns_cfgctx_t; 313 314 /*% 315 * A function to write out added-zone configuration to the new_zone_file 316 * specified in 'view'. Maybe called by delete_zoneconf(). 317 */ 318 typedef isc_result_t (*nzfwriter_t)(const cfg_obj_t *config, dns_view_t *view); 319 320 /*% 321 * Holds state information for the initial zone loading process. 322 * Uses the isc_refcount structure to count the number of views 323 * with pending zone loads, dereferencing as each view finishes. 324 */ 325 typedef struct { 326 named_server_t *server; 327 bool reconfig; 328 isc_refcount_t refs; 329 } ns_zoneload_t; 330 331 typedef struct { 332 named_server_t *server; 333 } catz_cb_data_t; 334 335 typedef struct catz_chgzone { 336 isc_mem_t *mctx; 337 dns_catz_entry_t *entry; 338 dns_catz_zone_t *origin; 339 dns_view_t *view; 340 catz_cb_data_t *cbd; 341 bool mod; 342 } catz_chgzone_t; 343 344 typedef struct catz_reconfig_data { 345 dns_catz_zone_t *catz; 346 const cfg_obj_t *config; 347 catz_cb_data_t *cbd; 348 } catz_reconfig_data_t; 349 350 typedef enum { 351 CATZ_ADDZONE, 352 CATZ_MODZONE, 353 CATZ_DELZONE, 354 } catz_type_t; 355 356 typedef struct { 357 unsigned int magic; 358 #define DZARG_MAGIC ISC_MAGIC('D', 'z', 'a', 'r') 359 isc_buffer_t **text; 360 isc_result_t result; 361 } ns_dzarg_t; 362 363 typedef enum { 364 MEMPROF_UNSUPPORTED = 0x00, 365 MEMPROF_INACTIVE = 0x01, 366 MEMPROF_FAILING = 0x02, 367 MEMPROF_OFF = 0x03, 368 MEMPROF_ON = 0x04, 369 } memprof_status; 370 371 static const char *memprof_status_text[] = { 372 [MEMPROF_UNSUPPORTED] = "UNSUPPORTED", 373 [MEMPROF_INACTIVE] = "INACTIVE", 374 [MEMPROF_FAILING] = "FAILING", 375 [MEMPROF_OFF] = "OFF", 376 [MEMPROF_ON] = "ON", 377 }; 378 379 /* 380 * These zones should not leak onto the Internet. 381 */ 382 const char *empty_zones[] = { 383 /* RFC 1918 */ 384 "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA", 385 "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA", 386 "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA", 387 "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA", 388 "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA", 389 "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA", 390 391 /* RFC 6598 */ 392 "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA", 393 "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA", 394 "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA", 395 "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA", 396 "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA", 397 "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA", 398 "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA", 399 "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA", 400 "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA", 401 "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA", 402 "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA", 403 "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA", 404 "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA", "102.100.IN-ADDR.ARPA", 405 "103.100.IN-ADDR.ARPA", "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA", 406 "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA", "108.100.IN-ADDR.ARPA", 407 "109.100.IN-ADDR.ARPA", "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA", 408 "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA", "114.100.IN-ADDR.ARPA", 409 "115.100.IN-ADDR.ARPA", "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA", 410 "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA", "120.100.IN-ADDR.ARPA", 411 "121.100.IN-ADDR.ARPA", "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA", 412 "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA", "126.100.IN-ADDR.ARPA", 413 "127.100.IN-ADDR.ARPA", 414 415 /* RFC 5735 and RFC 5737 */ 416 "0.IN-ADDR.ARPA", /* THIS NETWORK */ 417 "127.IN-ADDR.ARPA", /* LOOPBACK */ 418 "254.169.IN-ADDR.ARPA", /* LINK LOCAL */ 419 "2.0.192.IN-ADDR.ARPA", /* TEST NET */ 420 "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */ 421 "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */ 422 "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */ 423 424 /* Local IPv6 Unicast Addresses */ 425 /* clang-format off */ 426 "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", 427 "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", 428 /* clang-format on */ 429 430 /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ 431 "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", /* LINK LOCAL */ 432 "9.E.F.IP6.ARPA", /* LINK LOCAL */ 433 "A.E.F.IP6.ARPA", /* LINK LOCAL */ 434 "B.E.F.IP6.ARPA", /* LINK LOCAL */ 435 436 /* Example Prefix, RFC 3849. */ 437 "8.B.D.0.1.0.0.2.IP6.ARPA", 438 439 /* RFC 7534 */ 440 "EMPTY.AS112.ARPA", 441 442 /* RFC 8375 */ 443 "HOME.ARPA", 444 445 /* RFC 9462 */ 446 "RESOLVER.ARPA", 447 448 NULL 449 }; 450 451 noreturn static void 452 fatal(const char *msg, isc_result_t result); 453 454 static void 455 named_server_reload(void *arg); 456 457 #ifdef HAVE_LIBNGHTTP2 458 static isc_result_t 459 listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, 460 const ns_listen_tls_params_t *tls_params, 461 isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, 462 isc_mem_t *mctx, isc_nm_proxy_type_t proxy, 463 ns_listenelt_t **target); 464 #endif 465 466 static isc_result_t 467 listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 468 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 469 isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target); 470 471 static isc_result_t 472 listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 473 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 474 isc_tlsctx_cache_t *tlsctx_cache, 475 ns_listenlist_t **target); 476 477 static isc_result_t 478 configure_forward(const cfg_obj_t *config, dns_view_t *view, 479 const dns_name_t *origin, const cfg_obj_t *forwarders, 480 const cfg_obj_t *forwardtype); 481 482 static isc_result_t 483 configure_alternates(const cfg_obj_t *config, dns_view_t *view, 484 const cfg_obj_t *alternates); 485 486 static isc_result_t 487 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 488 const cfg_obj_t *vconfig, dns_view_t *view, 489 dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, 490 dns_keystorelist_t *keystores, cfg_aclconfctx_t *aclconf, 491 bool added, bool old_rpz_ok, bool is_catz_member, bool modify); 492 493 static void 494 configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, 495 dns_view_t *view); 496 497 static isc_result_t 498 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 499 cfg_aclconfctx_t *actx); 500 501 static const cfg_obj_t * 502 find_maplist(const cfg_obj_t *config, const char *listname, const char *name); 503 504 static isc_result_t 505 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); 506 507 static void 508 newzone_cfgctx_destroy(void **cfgp); 509 510 static isc_result_t 511 putstr(isc_buffer_t **b, const char *str); 512 513 static isc_result_t 514 putmem(isc_buffer_t **b, const char *str, size_t len); 515 516 static isc_result_t 517 putuint8(isc_buffer_t **b, uint8_t val); 518 519 static isc_result_t 520 putnull(isc_buffer_t **b); 521 522 #ifdef HAVE_LMDB 523 static isc_result_t 524 nzd_writable(dns_view_t *view); 525 526 static isc_result_t 527 nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi); 528 529 static isc_result_t 530 nzd_env_reopen(dns_view_t *view); 531 532 static void 533 nzd_env_close(dns_view_t *view); 534 535 static isc_result_t 536 nzd_close(MDB_txn **txnp, bool commit); 537 #else /* ifdef HAVE_LMDB */ 538 static isc_result_t 539 nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); 540 #endif /* ifdef HAVE_LMDB */ 541 542 static isc_result_t 543 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg); 544 545 /*% 546 * Configure a single view ACL at '*aclp'. Get its configuration from 547 * 'vconfig' (for per-view configuration) and maybe from 'config' 548 */ 549 static isc_result_t 550 configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, 551 const cfg_obj_t *gconfig, const char *aclname, 552 const char *acltuplename, cfg_aclconfctx_t *actx, 553 isc_mem_t *mctx, dns_acl_t **aclp) { 554 isc_result_t result; 555 const cfg_obj_t *maps[4]; 556 const cfg_obj_t *aclobj = NULL; 557 int i = 0; 558 559 if (*aclp != NULL) { 560 dns_acl_detach(aclp); 561 } 562 if (vconfig != NULL) { 563 maps[i++] = cfg_tuple_get(vconfig, "options"); 564 } 565 if (config != NULL) { 566 const cfg_obj_t *options = NULL; 567 (void)cfg_map_get(config, "options", &options); 568 if (options != NULL) { 569 maps[i++] = options; 570 } 571 } 572 if (gconfig != NULL) { 573 const cfg_obj_t *options = NULL; 574 (void)cfg_map_get(gconfig, "options", &options); 575 if (options != NULL) { 576 maps[i++] = options; 577 } 578 } 579 maps[i] = NULL; 580 581 (void)named_config_get(maps, aclname, &aclobj); 582 if (aclobj == NULL) { 583 /* 584 * No value available. *aclp == NULL. 585 */ 586 return ISC_R_SUCCESS; 587 } 588 589 if (acltuplename != NULL) { 590 /* 591 * If the ACL is given in an optional tuple, retrieve it. 592 * The parser should have ensured that a valid object be 593 * returned. 594 */ 595 aclobj = cfg_tuple_get(aclobj, acltuplename); 596 } 597 598 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 0, 599 aclp); 600 601 return result; 602 } 603 604 /*% 605 * Configure a sortlist at '*aclp'. Essentially the same as 606 * configure_view_acl() except it calls cfg_acl_fromconfig with a 607 * nest_level value of 2. 608 */ 609 static isc_result_t 610 configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, 611 cfg_aclconfctx_t *actx, isc_mem_t *mctx, 612 dns_acl_t **aclp) { 613 isc_result_t result; 614 const cfg_obj_t *maps[3]; 615 const cfg_obj_t *aclobj = NULL; 616 int i = 0; 617 618 if (*aclp != NULL) { 619 dns_acl_detach(aclp); 620 } 621 if (vconfig != NULL) { 622 maps[i++] = cfg_tuple_get(vconfig, "options"); 623 } 624 if (config != NULL) { 625 const cfg_obj_t *options = NULL; 626 (void)cfg_map_get(config, "options", &options); 627 if (options != NULL) { 628 maps[i++] = options; 629 } 630 } 631 maps[i] = NULL; 632 633 (void)named_config_get(maps, "sortlist", &aclobj); 634 if (aclobj == NULL) { 635 return ISC_R_SUCCESS; 636 } 637 638 /* 639 * Use a nest level of 3 for the "top level" of the sortlist; 640 * this means each entry in the top three levels will be stored 641 * as lists of separate, nested ACLs, rather than merged together 642 * into IP tables as is usually done with ACLs. 643 */ 644 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 3, 645 aclp); 646 647 return result; 648 } 649 650 static isc_result_t 651 configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, 652 const char *confname, const char *conftuplename, 653 isc_mem_t *mctx, dns_nametree_t **ntp) { 654 isc_result_t result = ISC_R_SUCCESS; 655 const cfg_obj_t *maps[3]; 656 const cfg_obj_t *obj = NULL; 657 const cfg_listelt_t *element = NULL; 658 int i = 0; 659 dns_fixedname_t fixed; 660 dns_name_t *name = NULL; 661 isc_buffer_t b; 662 const char *str = NULL; 663 const cfg_obj_t *nameobj = NULL; 664 665 if (*ntp != NULL) { 666 dns_nametree_detach(ntp); 667 } 668 dns_nametree_create(mctx, DNS_NAMETREE_BOOL, confname, ntp); 669 670 if (vconfig != NULL) { 671 maps[i++] = cfg_tuple_get(vconfig, "options"); 672 } 673 if (config != NULL) { 674 const cfg_obj_t *options = NULL; 675 (void)cfg_map_get(config, "options", &options); 676 if (options != NULL) { 677 maps[i++] = options; 678 } 679 } 680 maps[i] = NULL; 681 682 (void)named_config_get(maps, confname, &obj); 683 if (obj == NULL) { 684 /* 685 * No value available. *ntp == NULL. 686 */ 687 return ISC_R_SUCCESS; 688 } 689 690 if (conftuplename != NULL) { 691 obj = cfg_tuple_get(obj, conftuplename); 692 if (cfg_obj_isvoid(obj)) { 693 return ISC_R_SUCCESS; 694 } 695 } 696 697 name = dns_fixedname_initname(&fixed); 698 for (element = cfg_list_first(obj); element != NULL; 699 element = cfg_list_next(element)) 700 { 701 nameobj = cfg_listelt_value(element); 702 str = cfg_obj_asstring(nameobj); 703 isc_buffer_constinit(&b, str, strlen(str)); 704 isc_buffer_add(&b, strlen(str)); 705 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 706 result = dns_nametree_add(*ntp, name, true); 707 if (result != ISC_R_SUCCESS) { 708 cfg_obj_log(nameobj, named_g_lctx, ISC_LOG_ERROR, 709 "failed to add %s for %s: %s", str, 710 confname, isc_result_totext(result)); 711 goto cleanup; 712 } 713 } 714 715 return ISC_R_SUCCESS; 716 717 cleanup: 718 dns_nametree_detach(ntp); 719 return result; 720 } 721 722 static isc_result_t 723 ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp, 724 unsigned char *digest, dns_rdata_ds_t *ds) { 725 isc_result_t result; 726 dns_rdata_dnskey_t keystruct; 727 dns_rdata_t rdata = DNS_RDATA_INIT; 728 uint32_t rdata1, rdata2, rdata3; 729 const char *datastr = NULL, *namestr = NULL; 730 unsigned char data[4096]; 731 isc_buffer_t databuf; 732 unsigned char rrdata[4096]; 733 isc_buffer_t rrdatabuf; 734 isc_region_t r; 735 dns_fixedname_t fname; 736 dns_name_t *name = NULL; 737 isc_buffer_t namebuf; 738 const char *atstr = NULL; 739 enum { 740 INIT_DNSKEY, 741 STATIC_DNSKEY, 742 INIT_DS, 743 STATIC_DS, 744 TRUSTED 745 } anchortype; 746 747 REQUIRE(namestrp != NULL && *namestrp == NULL); 748 REQUIRE(ds != NULL); 749 750 /* if DNSKEY, flags; if DS, key tag */ 751 rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1")); 752 753 /* if DNSKEY, protocol; if DS, algorithm */ 754 rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2")); 755 756 /* if DNSKEY, algorithm; if DS, digest type */ 757 rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3")); 758 759 namestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 760 *namestrp = namestr; 761 762 name = dns_fixedname_initname(&fname); 763 isc_buffer_constinit(&namebuf, namestr, strlen(namestr)); 764 isc_buffer_add(&namebuf, strlen(namestr)); 765 CHECK(dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL)); 766 767 if (*initialp) { 768 atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype")); 769 770 if (strcasecmp(atstr, "static-key") == 0) { 771 *initialp = false; 772 anchortype = STATIC_DNSKEY; 773 } else if (strcasecmp(atstr, "static-ds") == 0) { 774 *initialp = false; 775 anchortype = STATIC_DS; 776 } else if (strcasecmp(atstr, "initial-key") == 0) { 777 anchortype = INIT_DNSKEY; 778 } else if (strcasecmp(atstr, "initial-ds") == 0) { 779 anchortype = INIT_DS; 780 } else { 781 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 782 "key '%s': " 783 "invalid initialization method '%s'", 784 namestr, atstr); 785 result = ISC_R_FAILURE; 786 goto cleanup; 787 } 788 } else { 789 anchortype = TRUSTED; 790 } 791 792 isc_buffer_init(&databuf, data, sizeof(data)); 793 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 794 795 *ds = (dns_rdata_ds_t){ .common.rdclass = dns_rdataclass_in, 796 .common.rdtype = dns_rdatatype_ds }; 797 798 ISC_LINK_INIT(&ds->common, link); 799 800 switch (anchortype) { 801 case INIT_DNSKEY: 802 case STATIC_DNSKEY: 803 case TRUSTED: 804 /* 805 * This function should never be reached for view 806 * class other than IN 807 */ 808 keystruct.common.rdclass = dns_rdataclass_in; 809 keystruct.common.rdtype = dns_rdatatype_dnskey; 810 811 /* 812 * The key data in keystruct is not dynamically allocated. 813 */ 814 keystruct.mctx = NULL; 815 816 ISC_LINK_INIT(&keystruct.common, link); 817 818 if (rdata1 > 0xffff) { 819 CHECKM(ISC_R_RANGE, "key flags"); 820 } 821 if (rdata1 & DNS_KEYFLAG_REVOKE) { 822 CHECKM(DST_R_BADKEYTYPE, "key flags revoke bit set"); 823 } 824 if (rdata2 > 0xff) { 825 CHECKM(ISC_R_RANGE, "key protocol"); 826 } 827 if (rdata3 > 0xff) { 828 CHECKM(ISC_R_RANGE, "key algorithm"); 829 } 830 831 keystruct.flags = (uint16_t)rdata1; 832 keystruct.protocol = (uint8_t)rdata2; 833 keystruct.algorithm = (uint8_t)rdata3; 834 835 if (!dst_algorithm_supported(keystruct.algorithm)) { 836 CHECK(DST_R_UNSUPPORTEDALG); 837 } 838 839 datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); 840 CHECK(isc_base64_decodestring(datastr, &databuf)); 841 isc_buffer_usedregion(&databuf, &r); 842 keystruct.datalen = r.length; 843 keystruct.data = r.base; 844 845 CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass, 846 keystruct.common.rdtype, &keystruct, 847 &rrdatabuf)); 848 CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, 849 digest, ds)); 850 break; 851 852 case INIT_DS: 853 case STATIC_DS: 854 if (rdata1 > 0xffff) { 855 CHECKM(ISC_R_RANGE, "key tag"); 856 } 857 if (rdata2 > 0xff) { 858 CHECKM(ISC_R_RANGE, "key algorithm"); 859 } 860 if (rdata3 > 0xff) { 861 CHECKM(ISC_R_RANGE, "digest type"); 862 } 863 864 ds->key_tag = (uint16_t)rdata1; 865 ds->algorithm = (uint8_t)rdata2; 866 ds->digest_type = (uint8_t)rdata3; 867 868 datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); 869 CHECK(isc_hex_decodestring(datastr, &databuf)); 870 isc_buffer_usedregion(&databuf, &r); 871 872 switch (ds->digest_type) { 873 case DNS_DSDIGEST_SHA1: 874 if (r.length != ISC_SHA1_DIGESTLENGTH) { 875 CHECK(ISC_R_UNEXPECTEDEND); 876 } 877 break; 878 case DNS_DSDIGEST_SHA256: 879 if (r.length != ISC_SHA256_DIGESTLENGTH) { 880 CHECK(ISC_R_UNEXPECTEDEND); 881 } 882 break; 883 case DNS_DSDIGEST_SHA384: 884 if (r.length != ISC_SHA384_DIGESTLENGTH) { 885 CHECK(ISC_R_UNEXPECTEDEND); 886 } 887 break; 888 default: 889 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 890 "key '%s': " 891 "unknown ds digest type %u", 892 namestr, ds->digest_type); 893 result = ISC_R_FAILURE; 894 goto cleanup; 895 break; 896 } 897 898 ds->length = r.length; 899 ds->digest = digest; 900 memmove(ds->digest, r.base, r.length); 901 902 break; 903 904 default: 905 UNREACHABLE(); 906 } 907 908 return ISC_R_SUCCESS; 909 910 cleanup: 911 return result; 912 } 913 914 static void 915 sfd_add(const dns_name_t *name, void *arg) { 916 if (arg != NULL) { 917 dns_view_sfd_add(arg, name); 918 } 919 } 920 921 /*% 922 * Parse 'key' in the context of view configuration 'vconfig'. If successful, 923 * add the key to 'secroots' if both of the following conditions are true: 924 * 925 * - 'keyname_match' is NULL or it matches the owner name of 'key', 926 * - support for the algorithm used by 'key' is not disabled by 'resolver' 927 * for the owner name of 'key'. 928 * 929 * 'managed' is true for managed keys and false for trusted keys. 'mctx' is 930 * the memory context to use for allocating memory. 931 */ 932 static isc_result_t 933 process_key(const cfg_obj_t *key, dns_keytable_t *secroots, 934 const dns_name_t *keyname_match, dns_view_t *view, bool managed) { 935 dns_fixedname_t fkeyname; 936 dns_name_t *keyname = NULL; 937 const char *namestr = NULL; 938 dns_rdata_ds_t ds; 939 isc_result_t result; 940 bool initializing = managed; 941 unsigned char digest[ISC_MAX_MD_SIZE]; 942 isc_buffer_t b; 943 944 result = ta_fromconfig(key, &initializing, &namestr, digest, &ds); 945 946 switch (result) { 947 case ISC_R_SUCCESS: 948 /* 949 * Trust anchor was parsed correctly. 950 */ 951 isc_buffer_constinit(&b, namestr, strlen(namestr)); 952 isc_buffer_add(&b, strlen(namestr)); 953 keyname = dns_fixedname_initname(&fkeyname); 954 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); 955 if (result != ISC_R_SUCCESS) { 956 return result; 957 } 958 break; 959 case DST_R_UNSUPPORTEDALG: 960 case DST_R_BADKEYTYPE: 961 /* 962 * Key was parsed correctly, but it cannot be used; this is not 963 * a fatal error - log a warning about this key being ignored, 964 * but do not prevent any further ones from being processed. 965 */ 966 cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, 967 "ignoring %s for '%s': %s", 968 initializing ? "initial-key" : "static-key", 969 namestr, isc_result_totext(result)); 970 return ISC_R_SUCCESS; 971 case DST_R_NOCRYPTO: 972 /* 973 * Crypto support is not available. 974 */ 975 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 976 "ignoring %s for '%s': no crypto support", 977 initializing ? "initial-key" : "static-key", 978 namestr); 979 return result; 980 default: 981 /* 982 * Something unexpected happened; we have no choice but to 983 * indicate an error so that the configuration loading process 984 * is interrupted. 985 */ 986 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 987 "configuring %s for '%s': %s", 988 initializing ? "initial-key" : "static-key", 989 namestr, isc_result_totext(result)); 990 return ISC_R_FAILURE; 991 } 992 993 /* 994 * If the caller requested to only load keys for a specific name and 995 * the owner name of this key does not match the requested name, do not 996 * load it. 997 */ 998 if (keyname_match != NULL && !dns_name_equal(keyname_match, keyname)) { 999 goto done; 1000 } 1001 1002 /* 1003 * Ensure that 'resolver' allows using the algorithm of this key for 1004 * its owner name. If it does not, do not load the key and log a 1005 * warning, but do not prevent further keys from being processed. 1006 */ 1007 if (!dns_resolver_algorithm_supported(view->resolver, keyname, 1008 ds.algorithm)) 1009 { 1010 cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, 1011 "ignoring %s for '%s': algorithm is disabled", 1012 initializing ? "initial-key" : "static-key", 1013 namestr); 1014 goto done; 1015 } 1016 1017 /* 1018 * Add the key to 'secroots'. Keys from a "trust-anchors" or 1019 * "managed-keys" statement may be either static or initializing 1020 * keys. If it's not initializing, we don't want to treat it as 1021 * managed, so we use 'initializing' twice here, for both the 1022 * 'managed' and 'initializing' arguments to dns_keytable_add(). 1023 */ 1024 result = dns_keytable_add(secroots, initializing, initializing, keyname, 1025 &ds, sfd_add, view); 1026 1027 done: 1028 return result; 1029 } 1030 1031 /* 1032 * Load keys from configuration into key table. If 'keyname' is specified, 1033 * only load keys matching that name. If 'managed' is true, load the key as 1034 * an initializing key. 1035 */ 1036 static isc_result_t 1037 load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, 1038 const dns_name_t *keyname) { 1039 const cfg_listelt_t *elt, *elt2; 1040 const cfg_obj_t *keylist; 1041 isc_result_t result; 1042 dns_keytable_t *secroots = NULL; 1043 1044 CHECK(dns_view_getsecroots(view, &secroots)); 1045 1046 for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) 1047 { 1048 keylist = cfg_listelt_value(elt); 1049 1050 for (elt2 = cfg_list_first(keylist); elt2 != NULL; 1051 elt2 = cfg_list_next(elt2)) 1052 { 1053 CHECK(process_key(cfg_listelt_value(elt2), secroots, 1054 keyname, view, managed)); 1055 } 1056 } 1057 1058 cleanup: 1059 if (secroots != NULL) { 1060 dns_keytable_detach(&secroots); 1061 } 1062 if (result == DST_R_NOCRYPTO) { 1063 result = ISC_R_SUCCESS; 1064 } 1065 return result; 1066 } 1067 1068 /*% 1069 * Check whether a key has been successfully loaded. 1070 */ 1071 static bool 1072 keyloaded(dns_view_t *view, const dns_name_t *name) { 1073 isc_result_t result; 1074 dns_keytable_t *secroots = NULL; 1075 dns_keynode_t *keynode = NULL; 1076 1077 result = dns_view_getsecroots(view, &secroots); 1078 if (result != ISC_R_SUCCESS) { 1079 return false; 1080 } 1081 1082 result = dns_keytable_find(secroots, name, &keynode); 1083 1084 if (keynode != NULL) { 1085 dns_keynode_detach(&keynode); 1086 } 1087 if (secroots != NULL) { 1088 dns_keytable_detach(&secroots); 1089 } 1090 1091 return result == ISC_R_SUCCESS; 1092 } 1093 1094 /*% 1095 * Configure DNSSEC keys for a view. 1096 * 1097 * The per-view configuration values and the server-global defaults are read 1098 * from 'vconfig' and 'config'. 1099 */ 1100 static isc_result_t 1101 configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, 1102 const cfg_obj_t *config, const cfg_obj_t *bindkeys, 1103 bool auto_root) { 1104 isc_result_t result = ISC_R_SUCCESS; 1105 const cfg_obj_t *view_keys = NULL; 1106 const cfg_obj_t *global_keys = NULL; 1107 const cfg_obj_t *view_managed_keys = NULL; 1108 const cfg_obj_t *view_trust_anchors = NULL; 1109 const cfg_obj_t *global_managed_keys = NULL; 1110 const cfg_obj_t *global_trust_anchors = NULL; 1111 const cfg_obj_t *maps[4]; 1112 const cfg_obj_t *voptions = NULL; 1113 const cfg_obj_t *options = NULL; 1114 const cfg_obj_t *obj = NULL; 1115 const char *directory; 1116 int i = 0; 1117 1118 /* We don't need trust anchors for the _bind view */ 1119 if (strcmp(view->name, "_bind") == 0 && 1120 view->rdclass == dns_rdataclass_chaos) 1121 { 1122 return ISC_R_SUCCESS; 1123 } 1124 1125 if (vconfig != NULL) { 1126 voptions = cfg_tuple_get(vconfig, "options"); 1127 if (voptions != NULL) { 1128 (void)cfg_map_get(voptions, "trusted-keys", &view_keys); 1129 1130 /* managed-keys and trust-anchors are synonyms. */ 1131 (void)cfg_map_get(voptions, "managed-keys", 1132 &view_managed_keys); 1133 (void)cfg_map_get(voptions, "trust-anchors", 1134 &view_trust_anchors); 1135 1136 maps[i++] = voptions; 1137 } 1138 } 1139 1140 if (config != NULL) { 1141 (void)cfg_map_get(config, "trusted-keys", &global_keys); 1142 1143 /* managed-keys and trust-anchors are synonyms. */ 1144 (void)cfg_map_get(config, "managed-keys", &global_managed_keys); 1145 (void)cfg_map_get(config, "trust-anchors", 1146 &global_trust_anchors); 1147 1148 (void)cfg_map_get(config, "options", &options); 1149 if (options != NULL) { 1150 maps[i++] = options; 1151 } 1152 } 1153 1154 maps[i++] = named_g_defaults; 1155 maps[i] = NULL; 1156 1157 dns_view_initsecroots(view); 1158 dns_view_initntatable(view, named_g_loopmgr); 1159 1160 if (auto_root && view->rdclass == dns_rdataclass_in) { 1161 const cfg_obj_t *builtin_keys = NULL; 1162 1163 /* 1164 * If bind.keys exists and is populated, it overrides 1165 * the trust-anchors clause hard-coded in named_g_config. 1166 */ 1167 if (bindkeys != NULL) { 1168 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1169 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1170 "obtaining root key for view %s " 1171 "from '%s'", 1172 view->name, named_g_server->bindkeysfile); 1173 1174 (void)cfg_map_get(bindkeys, "trust-anchors", 1175 &builtin_keys); 1176 1177 if (builtin_keys == NULL) { 1178 isc_log_write( 1179 named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1180 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 1181 "dnssec-validation auto: " 1182 "WARNING: root zone key " 1183 "not found"); 1184 } 1185 } 1186 1187 if (builtin_keys == NULL) { 1188 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1189 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1190 "using built-in root key for view %s", 1191 view->name); 1192 1193 (void)cfg_map_get(named_g_config, "trust-anchors", 1194 &builtin_keys); 1195 } 1196 1197 if (builtin_keys != NULL) { 1198 CHECK(load_view_keys(builtin_keys, view, true, 1199 dns_rootname)); 1200 } 1201 1202 if (!keyloaded(view, dns_rootname)) { 1203 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1204 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1205 "root key not loaded"); 1206 result = ISC_R_FAILURE; 1207 goto cleanup; 1208 } 1209 } 1210 1211 if (view->rdclass == dns_rdataclass_in) { 1212 CHECK(load_view_keys(view_keys, view, false, NULL)); 1213 CHECK(load_view_keys(view_trust_anchors, view, true, NULL)); 1214 CHECK(load_view_keys(view_managed_keys, view, true, NULL)); 1215 1216 CHECK(load_view_keys(global_keys, view, false, NULL)); 1217 CHECK(load_view_keys(global_trust_anchors, view, true, NULL)); 1218 CHECK(load_view_keys(global_managed_keys, view, true, NULL)); 1219 } 1220 1221 /* 1222 * Add key zone for managed keys. 1223 */ 1224 obj = NULL; 1225 (void)named_config_get(maps, "managed-keys-directory", &obj); 1226 directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL); 1227 if (directory != NULL) { 1228 result = isc_file_isdirectory(directory); 1229 } 1230 if (result != ISC_R_SUCCESS) { 1231 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1232 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1233 "invalid managed-keys-directory %s: %s", 1234 directory, isc_result_totext(result)); 1235 goto cleanup; 1236 } else if (directory != NULL) { 1237 if (!isc_file_isdirwritable(directory)) { 1238 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1239 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1240 "managed-keys-directory '%s' " 1241 "is not writable", 1242 directory); 1243 result = ISC_R_NOPERM; 1244 goto cleanup; 1245 } 1246 } 1247 1248 if (auto_root) { 1249 CHECK(add_keydata_zone(view, directory, named_g_mctx)); 1250 } 1251 1252 cleanup: 1253 return result; 1254 } 1255 1256 static isc_result_t 1257 mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { 1258 const cfg_listelt_t *element; 1259 const cfg_obj_t *obj; 1260 const char *str; 1261 dns_fixedname_t fixed; 1262 dns_name_t *name; 1263 bool value; 1264 isc_result_t result; 1265 isc_buffer_t b; 1266 1267 name = dns_fixedname_initname(&fixed); 1268 for (element = cfg_list_first(mbs); element != NULL; 1269 element = cfg_list_next(element)) 1270 { 1271 obj = cfg_listelt_value(element); 1272 str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 1273 isc_buffer_constinit(&b, str, strlen(str)); 1274 isc_buffer_add(&b, strlen(str)); 1275 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1276 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); 1277 CHECK(dns_resolver_setmustbesecure(resolver, name, value)); 1278 } 1279 1280 result = ISC_R_SUCCESS; 1281 1282 cleanup: 1283 return result; 1284 } 1285 1286 /*% 1287 * Get a dispatch appropriate for the resolver of a given view. 1288 */ 1289 static isc_result_t 1290 get_view_querysource_dispatch(const cfg_obj_t **maps, int af, 1291 dns_dispatch_t **dispatchp, bool is_firstview) { 1292 isc_result_t result = ISC_R_FAILURE; 1293 dns_dispatch_t *disp = NULL; 1294 isc_sockaddr_t sa; 1295 const cfg_obj_t *obj = NULL; 1296 1297 switch (af) { 1298 case AF_INET: 1299 result = named_config_get(maps, "query-source", &obj); 1300 INSIST(result == ISC_R_SUCCESS); 1301 break; 1302 case AF_INET6: 1303 result = named_config_get(maps, "query-source-v6", &obj); 1304 INSIST(result == ISC_R_SUCCESS); 1305 break; 1306 default: 1307 UNREACHABLE(); 1308 } 1309 1310 if (cfg_obj_isvoid(obj)) { 1311 /* 1312 * We don't want to use this address family, let's 1313 * bail now. The dispatch object for this family will 1314 * be null then not used to run queries. 1315 */ 1316 return ISC_R_SUCCESS; 1317 } else { 1318 /* 1319 * obj _has_ to be sockaddr here, cfg_obj_assockaddr() 1320 * asserts this internally. 1321 */ 1322 sa = *(cfg_obj_assockaddr(obj)); 1323 INSIST(isc_sockaddr_pf(&sa) == af); 1324 } 1325 1326 /* 1327 * If we don't support this address family, we're done! 1328 */ 1329 switch (af) { 1330 case AF_INET: 1331 result = isc_net_probeipv4(); 1332 break; 1333 case AF_INET6: 1334 result = isc_net_probeipv6(); 1335 break; 1336 default: 1337 UNREACHABLE(); 1338 } 1339 if (result != ISC_R_SUCCESS) { 1340 return ISC_R_SUCCESS; 1341 } 1342 1343 /* 1344 * Try to find a dispatcher that we can share. 1345 */ 1346 if (isc_sockaddr_getport(&sa) != 0) { 1347 INSIST(obj != NULL); 1348 if (is_firstview) { 1349 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 1350 "using specific query-source port " 1351 "suppresses port randomization and can be " 1352 "insecure."); 1353 } 1354 } 1355 1356 result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, &disp); 1357 if (result != ISC_R_SUCCESS) { 1358 isc_sockaddr_t any; 1359 char buf[ISC_SOCKADDR_FORMATSIZE]; 1360 1361 switch (af) { 1362 case AF_INET: 1363 isc_sockaddr_any(&any); 1364 break; 1365 case AF_INET6: 1366 isc_sockaddr_any6(&any); 1367 break; 1368 } 1369 if (isc_sockaddr_equal(&sa, &any)) { 1370 return ISC_R_SUCCESS; 1371 } 1372 isc_sockaddr_format(&sa, buf, sizeof(buf)); 1373 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1374 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1375 "could not get query source dispatcher (%s): %s", 1376 buf, isc_result_totext(result)); 1377 return result; 1378 } 1379 1380 *dispatchp = disp; 1381 1382 return ISC_R_SUCCESS; 1383 } 1384 1385 static isc_result_t 1386 configure_order(dns_order_t *order, const cfg_obj_t *ent) { 1387 dns_rdataclass_t rdclass; 1388 dns_rdatatype_t rdtype; 1389 const cfg_obj_t *obj; 1390 dns_fixedname_t fixed; 1391 unsigned int mode = 0; 1392 const char *str; 1393 isc_buffer_t b; 1394 isc_result_t result; 1395 bool addroot; 1396 1397 result = named_config_getclass(cfg_tuple_get(ent, "class"), 1398 dns_rdataclass_any, &rdclass); 1399 if (result != ISC_R_SUCCESS) { 1400 return result; 1401 } 1402 1403 result = named_config_gettype(cfg_tuple_get(ent, "type"), 1404 dns_rdatatype_any, &rdtype); 1405 if (result != ISC_R_SUCCESS) { 1406 return result; 1407 } 1408 1409 obj = cfg_tuple_get(ent, "name"); 1410 if (cfg_obj_isstring(obj)) { 1411 str = cfg_obj_asstring(obj); 1412 } else { 1413 str = "*"; 1414 } 1415 addroot = (strcmp(str, "*") == 0); 1416 isc_buffer_constinit(&b, str, strlen(str)); 1417 isc_buffer_add(&b, strlen(str)); 1418 dns_fixedname_init(&fixed); 1419 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, dns_rootname, 1420 0, NULL); 1421 if (result != ISC_R_SUCCESS) { 1422 return result; 1423 } 1424 1425 obj = cfg_tuple_get(ent, "ordering"); 1426 INSIST(cfg_obj_isstring(obj)); 1427 str = cfg_obj_asstring(obj); 1428 if (!strcasecmp(str, "fixed")) { 1429 #if DNS_RDATASET_FIXED 1430 mode = DNS_RDATASETATTR_FIXEDORDER; 1431 #else /* if DNS_RDATASET_FIXED */ 1432 mode = DNS_RDATASETATTR_CYCLIC; 1433 #endif /* DNS_RDATASET_FIXED */ 1434 } else if (!strcasecmp(str, "random")) { 1435 mode = DNS_RDATASETATTR_RANDOMIZE; 1436 } else if (!strcasecmp(str, "cyclic")) { 1437 mode = DNS_RDATASETATTR_CYCLIC; 1438 } else if (!strcasecmp(str, "none")) { 1439 mode = DNS_RDATASETATTR_NONE; 1440 } else { 1441 UNREACHABLE(); 1442 } 1443 1444 /* 1445 * "*" should match everything including the root (BIND 8 compat). 1446 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a 1447 * explicit entry for "." when the name is "*". 1448 */ 1449 if (addroot) { 1450 result = dns_order_add(order, dns_rootname, rdtype, rdclass, 1451 mode); 1452 if (result != ISC_R_SUCCESS) { 1453 return result; 1454 } 1455 } 1456 1457 return dns_order_add(order, dns_fixedname_name(&fixed), rdtype, rdclass, 1458 mode); 1459 } 1460 1461 static isc_result_t 1462 configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { 1463 isc_netaddr_t na; 1464 dns_peer_t *peer; 1465 const cfg_obj_t *obj; 1466 const char *str; 1467 isc_result_t result; 1468 unsigned int prefixlen; 1469 1470 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); 1471 1472 peer = NULL; 1473 result = dns_peer_newprefix(mctx, &na, prefixlen, &peer); 1474 if (result != ISC_R_SUCCESS) { 1475 return result; 1476 } 1477 1478 obj = NULL; 1479 (void)cfg_map_get(cpeer, "bogus", &obj); 1480 if (obj != NULL) { 1481 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); 1482 } 1483 1484 obj = NULL; 1485 (void)cfg_map_get(cpeer, "provide-ixfr", &obj); 1486 if (obj != NULL) { 1487 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); 1488 } 1489 1490 obj = NULL; 1491 (void)cfg_map_get(cpeer, "request-expire", &obj); 1492 if (obj != NULL) { 1493 CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj))); 1494 } 1495 1496 obj = NULL; 1497 (void)cfg_map_get(cpeer, "request-ixfr", &obj); 1498 if (obj != NULL) { 1499 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); 1500 } 1501 1502 obj = NULL; 1503 (void)cfg_map_get(cpeer, "request-nsid", &obj); 1504 if (obj != NULL) { 1505 CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); 1506 } 1507 1508 obj = NULL; 1509 (void)cfg_map_get(cpeer, "send-cookie", &obj); 1510 if (obj != NULL) { 1511 CHECK(dns_peer_setsendcookie(peer, cfg_obj_asboolean(obj))); 1512 } 1513 1514 obj = NULL; 1515 (void)cfg_map_get(cpeer, "require-cookie", &obj); 1516 if (obj != NULL) { 1517 CHECK(dns_peer_setrequirecookie(peer, cfg_obj_asboolean(obj))); 1518 } 1519 1520 obj = NULL; 1521 (void)cfg_map_get(cpeer, "edns", &obj); 1522 if (obj != NULL) { 1523 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); 1524 } 1525 1526 obj = NULL; 1527 (void)cfg_map_get(cpeer, "edns-udp-size", &obj); 1528 if (obj != NULL) { 1529 uint32_t udpsize = cfg_obj_asuint32(obj); 1530 if (udpsize < 512U) { 1531 udpsize = 512U; 1532 } 1533 if (udpsize > 4096U) { 1534 udpsize = 4096U; 1535 } 1536 CHECK(dns_peer_setudpsize(peer, (uint16_t)udpsize)); 1537 } 1538 1539 obj = NULL; 1540 (void)cfg_map_get(cpeer, "edns-version", &obj); 1541 if (obj != NULL) { 1542 uint32_t ednsversion = cfg_obj_asuint32(obj); 1543 if (ednsversion > 255U) { 1544 ednsversion = 255U; 1545 } 1546 CHECK(dns_peer_setednsversion(peer, (uint8_t)ednsversion)); 1547 } 1548 1549 obj = NULL; 1550 (void)cfg_map_get(cpeer, "max-udp-size", &obj); 1551 if (obj != NULL) { 1552 uint32_t udpsize = cfg_obj_asuint32(obj); 1553 if (udpsize < 512U) { 1554 udpsize = 512U; 1555 } 1556 if (udpsize > 4096U) { 1557 udpsize = 4096U; 1558 } 1559 CHECK(dns_peer_setmaxudp(peer, (uint16_t)udpsize)); 1560 } 1561 1562 obj = NULL; 1563 (void)cfg_map_get(cpeer, "padding", &obj); 1564 if (obj != NULL) { 1565 uint32_t padding = cfg_obj_asuint32(obj); 1566 if (padding > 512U) { 1567 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 1568 "server padding value cannot " 1569 "exceed 512: lowering"); 1570 padding = 512U; 1571 } 1572 CHECK(dns_peer_setpadding(peer, (uint16_t)padding)); 1573 } 1574 1575 obj = NULL; 1576 (void)cfg_map_get(cpeer, "tcp-only", &obj); 1577 if (obj != NULL) { 1578 CHECK(dns_peer_setforcetcp(peer, cfg_obj_asboolean(obj))); 1579 } 1580 1581 obj = NULL; 1582 (void)cfg_map_get(cpeer, "tcp-keepalive", &obj); 1583 if (obj != NULL) { 1584 CHECK(dns_peer_settcpkeepalive(peer, cfg_obj_asboolean(obj))); 1585 } 1586 1587 obj = NULL; 1588 (void)cfg_map_get(cpeer, "transfers", &obj); 1589 if (obj != NULL) { 1590 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); 1591 } 1592 1593 obj = NULL; 1594 (void)cfg_map_get(cpeer, "transfer-format", &obj); 1595 if (obj != NULL) { 1596 str = cfg_obj_asstring(obj); 1597 if (strcasecmp(str, "many-answers") == 0) { 1598 CHECK(dns_peer_settransferformat(peer, 1599 dns_many_answers)); 1600 } else if (strcasecmp(str, "one-answer") == 0) { 1601 CHECK(dns_peer_settransferformat(peer, dns_one_answer)); 1602 } else { 1603 UNREACHABLE(); 1604 } 1605 } 1606 1607 obj = NULL; 1608 (void)cfg_map_get(cpeer, "keys", &obj); 1609 if (obj != NULL) { 1610 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); 1611 if (result != ISC_R_SUCCESS) { 1612 goto cleanup; 1613 } 1614 } 1615 1616 obj = NULL; 1617 if (na.family == AF_INET) { 1618 (void)cfg_map_get(cpeer, "transfer-source", &obj); 1619 } else { 1620 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); 1621 } 1622 if (obj != NULL) { 1623 result = dns_peer_settransfersource(peer, 1624 cfg_obj_assockaddr(obj)); 1625 if (result != ISC_R_SUCCESS) { 1626 goto cleanup; 1627 } 1628 } 1629 1630 obj = NULL; 1631 if (na.family == AF_INET) { 1632 (void)cfg_map_get(cpeer, "notify-source", &obj); 1633 } else { 1634 (void)cfg_map_get(cpeer, "notify-source-v6", &obj); 1635 } 1636 if (obj != NULL) { 1637 result = dns_peer_setnotifysource(peer, 1638 cfg_obj_assockaddr(obj)); 1639 if (result != ISC_R_SUCCESS) { 1640 goto cleanup; 1641 } 1642 } 1643 1644 obj = NULL; 1645 if (na.family == AF_INET) { 1646 (void)cfg_map_get(cpeer, "query-source", &obj); 1647 } else { 1648 (void)cfg_map_get(cpeer, "query-source-v6", &obj); 1649 } 1650 if (obj != NULL) { 1651 INSIST(cfg_obj_issockaddr(obj)); 1652 result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj)); 1653 if (result != ISC_R_SUCCESS) { 1654 goto cleanup; 1655 } 1656 } 1657 1658 *peerp = peer; 1659 return ISC_R_SUCCESS; 1660 1661 cleanup: 1662 dns_peer_detach(&peer); 1663 return result; 1664 } 1665 1666 static isc_result_t 1667 configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, 1668 const dns_dyndbctx_t *dctx) { 1669 isc_result_t result = ISC_R_SUCCESS; 1670 const cfg_obj_t *obj; 1671 const char *name, *library; 1672 1673 /* Get the name of the dyndb instance and the library path . */ 1674 name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name")); 1675 library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library")); 1676 1677 obj = cfg_tuple_get(dyndb, "parameters"); 1678 if (obj != NULL) { 1679 result = dns_dyndb_load(library, name, cfg_obj_asstring(obj), 1680 cfg_obj_file(obj), cfg_obj_line(obj), 1681 mctx, dctx); 1682 } 1683 1684 if (result != ISC_R_SUCCESS) { 1685 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1686 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1687 "dynamic database '%s' configuration failed: %s", 1688 name, isc_result_totext(result)); 1689 } 1690 return result; 1691 } 1692 1693 static isc_result_t 1694 disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1695 isc_result_t result; 1696 const cfg_obj_t *algorithms; 1697 const cfg_listelt_t *element; 1698 const char *str; 1699 dns_fixedname_t fixed; 1700 dns_name_t *name; 1701 isc_buffer_t b; 1702 1703 name = dns_fixedname_initname(&fixed); 1704 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1705 isc_buffer_constinit(&b, str, strlen(str)); 1706 isc_buffer_add(&b, strlen(str)); 1707 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1708 1709 algorithms = cfg_tuple_get(disabled, "algorithms"); 1710 for (element = cfg_list_first(algorithms); element != NULL; 1711 element = cfg_list_next(element)) 1712 { 1713 isc_textregion_t r; 1714 dns_secalg_t alg; 1715 1716 r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element))); 1717 r.length = strlen(r.base); 1718 1719 result = dns_secalg_fromtext(&alg, &r); 1720 if (result != ISC_R_SUCCESS) { 1721 uint8_t ui; 1722 result = isc_parse_uint8(&ui, r.base, 10); 1723 alg = ui; 1724 } 1725 if (result != ISC_R_SUCCESS) { 1726 cfg_obj_log(cfg_listelt_value(element), named_g_lctx, 1727 ISC_LOG_ERROR, "invalid algorithm"); 1728 CHECK(result); 1729 } 1730 CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); 1731 } 1732 cleanup: 1733 return result; 1734 } 1735 1736 static isc_result_t 1737 disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1738 isc_result_t result; 1739 const cfg_obj_t *digests; 1740 const cfg_listelt_t *element; 1741 const char *str; 1742 dns_fixedname_t fixed; 1743 dns_name_t *name; 1744 isc_buffer_t b; 1745 1746 name = dns_fixedname_initname(&fixed); 1747 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1748 isc_buffer_constinit(&b, str, strlen(str)); 1749 isc_buffer_add(&b, strlen(str)); 1750 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1751 1752 digests = cfg_tuple_get(disabled, "digests"); 1753 for (element = cfg_list_first(digests); element != NULL; 1754 element = cfg_list_next(element)) 1755 { 1756 isc_textregion_t r; 1757 dns_dsdigest_t digest; 1758 1759 r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element))); 1760 r.length = strlen(r.base); 1761 1762 /* disable_ds_digests handles numeric values. */ 1763 result = dns_dsdigest_fromtext(&digest, &r); 1764 if (result != ISC_R_SUCCESS) { 1765 cfg_obj_log(cfg_listelt_value(element), named_g_lctx, 1766 ISC_LOG_ERROR, "invalid algorithm"); 1767 CHECK(result); 1768 } 1769 CHECK(dns_resolver_disable_ds_digest(resolver, name, digest)); 1770 } 1771 cleanup: 1772 return result; 1773 } 1774 1775 static bool 1776 on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { 1777 const cfg_listelt_t *element; 1778 dns_fixedname_t fixed; 1779 dns_name_t *name; 1780 isc_result_t result; 1781 const cfg_obj_t *value; 1782 const char *str; 1783 isc_buffer_t b; 1784 1785 name = dns_fixedname_initname(&fixed); 1786 1787 for (element = cfg_list_first(disablelist); element != NULL; 1788 element = cfg_list_next(element)) 1789 { 1790 value = cfg_listelt_value(element); 1791 str = cfg_obj_asstring(value); 1792 isc_buffer_constinit(&b, str, strlen(str)); 1793 isc_buffer_add(&b, strlen(str)); 1794 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 1795 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1796 if (dns_name_equal(name, zonename)) { 1797 return true; 1798 } 1799 } 1800 return false; 1801 } 1802 1803 static isc_result_t 1804 check_dbtype(dns_zone_t *zone, unsigned int dbtypec, const char **dbargv, 1805 isc_mem_t *mctx) { 1806 char **argv = NULL; 1807 unsigned int i; 1808 isc_result_t result = ISC_R_SUCCESS; 1809 1810 CHECK(dns_zone_getdbtype(zone, &argv, mctx)); 1811 1812 /* 1813 * Check that all the arguments match. 1814 */ 1815 for (i = 0; i < dbtypec; i++) { 1816 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) { 1817 CHECK(ISC_R_FAILURE); 1818 } 1819 } 1820 1821 /* 1822 * Check that there are not extra arguments. 1823 */ 1824 if (i == dbtypec && argv[i] != NULL) { 1825 result = ISC_R_FAILURE; 1826 } 1827 1828 cleanup: 1829 isc_mem_free(mctx, argv); 1830 return result; 1831 } 1832 1833 static void 1834 setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) { 1835 isc_stats_t *zoneqrystats; 1836 1837 dns_zone_setstatlevel(zone, level); 1838 1839 zoneqrystats = NULL; 1840 if (level == dns_zonestat_full) { 1841 isc_stats_create(mctx, &zoneqrystats, ns_statscounter_max); 1842 } 1843 dns_zone_setrequeststats(zone, zoneqrystats); 1844 if (zoneqrystats != NULL) { 1845 isc_stats_detach(&zoneqrystats); 1846 } 1847 } 1848 1849 static named_cache_t * 1850 cachelist_find(named_cachelist_t *cachelist, const char *cachename, 1851 dns_rdataclass_t rdclass) { 1852 for (named_cache_t *nsc = ISC_LIST_HEAD(*cachelist); nsc != NULL; 1853 nsc = ISC_LIST_NEXT(nsc, link)) 1854 { 1855 if (nsc->rdclass == rdclass && 1856 strcmp(dns_cache_getname(nsc->cache), cachename) == 0) 1857 { 1858 return nsc; 1859 } 1860 } 1861 1862 return NULL; 1863 } 1864 1865 static bool 1866 cache_reusable(dns_view_t *originview, dns_view_t *view, 1867 bool new_zero_no_soattl) { 1868 if (originview->rdclass != view->rdclass || 1869 originview->checknames != view->checknames || 1870 originview->acceptexpired != view->acceptexpired || 1871 originview->enablevalidation != view->enablevalidation || 1872 originview->maxcachettl != view->maxcachettl || 1873 originview->maxncachettl != view->maxncachettl || 1874 originview->resolver == NULL || 1875 dns_resolver_getzeronosoattl(originview->resolver) != 1876 new_zero_no_soattl) 1877 { 1878 return false; 1879 } 1880 1881 return true; 1882 } 1883 1884 static bool 1885 cache_sharable(dns_view_t *originview, dns_view_t *view, 1886 bool new_zero_no_soattl, uint64_t new_max_cache_size, 1887 uint32_t new_stale_ttl, uint32_t new_stale_refresh_time) { 1888 /* 1889 * If the cache cannot even reused for the same view, it cannot be 1890 * shared with other views. 1891 */ 1892 if (!cache_reusable(originview, view, new_zero_no_soattl)) { 1893 return false; 1894 } 1895 1896 /* 1897 * Check other cache related parameters that must be consistent among 1898 * the sharing views. 1899 */ 1900 if (dns_cache_getservestalettl(originview->cache) != new_stale_ttl || 1901 dns_cache_getservestalerefresh(originview->cache) != 1902 new_stale_refresh_time || 1903 dns_cache_getcachesize(originview->cache) != new_max_cache_size) 1904 { 1905 return false; 1906 } 1907 1908 return true; 1909 } 1910 1911 /* 1912 * Callback from DLZ configure when the driver sets up a writeable zone 1913 */ 1914 static isc_result_t 1915 dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) { 1916 dns_name_t *origin = dns_zone_getorigin(zone); 1917 dns_rdataclass_t zclass = view->rdclass; 1918 isc_result_t result; 1919 1920 result = dns_zonemgr_managezone(named_g_server->zonemgr, zone); 1921 if (result != ISC_R_SUCCESS) { 1922 return result; 1923 } 1924 dns_zone_setstats(zone, named_g_server->zonestats); 1925 1926 return named_zone_configure_writeable_dlz(dlzdb, zone, zclass, origin); 1927 } 1928 1929 static isc_result_t 1930 dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, 1931 unsigned int prefixlen, const char *server, const char *contact) { 1932 char reverse[48 + sizeof("ip6.arpa.")] = { 0 }; 1933 char buf[sizeof("x.x.")]; 1934 const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." }; 1935 const char *sep = ": view "; 1936 const char *viewname = view->name; 1937 const unsigned char *s6; 1938 dns_fixedname_t fixed; 1939 dns_name_t *name; 1940 dns_zone_t *zone = NULL; 1941 int dns64_dbtypec = 4; 1942 isc_buffer_t b; 1943 isc_result_t result; 1944 1945 REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || 1946 prefixlen == 56 || prefixlen == 64 || prefixlen == 96); 1947 1948 if (!strcmp(viewname, "_default")) { 1949 sep = ""; 1950 viewname = ""; 1951 } 1952 1953 /* 1954 * Construct the reverse name of the zone. 1955 */ 1956 s6 = na->type.in6.s6_addr; 1957 while (prefixlen > 0) { 1958 prefixlen -= 8; 1959 snprintf(buf, sizeof(buf), "%x.%x.", s6[prefixlen / 8] & 0xf, 1960 (s6[prefixlen / 8] >> 4) & 0xf); 1961 strlcat(reverse, buf, sizeof(reverse)); 1962 } 1963 strlcat(reverse, "ip6.arpa.", sizeof(reverse)); 1964 1965 /* 1966 * Create the actual zone. 1967 */ 1968 if (server != NULL) { 1969 dns64_dbtype[2] = server; 1970 } 1971 if (contact != NULL) { 1972 dns64_dbtype[3] = contact; 1973 } 1974 name = dns_fixedname_initname(&fixed); 1975 isc_buffer_constinit(&b, reverse, strlen(reverse)); 1976 isc_buffer_add(&b, strlen(reverse)); 1977 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1978 dns_zone_create(&zone, mctx, 0); 1979 CHECK(dns_zone_setorigin(zone, name)); 1980 dns_zone_setview(zone, view); 1981 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 1982 dns_zone_setclass(zone, view->rdclass); 1983 dns_zone_settype(zone, dns_zone_primary); 1984 dns_zone_setstats(zone, named_g_server->zonestats); 1985 dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype); 1986 if (view->queryacl != NULL) { 1987 dns_zone_setqueryacl(zone, view->queryacl); 1988 } 1989 if (view->queryonacl != NULL) { 1990 dns_zone_setqueryonacl(zone, view->queryonacl); 1991 } 1992 dns_zone_setdialup(zone, dns_dialuptype_no); 1993 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 1994 dns_zone_setnotifytype(zone, dns_notifytype_no); 1995 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 1996 setquerystats(zone, mctx, dns_zonestat_none); 1997 CHECK(dns_view_addzone(view, zone)); 1998 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1999 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 2000 "dns64 reverse zone%s%s: %s", sep, viewname, reverse); 2001 2002 cleanup: 2003 if (zone != NULL) { 2004 dns_zone_detach(&zone); 2005 } 2006 return result; 2007 } 2008 2009 #ifdef USE_DNSRPS 2010 typedef struct conf_dnsrps_ctx conf_dnsrps_ctx_t; 2011 struct conf_dnsrps_ctx { 2012 isc_result_t result; 2013 char *cstr; 2014 size_t cstr_size; 2015 isc_mem_t *mctx; 2016 }; 2017 2018 /* 2019 * Add to the DNSRPS configuration string. 2020 */ 2021 static bool 2022 conf_dnsrps_sadd(conf_dnsrps_ctx_t *ctx, const char *p, ...) { 2023 size_t new_len, cur_len, new_cstr_size; 2024 char *new_cstr; 2025 va_list args; 2026 2027 if (ctx->cstr == NULL) { 2028 ctx->cstr = isc_mem_get(ctx->mctx, 256); 2029 ctx->cstr[0] = '\0'; 2030 ctx->cstr_size = 256; 2031 } 2032 2033 cur_len = strlen(ctx->cstr); 2034 va_start(args, p); 2035 new_len = vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, 2036 args) + 2037 1; 2038 va_end(args); 2039 2040 if (cur_len + new_len <= ctx->cstr_size) { 2041 return true; 2042 } 2043 2044 new_cstr_size = ((cur_len + new_len) / 256 + 1) * 256; 2045 new_cstr = isc_mem_get(ctx->mctx, new_cstr_size); 2046 2047 memmove(new_cstr, ctx->cstr, cur_len); 2048 isc_mem_put(ctx->mctx, ctx->cstr, ctx->cstr_size); 2049 ctx->cstr_size = new_cstr_size; 2050 ctx->cstr = new_cstr; 2051 2052 /* cannot use args twice after a single va_start()on some systems */ 2053 va_start(args, p); 2054 vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, args); 2055 va_end(args); 2056 return true; 2057 } 2058 2059 /* 2060 * Get a DNSRPS configuration value using the global and view options 2061 * for the default. Return false upon failure. 2062 */ 2063 static bool 2064 conf_dnsrps_get(const cfg_obj_t **sub_obj, const cfg_obj_t **maps, 2065 const cfg_obj_t *obj, const char *name, 2066 conf_dnsrps_ctx_t *ctx) { 2067 if (ctx != NULL && ctx->result != ISC_R_SUCCESS) { 2068 *sub_obj = NULL; 2069 return false; 2070 } 2071 2072 *sub_obj = cfg_tuple_get(obj, name); 2073 if (cfg_obj_isvoid(*sub_obj)) { 2074 *sub_obj = NULL; 2075 if (maps != NULL && 2076 ISC_R_SUCCESS != named_config_get(maps, name, sub_obj)) 2077 { 2078 *sub_obj = NULL; 2079 } 2080 } 2081 return true; 2082 } 2083 2084 /* 2085 * Handle a DNSRPS boolean configuration value with the global and view 2086 * options providing the default. 2087 */ 2088 static void 2089 conf_dnsrps_yes_no(const cfg_obj_t *obj, const char *name, 2090 conf_dnsrps_ctx_t *ctx) { 2091 const cfg_obj_t *sub_obj; 2092 2093 if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { 2094 return; 2095 } 2096 if (sub_obj == NULL) { 2097 return; 2098 } 2099 if (ctx == NULL) { 2100 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 2101 "\"%s\" without \"dnsrps-enable yes\"", name); 2102 return; 2103 } 2104 2105 conf_dnsrps_sadd(ctx, " %s %s", name, 2106 cfg_obj_asboolean(sub_obj) ? "yes" : "no"); 2107 } 2108 2109 static void 2110 conf_dnsrps_num(const cfg_obj_t *obj, const char *name, 2111 conf_dnsrps_ctx_t *ctx) { 2112 const cfg_obj_t *sub_obj; 2113 2114 if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { 2115 return; 2116 } 2117 if (sub_obj == NULL) { 2118 return; 2119 } 2120 if (ctx == NULL) { 2121 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 2122 "\"%s\" without \"dnsrps-enable yes\"", name); 2123 return; 2124 } 2125 2126 if (cfg_obj_isduration(sub_obj)) { 2127 conf_dnsrps_sadd(ctx, " %s %d", name, 2128 cfg_obj_asduration(sub_obj)); 2129 } else { 2130 conf_dnsrps_sadd(ctx, " %s %d", name, 2131 cfg_obj_asuint32(sub_obj)); 2132 } 2133 } 2134 2135 /* 2136 * Convert the parsed RPZ configuration statement to a string for 2137 * dns_rpz_new_zones(). 2138 */ 2139 static isc_result_t 2140 conf_dnsrps(dns_view_t *view, const cfg_obj_t **maps, bool nsip_enabled, 2141 bool nsdname_enabled, dns_rpz_zbits_t *nsip_on, 2142 dns_rpz_zbits_t *nsdname_on, char **rps_cstr, size_t *rps_cstr_size, 2143 const cfg_obj_t *rpz_obj, const cfg_listelt_t *zone_element) { 2144 conf_dnsrps_ctx_t ctx; 2145 const cfg_obj_t *zone_obj, *obj; 2146 dns_rpz_num_t rpz_num; 2147 bool on; 2148 const char *s; 2149 2150 memset(&ctx, 0, sizeof(ctx)); 2151 ctx.result = ISC_R_SUCCESS; 2152 ctx.mctx = view->mctx; 2153 2154 for (rpz_num = 0; zone_element != NULL && ctx.result == ISC_R_SUCCESS; 2155 ++rpz_num) 2156 { 2157 zone_obj = cfg_listelt_value(zone_element); 2158 2159 s = cfg_obj_asstring(cfg_tuple_get(zone_obj, "zone name")); 2160 conf_dnsrps_sadd(&ctx, "zone \"%s\"", s); 2161 2162 obj = cfg_tuple_get(zone_obj, "policy"); 2163 if (!cfg_obj_isvoid(obj)) { 2164 s = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 2165 conf_dnsrps_sadd(&ctx, " policy %s", s); 2166 if (strcasecmp(s, "cname") == 0) { 2167 s = cfg_obj_asstring( 2168 cfg_tuple_get(obj, "cname")); 2169 conf_dnsrps_sadd(&ctx, " %s", s); 2170 } 2171 } 2172 2173 conf_dnsrps_yes_no(zone_obj, "recursive-only", &ctx); 2174 conf_dnsrps_yes_no(zone_obj, "log", &ctx); 2175 conf_dnsrps_num(zone_obj, "max-policy-ttl", &ctx); 2176 obj = cfg_tuple_get(rpz_obj, "nsip-enable"); 2177 if (!cfg_obj_isvoid(obj)) { 2178 if (cfg_obj_asboolean(obj)) { 2179 *nsip_on |= DNS_RPZ_ZBIT(rpz_num); 2180 } else { 2181 *nsip_on &= ~DNS_RPZ_ZBIT(rpz_num); 2182 } 2183 } 2184 on = ((*nsip_on & DNS_RPZ_ZBIT(rpz_num)) != 0); 2185 if (nsip_enabled != on) { 2186 conf_dnsrps_sadd(&ctx, on ? " nsip-enable yes " 2187 : " nsip-enable no "); 2188 } 2189 obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); 2190 if (!cfg_obj_isvoid(obj)) { 2191 if (cfg_obj_asboolean(obj)) { 2192 *nsdname_on |= DNS_RPZ_ZBIT(rpz_num); 2193 } else { 2194 *nsdname_on &= ~DNS_RPZ_ZBIT(rpz_num); 2195 } 2196 } 2197 on = ((*nsdname_on & DNS_RPZ_ZBIT(rpz_num)) != 0); 2198 if (nsdname_enabled != on) { 2199 conf_dnsrps_sadd(&ctx, on ? " nsdname-enable yes " 2200 : " nsdname-enable no "); 2201 } 2202 conf_dnsrps_sadd(&ctx, ";\n"); 2203 zone_element = cfg_list_next(zone_element); 2204 } 2205 2206 conf_dnsrps_yes_no(rpz_obj, "recursive-only", &ctx); 2207 conf_dnsrps_num(rpz_obj, "max-policy-ttl", &ctx); 2208 conf_dnsrps_num(rpz_obj, "min-ns-dots", &ctx); 2209 conf_dnsrps_yes_no(rpz_obj, "qname-wait-recurse", &ctx); 2210 conf_dnsrps_yes_no(rpz_obj, "break-dnssec", &ctx); 2211 if (!nsip_enabled) { 2212 conf_dnsrps_sadd(&ctx, " nsip-enable no "); 2213 } 2214 if (!nsdname_enabled) { 2215 conf_dnsrps_sadd(&ctx, " nsdname-enable no "); 2216 } 2217 2218 /* 2219 * Get the general dnsrpzd parameters from the response-policy 2220 * statement in the view and the general options. 2221 */ 2222 if (conf_dnsrps_get(&obj, maps, rpz_obj, "dnsrps-options", &ctx) && 2223 obj != NULL) 2224 { 2225 conf_dnsrps_sadd(&ctx, " %s\n", cfg_obj_asstring(obj)); 2226 } 2227 2228 if (ctx.result == ISC_R_SUCCESS) { 2229 *rps_cstr = ctx.cstr; 2230 *rps_cstr_size = ctx.cstr_size; 2231 } else { 2232 if (ctx.cstr != NULL) { 2233 isc_mem_put(ctx.mctx, ctx.cstr, ctx.cstr_size); 2234 } 2235 *rps_cstr = NULL; 2236 *rps_cstr_size = 0; 2237 } 2238 return ctx.result; 2239 } 2240 #endif /* ifdef USE_DNSRPS */ 2241 2242 static isc_result_t 2243 configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 2244 const char *str, const char *msg) { 2245 isc_result_t result; 2246 2247 result = dns_name_fromstring(name, str, dns_rootname, DNS_NAME_DOWNCASE, 2248 view->mctx); 2249 if (result != ISC_R_SUCCESS) { 2250 cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2251 "invalid %s '%s'", msg, str); 2252 } 2253 return result; 2254 } 2255 2256 static isc_result_t 2257 configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 2258 const char *str, const dns_name_t *origin) { 2259 isc_result_t result; 2260 2261 result = dns_name_fromstring(name, str, origin, DNS_NAME_DOWNCASE, 2262 view->mctx); 2263 if (result != ISC_R_SUCCESS) { 2264 cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2265 "invalid zone '%s'", str); 2266 } 2267 return result; 2268 } 2269 2270 static isc_result_t 2271 configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, 2272 bool recursive_only_default, bool add_soa_default, 2273 dns_ttl_t ttl_default, uint32_t minupdateinterval_default, 2274 const dns_rpz_zone_t *old, bool *old_rpz_okp) { 2275 const cfg_obj_t *rpz_obj, *obj; 2276 const char *str; 2277 dns_rpz_zone_t *zone = NULL; 2278 isc_result_t result; 2279 dns_rpz_num_t rpz_num; 2280 2281 REQUIRE(old != NULL || !*old_rpz_okp); 2282 2283 rpz_obj = cfg_listelt_value(element); 2284 2285 if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) { 2286 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2287 "limit of %d response policy zones exceeded", 2288 DNS_RPZ_MAX_ZONES); 2289 return ISC_R_FAILURE; 2290 } 2291 2292 result = dns_rpz_new_zone(view->rpzs, &zone); 2293 if (result != ISC_R_SUCCESS) { 2294 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2295 "Error creating new RPZ zone : %s", 2296 isc_result_totext(result)); 2297 return result; 2298 } 2299 2300 obj = cfg_tuple_get(rpz_obj, "recursive-only"); 2301 if (cfg_obj_isvoid(obj) ? recursive_only_default 2302 : cfg_obj_asboolean(obj)) 2303 { 2304 view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(zone->num); 2305 } else { 2306 view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(zone->num); 2307 } 2308 2309 obj = cfg_tuple_get(rpz_obj, "log"); 2310 if (!cfg_obj_isvoid(obj) && !cfg_obj_asboolean(obj)) { 2311 view->rpzs->p.no_log |= DNS_RPZ_ZBIT(zone->num); 2312 } else { 2313 view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(zone->num); 2314 } 2315 2316 obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 2317 if (cfg_obj_isduration(obj)) { 2318 zone->max_policy_ttl = cfg_obj_asduration(obj); 2319 } else { 2320 zone->max_policy_ttl = ttl_default; 2321 } 2322 if (*old_rpz_okp && zone->max_policy_ttl != old->max_policy_ttl) { 2323 *old_rpz_okp = false; 2324 } 2325 2326 obj = cfg_tuple_get(rpz_obj, "min-update-interval"); 2327 if (cfg_obj_isduration(obj)) { 2328 zone->min_update_interval = cfg_obj_asduration(obj); 2329 } else { 2330 zone->min_update_interval = minupdateinterval_default; 2331 } 2332 if (*old_rpz_okp && 2333 zone->min_update_interval != old->min_update_interval) 2334 { 2335 *old_rpz_okp = false; 2336 } 2337 2338 str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); 2339 result = configure_rpz_name(view, rpz_obj, &zone->origin, str, "zone"); 2340 if (result != ISC_R_SUCCESS) { 2341 return result; 2342 } 2343 if (dns_name_equal(&zone->origin, dns_rootname)) { 2344 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2345 "invalid zone name '%s'", str); 2346 return DNS_R_EMPTYLABEL; 2347 } 2348 if (!view->rpzs->p.dnsrps_enabled) { 2349 for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones - 1; 2350 ++rpz_num) 2351 { 2352 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, 2353 &zone->origin)) 2354 { 2355 cfg_obj_log(rpz_obj, named_g_lctx, 2356 DNS_RPZ_ERROR_LEVEL, 2357 "duplicate '%s'", str); 2358 result = DNS_R_DUPLICATE; 2359 return result; 2360 } 2361 } 2362 } 2363 if (*old_rpz_okp && !dns_name_equal(&old->origin, &zone->origin)) { 2364 *old_rpz_okp = false; 2365 } 2366 2367 result = configure_rpz_name2(view, rpz_obj, &zone->client_ip, 2368 DNS_RPZ_CLIENT_IP_ZONE, &zone->origin); 2369 if (result != ISC_R_SUCCESS) { 2370 return result; 2371 } 2372 2373 result = configure_rpz_name2(view, rpz_obj, &zone->ip, DNS_RPZ_IP_ZONE, 2374 &zone->origin); 2375 if (result != ISC_R_SUCCESS) { 2376 return result; 2377 } 2378 2379 result = configure_rpz_name2(view, rpz_obj, &zone->nsdname, 2380 DNS_RPZ_NSDNAME_ZONE, &zone->origin); 2381 if (result != ISC_R_SUCCESS) { 2382 return result; 2383 } 2384 2385 result = configure_rpz_name2(view, rpz_obj, &zone->nsip, 2386 DNS_RPZ_NSIP_ZONE, &zone->origin); 2387 if (result != ISC_R_SUCCESS) { 2388 return result; 2389 } 2390 2391 result = configure_rpz_name(view, rpz_obj, &zone->passthru, 2392 DNS_RPZ_PASSTHRU_NAME, "name"); 2393 if (result != ISC_R_SUCCESS) { 2394 return result; 2395 } 2396 2397 result = configure_rpz_name(view, rpz_obj, &zone->drop, 2398 DNS_RPZ_DROP_NAME, "name"); 2399 if (result != ISC_R_SUCCESS) { 2400 return result; 2401 } 2402 2403 result = configure_rpz_name(view, rpz_obj, &zone->tcp_only, 2404 DNS_RPZ_TCP_ONLY_NAME, "name"); 2405 if (result != ISC_R_SUCCESS) { 2406 return result; 2407 } 2408 2409 obj = cfg_tuple_get(rpz_obj, "policy"); 2410 if (cfg_obj_isvoid(obj)) { 2411 zone->policy = DNS_RPZ_POLICY_GIVEN; 2412 } else { 2413 str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 2414 zone->policy = dns_rpz_str2policy(str); 2415 INSIST(zone->policy != DNS_RPZ_POLICY_ERROR); 2416 if (zone->policy == DNS_RPZ_POLICY_CNAME) { 2417 str = cfg_obj_asstring(cfg_tuple_get(obj, "cname")); 2418 result = configure_rpz_name(view, rpz_obj, &zone->cname, 2419 str, "cname"); 2420 if (result != ISC_R_SUCCESS) { 2421 return result; 2422 } 2423 } 2424 } 2425 if (*old_rpz_okp && (zone->policy != old->policy || 2426 !dns_name_equal(&old->cname, &zone->cname))) 2427 { 2428 *old_rpz_okp = false; 2429 } 2430 2431 obj = cfg_tuple_get(rpz_obj, "ede"); 2432 if (!cfg_obj_isstring(obj)) { 2433 zone->ede = 0; 2434 } else { 2435 str = cfg_obj_asstring(obj); 2436 zone->ede = dns_rpz_str2ede(str); 2437 INSIST(zone->ede != UINT16_MAX); 2438 } 2439 if (*old_rpz_okp && zone->ede != old->ede) { 2440 *old_rpz_okp = false; 2441 } 2442 2443 obj = cfg_tuple_get(rpz_obj, "add-soa"); 2444 if (cfg_obj_isvoid(obj)) { 2445 zone->addsoa = add_soa_default; 2446 } else { 2447 zone->addsoa = cfg_obj_asboolean(obj); 2448 } 2449 if (*old_rpz_okp && zone->addsoa != old->addsoa) { 2450 *old_rpz_okp = false; 2451 } 2452 2453 return ISC_R_SUCCESS; 2454 } 2455 2456 static isc_result_t 2457 configure_rpz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t **maps, 2458 const cfg_obj_t *rpz_obj, bool *old_rpz_okp, bool first_time) { 2459 bool dnsrps_enabled; 2460 const cfg_listelt_t *zone_element; 2461 char *rps_cstr; 2462 size_t rps_cstr_size; 2463 const cfg_obj_t *sub_obj; 2464 bool recursive_only_default, add_soa_default; 2465 bool nsip_enabled, nsdname_enabled; 2466 dns_rpz_zbits_t nsip_on, nsdname_on; 2467 dns_ttl_t ttl_default; 2468 uint32_t minupdateinterval_default; 2469 dns_rpz_zones_t *zones; 2470 const dns_rpz_zones_t *old; 2471 bool pview_must_detach = false; 2472 const dns_rpz_zone_t *old_zone; 2473 isc_result_t result; 2474 int i; 2475 2476 *old_rpz_okp = false; 2477 2478 zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list")); 2479 if (zone_element == NULL) { 2480 return ISC_R_SUCCESS; 2481 } 2482 2483 nsip_enabled = true; 2484 sub_obj = cfg_tuple_get(rpz_obj, "nsip-enable"); 2485 if (!cfg_obj_isvoid(sub_obj)) { 2486 nsip_enabled = cfg_obj_asboolean(sub_obj); 2487 } 2488 nsip_on = nsip_enabled ? DNS_RPZ_ALL_ZBITS : 0; 2489 2490 nsdname_enabled = true; 2491 sub_obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); 2492 if (!cfg_obj_isvoid(sub_obj)) { 2493 nsdname_enabled = cfg_obj_asboolean(sub_obj); 2494 } 2495 nsdname_on = nsdname_enabled ? DNS_RPZ_ALL_ZBITS : 0; 2496 2497 /* 2498 * "dnsrps-enable yes|no" can be either a global or response-policy 2499 * clause. 2500 */ 2501 dnsrps_enabled = false; 2502 rps_cstr = NULL; 2503 rps_cstr_size = 0; 2504 sub_obj = NULL; 2505 (void)named_config_get(maps, "dnsrps-enable", &sub_obj); 2506 if (sub_obj != NULL) { 2507 dnsrps_enabled = cfg_obj_asboolean(sub_obj); 2508 } 2509 sub_obj = cfg_tuple_get(rpz_obj, "dnsrps-enable"); 2510 if (!cfg_obj_isvoid(sub_obj)) { 2511 dnsrps_enabled = cfg_obj_asboolean(sub_obj); 2512 } 2513 #ifndef USE_DNSRPS 2514 if (dnsrps_enabled) { 2515 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2516 "\"dnsrps-enable yes\" but" 2517 " without `./configure --enable-dnsrps`"); 2518 return ISC_R_FAILURE; 2519 } 2520 #else /* ifndef USE_DNSRPS */ 2521 if (dnsrps_enabled) { 2522 if (librpz == NULL) { 2523 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2524 "\"dnsrps-enable yes\" but %s", 2525 librpz_lib_open_emsg.c); 2526 return ISC_R_FAILURE; 2527 } 2528 2529 /* 2530 * Generate the DNS Response Policy Service 2531 * configuration string. 2532 */ 2533 result = conf_dnsrps(view, maps, nsip_enabled, nsdname_enabled, 2534 &nsip_on, &nsdname_on, &rps_cstr, 2535 &rps_cstr_size, rpz_obj, zone_element); 2536 if (result != ISC_R_SUCCESS) { 2537 return result; 2538 } 2539 } 2540 #endif /* ifndef USE_DNSRPS */ 2541 2542 result = dns_rpz_new_zones(view, named_g_loopmgr, rps_cstr, 2543 rps_cstr_size, &view->rpzs, first_time); 2544 if (result != ISC_R_SUCCESS) { 2545 return result; 2546 } 2547 2548 zones = view->rpzs; 2549 2550 zones->p.nsip_on = nsip_on; 2551 zones->p.nsdname_on = nsdname_on; 2552 zones->p.slow_mode = ns_server_getoption(named_g_server->sctx, 2553 NS_SERVER_RPZSLOW); 2554 2555 sub_obj = cfg_tuple_get(rpz_obj, "recursive-only"); 2556 if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { 2557 recursive_only_default = false; 2558 } else { 2559 recursive_only_default = true; 2560 } 2561 2562 sub_obj = cfg_tuple_get(rpz_obj, "add-soa"); 2563 if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { 2564 add_soa_default = false; 2565 } else { 2566 add_soa_default = true; 2567 } 2568 2569 sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec"); 2570 if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) { 2571 zones->p.break_dnssec = true; 2572 } else { 2573 zones->p.break_dnssec = false; 2574 } 2575 2576 sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 2577 if (cfg_obj_isduration(sub_obj)) { 2578 ttl_default = cfg_obj_asduration(sub_obj); 2579 } else { 2580 ttl_default = DNS_RPZ_MAX_TTL_DEFAULT; 2581 } 2582 2583 sub_obj = cfg_tuple_get(rpz_obj, "min-update-interval"); 2584 if (cfg_obj_isduration(sub_obj)) { 2585 minupdateinterval_default = cfg_obj_asduration(sub_obj); 2586 } else { 2587 minupdateinterval_default = DNS_RPZ_MINUPDATEINTERVAL_DEFAULT; 2588 } 2589 2590 sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots"); 2591 if (cfg_obj_isuint32(sub_obj)) { 2592 zones->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1; 2593 } else { 2594 zones->p.min_ns_labels = 2; 2595 } 2596 2597 sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse"); 2598 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2599 zones->p.qname_wait_recurse = true; 2600 } else { 2601 zones->p.qname_wait_recurse = false; 2602 } 2603 2604 sub_obj = cfg_tuple_get(rpz_obj, "nsdname-wait-recurse"); 2605 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2606 zones->p.nsdname_wait_recurse = true; 2607 } else { 2608 zones->p.nsdname_wait_recurse = false; 2609 } 2610 2611 sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse"); 2612 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2613 zones->p.nsip_wait_recurse = true; 2614 } else { 2615 zones->p.nsip_wait_recurse = false; 2616 } 2617 2618 sub_obj = cfg_tuple_get(rpz_obj, "servfail-until-ready"); 2619 if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) { 2620 zones->p.servfail_until_ready = true; 2621 } else { 2622 zones->p.servfail_until_ready = false; 2623 } 2624 2625 if (dnsrps_enabled && zones->p.servfail_until_ready) { 2626 zones->p.servfail_until_ready = false; 2627 cfg_obj_log(rpz_obj, named_g_lctx, ISC_LOG_WARNING, 2628 "\"servfail-until-ready yes\" has no effect when " 2629 "used with \"dnsrps-enable yes\""); 2630 } 2631 2632 if (pview != NULL) { 2633 old = pview->rpzs; 2634 } else { 2635 result = dns_viewlist_find(&named_g_server->viewlist, 2636 view->name, view->rdclass, &pview); 2637 if (result == ISC_R_SUCCESS) { 2638 pview_must_detach = true; 2639 old = pview->rpzs; 2640 } else { 2641 old = NULL; 2642 } 2643 } 2644 2645 if (old == NULL) { 2646 *old_rpz_okp = false; 2647 } else { 2648 *old_rpz_okp = true; 2649 } 2650 2651 for (i = 0; zone_element != NULL; 2652 ++i, zone_element = cfg_list_next(zone_element)) 2653 { 2654 INSIST(!*old_rpz_okp || old != NULL); 2655 if (*old_rpz_okp && i < old->p.num_zones) { 2656 old_zone = old->zones[i]; 2657 } else { 2658 *old_rpz_okp = false; 2659 old_zone = NULL; 2660 } 2661 result = configure_rpz_zone( 2662 view, zone_element, recursive_only_default, 2663 add_soa_default, ttl_default, minupdateinterval_default, 2664 old_zone, old_rpz_okp); 2665 if (result != ISC_R_SUCCESS) { 2666 if (pview_must_detach) { 2667 dns_view_detach(&pview); 2668 } 2669 return result; 2670 } 2671 } 2672 2673 /* 2674 * If this is a reloading and the parameters and list of policy 2675 * zones are unchanged, then use the same policy data. 2676 * Data for individual zones that must be reloaded will be merged. 2677 */ 2678 if (*old_rpz_okp) { 2679 if (old != NULL && 2680 memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0) 2681 { 2682 *old_rpz_okp = false; 2683 } else if ((old == NULL || old->rps_cstr == NULL) != 2684 (zones->rps_cstr == NULL)) 2685 { 2686 *old_rpz_okp = false; 2687 } else if (old != NULL && zones->rps_cstr != NULL && 2688 strcmp(old->rps_cstr, zones->rps_cstr) != 0) 2689 { 2690 *old_rpz_okp = false; 2691 } 2692 } 2693 2694 if (*old_rpz_okp) { 2695 INSIST(pview->rpzs != NULL); 2696 2697 /* Discard the newly created rpzs. */ 2698 dns_rpz_zones_shutdown(view->rpzs); 2699 dns_rpz_zones_detach(&view->rpzs); 2700 2701 /* 2702 * We are reusing the old rpzs, so it can no longer be its 2703 * first time. 2704 */ 2705 pview->rpzs->first_time = false; 2706 2707 /* Reuse rpzs from the old view. */ 2708 dns_rpz_zones_attach(pview->rpzs, &view->rpzs); 2709 dns_rpz_zones_detach(&pview->rpzs); 2710 } else if (old != NULL && pview != NULL) { 2711 INSIST(pview->rpzs != NULL); 2712 2713 ++pview->rpzs->rpz_ver; 2714 view->rpzs->rpz_ver = pview->rpzs->rpz_ver; 2715 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_DEBUG_LEVEL1, 2716 "updated RPZ policy: version %d", 2717 view->rpzs->rpz_ver); 2718 } 2719 2720 if (pview_must_detach) { 2721 dns_view_detach(&pview); 2722 } 2723 2724 return ISC_R_SUCCESS; 2725 } 2726 2727 static void 2728 catz_addmodzone_cb(void *arg) { 2729 catz_chgzone_t *cz = (catz_chgzone_t *)arg; 2730 isc_result_t result; 2731 dns_forwarders_t *dnsforwarders = NULL; 2732 dns_name_t *name = NULL; 2733 isc_buffer_t namebuf; 2734 isc_buffer_t *confbuf = NULL; 2735 char nameb[DNS_NAME_FORMATSIZE]; 2736 const cfg_obj_t *zlist = NULL; 2737 cfg_obj_t *zoneconf = NULL; 2738 cfg_obj_t *zoneobj = NULL; 2739 ns_cfgctx_t *cfg = NULL; 2740 dns_zone_t *zone = NULL; 2741 2742 if (isc_loop_shuttingdown(isc_loop_get(named_g_loopmgr, isc_tid()))) { 2743 goto cleanup; 2744 } 2745 2746 /* 2747 * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' 2748 * is true, so this is expected to be non-NULL. 2749 */ 2750 cfg = (ns_cfgctx_t *)cz->view->new_zone_config; 2751 if (cfg == NULL) { 2752 CHECK(ISC_R_FAILURE); 2753 } 2754 2755 name = dns_catz_entry_getname(cz->entry); 2756 2757 isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); 2758 dns_name_totext(name, DNS_NAME_OMITFINALDOT, &namebuf); 2759 isc_buffer_putuint8(&namebuf, 0); 2760 2761 result = dns_fwdtable_find(cz->view->fwdtable, name, &dnsforwarders); 2762 if (result == ISC_R_SUCCESS && 2763 dnsforwarders->fwdpolicy == dns_fwdpolicy_only) 2764 { 2765 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2766 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2767 "catz: catz_addmodzone_cb: " 2768 "zone '%s' will not be processed because of the " 2769 "explicitly configured forwarding for that zone", 2770 nameb); 2771 goto cleanup; 2772 } 2773 2774 result = dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone); 2775 2776 if (cz->mod) { 2777 dns_catz_zone_t *parentcatz; 2778 2779 if (result != ISC_R_SUCCESS) { 2780 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2781 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2782 "catz: error \"%s\" while trying to " 2783 "modify zone '%s'", 2784 isc_result_totext(result), nameb); 2785 goto cleanup; 2786 } 2787 2788 if (!dns_zone_getadded(zone)) { 2789 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2790 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2791 "catz: catz_addmodzone_cb: " 2792 "zone '%s' is not a dynamically " 2793 "added zone", 2794 nameb); 2795 goto cleanup; 2796 } 2797 2798 parentcatz = dns_zone_get_parentcatz(zone); 2799 2800 if (parentcatz == NULL) { 2801 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2802 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2803 "catz: catz_addmodzone_cb: " 2804 "zone '%s' exists and is not added by " 2805 "a catalog zone, so won't be modified", 2806 nameb); 2807 goto cleanup; 2808 } 2809 if (parentcatz != cz->origin) { 2810 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2811 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2812 "catz: catz_addmodzone_cb: " 2813 "zone '%s' exists in multiple " 2814 "catalog zones", 2815 nameb); 2816 goto cleanup; 2817 } 2818 2819 dns_zone_detach(&zone); 2820 } else { 2821 /* Zone shouldn't already exist when adding */ 2822 if (result == ISC_R_SUCCESS) { 2823 if (dns_zone_get_parentcatz(zone) == NULL) { 2824 isc_log_write( 2825 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2826 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2827 "catz: " 2828 "catz_addmodzone_cb: " 2829 "zone '%s' will not be added " 2830 "because it is an explicitly " 2831 "configured zone", 2832 nameb); 2833 } else { 2834 isc_log_write( 2835 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2836 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2837 "catz: " 2838 "catz_addmodzone_cb: " 2839 "zone '%s' will not be added " 2840 "because another catalog zone " 2841 "already contains an entry with " 2842 "that zone", 2843 nameb); 2844 } 2845 goto cleanup; 2846 } else { 2847 RUNTIME_CHECK(result == ISC_R_NOTFOUND); 2848 } 2849 } 2850 RUNTIME_CHECK(zone == NULL); 2851 /* Create a config for new zone */ 2852 confbuf = NULL; 2853 result = dns_catz_generate_zonecfg(cz->origin, cz->entry, &confbuf); 2854 if (result == ISC_R_SUCCESS) { 2855 cfg_parser_reset(cfg->add_parser); 2856 result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, 2857 &cfg_type_addzoneconf, 0, &zoneconf); 2858 } 2859 /* 2860 * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() 2861 * failed. 2862 */ 2863 if (result != ISC_R_SUCCESS) { 2864 isc_log_write( 2865 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2866 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 2867 "catz: error \"%s\" while trying to generate " 2868 "config for zone '%s'%s%.*s%s", 2869 isc_result_totext(result), nameb, 2870 confbuf != NULL ? " buffer '" : "", 2871 confbuf != NULL ? (int)isc_buffer_usedlength(confbuf) 2872 : 0, 2873 confbuf != NULL ? (char *)isc_buffer_base(confbuf) : "", 2874 confbuf != NULL ? "'" : ""); 2875 goto cleanup; 2876 } 2877 isc_buffer_free(&confbuf); 2878 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 2879 if (!cfg_obj_islist(zlist)) { 2880 CHECK(ISC_R_FAILURE); 2881 } 2882 2883 /* For now we only support adding one zone at a time */ 2884 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 2885 2886 /* Mark view unfrozen so that zone can be added */ 2887 isc_loopmgr_pause(named_g_loopmgr); 2888 dns_view_thaw(cz->view); 2889 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, cz->view, 2890 &cz->cbd->server->viewlist, 2891 &cz->cbd->server->kasplist, 2892 &cz->cbd->server->keystorelist, cfg->actx, true, 2893 false, true, cz->mod); 2894 dns_view_freeze(cz->view); 2895 isc_loopmgr_resume(named_g_loopmgr); 2896 2897 if (result != ISC_R_SUCCESS) { 2898 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2899 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2900 "catz: failed to configure zone '%s' - %d", nameb, 2901 result); 2902 goto cleanup; 2903 } 2904 2905 /* Is it there yet? */ 2906 CHECK(dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone)); 2907 2908 /* 2909 * Load the zone from the master file. If this fails, we'll 2910 * need to undo the configuration we've done already. 2911 */ 2912 result = dns_zone_load(zone, true); 2913 if (result != ISC_R_SUCCESS) { 2914 dns_db_t *dbp = NULL; 2915 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2916 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 2917 "catz: dns_zone_load() failed " 2918 "with %s; reverting.", 2919 isc_result_totext(result)); 2920 2921 /* If the zone loaded partially, unload it */ 2922 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 2923 dns_db_detach(&dbp); 2924 dns_zone_unload(zone); 2925 } 2926 2927 /* Remove the zone from the zone table */ 2928 dns_view_delzone(cz->view, zone); 2929 goto cleanup; 2930 } 2931 2932 /* Flag the zone as having been added at runtime */ 2933 dns_zone_setadded(zone, true); 2934 dns_zone_set_parentcatz(zone, cz->origin); 2935 2936 cleanup: 2937 if (confbuf != NULL) { 2938 isc_buffer_free(&confbuf); 2939 } 2940 if (zone != NULL) { 2941 dns_zone_detach(&zone); 2942 } 2943 if (zoneconf != NULL) { 2944 cfg_obj_destroy(cfg->add_parser, &zoneconf); 2945 } 2946 if (dnsforwarders != NULL) { 2947 dns_forwarders_detach(&dnsforwarders); 2948 } 2949 dns_catz_entry_detach(cz->origin, &cz->entry); 2950 dns_catz_zone_detach(&cz->origin); 2951 dns_view_weakdetach(&cz->view); 2952 isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); 2953 } 2954 2955 static void 2956 catz_delzone_cb(void *arg) { 2957 catz_chgzone_t *cz = (catz_chgzone_t *)arg; 2958 isc_result_t result; 2959 dns_zone_t *zone = NULL; 2960 dns_db_t *dbp = NULL; 2961 char cname[DNS_NAME_FORMATSIZE]; 2962 const char *file = NULL; 2963 2964 if (isc_loop_shuttingdown(isc_loop_get(named_g_loopmgr, isc_tid()))) { 2965 goto cleanup; 2966 } 2967 2968 isc_loopmgr_pause(named_g_loopmgr); 2969 2970 dns_name_format(dns_catz_entry_getname(cz->entry), cname, 2971 DNS_NAME_FORMATSIZE); 2972 result = dns_view_findzone(cz->view, dns_catz_entry_getname(cz->entry), 2973 DNS_ZTFIND_EXACT, &zone); 2974 if (result != ISC_R_SUCCESS) { 2975 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2976 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2977 "catz: catz_delzone_cb: " 2978 "zone '%s' not found", 2979 cname); 2980 goto resume; 2981 } 2982 2983 if (!dns_zone_getadded(zone)) { 2984 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2985 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2986 "catz: catz_delzone_cb: " 2987 "zone '%s' is not a dynamically added zone", 2988 cname); 2989 goto resume; 2990 } 2991 2992 if (dns_zone_get_parentcatz(zone) != cz->origin) { 2993 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2994 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2995 "catz: catz_delzone_cb: zone " 2996 "'%s' exists in multiple catalog zones", 2997 cname); 2998 goto resume; 2999 } 3000 3001 /* Stop answering for this zone */ 3002 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 3003 dns_db_detach(&dbp); 3004 dns_zone_unload(zone); 3005 } 3006 3007 if (dns_view_delzone(cz->view, zone) != ISC_R_SUCCESS) { 3008 goto resume; 3009 } 3010 file = dns_zone_getfile(zone); 3011 if (file != NULL) { 3012 isc_file_remove(file); 3013 file = dns_zone_getjournal(zone); 3014 if (file != NULL) { 3015 isc_file_remove(file); 3016 } 3017 } 3018 3019 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3020 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 3021 "catz: catz_delzone_cb: " 3022 "zone '%s' deleted", 3023 cname); 3024 resume: 3025 isc_loopmgr_resume(named_g_loopmgr); 3026 cleanup: 3027 if (zone != NULL) { 3028 dns_zone_detach(&zone); 3029 } 3030 dns_catz_entry_detach(cz->origin, &cz->entry); 3031 dns_catz_zone_detach(&cz->origin); 3032 dns_view_weakdetach(&cz->view); 3033 isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); 3034 } 3035 3036 static isc_result_t 3037 catz_run(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3038 void *udata, catz_type_t type) { 3039 catz_chgzone_t *cz = NULL; 3040 isc_job_cb action = NULL; 3041 3042 switch (type) { 3043 case CATZ_ADDZONE: 3044 case CATZ_MODZONE: 3045 action = catz_addmodzone_cb; 3046 break; 3047 case CATZ_DELZONE: 3048 action = catz_delzone_cb; 3049 break; 3050 default: 3051 REQUIRE(0); 3052 UNREACHABLE(); 3053 } 3054 3055 cz = isc_mem_get(view->mctx, sizeof(*cz)); 3056 *cz = (catz_chgzone_t){ 3057 .cbd = (catz_cb_data_t *)udata, 3058 .mod = (type == CATZ_MODZONE), 3059 }; 3060 isc_mem_attach(view->mctx, &cz->mctx); 3061 3062 dns_catz_entry_attach(entry, &cz->entry); 3063 dns_catz_zone_attach(origin, &cz->origin); 3064 dns_view_weakattach(view, &cz->view); 3065 3066 isc_async_run(named_g_mainloop, action, cz); 3067 3068 return ISC_R_SUCCESS; 3069 } 3070 3071 static isc_result_t 3072 catz_addzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3073 void *udata) { 3074 return catz_run(entry, origin, view, udata, CATZ_ADDZONE); 3075 } 3076 3077 static isc_result_t 3078 catz_delzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3079 void *udata) { 3080 return catz_run(entry, origin, view, udata, CATZ_DELZONE); 3081 } 3082 3083 static isc_result_t 3084 catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3085 void *udata) { 3086 return catz_run(entry, origin, view, udata, CATZ_MODZONE); 3087 } 3088 3089 static void 3090 catz_changeview(dns_catz_entry_t *entry, void *arg1, void *arg2) { 3091 dns_view_t *pview = arg1; 3092 dns_view_t *view = arg2; 3093 3094 dns_zone_t *zone = NULL; 3095 isc_result_t result = dns_view_findzone( 3096 pview, dns_catz_entry_getname(entry), DNS_ZTFIND_EXACT, &zone); 3097 3098 if (result != ISC_R_SUCCESS) { 3099 return; 3100 } 3101 3102 dns_zone_setview(zone, view); 3103 dns_view_addzone(view, zone); 3104 3105 dns_zone_detach(&zone); 3106 } 3107 3108 static void 3109 catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { 3110 dns_view_t *view = arg1; 3111 catz_reconfig_data_t *data = arg2; 3112 isc_buffer_t namebuf; 3113 isc_buffer_t *confbuf = NULL; 3114 const cfg_obj_t *zlist = NULL; 3115 char nameb[DNS_NAME_FORMATSIZE]; 3116 cfg_obj_t *zoneconf = NULL; 3117 cfg_obj_t *zoneobj = NULL; 3118 ns_cfgctx_t *cfg = NULL; 3119 dns_zone_t *zone = NULL; 3120 isc_result_t result; 3121 3122 isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); 3123 dns_name_totext(dns_catz_entry_getname(entry), DNS_NAME_OMITFINALDOT, 3124 &namebuf); 3125 isc_buffer_putuint8(&namebuf, 0); 3126 3127 result = dns_view_findzone(view, dns_catz_entry_getname(entry), 3128 DNS_ZTFIND_EXACT, &zone); 3129 if (result != ISC_R_SUCCESS) { 3130 return; 3131 } 3132 3133 /* 3134 * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' 3135 * is true, so this is expected to be non-NULL. 3136 */ 3137 cfg = (ns_cfgctx_t *)view->new_zone_config; 3138 if (cfg == NULL) { 3139 CHECK(ISC_R_FAILURE); 3140 } 3141 3142 result = dns_catz_generate_zonecfg(data->catz, entry, &confbuf); 3143 if (result == ISC_R_SUCCESS) { 3144 cfg_parser_reset(cfg->add_parser); 3145 result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, 3146 &cfg_type_addzoneconf, 0, &zoneconf); 3147 isc_buffer_free(&confbuf); 3148 } 3149 /* 3150 * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() 3151 * failed. 3152 */ 3153 if (result != ISC_R_SUCCESS) { 3154 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3155 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 3156 "catz_reconfigure: error \"%s\" while trying to " 3157 "generate config for member zone '%s'", 3158 isc_result_totext(result), nameb); 3159 goto cleanup; 3160 } 3161 3162 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 3163 if (!cfg_obj_islist(zlist)) { 3164 CHECK(ISC_R_FAILURE); 3165 } 3166 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 3167 3168 result = configure_zone(data->config, zoneobj, cfg->vconfig, view, 3169 &data->cbd->server->viewlist, 3170 &data->cbd->server->kasplist, 3171 &data->cbd->server->keystorelist, cfg->actx, 3172 true, false, true, true); 3173 if (result != ISC_R_SUCCESS) { 3174 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3175 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 3176 "catz_reconfigure : error \"%s\" while trying to " 3177 "reconfigure member zone '%s'", 3178 isc_result_totext(result), nameb); 3179 goto cleanup; 3180 } 3181 3182 cleanup: 3183 if (zoneconf != NULL) { 3184 cfg_obj_destroy(cfg->add_parser, &zoneconf); 3185 } 3186 3187 dns_zone_detach(&zone); 3188 } 3189 3190 static isc_result_t 3191 configure_catz_zone(dns_view_t *view, dns_view_t *pview, 3192 const cfg_obj_t *config, const cfg_listelt_t *element) { 3193 const cfg_obj_t *catz_obj, *obj; 3194 dns_catz_zone_t *zone = NULL; 3195 const char *str; 3196 isc_result_t result; 3197 dns_name_t origin; 3198 dns_ipkeylist_t ipkl; 3199 dns_catz_options_t *opts; 3200 3201 dns_name_init(&origin, NULL); 3202 dns_ipkeylist_init(&ipkl); 3203 catz_obj = cfg_listelt_value(element); 3204 3205 str = cfg_obj_asstring(cfg_tuple_get(catz_obj, "zone name")); 3206 3207 result = dns_name_fromstring(&origin, str, dns_rootname, 3208 DNS_NAME_DOWNCASE, view->mctx); 3209 if (result == ISC_R_SUCCESS && dns_name_equal(&origin, dns_rootname)) { 3210 result = DNS_R_EMPTYLABEL; 3211 } 3212 3213 if (result != ISC_R_SUCCESS) { 3214 cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3215 "catz: invalid zone name '%s'", str); 3216 goto cleanup; 3217 } 3218 3219 obj = cfg_tuple_get(catz_obj, "default-masters"); 3220 if (obj == NULL || !cfg_obj_istuple(obj)) { 3221 obj = cfg_tuple_get(catz_obj, "default-primaries"); 3222 } 3223 if (obj != NULL && cfg_obj_istuple(obj)) { 3224 result = named_config_getipandkeylist(config, obj, view->mctx, 3225 &ipkl); 3226 if (result != ISC_R_SUCCESS) { 3227 cfg_obj_log(catz_obj, named_g_lctx, 3228 DNS_CATZ_ERROR_LEVEL, 3229 "catz: default-primaries parse error: %s", 3230 isc_result_totext(result)); 3231 goto cleanup; 3232 } 3233 } 3234 3235 result = dns_catz_zone_add(view->catzs, &origin, &zone); 3236 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) { 3237 cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3238 "catz: dns_catz_zone_add failed: %s", 3239 isc_result_totext(result)); 3240 goto cleanup; 3241 } 3242 3243 dns_catz_zone_prereconfig(zone); 3244 3245 if (result == ISC_R_EXISTS) { 3246 catz_reconfig_data_t data = { 3247 .catz = zone, 3248 .config = config, 3249 .cbd = (catz_cb_data_t *)dns_catz_zones_get_udata( 3250 view->catzs), 3251 }; 3252 3253 /* 3254 * We have to walk through all the member zones, re-attach 3255 * them to the current view and reconfigure 3256 */ 3257 dns_catz_zone_for_each_entry2(zone, catz_changeview, pview, 3258 view); 3259 dns_catz_zone_for_each_entry2(zone, catz_reconfigure, view, 3260 &data); 3261 3262 result = ISC_R_SUCCESS; 3263 } 3264 3265 dns_catz_zone_resetdefoptions(zone); 3266 opts = dns_catz_zone_getdefoptions(zone); 3267 if (ipkl.count != 0) { 3268 /* 3269 * Transfer the ownership of the pointers inside 'ipkl' and 3270 * set its count to 0 in order to not cleanup it later below. 3271 */ 3272 opts->masters = ipkl; 3273 ipkl.count = 0; 3274 } 3275 3276 obj = cfg_tuple_get(catz_obj, "in-memory"); 3277 if (obj != NULL && cfg_obj_isboolean(obj)) { 3278 opts->in_memory = cfg_obj_asboolean(obj); 3279 } 3280 3281 obj = cfg_tuple_get(catz_obj, "zone-directory"); 3282 if (!opts->in_memory && obj != NULL && cfg_obj_isstring(obj)) { 3283 opts->zonedir = isc_mem_strdup(view->mctx, 3284 cfg_obj_asstring(obj)); 3285 if (isc_file_isdirectory(opts->zonedir) != ISC_R_SUCCESS) { 3286 cfg_obj_log(obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3287 "catz: zone-directory '%s' " 3288 "not found; zone files will not be " 3289 "saved", 3290 opts->zonedir); 3291 opts->in_memory = true; 3292 } 3293 } 3294 3295 obj = cfg_tuple_get(catz_obj, "min-update-interval"); 3296 if (obj != NULL && cfg_obj_isduration(obj)) { 3297 opts->min_update_interval = cfg_obj_asduration(obj); 3298 } 3299 3300 dns_catz_zone_postreconfig(zone); 3301 3302 cleanup: 3303 dns_name_free(&origin, view->mctx); 3304 if (ipkl.count != 0) { 3305 dns_ipkeylist_clear(view->mctx, &ipkl); 3306 } 3307 3308 return result; 3309 } 3310 3311 static catz_cb_data_t ns_catz_cbdata; 3312 static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = { 3313 catz_addzone, catz_modzone, catz_delzone, &ns_catz_cbdata 3314 }; 3315 3316 static isc_result_t 3317 configure_catz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t *config, 3318 const cfg_obj_t *catz_obj) { 3319 const cfg_listelt_t *zone_element = NULL; 3320 const dns_catz_zones_t *old = NULL; 3321 bool pview_must_detach = false; 3322 isc_result_t result; 3323 3324 /* xxxwpk TODO do it cleaner, once, somewhere */ 3325 ns_catz_cbdata.server = named_g_server; 3326 3327 zone_element = cfg_list_first(cfg_tuple_get(catz_obj, "zone list")); 3328 if (zone_element == NULL) { 3329 return ISC_R_SUCCESS; 3330 } 3331 3332 if (pview != NULL) { 3333 old = pview->catzs; 3334 } else { 3335 result = dns_viewlist_find(&named_g_server->viewlist, 3336 view->name, view->rdclass, &pview); 3337 if (result == ISC_R_SUCCESS) { 3338 pview_must_detach = true; 3339 old = pview->catzs; 3340 } 3341 } 3342 3343 if (old != NULL) { 3344 dns_catz_zones_attach(pview->catzs, &view->catzs); 3345 dns_catz_zones_detach(&pview->catzs); 3346 dns_catz_prereconfig(view->catzs); 3347 } else { 3348 view->catzs = dns_catz_zones_new(view->mctx, named_g_loopmgr, 3349 &ns_catz_zonemodmethods); 3350 } 3351 3352 while (zone_element != NULL) { 3353 CHECK(configure_catz_zone(view, pview, config, zone_element)); 3354 zone_element = cfg_list_next(zone_element); 3355 } 3356 3357 if (old != NULL) { 3358 dns_catz_postreconfig(view->catzs); 3359 } 3360 3361 result = ISC_R_SUCCESS; 3362 3363 cleanup: 3364 if (pview_must_detach) { 3365 dns_view_detach(&pview); 3366 } 3367 3368 return result; 3369 } 3370 3371 #define CHECK_RRL(cond, pat, val1, val2) \ 3372 do { \ 3373 if (!(cond)) { \ 3374 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, pat, \ 3375 val1, val2); \ 3376 result = ISC_R_RANGE; \ 3377 goto cleanup; \ 3378 } \ 3379 } while (0) 3380 3381 #define CHECK_RRL_RATE(rate, def, max_rate, name) \ 3382 do { \ 3383 obj = NULL; \ 3384 rrl->rate.str = name; \ 3385 result = cfg_map_get(map, name, &obj); \ 3386 if (result == ISC_R_SUCCESS) { \ 3387 rrl->rate.r = cfg_obj_asuint32(obj); \ 3388 CHECK_RRL(rrl->rate.r <= max_rate, name " %d > %d", \ 3389 rrl->rate.r, max_rate); \ 3390 } else { \ 3391 rrl->rate.r = def; \ 3392 } \ 3393 rrl->rate.scaled = rrl->rate.r; \ 3394 } while (0) 3395 3396 static isc_result_t 3397 configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) { 3398 const cfg_obj_t *obj; 3399 dns_rrl_t *rrl; 3400 isc_result_t result; 3401 int min_entries, i, j; 3402 3403 /* 3404 * Most DNS servers have few clients, but intentinally open 3405 * recursive and authoritative servers often have many. 3406 * So start with a small number of entries unless told otherwise 3407 * to reduce cold-start costs. 3408 */ 3409 min_entries = 500; 3410 obj = NULL; 3411 result = cfg_map_get(map, "min-table-size", &obj); 3412 if (result == ISC_R_SUCCESS) { 3413 min_entries = cfg_obj_asuint32(obj); 3414 if (min_entries < 1) { 3415 min_entries = 1; 3416 } 3417 } 3418 result = dns_rrl_init(&rrl, view, min_entries); 3419 if (result != ISC_R_SUCCESS) { 3420 return result; 3421 } 3422 3423 i = ISC_MAX(20000, min_entries); 3424 obj = NULL; 3425 result = cfg_map_get(map, "max-table-size", &obj); 3426 if (result == ISC_R_SUCCESS) { 3427 i = cfg_obj_asuint32(obj); 3428 CHECK_RRL(i >= min_entries, 3429 "max-table-size %d < min-table-size %d", i, 3430 min_entries); 3431 } 3432 rrl->max_entries = i; 3433 3434 CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE, 3435 "responses-per-second"); 3436 CHECK_RRL_RATE(referrals_per_second, rrl->responses_per_second.r, 3437 DNS_RRL_MAX_RATE, "referrals-per-second"); 3438 CHECK_RRL_RATE(nodata_per_second, rrl->responses_per_second.r, 3439 DNS_RRL_MAX_RATE, "nodata-per-second"); 3440 CHECK_RRL_RATE(nxdomains_per_second, rrl->responses_per_second.r, 3441 DNS_RRL_MAX_RATE, "nxdomains-per-second"); 3442 CHECK_RRL_RATE(errors_per_second, rrl->responses_per_second.r, 3443 DNS_RRL_MAX_RATE, "errors-per-second"); 3444 3445 CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, "all-per-second"); 3446 3447 CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, "slip"); 3448 3449 i = 15; 3450 obj = NULL; 3451 result = cfg_map_get(map, "window", &obj); 3452 if (result == ISC_R_SUCCESS) { 3453 i = cfg_obj_asuint32(obj); 3454 CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW, 3455 "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW); 3456 } 3457 rrl->window = i; 3458 3459 i = 0; 3460 obj = NULL; 3461 result = cfg_map_get(map, "qps-scale", &obj); 3462 if (result == ISC_R_SUCCESS) { 3463 i = cfg_obj_asuint32(obj); 3464 CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, ""); 3465 } 3466 rrl->qps_scale = i; 3467 rrl->qps = 1.0; 3468 3469 i = 24; 3470 obj = NULL; 3471 result = cfg_map_get(map, "ipv4-prefix-length", &obj); 3472 if (result == ISC_R_SUCCESS) { 3473 i = cfg_obj_asuint32(obj); 3474 CHECK_RRL(i >= 8 && i <= 32, 3475 "invalid 'ipv4-prefix-length %d'%s", i, ""); 3476 } 3477 rrl->ipv4_prefixlen = i; 3478 if (i == 32) { 3479 rrl->ipv4_mask = 0xffffffff; 3480 } else { 3481 rrl->ipv4_mask = htonl(0xffffffff << (32 - i)); 3482 } 3483 3484 i = 56; 3485 obj = NULL; 3486 result = cfg_map_get(map, "ipv6-prefix-length", &obj); 3487 if (result == ISC_R_SUCCESS) { 3488 i = cfg_obj_asuint32(obj); 3489 CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX, 3490 "ipv6-prefix-length %d < 16 or > %d", i, 3491 DNS_RRL_MAX_PREFIX); 3492 } 3493 rrl->ipv6_prefixlen = i; 3494 for (j = 0; j < 4; ++j) { 3495 if (i <= 0) { 3496 rrl->ipv6_mask[j] = 0; 3497 } else if (i < 32) { 3498 rrl->ipv6_mask[j] = htonl(0xffffffff << (32 - i)); 3499 } else { 3500 rrl->ipv6_mask[j] = 0xffffffff; 3501 } 3502 i -= 32; 3503 } 3504 3505 obj = NULL; 3506 result = cfg_map_get(map, "exempt-clients", &obj); 3507 if (result == ISC_R_SUCCESS) { 3508 result = cfg_acl_fromconfig(obj, config, named_g_lctx, 3509 named_g_aclconfctx, named_g_mctx, 0, 3510 &rrl->exempt); 3511 CHECK_RRL(result == ISC_R_SUCCESS, "invalid %s%s", 3512 "address match list", ""); 3513 } 3514 3515 obj = NULL; 3516 result = cfg_map_get(map, "log-only", &obj); 3517 if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj)) { 3518 rrl->log_only = true; 3519 } else { 3520 rrl->log_only = false; 3521 } 3522 3523 return ISC_R_SUCCESS; 3524 3525 cleanup: 3526 dns_rrl_view_destroy(view); 3527 return result; 3528 } 3529 3530 static isc_result_t 3531 add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 3532 const dns_name_t *origin, const dns_name_t *contact) { 3533 dns_dbnode_t *node = NULL; 3534 dns_rdata_t rdata = DNS_RDATA_INIT; 3535 dns_rdatalist_t rdatalist; 3536 dns_rdataset_t rdataset; 3537 isc_result_t result; 3538 unsigned char buf[DNS_SOA_BUFFERSIZE]; 3539 3540 CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800, 3541 7200, 604800, 86400, buf, &rdata)); 3542 3543 dns_rdatalist_init(&rdatalist); 3544 rdatalist.type = rdata.type; 3545 rdatalist.rdclass = rdata.rdclass; 3546 rdatalist.ttl = 86400; 3547 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 3548 3549 dns_rdataset_init(&rdataset); 3550 dns_rdatalist_tordataset(&rdatalist, &rdataset); 3551 CHECK(dns_db_findnode(db, name, true, &node)); 3552 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 3553 3554 cleanup: 3555 if (node != NULL) { 3556 dns_db_detachnode(db, &node); 3557 } 3558 return result; 3559 } 3560 3561 static isc_result_t 3562 add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 3563 const dns_name_t *nsname) { 3564 dns_dbnode_t *node = NULL; 3565 dns_rdata_ns_t ns; 3566 dns_rdata_t rdata = DNS_RDATA_INIT; 3567 dns_rdatalist_t rdatalist; 3568 dns_rdataset_t rdataset; 3569 isc_result_t result; 3570 isc_buffer_t b; 3571 unsigned char buf[DNS_NAME_MAXWIRE]; 3572 3573 isc_buffer_init(&b, buf, sizeof(buf)); 3574 3575 ns.common.rdtype = dns_rdatatype_ns; 3576 ns.common.rdclass = dns_db_class(db); 3577 ns.mctx = NULL; 3578 dns_name_init(&ns.name, NULL); 3579 dns_name_clone(nsname, &ns.name); 3580 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, 3581 &ns, &b)); 3582 3583 dns_rdatalist_init(&rdatalist); 3584 rdatalist.type = rdata.type; 3585 rdatalist.rdclass = rdata.rdclass; 3586 rdatalist.ttl = 86400; 3587 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 3588 3589 dns_rdataset_init(&rdataset); 3590 dns_rdatalist_tordataset(&rdatalist, &rdataset); 3591 CHECK(dns_db_findnode(db, name, true, &node)); 3592 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 3593 3594 cleanup: 3595 if (node != NULL) { 3596 dns_db_detachnode(db, &node); 3597 } 3598 return result; 3599 } 3600 3601 static isc_result_t 3602 create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view, 3603 const cfg_obj_t *zonelist, const char **empty_dbtype, 3604 int empty_dbtypec, dns_zonestat_level_t statlevel) { 3605 char namebuf[DNS_NAME_FORMATSIZE]; 3606 const cfg_listelt_t *element; 3607 const cfg_obj_t *obj; 3608 const cfg_obj_t *zconfig; 3609 const cfg_obj_t *zoptions; 3610 const char *default_dbtype[4] = { ZONEDB_DEFAULT }; 3611 const char *sep = ": view "; 3612 const char *str; 3613 const char *viewname = view->name; 3614 dns_db_t *db = NULL; 3615 dns_dbversion_t *version = NULL; 3616 dns_fixedname_t cfixed; 3617 dns_fixedname_t fixed; 3618 dns_fixedname_t nsfixed; 3619 dns_name_t *contact; 3620 dns_name_t *ns; 3621 dns_name_t *zname; 3622 dns_zone_t *zone = NULL; 3623 int default_dbtypec = 1; 3624 isc_result_t result; 3625 dns_namereln_t namereln; 3626 int order; 3627 unsigned int nlabels; 3628 3629 zname = dns_fixedname_initname(&fixed); 3630 ns = dns_fixedname_initname(&nsfixed); 3631 contact = dns_fixedname_initname(&cfixed); 3632 3633 /* 3634 * Look for forward "zones" beneath this empty zone and if so 3635 * create a custom db for the empty zone. 3636 */ 3637 for (element = cfg_list_first(zonelist); element != NULL; 3638 element = cfg_list_next(element)) 3639 { 3640 zconfig = cfg_listelt_value(element); 3641 str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 3642 CHECK(dns_name_fromstring(zname, str, dns_rootname, 0, NULL)); 3643 namereln = dns_name_fullcompare(zname, name, &order, &nlabels); 3644 if (namereln != dns_namereln_subdomain) { 3645 continue; 3646 } 3647 3648 zoptions = cfg_tuple_get(zconfig, "options"); 3649 3650 obj = NULL; 3651 (void)cfg_map_get(zoptions, "type", &obj); 3652 if (obj != NULL && 3653 strcasecmp(cfg_obj_asstring(obj), "forward") == 0) 3654 { 3655 obj = NULL; 3656 (void)cfg_map_get(zoptions, "forward", &obj); 3657 if (obj == NULL) { 3658 continue; 3659 } 3660 if (strcasecmp(cfg_obj_asstring(obj), "only") != 0) { 3661 continue; 3662 } 3663 } 3664 if (db == NULL) { 3665 CHECK(dns_db_create(view->mctx, ZONEDB_DEFAULT, name, 3666 dns_dbtype_zone, view->rdclass, 0, 3667 NULL, &db)); 3668 CHECK(dns_db_newversion(db, &version)); 3669 if (strcmp(empty_dbtype[2], "@") == 0) { 3670 dns_name_clone(name, ns); 3671 } else { 3672 CHECK(dns_name_fromstring(ns, empty_dbtype[2], 3673 dns_rootname, 0, 3674 NULL)); 3675 } 3676 CHECK(dns_name_fromstring(contact, empty_dbtype[3], 3677 dns_rootname, 0, NULL)); 3678 CHECK(add_soa(db, version, name, ns, contact)); 3679 CHECK(add_ns(db, version, name, ns)); 3680 } 3681 CHECK(add_ns(db, version, zname, dns_rootname)); 3682 } 3683 3684 /* 3685 * Is the existing zone ok to use? 3686 */ 3687 if (pzone != NULL) { 3688 unsigned int typec; 3689 const char **dbargv = NULL; 3690 3691 if (db != NULL) { 3692 typec = default_dbtypec; 3693 dbargv = default_dbtype; 3694 } else { 3695 typec = empty_dbtypec; 3696 dbargv = empty_dbtype; 3697 } 3698 3699 result = check_dbtype(pzone, typec, dbargv, view->mctx); 3700 if (result != ISC_R_SUCCESS) { 3701 pzone = NULL; 3702 } 3703 3704 if (pzone != NULL && 3705 dns_zone_gettype(pzone) != dns_zone_primary) 3706 { 3707 pzone = NULL; 3708 } 3709 if (pzone != NULL && dns_zone_getfile(pzone) != NULL) { 3710 pzone = NULL; 3711 } 3712 if (pzone != NULL) { 3713 dns_zone_getraw(pzone, &zone); 3714 if (zone != NULL) { 3715 dns_zone_detach(&zone); 3716 pzone = NULL; 3717 } 3718 } 3719 } 3720 3721 if (pzone == NULL) { 3722 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 3723 CHECK(dns_zone_setorigin(zone, name)); 3724 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 3725 if (db == NULL) { 3726 dns_zone_setdbtype(zone, empty_dbtypec, empty_dbtype); 3727 } 3728 dns_zone_setclass(zone, view->rdclass); 3729 dns_zone_settype(zone, dns_zone_primary); 3730 dns_zone_setstats(zone, named_g_server->zonestats); 3731 } else { 3732 dns_zone_attach(pzone, &zone); 3733 } 3734 3735 dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, false); 3736 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 3737 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 3738 dns_zone_setnotifytype(zone, dns_notifytype_no); 3739 dns_zone_setdialup(zone, dns_dialuptype_no); 3740 dns_zone_setautomatic(zone, true); 3741 if (view->queryacl != NULL) { 3742 dns_zone_setqueryacl(zone, view->queryacl); 3743 } else { 3744 dns_zone_clearqueryacl(zone); 3745 } 3746 if (view->queryonacl != NULL) { 3747 dns_zone_setqueryonacl(zone, view->queryonacl); 3748 } else { 3749 dns_zone_clearqueryonacl(zone); 3750 } 3751 dns_zone_clearupdateacl(zone); 3752 if (view->transferacl != NULL) { 3753 dns_zone_setxfracl(zone, view->transferacl); 3754 } else { 3755 dns_zone_clearxfracl(zone); 3756 } 3757 3758 setquerystats(zone, view->mctx, statlevel); 3759 if (db != NULL) { 3760 dns_db_closeversion(db, &version, true); 3761 CHECK(dns_zone_replacedb(zone, db, false)); 3762 } 3763 dns_zone_setoption(zone, DNS_ZONEOPT_AUTOEMPTY, true); 3764 dns_zone_setview(zone, view); 3765 CHECK(dns_view_addzone(view, zone)); 3766 3767 if (!strcmp(viewname, "_default")) { 3768 sep = ""; 3769 viewname = ""; 3770 } 3771 dns_name_format(name, namebuf, sizeof(namebuf)); 3772 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_ZONELOAD, 3773 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 3774 "automatic empty zone%s%s: %s", sep, viewname, namebuf); 3775 3776 cleanup: 3777 if (zone != NULL) { 3778 dns_zone_detach(&zone); 3779 } 3780 if (version != NULL) { 3781 dns_db_closeversion(db, &version, false); 3782 } 3783 if (db != NULL) { 3784 dns_db_detach(&db); 3785 } 3786 3787 INSIST(version == NULL); 3788 3789 return result; 3790 } 3791 3792 static isc_result_t 3793 create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view, 3794 const dns_name_t *name, const char *type, isc_mem_t *mctx, 3795 const char *server, const char *contact) { 3796 char namebuf[DNS_NAME_FORMATSIZE]; 3797 const char *dbtype[4] = { "_builtin", NULL, "@", "." }; 3798 const char *sep = ": view "; 3799 const char *viewname = view->name; 3800 dns_zone_t *zone = NULL; 3801 int dbtypec = 4; 3802 isc_result_t result; 3803 3804 REQUIRE(type != NULL); 3805 3806 if (!strcmp(viewname, "_default")) { 3807 sep = ""; 3808 viewname = ""; 3809 } 3810 3811 dbtype[1] = type; 3812 if (server != NULL) { 3813 dbtype[2] = server; 3814 } 3815 if (contact != NULL) { 3816 dbtype[3] = contact; 3817 } 3818 3819 if (pzone != NULL) { 3820 result = check_dbtype(pzone, dbtypec, dbtype, view->mctx); 3821 if (result != ISC_R_SUCCESS) { 3822 pzone = NULL; 3823 } 3824 } 3825 3826 if (pzone == NULL) { 3827 /* 3828 * Create the actual zone. 3829 */ 3830 dns_zone_create(&zone, mctx, 0); 3831 CHECK(dns_zone_setorigin(zone, name)); 3832 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 3833 dns_zone_setclass(zone, view->rdclass); 3834 dns_zone_settype(zone, dns_zone_primary); 3835 dns_zone_setstats(zone, named_g_server->zonestats); 3836 dns_zone_setdbtype(zone, dbtypec, dbtype); 3837 dns_zone_setdialup(zone, dns_dialuptype_no); 3838 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 3839 dns_zone_setnotifytype(zone, dns_notifytype_no); 3840 dns_zone_setautomatic(zone, true); 3841 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 3842 } else { 3843 dns_zone_attach(pzone, &zone); 3844 } 3845 if (view->queryacl != NULL) { 3846 dns_zone_setqueryacl(zone, view->queryacl); 3847 } else { 3848 dns_zone_clearqueryacl(zone); 3849 } 3850 if (view->queryonacl != NULL) { 3851 dns_zone_setqueryonacl(zone, view->queryonacl); 3852 } else { 3853 dns_zone_clearqueryonacl(zone); 3854 } 3855 dns_zone_setview(zone, view); 3856 CHECK(dns_view_addzone(view, zone)); 3857 3858 dns_name_format(name, namebuf, sizeof(namebuf)); 3859 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3860 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 3861 "automatic ipv4only zone%s%s: %s", sep, viewname, 3862 namebuf); 3863 3864 cleanup: 3865 if (zone != NULL) { 3866 dns_zone_detach(&zone); 3867 } 3868 return result; 3869 } 3870 3871 #ifdef HAVE_DNSTAP 3872 static isc_result_t 3873 configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) { 3874 isc_result_t result; 3875 const cfg_obj_t *obj, *obj2; 3876 const cfg_listelt_t *element; 3877 const char *dpath; 3878 const cfg_obj_t *dlist = NULL; 3879 dns_dtmsgtype_t dttypes = 0; 3880 unsigned int i; 3881 struct fstrm_iothr_options *fopt = NULL; 3882 3883 result = named_config_get(maps, "dnstap", &dlist); 3884 if (result != ISC_R_SUCCESS) { 3885 return ISC_R_SUCCESS; 3886 } 3887 3888 for (element = cfg_list_first(dlist); element != NULL; 3889 element = cfg_list_next(element)) 3890 { 3891 const char *str; 3892 dns_dtmsgtype_t dt = 0; 3893 3894 obj = cfg_listelt_value(element); 3895 obj2 = cfg_tuple_get(obj, "type"); 3896 str = cfg_obj_asstring(obj2); 3897 if (strcasecmp(str, "client") == 0) { 3898 dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR; 3899 } else if (strcasecmp(str, "auth") == 0) { 3900 dt |= DNS_DTTYPE_AQ | DNS_DTTYPE_AR; 3901 } else if (strcasecmp(str, "resolver") == 0) { 3902 dt |= DNS_DTTYPE_RQ | DNS_DTTYPE_RR; 3903 } else if (strcasecmp(str, "forwarder") == 0) { 3904 dt |= DNS_DTTYPE_FQ | DNS_DTTYPE_FR; 3905 } else if (strcasecmp(str, "update") == 0) { 3906 dt |= DNS_DTTYPE_UQ | DNS_DTTYPE_UR; 3907 } else if (strcasecmp(str, "all") == 0) { 3908 dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR | DNS_DTTYPE_AQ | 3909 DNS_DTTYPE_AR | DNS_DTTYPE_RQ | DNS_DTTYPE_RR | 3910 DNS_DTTYPE_FQ | DNS_DTTYPE_FR | DNS_DTTYPE_UQ | 3911 DNS_DTTYPE_UR; 3912 } 3913 3914 obj2 = cfg_tuple_get(obj, "mode"); 3915 if (obj2 == NULL || cfg_obj_isvoid(obj2)) { 3916 dttypes |= dt; 3917 continue; 3918 } 3919 3920 str = cfg_obj_asstring(obj2); 3921 if (strcasecmp(str, "query") == 0) { 3922 dt &= ~DNS_DTTYPE_RESPONSE; 3923 } else if (strcasecmp(str, "response") == 0) { 3924 dt &= ~DNS_DTTYPE_QUERY; 3925 } 3926 3927 dttypes |= dt; 3928 } 3929 3930 if (named_g_server->dtenv == NULL && dttypes != 0) { 3931 dns_dtmode_t dmode; 3932 uint64_t max_size = 0; 3933 uint32_t rolls = 0; 3934 isc_log_rollsuffix_t suffix = isc_log_rollsuffix_increment; 3935 3936 obj = NULL; 3937 CHECKM(named_config_get(maps, "dnstap-output", &obj), 3938 "'dnstap-output' must be set if 'dnstap' is set"); 3939 3940 obj2 = cfg_tuple_get(obj, "mode"); 3941 if (obj2 == NULL) { 3942 CHECKM(ISC_R_FAILURE, "dnstap-output mode not found"); 3943 } 3944 if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0) { 3945 dmode = dns_dtmode_file; 3946 } else { 3947 dmode = dns_dtmode_unix; 3948 } 3949 3950 obj2 = cfg_tuple_get(obj, "path"); 3951 if (obj2 == NULL) { 3952 CHECKM(ISC_R_FAILURE, "dnstap-output path not found"); 3953 } 3954 3955 dpath = cfg_obj_asstring(obj2); 3956 3957 obj2 = cfg_tuple_get(obj, "size"); 3958 if (obj2 != NULL && cfg_obj_isuint64(obj2)) { 3959 max_size = cfg_obj_asuint64(obj2); 3960 if (max_size > SIZE_MAX) { 3961 cfg_obj_log(obj2, named_g_lctx, ISC_LOG_WARNING, 3962 "'dnstap-output size " 3963 "%" PRIu64 "' " 3964 "is too large for this " 3965 "system; reducing to %lu", 3966 max_size, (unsigned long)SIZE_MAX); 3967 max_size = SIZE_MAX; 3968 } 3969 } 3970 3971 obj2 = cfg_tuple_get(obj, "versions"); 3972 if (obj2 != NULL && cfg_obj_isuint32(obj2)) { 3973 rolls = cfg_obj_asuint32(obj2); 3974 } else { 3975 rolls = ISC_LOG_ROLLINFINITE; 3976 } 3977 3978 obj2 = cfg_tuple_get(obj, "suffix"); 3979 if (obj2 != NULL && cfg_obj_isstring(obj2) && 3980 strcasecmp(cfg_obj_asstring(obj2), "timestamp") == 0) 3981 { 3982 suffix = isc_log_rollsuffix_timestamp; 3983 } 3984 3985 fopt = fstrm_iothr_options_init(); 3986 /* 3987 * Both network threads and worker threads may log dnstap data. 3988 */ 3989 fstrm_iothr_options_set_num_input_queues(fopt, 3990 2 * named_g_cpus); 3991 fstrm_iothr_options_set_queue_model( 3992 fopt, FSTRM_IOTHR_QUEUE_MODEL_MPSC); 3993 3994 obj = NULL; 3995 result = named_config_get(maps, "fstrm-set-buffer-hint", &obj); 3996 if (result == ISC_R_SUCCESS) { 3997 i = cfg_obj_asuint32(obj); 3998 fstrm_iothr_options_set_buffer_hint(fopt, i); 3999 } 4000 4001 obj = NULL; 4002 result = named_config_get(maps, "fstrm-set-flush-timeout", 4003 &obj); 4004 if (result == ISC_R_SUCCESS) { 4005 i = cfg_obj_asuint32(obj); 4006 fstrm_iothr_options_set_flush_timeout(fopt, i); 4007 } 4008 4009 obj = NULL; 4010 result = named_config_get(maps, "fstrm-set-input-queue-size", 4011 &obj); 4012 if (result == ISC_R_SUCCESS) { 4013 i = cfg_obj_asuint32(obj); 4014 fstrm_iothr_options_set_input_queue_size(fopt, i); 4015 } 4016 4017 obj = NULL; 4018 result = named_config_get( 4019 maps, "fstrm-set-output-notify-threshold", &obj); 4020 if (result == ISC_R_SUCCESS) { 4021 i = cfg_obj_asuint32(obj); 4022 fstrm_iothr_options_set_queue_notify_threshold(fopt, i); 4023 } 4024 4025 obj = NULL; 4026 result = named_config_get(maps, "fstrm-set-output-queue-model", 4027 &obj); 4028 if (result == ISC_R_SUCCESS) { 4029 if (strcasecmp(cfg_obj_asstring(obj), "spsc") == 0) { 4030 i = FSTRM_IOTHR_QUEUE_MODEL_SPSC; 4031 } else { 4032 i = FSTRM_IOTHR_QUEUE_MODEL_MPSC; 4033 } 4034 fstrm_iothr_options_set_queue_model(fopt, i); 4035 } 4036 4037 obj = NULL; 4038 result = named_config_get(maps, "fstrm-set-output-queue-size", 4039 &obj); 4040 if (result == ISC_R_SUCCESS) { 4041 i = cfg_obj_asuint32(obj); 4042 fstrm_iothr_options_set_output_queue_size(fopt, i); 4043 } 4044 4045 obj = NULL; 4046 result = named_config_get(maps, "fstrm-set-reopen-interval", 4047 &obj); 4048 if (result == ISC_R_SUCCESS) { 4049 i = cfg_obj_asduration(obj); 4050 fstrm_iothr_options_set_reopen_interval(fopt, i); 4051 } 4052 4053 CHECKM(dns_dt_create(named_g_mctx, dmode, dpath, &fopt, 4054 named_g_mainloop, &named_g_server->dtenv), 4055 "unable to create dnstap environment"); 4056 4057 CHECKM(dns_dt_setupfile(named_g_server->dtenv, max_size, rolls, 4058 suffix), 4059 "unable to set up dnstap logfile"); 4060 } 4061 4062 if (named_g_server->dtenv == NULL) { 4063 return ISC_R_SUCCESS; 4064 } 4065 4066 obj = NULL; 4067 result = named_config_get(maps, "dnstap-version", &obj); 4068 if (result != ISC_R_SUCCESS) { 4069 /* not specified; use the product and version */ 4070 dns_dt_setversion(named_g_server->dtenv, PACKAGE_STRING); 4071 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 4072 /* Quoted string */ 4073 dns_dt_setversion(named_g_server->dtenv, cfg_obj_asstring(obj)); 4074 } 4075 4076 obj = NULL; 4077 result = named_config_get(maps, "dnstap-identity", &obj); 4078 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 4079 /* "hostname" is interpreted as boolean true */ 4080 char buf[256]; 4081 if (gethostname(buf, sizeof(buf)) == 0) { 4082 dns_dt_setidentity(named_g_server->dtenv, buf); 4083 } 4084 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 4085 /* Quoted string */ 4086 dns_dt_setidentity(named_g_server->dtenv, 4087 cfg_obj_asstring(obj)); 4088 } 4089 4090 dns_dt_attach(named_g_server->dtenv, &view->dtenv); 4091 view->dttypes = dttypes; 4092 4093 result = ISC_R_SUCCESS; 4094 4095 cleanup: 4096 if (fopt != NULL) { 4097 fstrm_iothr_options_destroy(&fopt); 4098 } 4099 4100 return result; 4101 } 4102 #endif /* HAVE_DNSTAP */ 4103 4104 static isc_result_t 4105 create_mapped_acl(void) { 4106 isc_result_t result; 4107 dns_acl_t *acl = NULL; 4108 struct in6_addr in6 = IN6ADDR_V4MAPPED_INIT; 4109 isc_netaddr_t addr; 4110 4111 isc_netaddr_fromin6(&addr, &in6); 4112 4113 dns_acl_create(named_g_mctx, 1, &acl); 4114 4115 result = dns_iptable_addprefix(acl->iptable, &addr, 96, true); 4116 if (result == ISC_R_SUCCESS) { 4117 dns_acl_attach(acl, &named_g_mapped); 4118 } 4119 dns_acl_detach(&acl); 4120 return result; 4121 } 4122 4123 /*% 4124 * A callback for the cfg_pluginlist_foreach() call in configure_view() below. 4125 * If registering any plugin fails, registering subsequent ones is not 4126 * attempted. 4127 */ 4128 static isc_result_t 4129 register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj, 4130 const char *plugin_path, const char *parameters, 4131 void *callback_data) { 4132 dns_view_t *view = callback_data; 4133 char full_path[PATH_MAX]; 4134 isc_result_t result; 4135 4136 result = ns_plugin_expandpath(plugin_path, full_path, 4137 sizeof(full_path)); 4138 if (result != ISC_R_SUCCESS) { 4139 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4140 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4141 "%s: plugin configuration failed: " 4142 "unable to get full plugin path: %s", 4143 plugin_path, isc_result_totext(result)); 4144 return result; 4145 } 4146 4147 result = ns_plugin_register(full_path, parameters, config, 4148 cfg_obj_file(obj), cfg_obj_line(obj), 4149 named_g_mctx, named_g_lctx, 4150 named_g_aclconfctx, view); 4151 if (result != ISC_R_SUCCESS) { 4152 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4153 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4154 "%s: plugin configuration failed: %s", full_path, 4155 isc_result_totext(result)); 4156 } 4157 4158 return result; 4159 } 4160 4161 static const char *const response_synonyms[] = { "response", NULL }; 4162 4163 /* 4164 * Configure 'view' according to 'vconfig', taking defaults from 4165 * 'config' where values are missing in 'vconfig'. 4166 * 4167 * When configuring the default view, 'vconfig' will be NULL and the 4168 * global defaults in 'config' used exclusively. 4169 */ 4170 static isc_result_t 4171 configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, 4172 cfg_obj_t *vconfig, named_cachelist_t *cachelist, 4173 named_cachelist_t *oldcachelist, dns_kasplist_t *kasplist, 4174 dns_keystorelist_t *keystores, const cfg_obj_t *bindkeys, 4175 isc_mem_t *mctx, cfg_aclconfctx_t *actx, bool need_hints, 4176 bool first_time) { 4177 const cfg_obj_t *maps[4] = { 0 }; 4178 const cfg_obj_t *cfgmaps[3] = { 0 }; 4179 const cfg_obj_t *options = NULL; 4180 const cfg_obj_t *voptions = NULL; 4181 const cfg_obj_t *forwardtype; 4182 const cfg_obj_t *forwarders; 4183 const cfg_obj_t *alternates; 4184 const cfg_obj_t *zonelist; 4185 const cfg_obj_t *dlzlist; 4186 const cfg_obj_t *dlz; 4187 const cfg_obj_t *prefetch_trigger; 4188 const cfg_obj_t *prefetch_eligible; 4189 unsigned int dlzargc; 4190 char **dlzargv; 4191 const cfg_obj_t *dyndb_list, *plugin_list; 4192 const cfg_obj_t *disabled; 4193 const cfg_obj_t *obj, *obj2; 4194 const cfg_listelt_t *element = NULL; 4195 const cfg_listelt_t *zone_element_latest = NULL; 4196 in_port_t port; 4197 dns_cache_t *cache = NULL; 4198 isc_result_t result; 4199 size_t max_cache_size; 4200 uint32_t max_cache_size_percent = 0; 4201 size_t max_adb_size; 4202 uint32_t lame_ttl, fail_ttl; 4203 uint32_t max_stale_ttl = 0; 4204 uint32_t stale_refresh_time = 0; 4205 dns_tsigkeyring_t *ring = NULL; 4206 dns_transport_list_t *transports = NULL; 4207 dns_view_t *pview = NULL; /* Production view */ 4208 dns_dispatch_t *dispatch4 = NULL; 4209 dns_dispatch_t *dispatch6 = NULL; 4210 bool rpz_configured = false; 4211 bool catz_configured = false; 4212 bool shared_cache = false; 4213 int i = 0, j = 0; 4214 const char *str = NULL; 4215 const char *cachename = NULL; 4216 dns_order_t *order = NULL; 4217 uint32_t udpsize; 4218 uint32_t maxbits; 4219 unsigned int resopts = 0; 4220 dns_zone_t *zone = NULL; 4221 uint32_t clients_per_query, max_clients_per_query; 4222 bool empty_zones_enable; 4223 const cfg_obj_t *disablelist = NULL; 4224 isc_stats_t *resstats = NULL; 4225 dns_stats_t *resquerystats = NULL; 4226 bool auto_root = false; 4227 named_cache_t *nsc = NULL; 4228 bool zero_no_soattl; 4229 dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; 4230 unsigned int query_timeout; 4231 bool old_rpz_ok = false; 4232 dns_dyndbctx_t *dctx = NULL; 4233 dns_ntatable_t *ntatable = NULL; 4234 const char *qminmode = NULL; 4235 dns_adb_t *adb = NULL; 4236 bool oldcache = false; 4237 uint32_t padding; 4238 4239 REQUIRE(DNS_VIEW_VALID(view)); 4240 4241 if (config != NULL) { 4242 (void)cfg_map_get(config, "options", &options); 4243 } 4244 4245 /* 4246 * maps: view options, options, defaults 4247 * cfgmaps: view options, top-level config 4248 */ 4249 if (vconfig != NULL) { 4250 voptions = cfg_tuple_get(vconfig, "options"); 4251 maps[i++] = voptions; 4252 cfgmaps[j++] = voptions; 4253 } 4254 if (options != NULL) { 4255 maps[i++] = options; 4256 } 4257 maps[i++] = named_g_defaults; 4258 4259 if (config != NULL) { 4260 cfgmaps[j++] = config; 4261 } 4262 4263 /* 4264 * Set the view's port number for outgoing queries. 4265 */ 4266 CHECKM(named_config_getport(config, "port", &port), "port"); 4267 dns_view_setdstport(view, port); 4268 4269 /* 4270 * Make the list of response policy zone names for a view that 4271 * is used for real lookups and so cares about hints. 4272 */ 4273 obj = NULL; 4274 if (view->rdclass == dns_rdataclass_in && need_hints && 4275 named_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) 4276 { 4277 CHECK(configure_rpz(view, NULL, maps, obj, &old_rpz_ok, 4278 first_time)); 4279 rpz_configured = true; 4280 } 4281 4282 obj = NULL; 4283 if (view->rdclass != dns_rdataclass_in && need_hints && 4284 named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) 4285 { 4286 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4287 "'catalog-zones' option is only supported " 4288 "for views with class IN"); 4289 } 4290 4291 obj = NULL; 4292 if (view->rdclass == dns_rdataclass_in && need_hints && 4293 named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) 4294 { 4295 CHECK(configure_catz(view, NULL, config, obj)); 4296 catz_configured = true; 4297 } 4298 4299 /* 4300 * Configure the zones. 4301 */ 4302 zonelist = NULL; 4303 if (voptions != NULL) { 4304 (void)cfg_map_get(voptions, "zone", &zonelist); 4305 } else { 4306 (void)cfg_map_get(config, "zone", &zonelist); 4307 } 4308 4309 /* 4310 * Load zone configuration 4311 */ 4312 for (element = cfg_list_first(zonelist); element != NULL; 4313 element = cfg_list_next(element)) 4314 { 4315 const cfg_obj_t *zconfig = cfg_listelt_value(element); 4316 CHECK(configure_zone(config, zconfig, vconfig, view, viewlist, 4317 kasplist, keystores, actx, false, 4318 old_rpz_ok, false, false)); 4319 zone_element_latest = element; 4320 } 4321 4322 /* 4323 * Check that a primary or secondary zone was found for each 4324 * zone named in the response policy statement, unless we are 4325 * using RPZ service interface. 4326 */ 4327 if (view->rpzs != NULL && !view->rpzs->p.dnsrps_enabled) { 4328 dns_rpz_num_t n; 4329 4330 for (n = 0; n < view->rpzs->p.num_zones; ++n) { 4331 if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) { 4332 char namebuf[DNS_NAME_FORMATSIZE]; 4333 4334 dns_name_format(&view->rpzs->zones[n]->origin, 4335 namebuf, sizeof(namebuf)); 4336 isc_log_write(named_g_lctx, 4337 NAMED_LOGCATEGORY_GENERAL, 4338 NAMED_LOGMODULE_SERVER, 4339 DNS_RPZ_ERROR_LEVEL, 4340 "rpz '%s' is not a primary or a " 4341 "secondary zone", 4342 namebuf); 4343 result = ISC_R_NOTFOUND; 4344 goto cleanup; 4345 } 4346 } 4347 } 4348 4349 /* 4350 * If we're allowing added zones, then load zone configuration 4351 * from the newzone file for zones that were added during previous 4352 * runs. 4353 */ 4354 CHECK(configure_newzones(view, config, vconfig, actx)); 4355 4356 /* 4357 * Create Dynamically Loadable Zone driver. 4358 */ 4359 dlzlist = NULL; 4360 if (voptions != NULL) { 4361 (void)cfg_map_get(voptions, "dlz", &dlzlist); 4362 } else { 4363 (void)cfg_map_get(config, "dlz", &dlzlist); 4364 } 4365 4366 for (element = cfg_list_first(dlzlist); element != NULL; 4367 element = cfg_list_next(element)) 4368 { 4369 dlz = cfg_listelt_value(element); 4370 4371 obj = NULL; 4372 (void)cfg_map_get(dlz, "database", &obj); 4373 if (obj != NULL) { 4374 dns_dlzdb_t *dlzdb = NULL; 4375 const cfg_obj_t *name, *search = NULL; 4376 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 4377 4378 if (s == NULL) { 4379 result = ISC_R_NOMEMORY; 4380 goto cleanup; 4381 } 4382 4383 result = isc_commandline_strtoargv(mctx, s, &dlzargc, 4384 &dlzargv, 0); 4385 if (result != ISC_R_SUCCESS) { 4386 isc_mem_free(mctx, s); 4387 goto cleanup; 4388 } 4389 4390 name = cfg_map_getname(dlz); 4391 result = dns_dlzcreate(mctx, cfg_obj_asstring(name), 4392 dlzargv[0], dlzargc, dlzargv, 4393 &dlzdb); 4394 isc_mem_free(mctx, s); 4395 isc_mem_cput(mctx, dlzargv, dlzargc, sizeof(*dlzargv)); 4396 if (result != ISC_R_SUCCESS) { 4397 goto cleanup; 4398 } 4399 4400 /* 4401 * If the DLZ backend supports configuration, 4402 * and is searchable, then call its configure 4403 * method now. If not searchable, we'll take 4404 * care of it when we process the zone statement. 4405 */ 4406 (void)cfg_map_get(dlz, "search", &search); 4407 if (search == NULL || cfg_obj_asboolean(search)) { 4408 dlzdb->search = true; 4409 result = dns_dlzconfigure( 4410 view, dlzdb, dlzconfigure_callback); 4411 if (result != ISC_R_SUCCESS) { 4412 goto cleanup; 4413 } 4414 ISC_LIST_APPEND(view->dlz_searched, dlzdb, 4415 link); 4416 } else { 4417 dlzdb->search = false; 4418 ISC_LIST_APPEND(view->dlz_unsearched, dlzdb, 4419 link); 4420 } 4421 } 4422 } 4423 4424 /* 4425 * Obtain configuration parameters that affect the decision of whether 4426 * we can reuse/share an existing cache. 4427 */ 4428 obj = NULL; 4429 result = named_config_get(maps, "recursion", &obj); 4430 INSIST(result == ISC_R_SUCCESS); 4431 view->recursion = cfg_obj_asboolean(obj); 4432 4433 if (named_g_maxcachesize != 0) { 4434 /* 4435 * If "-T maxcachesize=..." is in effect, it overrides any 4436 * other "max-cache-size" setting found in configuration, 4437 * either implicit or explicit. For simplicity, the value 4438 * passed to that command line option is always treated as 4439 * the number of bytes to set "max-cache-size" to. 4440 */ 4441 max_cache_size = named_g_maxcachesize; 4442 } else { 4443 obj = NULL; 4444 result = named_config_get(maps, "max-cache-size", &obj); 4445 INSIST(result == ISC_R_SUCCESS); 4446 if (cfg_obj_isstring(obj) && 4447 strcasecmp(cfg_obj_asstring(obj), "default") == 0) 4448 { 4449 /* 4450 * The default for a view with recursion 4451 * is 90% of memory. With no recursion, 4452 * it's the minimum cache size allowed by 4453 * dns_cache_setcachesize(). 4454 */ 4455 if (view->recursion) { 4456 max_cache_size = SIZE_AS_PERCENT; 4457 max_cache_size_percent = 90; 4458 } else { 4459 max_cache_size = 1; 4460 } 4461 } else if (cfg_obj_isstring(obj)) { 4462 str = cfg_obj_asstring(obj); 4463 INSIST(strcasecmp(str, "unlimited") == 0); 4464 max_cache_size = 0; 4465 } else if (cfg_obj_ispercentage(obj)) { 4466 max_cache_size = SIZE_AS_PERCENT; 4467 max_cache_size_percent = cfg_obj_aspercentage(obj); 4468 } else if (cfg_obj_isuint64(obj)) { 4469 uint64_t value = cfg_obj_asuint64(obj); 4470 if (value > SIZE_MAX) { 4471 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4472 "'max-cache-size " 4473 "%" PRIu64 "' " 4474 "is too large for this " 4475 "system; reducing to %lu", 4476 value, (unsigned long)SIZE_MAX); 4477 value = SIZE_MAX; 4478 } 4479 max_cache_size = (size_t)value; 4480 } else { 4481 UNREACHABLE(); 4482 } 4483 } 4484 4485 if (max_cache_size == SIZE_AS_PERCENT) { 4486 uint64_t totalphys = isc_meminfo_totalphys(); 4487 4488 max_cache_size = 4489 (size_t)(totalphys * max_cache_size_percent / 100); 4490 if (totalphys == 0) { 4491 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4492 "Unable to determine amount of physical " 4493 "memory, setting 'max-cache-size' to " 4494 "unlimited"); 4495 } else { 4496 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 4497 "'max-cache-size %d%%' " 4498 "- setting to %" PRIu64 "MB " 4499 "(out of %" PRIu64 "MB)", 4500 max_cache_size_percent, 4501 (uint64_t)(max_cache_size / (1024 * 1024)), 4502 totalphys / (1024 * 1024)); 4503 } 4504 } 4505 4506 /* Check-names. */ 4507 obj = NULL; 4508 result = named_checknames_get(maps, response_synonyms, &obj); 4509 INSIST(result == ISC_R_SUCCESS); 4510 4511 str = cfg_obj_asstring(obj); 4512 if (strcasecmp(str, "fail") == 0) { 4513 resopts |= DNS_RESOLVER_CHECKNAMES | 4514 DNS_RESOLVER_CHECKNAMESFAIL; 4515 view->checknames = true; 4516 } else if (strcasecmp(str, "warn") == 0) { 4517 resopts |= DNS_RESOLVER_CHECKNAMES; 4518 view->checknames = false; 4519 } else if (strcasecmp(str, "ignore") == 0) { 4520 view->checknames = false; 4521 } else { 4522 UNREACHABLE(); 4523 } 4524 4525 obj = NULL; 4526 result = named_config_get(maps, "zero-no-soa-ttl-cache", &obj); 4527 INSIST(result == ISC_R_SUCCESS); 4528 zero_no_soattl = cfg_obj_asboolean(obj); 4529 4530 obj = NULL; 4531 result = named_config_get(maps, "resolver-use-dns64", &obj); 4532 INSIST(result == ISC_R_SUCCESS); 4533 view->usedns64 = cfg_obj_asboolean(obj); 4534 4535 obj = NULL; 4536 result = named_config_get(maps, "dns64", &obj); 4537 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && 4538 strcmp(view->name, "_meta")) 4539 { 4540 isc_netaddr_t na, suffix, *sp; 4541 unsigned int prefixlen; 4542 const char *server, *contact; 4543 const cfg_obj_t *myobj; 4544 4545 myobj = NULL; 4546 result = named_config_get(maps, "dns64-server", &myobj); 4547 if (result == ISC_R_SUCCESS) { 4548 server = cfg_obj_asstring(myobj); 4549 } else { 4550 server = NULL; 4551 } 4552 4553 myobj = NULL; 4554 result = named_config_get(maps, "dns64-contact", &myobj); 4555 if (result == ISC_R_SUCCESS) { 4556 contact = cfg_obj_asstring(myobj); 4557 } else { 4558 contact = NULL; 4559 } 4560 4561 for (element = cfg_list_first(obj); element != NULL; 4562 element = cfg_list_next(element)) 4563 { 4564 const cfg_obj_t *map = cfg_listelt_value(element); 4565 dns_dns64_t *dns64 = NULL; 4566 unsigned int dns64options = 0; 4567 4568 cfg_obj_asnetprefix(cfg_map_getname(map), &na, 4569 &prefixlen); 4570 4571 obj = NULL; 4572 (void)cfg_map_get(map, "suffix", &obj); 4573 if (obj != NULL) { 4574 sp = &suffix; 4575 isc_netaddr_fromsockaddr( 4576 sp, cfg_obj_assockaddr(obj)); 4577 } else { 4578 sp = NULL; 4579 } 4580 4581 clients = mapped = excluded = NULL; 4582 obj = NULL; 4583 (void)cfg_map_get(map, "clients", &obj); 4584 if (obj != NULL) { 4585 result = cfg_acl_fromconfig(obj, config, 4586 named_g_lctx, actx, 4587 mctx, 0, &clients); 4588 if (result != ISC_R_SUCCESS) { 4589 goto cleanup; 4590 } 4591 } 4592 obj = NULL; 4593 (void)cfg_map_get(map, "mapped", &obj); 4594 if (obj != NULL) { 4595 result = cfg_acl_fromconfig(obj, config, 4596 named_g_lctx, actx, 4597 mctx, 0, &mapped); 4598 if (result != ISC_R_SUCCESS) { 4599 goto cleanup; 4600 } 4601 } 4602 obj = NULL; 4603 (void)cfg_map_get(map, "exclude", &obj); 4604 if (obj != NULL) { 4605 result = cfg_acl_fromconfig(obj, config, 4606 named_g_lctx, actx, 4607 mctx, 0, &excluded); 4608 if (result != ISC_R_SUCCESS) { 4609 goto cleanup; 4610 } 4611 } else { 4612 if (named_g_mapped == NULL) { 4613 result = create_mapped_acl(); 4614 if (result != ISC_R_SUCCESS) { 4615 goto cleanup; 4616 } 4617 } 4618 dns_acl_attach(named_g_mapped, &excluded); 4619 } 4620 4621 obj = NULL; 4622 (void)cfg_map_get(map, "recursive-only", &obj); 4623 if (obj != NULL && cfg_obj_asboolean(obj)) { 4624 dns64options |= DNS_DNS64_RECURSIVE_ONLY; 4625 } 4626 4627 obj = NULL; 4628 (void)cfg_map_get(map, "break-dnssec", &obj); 4629 if (obj != NULL && cfg_obj_asboolean(obj)) { 4630 dns64options |= DNS_DNS64_BREAK_DNSSEC; 4631 } 4632 4633 result = dns_dns64_create(mctx, &na, prefixlen, sp, 4634 clients, mapped, excluded, 4635 dns64options, &dns64); 4636 if (result != ISC_R_SUCCESS) { 4637 goto cleanup; 4638 } 4639 dns_dns64_append(&view->dns64, dns64); 4640 view->dns64cnt++; 4641 result = dns64_reverse(view, mctx, &na, prefixlen, 4642 server, contact); 4643 if (result != ISC_R_SUCCESS) { 4644 goto cleanup; 4645 } 4646 if (clients != NULL) { 4647 dns_acl_detach(&clients); 4648 } 4649 if (mapped != NULL) { 4650 dns_acl_detach(&mapped); 4651 } 4652 if (excluded != NULL) { 4653 dns_acl_detach(&excluded); 4654 } 4655 } 4656 } 4657 4658 obj = NULL; 4659 result = named_config_get(maps, "dnssec-accept-expired", &obj); 4660 INSIST(result == ISC_R_SUCCESS); 4661 view->acceptexpired = cfg_obj_asboolean(obj); 4662 4663 obj = NULL; 4664 result = named_config_get(maps, "dnssec-validation", &obj); 4665 INSIST(result == ISC_R_SUCCESS); 4666 if (cfg_obj_isboolean(obj)) { 4667 view->enablevalidation = cfg_obj_asboolean(obj); 4668 } else { 4669 /* 4670 * If dnssec-validation is set but not boolean, 4671 * then it must be "auto" 4672 */ 4673 view->enablevalidation = true; 4674 auto_root = true; 4675 } 4676 4677 obj = NULL; 4678 result = named_config_get(maps, "max-cache-ttl", &obj); 4679 INSIST(result == ISC_R_SUCCESS); 4680 view->maxcachettl = cfg_obj_asduration(obj); 4681 4682 obj = NULL; 4683 result = named_config_get(maps, "max-ncache-ttl", &obj); 4684 INSIST(result == ISC_R_SUCCESS); 4685 view->maxncachettl = cfg_obj_asduration(obj); 4686 4687 obj = NULL; 4688 result = named_config_get(maps, "min-cache-ttl", &obj); 4689 INSIST(result == ISC_R_SUCCESS); 4690 view->mincachettl = cfg_obj_asduration(obj); 4691 4692 obj = NULL; 4693 result = named_config_get(maps, "min-ncache-ttl", &obj); 4694 INSIST(result == ISC_R_SUCCESS); 4695 view->minncachettl = cfg_obj_asduration(obj); 4696 4697 obj = NULL; 4698 result = named_config_get(maps, "synth-from-dnssec", &obj); 4699 INSIST(result == ISC_R_SUCCESS); 4700 view->synthfromdnssec = cfg_obj_asboolean(obj); 4701 4702 obj = NULL; 4703 result = named_config_get(maps, "stale-cache-enable", &obj); 4704 INSIST(result == ISC_R_SUCCESS); 4705 if (cfg_obj_asboolean(obj)) { 4706 obj = NULL; 4707 result = named_config_get(maps, "max-stale-ttl", &obj); 4708 INSIST(result == ISC_R_SUCCESS); 4709 max_stale_ttl = ISC_MAX(cfg_obj_asduration(obj), 1); 4710 } 4711 /* 4712 * If 'stale-cache-enable' is false, max_stale_ttl is set to 0, 4713 * meaning keeping stale RRsets in cache is disabled. 4714 */ 4715 4716 obj = NULL; 4717 result = named_config_get(maps, "stale-answer-enable", &obj); 4718 INSIST(result == ISC_R_SUCCESS); 4719 view->staleanswersenable = cfg_obj_asboolean(obj); 4720 4721 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 4722 view->rdclass, &pview); 4723 if (result == ISC_R_SUCCESS) { 4724 view->staleanswersok = pview->staleanswersok; 4725 dns_view_detach(&pview); 4726 } else { 4727 view->staleanswersok = dns_stale_answer_conf; 4728 } 4729 4730 obj = NULL; 4731 result = named_config_get(maps, "stale-answer-client-timeout", &obj); 4732 INSIST(result == ISC_R_SUCCESS); 4733 if (cfg_obj_isstring(obj)) { 4734 /* 4735 * The only string values available for this option 4736 * are "disabled" and "off". 4737 * We use (uint32_t) -1 to represent disabled since 4738 * a value of zero means that stale data can be used 4739 * to promptly answer the query, while an attempt to 4740 * refresh the RRset will still be made in background. 4741 */ 4742 view->staleanswerclienttimeout = (uint32_t)-1; 4743 } else { 4744 view->staleanswerclienttimeout = cfg_obj_asuint32(obj); 4745 4746 /* 4747 * BIND 9 no longer supports non-zero values of 4748 * stale-answer-client-timeout. 4749 */ 4750 if (view->staleanswerclienttimeout != 0) { 4751 view->staleanswerclienttimeout = 0; 4752 isc_log_write( 4753 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4754 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 4755 "BIND 9 no longer supports non-zero values of " 4756 "stale-answer-client-timeout, adjusted to 0"); 4757 } 4758 } 4759 4760 obj = NULL; 4761 result = named_config_get(maps, "stale-refresh-time", &obj); 4762 INSIST(result == ISC_R_SUCCESS); 4763 stale_refresh_time = cfg_obj_asduration(obj); 4764 4765 /* 4766 * Configure the view's cache. 4767 * 4768 * First, check to see if there are any attach-cache options. If yes, 4769 * attempt to lookup an existing cache at attach it to the view. If 4770 * there is not one, then try to reuse an existing cache if possible; 4771 * otherwise create a new cache. 4772 * 4773 * Note that the ADB is not preserved or shared in either case. 4774 * 4775 * When a matching view is found, the associated statistics are also 4776 * retrieved and reused. 4777 * 4778 * XXX Determining when it is safe to reuse or share a cache is tricky. 4779 * When the view's configuration changes, the cached data may become 4780 * invalid because it reflects our old view of the world. We check 4781 * some of the configuration parameters that could invalidate the cache 4782 * or otherwise make it unshareable, but there are other configuration 4783 * options that should be checked. For example, if a view uses a 4784 * forwarder, changes in the forwarder configuration may invalidate 4785 * the cache. At the moment, it's the administrator's responsibility to 4786 * ensure these configuration options don't invalidate reusing/sharing. 4787 */ 4788 obj = NULL; 4789 result = named_config_get(maps, "attach-cache", &obj); 4790 if (result == ISC_R_SUCCESS) { 4791 cachename = cfg_obj_asstring(obj); 4792 } else { 4793 cachename = view->name; 4794 } 4795 4796 nsc = cachelist_find(cachelist, cachename, view->rdclass); 4797 if (result == ISC_R_SUCCESS && nsc == NULL) { 4798 /* 4799 * If we're using 'attach-cache' but didn't find the 4800 * specified cache in the cache list already, check 4801 * the old list. 4802 */ 4803 nsc = cachelist_find(oldcachelist, cachename, view->rdclass); 4804 oldcache = true; 4805 } 4806 if (nsc != NULL) { 4807 if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, 4808 max_cache_size, max_stale_ttl, 4809 stale_refresh_time)) 4810 { 4811 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4812 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 4813 "view %s can't use existing cache %s due " 4814 "to configuration parameter mismatch", 4815 view->name, 4816 dns_cache_getname(nsc->cache)); 4817 nsc = NULL; 4818 } else { 4819 shared_cache = true; 4820 dns_cache_attach(nsc->cache, &cache); 4821 if (oldcache) { 4822 /* 4823 * We need to re-use the cache, but we don't 4824 * want to mutate the old production list. 4825 */ 4826 nsc = NULL; 4827 } 4828 } 4829 } else if (strcmp(cachename, view->name) == 0) { 4830 result = dns_viewlist_find(&named_g_server->viewlist, cachename, 4831 view->rdclass, &pview); 4832 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 4833 goto cleanup; 4834 } 4835 if (pview != NULL) { 4836 if (!cache_reusable(pview, view, zero_no_soattl)) { 4837 isc_log_write(named_g_lctx, 4838 NAMED_LOGCATEGORY_GENERAL, 4839 NAMED_LOGMODULE_SERVER, 4840 ISC_LOG_DEBUG(1), 4841 "cache cannot be reused " 4842 "for view %s due to " 4843 "configuration parameter " 4844 "mismatch", 4845 view->name); 4846 } else { 4847 INSIST(pview->cache != NULL); 4848 isc_log_write(named_g_lctx, 4849 NAMED_LOGCATEGORY_GENERAL, 4850 NAMED_LOGMODULE_SERVER, 4851 ISC_LOG_DEBUG(3), 4852 "reusing existing cache"); 4853 dns_cache_attach(pview->cache, &cache); 4854 } 4855 dns_resolver_getstats(pview->resolver, &resstats); 4856 dns_resolver_getquerystats(pview->resolver, 4857 &resquerystats); 4858 dns_view_detach(&pview); 4859 } 4860 } 4861 4862 if (nsc == NULL) { 4863 /* 4864 * Create a cache with the desired name. This normally 4865 * equals the view name, but may also be a forward 4866 * reference to a view that share the cache with this 4867 * view but is not yet configured. If it is not the 4868 * view name but not a forward reference either, then it 4869 * is simply a named cache that is not shared. 4870 */ 4871 if (cache == NULL) { 4872 CHECK(dns_cache_create(named_g_loopmgr, view->rdclass, 4873 cachename, mctx, &cache)); 4874 } 4875 4876 nsc = isc_mem_get(mctx, sizeof(*nsc)); 4877 *nsc = (named_cache_t){ 4878 .primaryview = view, 4879 .rdclass = view->rdclass, 4880 .link = ISC_LINK_INITIALIZER, 4881 }; 4882 4883 dns_cache_attach(cache, &nsc->cache); 4884 ISC_LIST_APPEND(*cachelist, nsc, link); 4885 } 4886 4887 dns_view_setcache(view, cache, shared_cache); 4888 4889 dns_cache_setcachesize(cache, max_cache_size); 4890 dns_cache_setservestalettl(cache, max_stale_ttl); 4891 dns_cache_setservestalerefresh(cache, stale_refresh_time); 4892 4893 dns_cache_detach(&cache); 4894 4895 obj = NULL; 4896 result = named_config_get(maps, "stale-answer-ttl", &obj); 4897 INSIST(result == ISC_R_SUCCESS); 4898 view->staleanswerttl = ISC_MAX(cfg_obj_asduration(obj), 1); 4899 4900 /* 4901 * Resolver. 4902 */ 4903 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4, 4904 ISC_LIST_PREV(view, link) == NULL)); 4905 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6, 4906 ISC_LIST_PREV(view, link) == NULL)); 4907 if (dispatch4 == NULL && dispatch6 == NULL) { 4908 UNEXPECTED_ERROR("unable to obtain either an IPv4 or" 4909 " an IPv6 dispatch"); 4910 result = ISC_R_UNEXPECTED; 4911 goto cleanup; 4912 } 4913 4914 CHECK(dns_view_createresolver(view, named_g_netmgr, resopts, 4915 named_g_server->tlsctx_client_cache, 4916 dispatch4, dispatch6)); 4917 4918 if (resstats == NULL) { 4919 isc_stats_create(mctx, &resstats, dns_resstatscounter_max); 4920 } 4921 dns_resolver_setstats(view->resolver, resstats); 4922 if (resquerystats == NULL) { 4923 dns_rdatatypestats_create(mctx, &resquerystats); 4924 } 4925 dns_resolver_setquerystats(view->resolver, resquerystats); 4926 4927 /* 4928 * Set the ADB cache size to 1/8th of the max-cache-size or 4929 * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. 4930 */ 4931 max_adb_size = 0; 4932 if (max_cache_size != 0U) { 4933 max_adb_size = max_cache_size / 8; 4934 if (max_adb_size == 0U) { 4935 max_adb_size = 1; /* Force minimum. */ 4936 } 4937 if (view != nsc->primaryview && 4938 max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) 4939 { 4940 max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; 4941 if (!nsc->adbsizeadjusted) { 4942 dns_view_getadb(nsc->primaryview, &adb); 4943 if (adb != NULL) { 4944 dns_adb_setadbsize( 4945 adb, 4946 MAX_ADB_SIZE_FOR_CACHESHARE); 4947 nsc->adbsizeadjusted = true; 4948 dns_adb_detach(&adb); 4949 } 4950 } 4951 } 4952 } 4953 dns_view_getadb(view, &adb); 4954 if (adb != NULL) { 4955 dns_adb_setadbsize(adb, max_adb_size); 4956 dns_adb_detach(&adb); 4957 } 4958 4959 /* 4960 * Set up ADB quotas 4961 */ 4962 { 4963 uint32_t fps, freq; 4964 double low, high, discount; 4965 4966 obj = NULL; 4967 result = named_config_get(maps, "fetches-per-server", &obj); 4968 INSIST(result == ISC_R_SUCCESS); 4969 obj2 = cfg_tuple_get(obj, "fetches"); 4970 fps = cfg_obj_asuint32(obj2); 4971 obj2 = cfg_tuple_get(obj, "response"); 4972 if (!cfg_obj_isvoid(obj2)) { 4973 const char *resp = cfg_obj_asstring(obj2); 4974 isc_result_t r = DNS_R_SERVFAIL; 4975 4976 if (strcasecmp(resp, "drop") == 0) { 4977 r = DNS_R_DROP; 4978 } else if (strcasecmp(resp, "fail") == 0) { 4979 r = DNS_R_SERVFAIL; 4980 } else { 4981 UNREACHABLE(); 4982 } 4983 4984 dns_resolver_setquotaresponse(view->resolver, 4985 dns_quotatype_server, r); 4986 } 4987 4988 obj = NULL; 4989 result = named_config_get(maps, "fetch-quota-params", &obj); 4990 INSIST(result == ISC_R_SUCCESS); 4991 4992 obj2 = cfg_tuple_get(obj, "frequency"); 4993 freq = cfg_obj_asuint32(obj2); 4994 4995 obj2 = cfg_tuple_get(obj, "low"); 4996 low = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 4997 4998 obj2 = cfg_tuple_get(obj, "high"); 4999 high = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 5000 5001 obj2 = cfg_tuple_get(obj, "discount"); 5002 discount = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 5003 5004 dns_view_getadb(view, &adb); 5005 if (adb != NULL) { 5006 dns_adb_setquota(adb, fps, freq, low, high, discount); 5007 dns_adb_detach(&adb); 5008 } 5009 } 5010 5011 /* 5012 * Set resolver's lame-ttl. 5013 */ 5014 obj = NULL; 5015 result = named_config_get(maps, "lame-ttl", &obj); 5016 INSIST(result == ISC_R_SUCCESS); 5017 lame_ttl = cfg_obj_asduration(obj); 5018 if (lame_ttl > 0) { 5019 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 5020 "disabling lame cache despite lame-ttl > 0 as it " 5021 "may cause performance issues"); 5022 } 5023 5024 /* 5025 * Set the resolver's query timeout. 5026 */ 5027 obj = NULL; 5028 result = named_config_get(maps, "resolver-query-timeout", &obj); 5029 INSIST(result == ISC_R_SUCCESS); 5030 query_timeout = cfg_obj_asuint32(obj); 5031 dns_resolver_settimeout(view->resolver, query_timeout); 5032 5033 /* Specify whether to use 0-TTL for negative response for SOA query */ 5034 dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); 5035 5036 /* 5037 * Set the resolver's EDNS UDP size. 5038 */ 5039 obj = NULL; 5040 result = named_config_get(maps, "edns-udp-size", &obj); 5041 INSIST(result == ISC_R_SUCCESS); 5042 udpsize = cfg_obj_asuint32(obj); 5043 if (udpsize < 512) { 5044 udpsize = 512; 5045 } 5046 if (udpsize > 4096) { 5047 udpsize = 4096; 5048 } 5049 dns_view_setudpsize(view, (uint16_t)udpsize); 5050 5051 /* 5052 * Set the maximum UDP response size. 5053 */ 5054 obj = NULL; 5055 result = named_config_get(maps, "max-udp-size", &obj); 5056 INSIST(result == ISC_R_SUCCESS); 5057 udpsize = cfg_obj_asuint32(obj); 5058 if (udpsize < 512) { 5059 udpsize = 512; 5060 } 5061 if (udpsize > 4096) { 5062 udpsize = 4096; 5063 } 5064 view->maxudp = udpsize; 5065 5066 /* 5067 * Set the maximum UDP when a COOKIE is not provided. 5068 */ 5069 obj = NULL; 5070 result = named_config_get(maps, "nocookie-udp-size", &obj); 5071 INSIST(result == ISC_R_SUCCESS); 5072 udpsize = cfg_obj_asuint32(obj); 5073 if (udpsize < 128) { 5074 udpsize = 128; 5075 } 5076 if (udpsize > view->maxudp) { 5077 udpsize = view->maxudp; 5078 } 5079 view->nocookieudp = udpsize; 5080 5081 /* 5082 * Set the maximum rsa exponent bits. 5083 */ 5084 obj = NULL; 5085 result = named_config_get(maps, "max-rsa-exponent-size", &obj); 5086 INSIST(result == ISC_R_SUCCESS); 5087 maxbits = cfg_obj_asuint32(obj); 5088 if (maxbits != 0 && maxbits < 35) { 5089 maxbits = 35; 5090 } 5091 if (maxbits > 4096) { 5092 maxbits = 4096; 5093 } 5094 view->maxbits = maxbits; 5095 5096 /* 5097 * Set supported DNSSEC algorithms. 5098 */ 5099 disabled = NULL; 5100 (void)named_config_get(maps, "disable-algorithms", &disabled); 5101 if (disabled != NULL) { 5102 for (element = cfg_list_first(disabled); element != NULL; 5103 element = cfg_list_next(element)) 5104 { 5105 CHECK(disable_algorithms(cfg_listelt_value(element), 5106 view->resolver)); 5107 } 5108 } 5109 5110 /* 5111 * Set supported DS digest types. 5112 */ 5113 disabled = NULL; 5114 (void)named_config_get(maps, "disable-ds-digests", &disabled); 5115 if (disabled != NULL) { 5116 for (element = cfg_list_first(disabled); element != NULL; 5117 element = cfg_list_next(element)) 5118 { 5119 CHECK(disable_ds_digests(cfg_listelt_value(element), 5120 view->resolver)); 5121 } 5122 } 5123 5124 /* 5125 * A global or view "forwarders" option, if present, 5126 * creates an entry for "." in the forwarding table. 5127 */ 5128 forwardtype = NULL; 5129 forwarders = NULL; 5130 (void)named_config_get(maps, "forward", &forwardtype); 5131 (void)named_config_get(maps, "forwarders", &forwarders); 5132 if (forwarders != NULL) { 5133 CHECK(configure_forward(config, view, dns_rootname, forwarders, 5134 forwardtype)); 5135 } 5136 5137 /* 5138 * Dual Stack Servers. 5139 */ 5140 alternates = NULL; 5141 (void)named_config_get(maps, "dual-stack-servers", &alternates); 5142 if (alternates != NULL) { 5143 CHECK(configure_alternates(config, view, alternates)); 5144 } 5145 5146 /* 5147 * We have default hints for class IN if we need them. 5148 */ 5149 if (view->rdclass == dns_rdataclass_in && view->hints == NULL) { 5150 dns_view_sethints(view, named_g_server->in_roothints); 5151 } 5152 5153 /* 5154 * If we still have no hints, this is a non-IN view with no 5155 * "hints zone" configured. Issue a warning, except if this 5156 * is a root server. Root servers never need to consult 5157 * their hints, so it's no point requiring users to configure 5158 * them. 5159 */ 5160 if (view->hints == NULL) { 5161 dns_zone_t *rootzone = NULL; 5162 (void)dns_view_findzone(view, dns_rootname, DNS_ZTFIND_EXACT, 5163 &rootzone); 5164 if (rootzone != NULL) { 5165 dns_zone_detach(&rootzone); 5166 need_hints = false; 5167 } 5168 if (need_hints) { 5169 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 5170 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 5171 "no root hints for view '%s'", 5172 view->name); 5173 } 5174 } 5175 5176 /* 5177 * Configure the view's transports (DoT/DoH) 5178 */ 5179 CHECK(named_transports_fromconfig(config, vconfig, view->mctx, 5180 &transports)); 5181 dns_view_settransports(view, transports); 5182 dns_transport_list_detach(&transports); 5183 5184 /* 5185 * Configure SIG(0) check limits when matching a DNS message to a view. 5186 */ 5187 obj = NULL; 5188 result = named_config_get(maps, "sig0key-checks-limit", &obj); 5189 INSIST(result == ISC_R_SUCCESS); 5190 view->sig0key_checks_limit = cfg_obj_asuint32(obj); 5191 5192 obj = NULL; 5193 result = named_config_get(maps, "sig0message-checks-limit", &obj); 5194 INSIST(result == ISC_R_SUCCESS); 5195 view->sig0message_checks_limit = cfg_obj_asuint32(obj); 5196 5197 /* 5198 * Configure the view's TSIG keys. 5199 */ 5200 CHECK(named_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); 5201 if (named_g_server->sessionkey != NULL) { 5202 dns_tsigkey_t *tsigkey = NULL; 5203 result = dns_tsigkey_createfromkey( 5204 named_g_server->session_keyname, 5205 named_g_server->session_keyalg, 5206 named_g_server->sessionkey, false, false, NULL, 0, 0, 5207 mctx, &tsigkey); 5208 if (result == ISC_R_SUCCESS) { 5209 result = dns_tsigkeyring_add(ring, tsigkey); 5210 dns_tsigkey_detach(&tsigkey); 5211 } 5212 CHECK(result); 5213 } 5214 dns_view_setkeyring(view, ring); 5215 dns_tsigkeyring_detach(&ring); 5216 5217 /* 5218 * See if we can re-use a dynamic key ring. 5219 */ 5220 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 5221 view->rdclass, &pview); 5222 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 5223 goto cleanup; 5224 } 5225 if (pview != NULL) { 5226 dns_view_getdynamickeyring(pview, &ring); 5227 if (ring != NULL) { 5228 dns_view_setdynamickeyring(view, ring); 5229 } 5230 dns_tsigkeyring_detach(&ring); 5231 dns_view_detach(&pview); 5232 } else { 5233 dns_view_restorekeyring(view); 5234 } 5235 5236 /* 5237 * Configure the view's peer list. 5238 */ 5239 { 5240 const cfg_obj_t *peers = NULL; 5241 dns_peerlist_t *newpeers = NULL; 5242 5243 (void)named_config_get(cfgmaps, "server", &peers); 5244 CHECK(dns_peerlist_new(mctx, &newpeers)); 5245 for (element = cfg_list_first(peers); element != NULL; 5246 element = cfg_list_next(element)) 5247 { 5248 const cfg_obj_t *cpeer = cfg_listelt_value(element); 5249 dns_peer_t *peer; 5250 5251 CHECK(configure_peer(cpeer, mctx, &peer)); 5252 dns_peerlist_addpeer(newpeers, peer); 5253 dns_peer_detach(&peer); 5254 } 5255 dns_peerlist_detach(&view->peers); 5256 view->peers = newpeers; /* Transfer ownership. */ 5257 } 5258 5259 /* 5260 * Configure the views rrset-order. 5261 */ 5262 { 5263 const cfg_obj_t *rrsetorder = NULL; 5264 5265 (void)named_config_get(maps, "rrset-order", &rrsetorder); 5266 CHECK(dns_order_create(mctx, &order)); 5267 for (element = cfg_list_first(rrsetorder); element != NULL; 5268 element = cfg_list_next(element)) 5269 { 5270 const cfg_obj_t *ent = cfg_listelt_value(element); 5271 5272 CHECK(configure_order(order, ent)); 5273 } 5274 if (view->order != NULL) { 5275 dns_order_detach(&view->order); 5276 } 5277 dns_order_attach(order, &view->order); 5278 dns_order_detach(&order); 5279 } 5280 /* 5281 * Copy the aclenv object. 5282 */ 5283 dns_aclenv_copy(view->aclenv, ns_interfacemgr_getaclenv( 5284 named_g_server->interfacemgr)); 5285 5286 /* 5287 * Configure the "match-clients" and "match-destinations" ACL. 5288 * (These are only meaningful at the view level, but 'config' 5289 * must be passed so that named ACLs defined at the global level 5290 * can be retrieved.) 5291 */ 5292 CHECK(configure_view_acl(vconfig, config, NULL, "match-clients", NULL, 5293 actx, named_g_mctx, &view->matchclients)); 5294 CHECK(configure_view_acl(vconfig, config, NULL, "match-destinations", 5295 NULL, actx, named_g_mctx, 5296 &view->matchdestinations)); 5297 5298 /* 5299 * Configure the "match-recursive-only" option. 5300 */ 5301 obj = NULL; 5302 (void)named_config_get(maps, "match-recursive-only", &obj); 5303 if (obj != NULL && cfg_obj_asboolean(obj)) { 5304 view->matchrecursiveonly = true; 5305 } else { 5306 view->matchrecursiveonly = false; 5307 } 5308 5309 /* 5310 * Configure other configurable data. 5311 */ 5312 obj = NULL; 5313 result = named_config_get(maps, "qname-minimization", &obj); 5314 INSIST(result == ISC_R_SUCCESS); 5315 qminmode = cfg_obj_asstring(obj); 5316 INSIST(qminmode != NULL); 5317 if (!strcmp(qminmode, "strict")) { 5318 view->qminimization = true; 5319 view->qmin_strict = true; 5320 } else if (!strcmp(qminmode, "relaxed")) { 5321 view->qminimization = true; 5322 view->qmin_strict = false; 5323 } else { /* "disabled" or "off" */ 5324 view->qminimization = false; 5325 view->qmin_strict = false; 5326 } 5327 5328 obj = NULL; 5329 result = named_config_get(maps, "auth-nxdomain", &obj); 5330 INSIST(result == ISC_R_SUCCESS); 5331 view->auth_nxdomain = cfg_obj_asboolean(obj); 5332 5333 obj = NULL; 5334 result = named_config_get(maps, "minimal-any", &obj); 5335 INSIST(result == ISC_R_SUCCESS); 5336 view->minimal_any = cfg_obj_asboolean(obj); 5337 5338 obj = NULL; 5339 result = named_config_get(maps, "minimal-responses", &obj); 5340 INSIST(result == ISC_R_SUCCESS); 5341 if (cfg_obj_isboolean(obj)) { 5342 if (cfg_obj_asboolean(obj)) { 5343 view->minimalresponses = dns_minimal_yes; 5344 } else { 5345 view->minimalresponses = dns_minimal_no; 5346 } 5347 } else { 5348 str = cfg_obj_asstring(obj); 5349 if (strcasecmp(str, "no-auth") == 0) { 5350 view->minimalresponses = dns_minimal_noauth; 5351 } else if (strcasecmp(str, "no-auth-recursive") == 0) { 5352 view->minimalresponses = dns_minimal_noauthrec; 5353 } else { 5354 UNREACHABLE(); 5355 } 5356 } 5357 5358 obj = NULL; 5359 result = named_config_get(maps, "transfer-format", &obj); 5360 INSIST(result == ISC_R_SUCCESS); 5361 str = cfg_obj_asstring(obj); 5362 if (strcasecmp(str, "many-answers") == 0) { 5363 view->transfer_format = dns_many_answers; 5364 } else if (strcasecmp(str, "one-answer") == 0) { 5365 view->transfer_format = dns_one_answer; 5366 } else { 5367 UNREACHABLE(); 5368 } 5369 5370 obj = NULL; 5371 result = named_config_get(maps, "trust-anchor-telemetry", &obj); 5372 INSIST(result == ISC_R_SUCCESS); 5373 view->trust_anchor_telemetry = cfg_obj_asboolean(obj); 5374 5375 obj = NULL; 5376 result = named_config_get(maps, "root-key-sentinel", &obj); 5377 INSIST(result == ISC_R_SUCCESS); 5378 view->root_key_sentinel = cfg_obj_asboolean(obj); 5379 5380 /* 5381 * Set the "allow-query", "allow-query-cache", "allow-recursion", 5382 * "allow-recursion-on" and "allow-query-cache-on" ACLs if 5383 * configured in named.conf, but NOT from the global defaults. 5384 * This is done by leaving the third argument to configure_view_acl() 5385 * NULL. 5386 * 5387 * We ignore the global defaults here because these ACLs 5388 * can inherit from each other. If any are still unset after 5389 * applying the inheritance rules, we'll look up the defaults at 5390 * that time. 5391 */ 5392 5393 /* named.conf only */ 5394 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query", NULL, 5395 actx, named_g_mctx, &view->queryacl)); 5396 5397 /* named.conf only */ 5398 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache", 5399 NULL, actx, named_g_mctx, &view->cacheacl)); 5400 /* named.conf only */ 5401 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on", 5402 NULL, actx, named_g_mctx, &view->cacheonacl)); 5403 5404 CHECK(configure_view_acl(vconfig, config, named_g_config, "allow-proxy", 5405 NULL, actx, named_g_mctx, &view->proxyacl)); 5406 5407 CHECK(configure_view_acl(vconfig, config, named_g_config, 5408 "allow-proxy-on", NULL, actx, named_g_mctx, 5409 &view->proxyonacl)); 5410 5411 if (strcmp(view->name, "_bind") != 0 && 5412 view->rdclass != dns_rdataclass_chaos) 5413 { 5414 /* named.conf only */ 5415 CHECK(configure_view_acl(vconfig, config, NULL, 5416 "allow-recursion", NULL, actx, 5417 named_g_mctx, &view->recursionacl)); 5418 /* named.conf only */ 5419 CHECK(configure_view_acl(vconfig, config, NULL, 5420 "allow-recursion-on", NULL, actx, 5421 named_g_mctx, &view->recursiononacl)); 5422 } 5423 5424 if (view->recursion) { 5425 /* 5426 * "allow-query-cache" inherits from "allow-recursion" if set, 5427 * otherwise from "allow-query" if set. 5428 */ 5429 if (view->cacheacl == NULL) { 5430 if (view->recursionacl != NULL) { 5431 dns_acl_attach(view->recursionacl, 5432 &view->cacheacl); 5433 } else if (view->queryacl != NULL) { 5434 dns_acl_attach(view->queryacl, &view->cacheacl); 5435 } 5436 } 5437 5438 /* 5439 * "allow-recursion" inherits from "allow-query-cache" if set, 5440 * otherwise from "allow-query" if set. 5441 */ 5442 if (view->recursionacl == NULL) { 5443 if (view->cacheacl != NULL) { 5444 dns_acl_attach(view->cacheacl, 5445 &view->recursionacl); 5446 } else if (view->queryacl != NULL) { 5447 dns_acl_attach(view->queryacl, 5448 &view->recursionacl); 5449 } 5450 } 5451 5452 /* 5453 * "allow-query-cache-on" inherits from "allow-recursion-on" 5454 * if set. 5455 */ 5456 if (view->cacheonacl == NULL) { 5457 if (view->recursiononacl != NULL) { 5458 dns_acl_attach(view->recursiononacl, 5459 &view->cacheonacl); 5460 } 5461 } 5462 5463 /* 5464 * "allow-recursion-on" inherits from "allow-query-cache-on" 5465 * if set. 5466 */ 5467 if (view->recursiononacl == NULL) { 5468 if (view->cacheonacl != NULL) { 5469 dns_acl_attach(view->cacheonacl, 5470 &view->recursiononacl); 5471 } 5472 } 5473 5474 /* 5475 * If any are still unset at this point, we now get default 5476 * values for from the global config. 5477 */ 5478 5479 if (view->recursionacl == NULL) { 5480 /* global default only */ 5481 CHECK(configure_view_acl( 5482 NULL, NULL, named_g_config, "allow-recursion", 5483 NULL, actx, named_g_mctx, &view->recursionacl)); 5484 } 5485 if (view->recursiononacl == NULL) { 5486 /* global default only */ 5487 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5488 "allow-recursion-on", NULL, 5489 actx, named_g_mctx, 5490 &view->recursiononacl)); 5491 } 5492 if (view->cacheacl == NULL) { 5493 /* global default only */ 5494 CHECK(configure_view_acl( 5495 NULL, NULL, named_g_config, "allow-query-cache", 5496 NULL, actx, named_g_mctx, &view->cacheacl)); 5497 } 5498 if (view->cacheonacl == NULL) { 5499 /* global default only */ 5500 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5501 "allow-query-cache-on", NULL, 5502 actx, named_g_mctx, 5503 &view->cacheonacl)); 5504 } 5505 } else { 5506 /* 5507 * We're not recursive; if the query-cache ACLs haven't 5508 * been set at the options/view level, set them to none. 5509 */ 5510 if (view->cacheacl == NULL) { 5511 CHECK(dns_acl_none(mctx, &view->cacheacl)); 5512 } 5513 if (view->cacheonacl == NULL) { 5514 CHECK(dns_acl_none(mctx, &view->cacheonacl)); 5515 } 5516 } 5517 5518 /* 5519 * Finished setting recursion and query-cache ACLs, so now we 5520 * can get the allow-query default if it wasn't set in named.conf 5521 */ 5522 if (view->queryacl == NULL) { 5523 /* global default only */ 5524 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5525 "allow-query", NULL, actx, 5526 named_g_mctx, &view->queryacl)); 5527 } 5528 5529 /* 5530 * Ignore case when compressing responses to the specified 5531 * clients. This causes case not always to be preserved, 5532 * and is needed by some broken clients. 5533 */ 5534 CHECK(configure_view_acl(vconfig, config, named_g_config, 5535 "no-case-compress", NULL, actx, named_g_mctx, 5536 &view->nocasecompress)); 5537 5538 /* 5539 * Disable name compression completely, this is a tradeoff 5540 * between CPU and network usage. 5541 */ 5542 obj = NULL; 5543 result = named_config_get(maps, "message-compression", &obj); 5544 INSIST(result == ISC_R_SUCCESS); 5545 view->msgcompression = cfg_obj_asboolean(obj); 5546 5547 /* 5548 * Filter setting on addresses in the answer section. 5549 */ 5550 CHECK(configure_view_acl(vconfig, config, named_g_config, 5551 "deny-answer-addresses", "acl", actx, 5552 named_g_mctx, &view->denyansweracl)); 5553 CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", 5554 "except-from", named_g_mctx, 5555 &view->answeracl_exclude)); 5556 5557 /* 5558 * Filter setting on names (CNAME/DNAME targets) in the answer section. 5559 */ 5560 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 5561 "name", named_g_mctx, 5562 &view->denyanswernames)); 5563 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 5564 "except-from", named_g_mctx, 5565 &view->answernames_exclude)); 5566 5567 /* 5568 * Configure sortlist, if set 5569 */ 5570 CHECK(configure_view_sortlist(vconfig, config, actx, named_g_mctx, 5571 &view->sortlist)); 5572 5573 /* 5574 * Configure default allow-update and allow-update-forwarding ACLs, 5575 * so they can be inherited by zones. (XXX: These are not 5576 * read from the options/view level here. However, they may be 5577 * read from there in zoneconf.c:configure_zone_acl() later.) 5578 */ 5579 if (view->updateacl == NULL) { 5580 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5581 "allow-update", NULL, actx, 5582 named_g_mctx, &view->updateacl)); 5583 } 5584 if (view->upfwdacl == NULL) { 5585 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5586 "allow-update-forwarding", NULL, actx, 5587 named_g_mctx, &view->upfwdacl)); 5588 } 5589 5590 /* 5591 * Configure default allow-transfer and allow-notify ACLs so they 5592 * can be inherited by zones. 5593 */ 5594 if (view->transferacl == NULL) { 5595 CHECK(configure_view_acl(vconfig, config, named_g_config, 5596 "allow-transfer", NULL, actx, 5597 named_g_mctx, &view->transferacl)); 5598 } 5599 if (view->notifyacl == NULL) { 5600 CHECK(configure_view_acl(vconfig, config, named_g_config, 5601 "allow-notify", NULL, actx, 5602 named_g_mctx, &view->notifyacl)); 5603 } 5604 5605 obj = NULL; 5606 result = named_config_get(maps, "provide-ixfr", &obj); 5607 INSIST(result == ISC_R_SUCCESS); 5608 view->provideixfr = cfg_obj_asboolean(obj); 5609 5610 obj = NULL; 5611 result = named_config_get(maps, "request-nsid", &obj); 5612 INSIST(result == ISC_R_SUCCESS); 5613 view->requestnsid = cfg_obj_asboolean(obj); 5614 5615 obj = NULL; 5616 result = named_config_get(maps, "send-cookie", &obj); 5617 INSIST(result == ISC_R_SUCCESS); 5618 view->sendcookie = cfg_obj_asboolean(obj); 5619 5620 obj = NULL; 5621 if (view->pad_acl != NULL) { 5622 dns_acl_detach(&view->pad_acl); 5623 } 5624 result = named_config_get(maps, "response-padding", &obj); 5625 INSIST(result == ISC_R_SUCCESS); 5626 padding = cfg_obj_asuint32(cfg_tuple_get(obj, "block-size")); 5627 if (padding > 512U) { 5628 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 5629 "response-padding block-size cannot " 5630 "exceed 512: lowering"); 5631 padding = 512U; 5632 } 5633 view->padding = (uint16_t)padding; 5634 CHECK(cfg_acl_fromconfig(cfg_tuple_get(obj, "acl"), config, 5635 named_g_lctx, actx, named_g_mctx, 0, 5636 &view->pad_acl)); 5637 5638 obj = NULL; 5639 result = named_config_get(maps, "require-server-cookie", &obj); 5640 INSIST(result == ISC_R_SUCCESS); 5641 view->requireservercookie = cfg_obj_asboolean(obj); 5642 5643 obj = NULL; 5644 result = named_config_get(maps, "v6-bias", &obj); 5645 INSIST(result == ISC_R_SUCCESS); 5646 view->v6bias = cfg_obj_asuint32(obj) * 1000; 5647 5648 obj = NULL; 5649 result = named_config_get(maps, "clients-per-query", &obj); 5650 INSIST(result == ISC_R_SUCCESS); 5651 clients_per_query = cfg_obj_asuint32(obj); 5652 5653 obj = NULL; 5654 result = named_config_get(maps, "max-clients-per-query", &obj); 5655 INSIST(result == ISC_R_SUCCESS); 5656 max_clients_per_query = cfg_obj_asuint32(obj); 5657 5658 if (max_clients_per_query < clients_per_query) { 5659 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 5660 "configured clients-per-query (%u) exceeds " 5661 "max-clients-per-query (%u); automatically " 5662 "adjusting max-clients-per-query to (%u)", 5663 clients_per_query, max_clients_per_query, 5664 clients_per_query); 5665 max_clients_per_query = clients_per_query; 5666 } 5667 dns_resolver_setclientsperquery(view->resolver, clients_per_query, 5668 max_clients_per_query); 5669 5670 /* 5671 * This is used for the cache and also as a default value 5672 * for zone databases. 5673 */ 5674 obj = NULL; 5675 result = named_config_get(maps, "max-records-per-type", &obj); 5676 INSIST(result == ISC_R_SUCCESS); 5677 dns_view_setmaxrrperset(view, cfg_obj_asuint32(obj)); 5678 5679 /* 5680 * This is used for the cache and also as a default value 5681 * for zone databases. 5682 */ 5683 obj = NULL; 5684 result = named_config_get(maps, "max-types-per-name", &obj); 5685 INSIST(result == ISC_R_SUCCESS); 5686 dns_view_setmaxtypepername(view, cfg_obj_asuint32(obj)); 5687 5688 obj = NULL; 5689 result = named_config_get(maps, "max-recursion-depth", &obj); 5690 INSIST(result == ISC_R_SUCCESS); 5691 dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); 5692 5693 obj = NULL; 5694 result = named_config_get(maps, "max-recursion-queries", &obj); 5695 INSIST(result == ISC_R_SUCCESS); 5696 dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); 5697 5698 obj = NULL; 5699 result = named_config_get(maps, "max-query-restarts", &obj); 5700 INSIST(result == ISC_R_SUCCESS); 5701 dns_view_setmaxrestarts(view, cfg_obj_asuint32(obj)); 5702 5703 obj = NULL; 5704 result = named_config_get(maps, "max-query-count", &obj); 5705 INSIST(result == ISC_R_SUCCESS); 5706 dns_view_setmaxqueries(view, cfg_obj_asuint32(obj)); 5707 5708 obj = NULL; 5709 result = named_config_get(maps, "max-validations-per-fetch", &obj); 5710 if (result == ISC_R_SUCCESS) { 5711 dns_resolver_setmaxvalidations(view->resolver, 5712 cfg_obj_asuint32(obj)); 5713 } 5714 5715 obj = NULL; 5716 result = named_config_get(maps, "max-validation-failures-per-fetch", 5717 &obj); 5718 if (result == ISC_R_SUCCESS) { 5719 dns_resolver_setmaxvalidationfails(view->resolver, 5720 cfg_obj_asuint32(obj)); 5721 } 5722 5723 obj = NULL; 5724 result = named_config_get(maps, "fetches-per-zone", &obj); 5725 INSIST(result == ISC_R_SUCCESS); 5726 obj2 = cfg_tuple_get(obj, "fetches"); 5727 dns_resolver_setfetchesperzone(view->resolver, cfg_obj_asuint32(obj2)); 5728 obj2 = cfg_tuple_get(obj, "response"); 5729 if (!cfg_obj_isvoid(obj2)) { 5730 const char *resp = cfg_obj_asstring(obj2); 5731 isc_result_t r = DNS_R_SERVFAIL; 5732 5733 if (strcasecmp(resp, "drop") == 0) { 5734 r = DNS_R_DROP; 5735 } else if (strcasecmp(resp, "fail") == 0) { 5736 r = DNS_R_SERVFAIL; 5737 } else { 5738 UNREACHABLE(); 5739 } 5740 5741 dns_resolver_setquotaresponse(view->resolver, 5742 dns_quotatype_zone, r); 5743 } 5744 5745 obj = NULL; 5746 result = named_config_get(maps, "prefetch", &obj); 5747 INSIST(result == ISC_R_SUCCESS); 5748 prefetch_trigger = cfg_tuple_get(obj, "trigger"); 5749 view->prefetch_trigger = cfg_obj_asuint32(prefetch_trigger); 5750 if (view->prefetch_trigger > 10) { 5751 view->prefetch_trigger = 10; 5752 } 5753 prefetch_eligible = cfg_tuple_get(obj, "eligible"); 5754 if (cfg_obj_isvoid(prefetch_eligible)) { 5755 int m; 5756 for (m = 1; maps[m] != NULL; m++) { 5757 obj = NULL; 5758 result = named_config_get(&maps[m], "prefetch", &obj); 5759 INSIST(result == ISC_R_SUCCESS); 5760 prefetch_eligible = cfg_tuple_get(obj, "eligible"); 5761 if (cfg_obj_isuint32(prefetch_eligible)) { 5762 break; 5763 } 5764 } 5765 INSIST(cfg_obj_isuint32(prefetch_eligible)); 5766 } 5767 view->prefetch_eligible = cfg_obj_asuint32(prefetch_eligible); 5768 if (view->prefetch_eligible < view->prefetch_trigger + 6) { 5769 view->prefetch_eligible = view->prefetch_trigger + 6; 5770 } 5771 5772 /* 5773 * For now, there is only one kind of trusted keys, the 5774 * "security roots". 5775 */ 5776 CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, 5777 auto_root)); 5778 5779 obj = NULL; 5780 result = named_config_get(maps, "dnssec-must-be-secure", &obj); 5781 if (result == ISC_R_SUCCESS) { 5782 CHECK(mustbesecure(obj, view->resolver)); 5783 } 5784 5785 obj = NULL; 5786 result = named_config_get(maps, "nta-recheck", &obj); 5787 INSIST(result == ISC_R_SUCCESS); 5788 view->nta_recheck = cfg_obj_asduration(obj); 5789 5790 obj = NULL; 5791 result = named_config_get(maps, "nta-lifetime", &obj); 5792 INSIST(result == ISC_R_SUCCESS); 5793 view->nta_lifetime = cfg_obj_asduration(obj); 5794 5795 obj = NULL; 5796 result = named_config_get(maps, "preferred-glue", &obj); 5797 if (result == ISC_R_SUCCESS) { 5798 str = cfg_obj_asstring(obj); 5799 if (strcasecmp(str, "a") == 0) { 5800 view->preferred_glue = dns_rdatatype_a; 5801 } else if (strcasecmp(str, "aaaa") == 0) { 5802 view->preferred_glue = dns_rdatatype_aaaa; 5803 } else { 5804 view->preferred_glue = 0; 5805 } 5806 } else { 5807 view->preferred_glue = 0; 5808 } 5809 5810 /* 5811 * Load DynDB modules. 5812 */ 5813 dyndb_list = NULL; 5814 if (voptions != NULL) { 5815 (void)cfg_map_get(voptions, "dyndb", &dyndb_list); 5816 } else { 5817 (void)cfg_map_get(config, "dyndb", &dyndb_list); 5818 } 5819 5820 for (element = cfg_list_first(dyndb_list); element != NULL; 5821 element = cfg_list_next(element)) 5822 { 5823 const cfg_obj_t *dyndb = cfg_listelt_value(element); 5824 5825 if (dctx == NULL) { 5826 const void *hashinit = isc_hash_get_initializer(); 5827 CHECK(dns_dyndb_createctx(mctx, hashinit, named_g_lctx, 5828 view, named_g_server->zonemgr, 5829 named_g_loopmgr, &dctx)); 5830 } 5831 5832 CHECK(configure_dyndb(dyndb, mctx, dctx)); 5833 } 5834 5835 /* 5836 * Load plugins. 5837 */ 5838 plugin_list = NULL; 5839 if (voptions != NULL) { 5840 (void)cfg_map_get(voptions, "plugin", &plugin_list); 5841 } else { 5842 (void)cfg_map_get(config, "plugin", &plugin_list); 5843 } 5844 5845 if (plugin_list != NULL) { 5846 INSIST(view->hooktable == NULL); 5847 CHECK(ns_hooktable_create(view->mctx, 5848 (ns_hooktable_t **)&view->hooktable)); 5849 view->hooktable_free = ns_hooktable_free; 5850 5851 ns_plugins_create(view->mctx, (ns_plugins_t **)&view->plugins); 5852 view->plugins_free = ns_plugins_free; 5853 5854 CHECK(cfg_pluginlist_foreach(config, plugin_list, named_g_lctx, 5855 register_one_plugin, view)); 5856 } 5857 5858 /* 5859 * Setup automatic empty zones. If recursion is off then 5860 * they are disabled by default. 5861 */ 5862 obj = NULL; 5863 (void)named_config_get(maps, "empty-zones-enable", &obj); 5864 (void)named_config_get(maps, "disable-empty-zone", &disablelist); 5865 if (obj == NULL && disablelist == NULL && 5866 view->rdclass == dns_rdataclass_in) 5867 { 5868 empty_zones_enable = view->recursion; 5869 } else if (view->rdclass == dns_rdataclass_in) { 5870 if (obj != NULL) { 5871 empty_zones_enable = cfg_obj_asboolean(obj); 5872 } else { 5873 empty_zones_enable = view->recursion; 5874 } 5875 } else { 5876 empty_zones_enable = false; 5877 } 5878 5879 if (empty_zones_enable) { 5880 const char *empty; 5881 int empty_zone = 0; 5882 dns_fixedname_t fixed; 5883 dns_name_t *name; 5884 isc_buffer_t buffer; 5885 char server[DNS_NAME_FORMATSIZE + 1]; 5886 char contact[DNS_NAME_FORMATSIZE + 1]; 5887 const char *empty_dbtype[4] = { "_builtin", "empty", NULL, 5888 NULL }; 5889 int empty_dbtypec = 4; 5890 dns_zonestat_level_t statlevel = dns_zonestat_none; 5891 5892 name = dns_fixedname_initname(&fixed); 5893 5894 obj = NULL; 5895 result = named_config_get(maps, "empty-server", &obj); 5896 if (result == ISC_R_SUCCESS) { 5897 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 5898 dns_rootname, 0, NULL)); 5899 isc_buffer_init(&buffer, server, sizeof(server) - 1); 5900 CHECK(dns_name_totext(name, 0, &buffer)); 5901 server[isc_buffer_usedlength(&buffer)] = 0; 5902 empty_dbtype[2] = server; 5903 } else { 5904 empty_dbtype[2] = "@"; 5905 } 5906 5907 obj = NULL; 5908 result = named_config_get(maps, "empty-contact", &obj); 5909 if (result == ISC_R_SUCCESS) { 5910 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 5911 dns_rootname, 0, NULL)); 5912 isc_buffer_init(&buffer, contact, sizeof(contact) - 1); 5913 CHECK(dns_name_totext(name, 0, &buffer)); 5914 contact[isc_buffer_usedlength(&buffer)] = 0; 5915 empty_dbtype[3] = contact; 5916 } else { 5917 empty_dbtype[3] = "."; 5918 } 5919 5920 obj = NULL; 5921 result = named_config_get(maps, "zone-statistics", &obj); 5922 INSIST(result == ISC_R_SUCCESS); 5923 if (cfg_obj_isboolean(obj)) { 5924 if (cfg_obj_asboolean(obj)) { 5925 statlevel = dns_zonestat_full; 5926 } else { 5927 statlevel = dns_zonestat_none; 5928 } 5929 } else { 5930 const char *levelstr = cfg_obj_asstring(obj); 5931 if (strcasecmp(levelstr, "full") == 0) { 5932 statlevel = dns_zonestat_full; 5933 } else if (strcasecmp(levelstr, "terse") == 0) { 5934 statlevel = dns_zonestat_terse; 5935 } else if (strcasecmp(levelstr, "none") == 0) { 5936 statlevel = dns_zonestat_none; 5937 } else { 5938 UNREACHABLE(); 5939 } 5940 } 5941 5942 for (empty = empty_zones[empty_zone]; empty != NULL; 5943 empty = empty_zones[++empty_zone]) 5944 { 5945 dns_forwarders_t *dnsforwarders = NULL; 5946 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 5947 5948 /* 5949 * Look for zone on drop list. 5950 */ 5951 CHECK(dns_name_fromstring(name, empty, dns_rootname, 0, 5952 NULL)); 5953 if (disablelist != NULL && 5954 on_disable_list(disablelist, name)) 5955 { 5956 continue; 5957 } 5958 5959 /* 5960 * This zone already exists. 5961 */ 5962 (void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 5963 &zone); 5964 if (zone != NULL) { 5965 dns_zone_detach(&zone); 5966 continue; 5967 } 5968 5969 /* 5970 * If we would forward this name don't add a 5971 * empty zone for it. 5972 */ 5973 result = dns_fwdtable_find(view->fwdtable, name, 5974 &dnsforwarders); 5975 if (result == ISC_R_SUCCESS || 5976 result == DNS_R_PARTIALMATCH) 5977 { 5978 fwdpolicy = dnsforwarders->fwdpolicy; 5979 dns_forwarders_detach(&dnsforwarders); 5980 } 5981 if (fwdpolicy == dns_fwdpolicy_only) { 5982 continue; 5983 } 5984 5985 /* 5986 * See if we can re-use a existing zone. 5987 */ 5988 result = dns_viewlist_find(&named_g_server->viewlist, 5989 view->name, view->rdclass, 5990 &pview); 5991 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 5992 { 5993 goto cleanup; 5994 } 5995 5996 if (pview != NULL) { 5997 (void)dns_view_findzone( 5998 pview, name, DNS_ZTFIND_EXACT, &zone); 5999 dns_view_detach(&pview); 6000 } 6001 6002 CHECK(create_empty_zone(zone, name, view, zonelist, 6003 empty_dbtype, empty_dbtypec, 6004 statlevel)); 6005 if (zone != NULL) { 6006 dns_zone_detach(&zone); 6007 } 6008 } 6009 } 6010 6011 obj = NULL; 6012 if (view->rdclass == dns_rdataclass_in) { 6013 (void)named_config_get(maps, "ipv4only-enable", &obj); 6014 } 6015 if (view->rdclass == dns_rdataclass_in && (obj != NULL) 6016 ? cfg_obj_asboolean(obj) 6017 : !ISC_LIST_EMPTY(view->dns64)) 6018 { 6019 const char *server, *contact; 6020 dns_fixedname_t fixed; 6021 dns_name_t *name; 6022 struct { 6023 const char *name; 6024 const char *type; 6025 } zones[] = { 6026 { "ipv4only.arpa", "ipv4only" }, 6027 { "170.0.0.192.in-addr.arpa", "ipv4reverse" }, 6028 { "171.0.0.192.in-addr.arpa", "ipv4reverse" }, 6029 }; 6030 size_t ipv4only_zone; 6031 6032 obj = NULL; 6033 result = named_config_get(maps, "ipv4only-server", &obj); 6034 if (result == ISC_R_SUCCESS) { 6035 server = cfg_obj_asstring(obj); 6036 } else { 6037 server = NULL; 6038 } 6039 6040 obj = NULL; 6041 result = named_config_get(maps, "ipv4only-contact", &obj); 6042 if (result == ISC_R_SUCCESS) { 6043 contact = cfg_obj_asstring(obj); 6044 } else { 6045 contact = NULL; 6046 } 6047 6048 name = dns_fixedname_initname(&fixed); 6049 for (ipv4only_zone = 0; ipv4only_zone < ARRAY_SIZE(zones); 6050 ipv4only_zone++) 6051 { 6052 dns_forwarders_t *dnsforwarders = NULL; 6053 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 6054 6055 CHECK(dns_name_fromstring(name, 6056 zones[ipv4only_zone].name, 6057 dns_rootname, 0, NULL)); 6058 6059 (void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 6060 &zone); 6061 if (zone != NULL) { 6062 dns_zone_detach(&zone); 6063 continue; 6064 } 6065 6066 /* 6067 * If we would forward this name don't add it. 6068 */ 6069 result = dns_fwdtable_find(view->fwdtable, name, 6070 &dnsforwarders); 6071 if (result == ISC_R_SUCCESS || 6072 result == DNS_R_PARTIALMATCH) 6073 { 6074 fwdpolicy = dnsforwarders->fwdpolicy; 6075 dns_forwarders_detach(&dnsforwarders); 6076 } 6077 if (fwdpolicy == dns_fwdpolicy_only) { 6078 continue; 6079 } 6080 6081 /* 6082 * See if we can re-use a existing zone. 6083 */ 6084 result = dns_viewlist_find(&named_g_server->viewlist, 6085 view->name, view->rdclass, 6086 &pview); 6087 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 6088 { 6089 goto cleanup; 6090 } 6091 6092 if (pview != NULL) { 6093 (void)dns_view_findzone( 6094 pview, name, DNS_ZTFIND_EXACT, &zone); 6095 dns_view_detach(&pview); 6096 } 6097 6098 CHECK(create_ipv4only_zone(zone, view, name, 6099 zones[ipv4only_zone].type, 6100 mctx, server, contact)); 6101 if (zone != NULL) { 6102 dns_zone_detach(&zone); 6103 } 6104 } 6105 } 6106 6107 obj = NULL; 6108 result = named_config_get(maps, "rate-limit", &obj); 6109 if (result == ISC_R_SUCCESS) { 6110 result = configure_rrl(view, config, obj); 6111 if (result != ISC_R_SUCCESS) { 6112 goto cleanup; 6113 } 6114 } 6115 6116 /* 6117 * Set the servfail-ttl. 6118 */ 6119 obj = NULL; 6120 result = named_config_get(maps, "servfail-ttl", &obj); 6121 INSIST(result == ISC_R_SUCCESS); 6122 fail_ttl = cfg_obj_asduration(obj); 6123 if (fail_ttl > 30) { 6124 fail_ttl = 30; 6125 } 6126 dns_view_setfailttl(view, fail_ttl); 6127 6128 /* 6129 * Name space to look up redirect information in. 6130 */ 6131 obj = NULL; 6132 result = named_config_get(maps, "nxdomain-redirect", &obj); 6133 if (result == ISC_R_SUCCESS) { 6134 dns_name_t *name = dns_fixedname_name(&view->redirectfixed); 6135 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 6136 dns_rootname, 0, NULL)); 6137 view->redirectzone = name; 6138 } else { 6139 view->redirectzone = NULL; 6140 } 6141 6142 /* 6143 * Exceptions to DNSSEC validation. 6144 */ 6145 obj = NULL; 6146 result = named_config_get(maps, "validate-except", &obj); 6147 if (result == ISC_R_SUCCESS) { 6148 result = dns_view_getntatable(view, &ntatable); 6149 } 6150 if (result == ISC_R_SUCCESS) { 6151 for (element = cfg_list_first(obj); element != NULL; 6152 element = cfg_list_next(element)) 6153 { 6154 dns_fixedname_t fntaname; 6155 dns_name_t *ntaname; 6156 6157 ntaname = dns_fixedname_initname(&fntaname); 6158 obj = cfg_listelt_value(element); 6159 CHECK(dns_name_fromstring(ntaname, 6160 cfg_obj_asstring(obj), 6161 dns_rootname, 0, NULL)); 6162 CHECK(dns_ntatable_add(ntatable, ntaname, true, 0, 6163 0xffffffffU)); 6164 } 6165 } 6166 6167 #ifdef HAVE_DNSTAP 6168 /* 6169 * Set up the dnstap environment and configure message 6170 * types to log. 6171 */ 6172 CHECK(configure_dnstap(maps, view)); 6173 #endif /* HAVE_DNSTAP */ 6174 6175 result = ISC_R_SUCCESS; 6176 6177 cleanup: 6178 /* 6179 * Revert to the old view if there was an error. 6180 */ 6181 if (result != ISC_R_SUCCESS) { 6182 isc_result_t result2; 6183 6184 result2 = dns_viewlist_find(&named_g_server->viewlist, 6185 view->name, view->rdclass, &pview); 6186 if (result2 == ISC_R_SUCCESS) { 6187 dns_view_thaw(pview); 6188 6189 obj = NULL; 6190 if (rpz_configured && 6191 pview->rdclass == dns_rdataclass_in && need_hints && 6192 named_config_get(maps, "response-policy", &obj) == 6193 ISC_R_SUCCESS) 6194 { 6195 /* 6196 * We are swapping the places of the `view` and 6197 * `pview` in the function's parameters list 6198 * because we are reverting the same operation 6199 * done previously in the "correct" order. 6200 */ 6201 result2 = configure_rpz(pview, view, maps, obj, 6202 &old_rpz_ok, 6203 first_time); 6204 if (result2 != ISC_R_SUCCESS) { 6205 isc_log_write(named_g_lctx, 6206 NAMED_LOGCATEGORY_GENERAL, 6207 NAMED_LOGMODULE_SERVER, 6208 ISC_LOG_ERROR, 6209 "rpz configuration " 6210 "revert failed for view " 6211 "'%s'", 6212 pview->name); 6213 } 6214 } 6215 6216 obj = NULL; 6217 if (catz_configured && 6218 pview->rdclass == dns_rdataclass_in && need_hints && 6219 named_config_get(maps, "catalog-zones", &obj) == 6220 ISC_R_SUCCESS) 6221 { 6222 /* 6223 * We are swapping the places of the `view` and 6224 * `pview` in the function's parameters list 6225 * because we are reverting the same operation 6226 * done previously in the "correct" order. 6227 */ 6228 result2 = configure_catz(pview, view, config, 6229 obj); 6230 if (result2 != ISC_R_SUCCESS) { 6231 isc_log_write(named_g_lctx, 6232 NAMED_LOGCATEGORY_GENERAL, 6233 NAMED_LOGMODULE_SERVER, 6234 ISC_LOG_ERROR, 6235 "catz configuration " 6236 "revert failed for view " 6237 "'%s'", 6238 pview->name); 6239 } 6240 } 6241 6242 dns_view_freeze(pview); 6243 } 6244 6245 if (pview != NULL) { 6246 dns_view_detach(&pview); 6247 } 6248 6249 if (zone_element_latest != NULL) { 6250 for (element = cfg_list_first(zonelist); 6251 element != NULL; element = cfg_list_next(element)) 6252 { 6253 const cfg_obj_t *zconfig = 6254 cfg_listelt_value(element); 6255 configure_zone_setviewcommit(result, zconfig, 6256 view); 6257 if (element == zone_element_latest) { 6258 /* 6259 * This was the latest element that was 6260 * successfully configured earlier. 6261 */ 6262 break; 6263 } 6264 } 6265 } 6266 } 6267 6268 if (ntatable != NULL) { 6269 dns_ntatable_detach(&ntatable); 6270 } 6271 if (clients != NULL) { 6272 dns_acl_detach(&clients); 6273 } 6274 if (mapped != NULL) { 6275 dns_acl_detach(&mapped); 6276 } 6277 if (excluded != NULL) { 6278 dns_acl_detach(&excluded); 6279 } 6280 if (ring != NULL) { 6281 dns_tsigkeyring_detach(&ring); 6282 } 6283 if (zone != NULL) { 6284 dns_zone_detach(&zone); 6285 } 6286 if (dispatch4 != NULL) { 6287 dns_dispatch_detach(&dispatch4); 6288 } 6289 if (dispatch6 != NULL) { 6290 dns_dispatch_detach(&dispatch6); 6291 } 6292 if (resstats != NULL) { 6293 isc_stats_detach(&resstats); 6294 } 6295 if (resquerystats != NULL) { 6296 dns_stats_detach(&resquerystats); 6297 } 6298 if (order != NULL) { 6299 dns_order_detach(&order); 6300 } 6301 if (cache != NULL) { 6302 dns_cache_detach(&cache); 6303 } 6304 if (dctx != NULL) { 6305 dns_dyndb_destroyctx(&dctx); 6306 } 6307 6308 return result; 6309 } 6310 6311 static isc_result_t 6312 configure_hints(dns_view_t *view, const char *filename) { 6313 isc_result_t result; 6314 dns_db_t *db; 6315 6316 db = NULL; 6317 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); 6318 if (result == ISC_R_SUCCESS) { 6319 dns_view_sethints(view, db); 6320 dns_db_detach(&db); 6321 } 6322 6323 return result; 6324 } 6325 6326 static isc_result_t 6327 configure_alternates(const cfg_obj_t *config, dns_view_t *view, 6328 const cfg_obj_t *alternates) { 6329 const cfg_obj_t *portobj; 6330 const cfg_obj_t *addresses; 6331 const cfg_listelt_t *element; 6332 isc_result_t result = ISC_R_SUCCESS; 6333 in_port_t port; 6334 6335 /* 6336 * Determine which port to send requests to. 6337 */ 6338 CHECKM(named_config_getport(config, "port", &port), "port"); 6339 6340 if (alternates != NULL) { 6341 portobj = cfg_tuple_get(alternates, "port"); 6342 if (cfg_obj_isuint32(portobj)) { 6343 uint32_t val = cfg_obj_asuint32(portobj); 6344 if (val > UINT16_MAX) { 6345 cfg_obj_log(portobj, named_g_lctx, 6346 ISC_LOG_ERROR, 6347 "port '%u' out of range", val); 6348 return ISC_R_RANGE; 6349 } 6350 port = (in_port_t)val; 6351 } 6352 } 6353 6354 addresses = NULL; 6355 if (alternates != NULL) { 6356 addresses = cfg_tuple_get(alternates, "addresses"); 6357 } 6358 6359 for (element = cfg_list_first(addresses); element != NULL; 6360 element = cfg_list_next(element)) 6361 { 6362 const cfg_obj_t *alternate = cfg_listelt_value(element); 6363 isc_sockaddr_t sa; 6364 6365 if (!cfg_obj_issockaddr(alternate)) { 6366 dns_fixedname_t fixed; 6367 dns_name_t *name; 6368 const char *str = cfg_obj_asstring( 6369 cfg_tuple_get(alternate, "name")); 6370 isc_buffer_t buffer; 6371 in_port_t myport = port; 6372 6373 isc_buffer_constinit(&buffer, str, strlen(str)); 6374 isc_buffer_add(&buffer, strlen(str)); 6375 name = dns_fixedname_initname(&fixed); 6376 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, 6377 NULL)); 6378 6379 portobj = cfg_tuple_get(alternate, "port"); 6380 if (cfg_obj_isuint32(portobj)) { 6381 uint32_t val = cfg_obj_asuint32(portobj); 6382 if (val > UINT16_MAX) { 6383 cfg_obj_log(portobj, named_g_lctx, 6384 ISC_LOG_ERROR, 6385 "port '%u' out of range", 6386 val); 6387 return ISC_R_RANGE; 6388 } 6389 myport = (in_port_t)val; 6390 } 6391 dns_resolver_addalternate(view->resolver, NULL, name, 6392 myport); 6393 continue; 6394 } 6395 6396 sa = *cfg_obj_assockaddr(alternate); 6397 if (isc_sockaddr_getport(&sa) == 0) { 6398 isc_sockaddr_setport(&sa, port); 6399 } 6400 dns_resolver_addalternate(view->resolver, &sa, NULL, 0); 6401 } 6402 6403 cleanup: 6404 return result; 6405 } 6406 6407 static isc_result_t 6408 validate_tls(const cfg_obj_t *config, dns_view_t *view, const cfg_obj_t *obj, 6409 isc_log_t *logctx, const char *str, dns_name_t **name) { 6410 dns_fixedname_t fname; 6411 dns_name_t *nm = dns_fixedname_initname(&fname); 6412 isc_result_t result = dns_name_fromstring(nm, str, dns_rootname, 0, 6413 NULL); 6414 6415 if (result != ISC_R_SUCCESS) { 6416 cfg_obj_log(obj, logctx, ISC_LOG_ERROR, 6417 "'%s' is not a valid name", str); 6418 return result; 6419 } 6420 6421 if (strcasecmp(str, "ephemeral") != 0) { 6422 const cfg_obj_t *tlsmap = find_maplist(config, "tls", str); 6423 6424 if (tlsmap == NULL) { 6425 cfg_obj_log(obj, logctx, ISC_LOG_ERROR, 6426 "tls '%s' is not defined", str); 6427 return ISC_R_FAILURE; 6428 } 6429 } 6430 6431 if (name != NULL && *name == NULL) { 6432 *name = isc_mem_get(view->mctx, sizeof(dns_name_t)); 6433 dns_name_init(*name, NULL); 6434 dns_name_dup(nm, view->mctx, *name); 6435 } 6436 6437 return ISC_R_SUCCESS; 6438 } 6439 6440 static isc_result_t 6441 configure_forward(const cfg_obj_t *config, dns_view_t *view, 6442 const dns_name_t *origin, const cfg_obj_t *forwarders, 6443 const cfg_obj_t *forwardtype) { 6444 const cfg_obj_t *portobj = NULL; 6445 const cfg_obj_t *tlspobj = NULL; 6446 const cfg_obj_t *faddresses = NULL; 6447 const cfg_listelt_t *element = NULL; 6448 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 6449 dns_forwarderlist_t fwdlist; 6450 dns_forwarder_t *fwd = NULL; 6451 isc_result_t result; 6452 in_port_t port; 6453 in_port_t tls_port; 6454 const char *tls = NULL; 6455 6456 ISC_LIST_INIT(fwdlist); 6457 6458 /* 6459 * Determine which port to send forwarded requests to. 6460 */ 6461 CHECKM(named_config_getport(config, "port", &port), "port"); 6462 CHECKM(named_config_getport(config, "tls-port", &tls_port), "tls-port"); 6463 6464 if (forwarders != NULL) { 6465 portobj = cfg_tuple_get(forwarders, "port"); 6466 if (cfg_obj_isuint32(portobj)) { 6467 uint32_t val = cfg_obj_asuint32(portobj); 6468 if (val > UINT16_MAX) { 6469 cfg_obj_log(portobj, named_g_lctx, 6470 ISC_LOG_ERROR, 6471 "port '%u' out of range", val); 6472 return ISC_R_RANGE; 6473 } 6474 port = tls_port = (in_port_t)val; 6475 } 6476 } 6477 6478 /* 6479 * TLS value for forwarded requests. 6480 */ 6481 if (forwarders != NULL) { 6482 tlspobj = cfg_tuple_get(forwarders, "tls"); 6483 if (cfg_obj_isstring(tlspobj)) { 6484 tls = cfg_obj_asstring(tlspobj); 6485 if (tls != NULL) { 6486 result = validate_tls(config, view, tlspobj, 6487 named_g_lctx, tls, NULL); 6488 if (result != ISC_R_SUCCESS) { 6489 return result; 6490 } 6491 } 6492 } 6493 } 6494 6495 faddresses = NULL; 6496 if (forwarders != NULL) { 6497 faddresses = cfg_tuple_get(forwarders, "addresses"); 6498 } 6499 6500 for (element = cfg_list_first(faddresses); element != NULL; 6501 element = cfg_list_next(element)) 6502 { 6503 const cfg_obj_t *forwarder = cfg_listelt_value(element); 6504 const char *cur_tls = NULL; 6505 6506 fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t)); 6507 fwd->tlsname = NULL; 6508 cur_tls = cfg_obj_getsockaddrtls(forwarder); 6509 if (cur_tls == NULL) { 6510 cur_tls = tls; 6511 } 6512 if (cur_tls != NULL) { 6513 result = validate_tls(config, view, faddresses, 6514 named_g_lctx, cur_tls, 6515 &fwd->tlsname); 6516 if (result != ISC_R_SUCCESS) { 6517 isc_mem_put(view->mctx, fwd, 6518 sizeof(dns_forwarder_t)); 6519 goto cleanup; 6520 } 6521 } 6522 fwd->addr = *cfg_obj_assockaddr(forwarder); 6523 if (isc_sockaddr_getport(&fwd->addr) == 0) { 6524 isc_sockaddr_setport(&fwd->addr, 6525 cur_tls != NULL ? tls_port : port); 6526 } 6527 ISC_LINK_INIT(fwd, link); 6528 ISC_LIST_APPEND(fwdlist, fwd, link); 6529 } 6530 6531 if (ISC_LIST_EMPTY(fwdlist)) { 6532 if (forwardtype != NULL) { 6533 cfg_obj_log(forwardtype, named_g_lctx, ISC_LOG_WARNING, 6534 "no forwarders seen; disabling " 6535 "forwarding"); 6536 } 6537 fwdpolicy = dns_fwdpolicy_none; 6538 } else { 6539 if (forwardtype == NULL) { 6540 fwdpolicy = dns_fwdpolicy_first; 6541 } else { 6542 const char *forwardstr = cfg_obj_asstring(forwardtype); 6543 if (strcasecmp(forwardstr, "first") == 0) { 6544 fwdpolicy = dns_fwdpolicy_first; 6545 } else if (strcasecmp(forwardstr, "only") == 0) { 6546 fwdpolicy = dns_fwdpolicy_only; 6547 } else { 6548 UNREACHABLE(); 6549 } 6550 } 6551 } 6552 6553 result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist, 6554 fwdpolicy); 6555 if (result != ISC_R_SUCCESS) { 6556 char namebuf[DNS_NAME_FORMATSIZE]; 6557 dns_name_format(origin, namebuf, sizeof(namebuf)); 6558 cfg_obj_log(forwarders, named_g_lctx, ISC_LOG_WARNING, 6559 "could not set up forwarding for domain '%s': %s", 6560 namebuf, isc_result_totext(result)); 6561 goto cleanup; 6562 } 6563 6564 if (fwdpolicy == dns_fwdpolicy_only) { 6565 dns_view_sfd_add(view, origin); 6566 } 6567 6568 result = ISC_R_SUCCESS; 6569 6570 cleanup: 6571 6572 while (!ISC_LIST_EMPTY(fwdlist)) { 6573 fwd = ISC_LIST_HEAD(fwdlist); 6574 ISC_LIST_UNLINK(fwdlist, fwd, link); 6575 if (fwd->tlsname != NULL) { 6576 dns_name_free(fwd->tlsname, view->mctx); 6577 isc_mem_put(view->mctx, fwd->tlsname, 6578 sizeof(dns_name_t)); 6579 } 6580 isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t)); 6581 } 6582 6583 return result; 6584 } 6585 6586 static isc_result_t 6587 get_viewinfo(const cfg_obj_t *vconfig, const char **namep, 6588 dns_rdataclass_t *classp) { 6589 isc_result_t result = ISC_R_SUCCESS; 6590 const char *viewname; 6591 dns_rdataclass_t viewclass; 6592 6593 REQUIRE(namep != NULL && *namep == NULL); 6594 REQUIRE(classp != NULL); 6595 6596 if (vconfig != NULL) { 6597 const cfg_obj_t *classobj = NULL; 6598 6599 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 6600 classobj = cfg_tuple_get(vconfig, "class"); 6601 CHECK(named_config_getclass(classobj, dns_rdataclass_in, 6602 &viewclass)); 6603 if (dns_rdataclass_ismeta(viewclass)) { 6604 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6605 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6606 "view '%s': class must not be meta", 6607 viewname); 6608 CHECK(ISC_R_FAILURE); 6609 } 6610 } else { 6611 viewname = "_default"; 6612 viewclass = dns_rdataclass_in; 6613 } 6614 6615 *namep = viewname; 6616 *classp = viewclass; 6617 6618 cleanup: 6619 return result; 6620 } 6621 6622 /* 6623 * Find a view based on its configuration info and attach to it. 6624 * 6625 * If 'vconfig' is NULL, attach to the default view. 6626 */ 6627 static isc_result_t 6628 find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 6629 dns_view_t **viewp) { 6630 isc_result_t result; 6631 const char *viewname = NULL; 6632 dns_rdataclass_t viewclass; 6633 dns_view_t *view = NULL; 6634 6635 result = get_viewinfo(vconfig, &viewname, &viewclass); 6636 if (result != ISC_R_SUCCESS) { 6637 return result; 6638 } 6639 6640 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 6641 if (result != ISC_R_SUCCESS) { 6642 return result; 6643 } 6644 6645 *viewp = view; 6646 return ISC_R_SUCCESS; 6647 } 6648 6649 /* 6650 * Create a new view and add it to the list. 6651 * 6652 * If 'vconfig' is NULL, create the default view. 6653 * 6654 * The view created is attached to '*viewp'. 6655 */ 6656 static isc_result_t 6657 create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 6658 dns_view_t **viewp) { 6659 isc_result_t result; 6660 const char *viewname = NULL; 6661 dns_rdataclass_t viewclass; 6662 dns_view_t *view = NULL; 6663 6664 result = get_viewinfo(vconfig, &viewname, &viewclass); 6665 if (result != ISC_R_SUCCESS) { 6666 return result; 6667 } 6668 6669 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 6670 if (result == ISC_R_SUCCESS) { 6671 return ISC_R_EXISTS; 6672 } 6673 if (result != ISC_R_NOTFOUND) { 6674 return result; 6675 } 6676 INSIST(view == NULL); 6677 6678 result = dns_view_create(named_g_mctx, named_g_loopmgr, 6679 named_g_dispatchmgr, viewclass, viewname, 6680 &view); 6681 if (result != ISC_R_SUCCESS) { 6682 return result; 6683 } 6684 6685 isc_nonce_buf(view->secret, sizeof(view->secret)); 6686 6687 ISC_LIST_APPEND(*viewlist, view, link); 6688 dns_view_attach(view, viewp); 6689 return ISC_R_SUCCESS; 6690 } 6691 6692 /* 6693 * Configure or reconfigure a zone. 6694 */ 6695 static isc_result_t 6696 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 6697 const cfg_obj_t *vconfig, dns_view_t *view, 6698 dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, 6699 dns_keystorelist_t *keystores, cfg_aclconfctx_t *aclconf, 6700 bool added, bool old_rpz_ok, bool is_catz_member, bool modify) { 6701 dns_view_t *pview = NULL; /* Production view */ 6702 dns_zone_t *zone = NULL; /* New or reused zone */ 6703 dns_zone_t *raw = NULL; /* New or reused raw zone */ 6704 dns_zone_t *dupzone = NULL; 6705 const cfg_obj_t *options = NULL; 6706 const cfg_obj_t *zoptions = NULL; 6707 const cfg_obj_t *typeobj = NULL; 6708 const cfg_obj_t *forwarders = NULL; 6709 const cfg_obj_t *forwardtype = NULL; 6710 const cfg_obj_t *ixfrfromdiffs = NULL; 6711 const cfg_obj_t *viewobj = NULL; 6712 isc_result_t result = ISC_R_SUCCESS; 6713 isc_result_t tresult; 6714 isc_buffer_t buffer; 6715 dns_fixedname_t fixorigin; 6716 dns_name_t *origin; 6717 const char *zname; 6718 dns_rdataclass_t zclass; 6719 const char *ztypestr; 6720 dns_rpz_num_t rpz_num; 6721 bool zone_is_catz = false; 6722 bool zone_maybe_inline = false; 6723 bool inline_signing = false; 6724 bool fullsign = false; 6725 6726 options = NULL; 6727 (void)cfg_map_get(config, "options", &options); 6728 6729 zoptions = cfg_tuple_get(zconfig, "options"); 6730 6731 /* 6732 * Get the zone origin as a dns_name_t. 6733 */ 6734 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 6735 isc_buffer_constinit(&buffer, zname, strlen(zname)); 6736 isc_buffer_add(&buffer, strlen(zname)); 6737 dns_fixedname_init(&fixorigin); 6738 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, 6739 dns_rootname, 0, NULL)); 6740 origin = dns_fixedname_name(&fixorigin); 6741 6742 CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"), 6743 view->rdclass, &zclass)); 6744 if (zclass != view->rdclass) { 6745 const char *vname = NULL; 6746 if (vconfig != NULL) { 6747 vname = cfg_obj_asstring( 6748 cfg_tuple_get(vconfig, "name")); 6749 } else { 6750 vname = "<default view>"; 6751 } 6752 6753 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6754 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6755 "zone '%s': wrong class for view '%s'", zname, 6756 vname); 6757 result = ISC_R_FAILURE; 6758 goto cleanup; 6759 } 6760 6761 (void)cfg_map_get(zoptions, "in-view", &viewobj); 6762 if (viewobj != NULL) { 6763 const char *inview = cfg_obj_asstring(viewobj); 6764 dns_view_t *otherview = NULL; 6765 6766 if (viewlist == NULL) { 6767 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6768 "'in-view' option is not permitted in " 6769 "dynamically added zones"); 6770 result = ISC_R_FAILURE; 6771 goto cleanup; 6772 } 6773 6774 result = dns_viewlist_find(viewlist, inview, view->rdclass, 6775 &otherview); 6776 if (result != ISC_R_SUCCESS) { 6777 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6778 "view '%s' is not yet defined.", inview); 6779 result = ISC_R_FAILURE; 6780 goto cleanup; 6781 } 6782 6783 result = dns_view_findzone(otherview, origin, DNS_ZTFIND_EXACT, 6784 &zone); 6785 dns_view_detach(&otherview); 6786 if (result != ISC_R_SUCCESS) { 6787 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6788 "zone '%s' not defined in view '%s'", zname, 6789 inview); 6790 result = ISC_R_FAILURE; 6791 goto cleanup; 6792 } 6793 6794 CHECK(dns_view_addzone(view, zone)); 6795 dns_zone_detach(&zone); 6796 6797 /* 6798 * If the zone contains a 'forwarders' statement, configure 6799 * selective forwarding. Note: this is not inherited from the 6800 * other view. 6801 */ 6802 forwarders = NULL; 6803 result = cfg_map_get(zoptions, "forwarders", &forwarders); 6804 if (result == ISC_R_SUCCESS) { 6805 forwardtype = NULL; 6806 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6807 CHECK(configure_forward(config, view, origin, 6808 forwarders, forwardtype)); 6809 } 6810 result = ISC_R_SUCCESS; 6811 goto cleanup; 6812 } 6813 6814 (void)cfg_map_get(zoptions, "type", &typeobj); 6815 if (typeobj == NULL) { 6816 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6817 "zone '%s' 'type' not specified", zname); 6818 result = ISC_R_FAILURE; 6819 goto cleanup; 6820 } 6821 ztypestr = cfg_obj_asstring(typeobj); 6822 6823 /* 6824 * "hints zones" aren't zones. If we've got one, 6825 * configure it and return. 6826 */ 6827 if (strcasecmp(ztypestr, "hint") == 0) { 6828 const cfg_obj_t *fileobj = NULL; 6829 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { 6830 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6831 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6832 "zone '%s': 'file' not specified", zname); 6833 result = ISC_R_FAILURE; 6834 goto cleanup; 6835 } 6836 if (dns_name_equal(origin, dns_rootname)) { 6837 const char *hintsfile = cfg_obj_asstring(fileobj); 6838 6839 CHECK(configure_hints(view, hintsfile)); 6840 } else { 6841 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6842 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 6843 "ignoring non-root hint zone '%s'", 6844 zname); 6845 result = ISC_R_SUCCESS; 6846 } 6847 /* Skip ordinary zone processing. */ 6848 goto cleanup; 6849 } 6850 6851 /* 6852 * "forward zones" aren't zones either. Translate this syntax into 6853 * the appropriate selective forwarding configuration and return. 6854 */ 6855 if (strcasecmp(ztypestr, "forward") == 0) { 6856 forwardtype = NULL; 6857 forwarders = NULL; 6858 6859 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6860 (void)cfg_map_get(zoptions, "forwarders", &forwarders); 6861 CHECK(configure_forward(config, view, origin, forwarders, 6862 forwardtype)); 6863 goto cleanup; 6864 } 6865 6866 /* 6867 * Redirect zones only require minimal configuration. 6868 */ 6869 if (strcasecmp(ztypestr, "redirect") == 0) { 6870 if (view->redirect != NULL) { 6871 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6872 "redirect zone already exists"); 6873 result = ISC_R_EXISTS; 6874 goto cleanup; 6875 } 6876 result = dns_viewlist_find(viewlist, view->name, view->rdclass, 6877 &pview); 6878 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6879 goto cleanup; 6880 } 6881 if (pview != NULL && pview->redirect != NULL) { 6882 dns_zone_attach(pview->redirect, &zone); 6883 dns_zone_setview(zone, view); 6884 } else { 6885 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, 6886 &zone)); 6887 CHECK(dns_zone_setorigin(zone, origin)); 6888 dns_zone_setview(zone, view); 6889 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, 6890 zone)); 6891 dns_zone_setstats(zone, named_g_server->zonestats); 6892 } 6893 CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, 6894 kasplist, keystores, zone, NULL)); 6895 dns_zone_attach(zone, &view->redirect); 6896 goto cleanup; 6897 } 6898 6899 if (!modify) { 6900 /* 6901 * Check for duplicates in the new zone table. 6902 */ 6903 result = dns_view_findzone(view, origin, DNS_ZTFIND_EXACT, 6904 &dupzone); 6905 if (result == ISC_R_SUCCESS) { 6906 /* 6907 * We already have this zone! 6908 */ 6909 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6910 "zone '%s' already exists", zname); 6911 dns_zone_detach(&dupzone); 6912 result = ISC_R_EXISTS; 6913 goto cleanup; 6914 } 6915 INSIST(dupzone == NULL); 6916 } 6917 6918 /* 6919 * Note whether this is a response policy zone and which one if so, 6920 * unless we are using RPZ service interface. In that case, the 6921 * BIND zone database has nothing to do with rpz and so we don't care. 6922 */ 6923 for (rpz_num = 0;; ++rpz_num) { 6924 if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones || 6925 view->rpzs->p.dnsrps_enabled) 6926 { 6927 rpz_num = DNS_RPZ_INVALID_NUM; 6928 break; 6929 } 6930 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin)) 6931 { 6932 break; 6933 } 6934 } 6935 6936 if (!is_catz_member && view->catzs != NULL && 6937 dns_catz_zone_get(view->catzs, origin) != NULL) 6938 { 6939 zone_is_catz = true; 6940 } 6941 6942 /* 6943 * See if we can reuse an existing zone. This is 6944 * only possible if all of these are true: 6945 * - The zone's view exists 6946 * - A zone with the right name exists in the view 6947 * - The zone is compatible with the config 6948 * options (e.g., an existing primary zone cannot 6949 * be reused if the options specify a secondary zone) 6950 * - The zone was not and is still not a response policy zone 6951 * or the zone is a policy zone with an unchanged number 6952 * and we are using the old policy zone summary data. 6953 */ 6954 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 6955 view->rdclass, &pview); 6956 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6957 goto cleanup; 6958 } 6959 if (pview != NULL) { 6960 result = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, 6961 &zone); 6962 } 6963 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6964 goto cleanup; 6965 } 6966 6967 if (zone != NULL && 6968 !named_zone_reusable(zone, zconfig, vconfig, config, kasplist)) 6969 { 6970 dns_zone_detach(&zone); 6971 fullsign = true; 6972 } 6973 6974 if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) || 6975 (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok))) 6976 { 6977 dns_zone_detach(&zone); 6978 } 6979 6980 if (zone != NULL) { 6981 /* 6982 * We found a reusable zone. Make it use the 6983 * new view. 6984 */ 6985 dns_zone_setview(zone, view); 6986 } else { 6987 /* 6988 * We cannot reuse an existing zone, we have 6989 * to create a new one. 6990 */ 6991 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 6992 CHECK(dns_zone_setorigin(zone, origin)); 6993 dns_zone_setview(zone, view); 6994 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 6995 dns_zone_setstats(zone, named_g_server->zonestats); 6996 } 6997 if (rpz_num != DNS_RPZ_INVALID_NUM) { 6998 result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num); 6999 if (result != ISC_R_SUCCESS) { 7000 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7001 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7002 "zone '%s': incompatible" 7003 " masterfile-format or database" 7004 " for a response policy zone", 7005 zname); 7006 goto cleanup; 7007 } 7008 } 7009 7010 if (zone_is_catz) { 7011 dns_zone_catz_enable(zone, view->catzs); 7012 } else if (dns_zone_catz_is_enabled(zone)) { 7013 dns_zone_catz_disable(zone); 7014 } 7015 7016 /* 7017 * If the zone contains a 'forwarders' statement, configure 7018 * selective forwarding. 7019 */ 7020 forwarders = NULL; 7021 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) { 7022 forwardtype = NULL; 7023 (void)cfg_map_get(zoptions, "forward", &forwardtype); 7024 CHECK(configure_forward(config, view, origin, forwarders, 7025 forwardtype)); 7026 } 7027 7028 /* 7029 * Mark whether the zone was originally added at runtime or not 7030 */ 7031 dns_zone_setadded(zone, added); 7032 7033 /* 7034 * Determine if we need to set up inline signing. 7035 */ 7036 zone_maybe_inline = (strcasecmp(ztypestr, "primary") == 0 || 7037 strcasecmp(ztypestr, "master") == 0 || 7038 strcasecmp(ztypestr, "secondary") == 0 || 7039 strcasecmp(ztypestr, "slave") == 0); 7040 7041 if (zone_maybe_inline) { 7042 inline_signing = named_zone_inlinesigning(zconfig, vconfig, 7043 config, kasplist); 7044 } 7045 if (inline_signing) { 7046 dns_zone_getraw(zone, &raw); 7047 if (raw == NULL) { 7048 dns_zone_create(&raw, dns_zone_getmem(zone), 7049 dns_zone_gettid(zone)); 7050 CHECK(dns_zone_setorigin(raw, origin)); 7051 dns_zone_setview(raw, view); 7052 dns_zone_setstats(raw, named_g_server->zonestats); 7053 CHECK(dns_zone_link(zone, raw)); 7054 } 7055 if (cfg_map_get(zoptions, "ixfr-from-differences", 7056 &ixfrfromdiffs) == ISC_R_SUCCESS) 7057 { 7058 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7059 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7060 "zone '%s': 'ixfr-from-differences' is " 7061 "ignored for inline-signed zones", 7062 zname); 7063 } 7064 } 7065 7066 /* 7067 * Configure the zone. 7068 */ 7069 CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, kasplist, 7070 keystores, zone, raw)); 7071 7072 /* 7073 * Add the zone to its view in the new view list. 7074 */ 7075 if (!modify) { 7076 CHECK(dns_view_addzone(view, zone)); 7077 } 7078 7079 if (zone_is_catz) { 7080 /* 7081 * force catz reload if the zone is loaded; 7082 * if it's not it'll get reloaded on zone load 7083 */ 7084 dns_db_t *db = NULL; 7085 7086 tresult = dns_zone_getdb(zone, &db); 7087 if (tresult == ISC_R_SUCCESS) { 7088 dns_catz_dbupdate_callback(db, view->catzs); 7089 dns_db_detach(&db); 7090 } 7091 } 7092 7093 /* 7094 * Ensure that zone keys are reloaded on reconfig 7095 */ 7096 if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0) { 7097 dns_zone_rekey(zone, fullsign, false); 7098 } 7099 7100 cleanup: 7101 if (zone != NULL) { 7102 dns_zone_detach(&zone); 7103 } 7104 if (raw != NULL) { 7105 dns_zone_detach(&raw); 7106 } 7107 if (pview != NULL) { 7108 dns_view_detach(&pview); 7109 } 7110 7111 return result; 7112 } 7113 7114 /* 7115 * Configure built-in zone for storing managed-key data. 7116 */ 7117 static isc_result_t 7118 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { 7119 isc_result_t result; 7120 dns_view_t *pview = NULL; 7121 dns_zone_t *zone = NULL; 7122 dns_acl_t *none = NULL; 7123 char filename[PATH_MAX]; 7124 bool defaultview; 7125 7126 REQUIRE(view != NULL); 7127 7128 /* See if we can re-use an existing keydata zone. */ 7129 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 7130 view->rdclass, &pview); 7131 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 7132 return result; 7133 } 7134 7135 if (pview != NULL) { 7136 if (pview->managed_keys != NULL) { 7137 dns_zone_attach(pview->managed_keys, 7138 &view->managed_keys); 7139 dns_zone_setview(pview->managed_keys, view); 7140 dns_zone_setviewcommit(pview->managed_keys); 7141 dns_view_detach(&pview); 7142 dns_zone_synckeyzone(view->managed_keys); 7143 return ISC_R_SUCCESS; 7144 } 7145 7146 dns_view_detach(&pview); 7147 } 7148 7149 /* No existing keydata zone was found; create one */ 7150 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 7151 CHECK(dns_zone_setorigin(zone, dns_rootname)); 7152 7153 defaultview = (strcmp(view->name, "_default") == 0); 7154 CHECK(isc_file_sanitize( 7155 directory, defaultview ? "managed-keys" : view->name, 7156 defaultview ? "bind" : "mkeys", filename, sizeof(filename))); 7157 CHECK(dns_zone_setfile(zone, filename, dns_masterformat_text, 7158 &dns_master_style_default)); 7159 7160 dns_zone_setview(zone, view); 7161 dns_zone_settype(zone, dns_zone_key); 7162 dns_zone_setclass(zone, view->rdclass); 7163 7164 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 7165 7166 CHECK(dns_acl_none(mctx, &none)); 7167 dns_zone_setqueryacl(zone, none); 7168 dns_zone_setqueryonacl(zone, none); 7169 dns_acl_detach(&none); 7170 7171 dns_zone_setdialup(zone, dns_dialuptype_no); 7172 dns_zone_setcheckdstype(zone, dns_checkdstype_no); 7173 dns_zone_setnotifytype(zone, dns_notifytype_no); 7174 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 7175 dns_zone_setjournalsize(zone, 0); 7176 7177 dns_zone_setstats(zone, named_g_server->zonestats); 7178 setquerystats(zone, mctx, dns_zonestat_none); 7179 7180 if (view->managed_keys != NULL) { 7181 dns_zone_detach(&view->managed_keys); 7182 } 7183 dns_zone_attach(zone, &view->managed_keys); 7184 7185 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7186 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7187 "set up managed keys zone for view %s, file '%s'", 7188 view->name, filename); 7189 7190 cleanup: 7191 if (zone != NULL) { 7192 dns_zone_detach(&zone); 7193 } 7194 if (none != NULL) { 7195 dns_acl_detach(&none); 7196 } 7197 7198 return result; 7199 } 7200 7201 /* 7202 * Configure a single server quota. 7203 */ 7204 static void 7205 configure_server_quota(const cfg_obj_t **maps, const char *name, 7206 isc_quota_t *quota) { 7207 const cfg_obj_t *obj = NULL; 7208 isc_result_t result; 7209 7210 result = named_config_get(maps, name, &obj); 7211 INSIST(result == ISC_R_SUCCESS); 7212 isc_quota_max(quota, cfg_obj_asuint32(obj)); 7213 } 7214 7215 /* 7216 * This function is called as soon as the 'directory' statement has been 7217 * parsed. This can be extended to support other options if necessary. 7218 */ 7219 static isc_result_t 7220 directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { 7221 isc_result_t result; 7222 const char *directory; 7223 7224 REQUIRE(strcasecmp("directory", clausename) == 0); 7225 7226 UNUSED(arg); 7227 UNUSED(clausename); 7228 7229 /* 7230 * Change directory. 7231 */ 7232 directory = cfg_obj_asstring(obj); 7233 7234 if (!isc_file_ischdiridempotent(directory)) { 7235 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 7236 "option 'directory' contains relative path '%s'", 7237 directory); 7238 } 7239 7240 if (!isc_file_isdirwritable(directory)) { 7241 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7242 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7243 "directory '%s' is not writable", directory); 7244 return ISC_R_NOPERM; 7245 } 7246 7247 result = isc_dir_chdir(directory); 7248 if (result != ISC_R_SUCCESS) { 7249 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7250 "change directory to '%s' failed: %s", directory, 7251 isc_result_totext(result)); 7252 return result; 7253 } 7254 7255 char cwd[PATH_MAX]; 7256 if (getcwd(cwd, sizeof(cwd)) == cwd) { 7257 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7258 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7259 "the working directory is now '%s'", cwd); 7260 } 7261 7262 return ISC_R_SUCCESS; 7263 } 7264 7265 /* 7266 * This event callback is invoked to do periodic network interface 7267 * scanning. 7268 */ 7269 7270 static void 7271 interface_timer_tick(void *arg) { 7272 named_server_t *server = (named_server_t *)arg; 7273 7274 (void)ns_interfacemgr_scan(server->interfacemgr, false, false); 7275 } 7276 7277 static void 7278 heartbeat_timer_tick(void *arg) { 7279 named_server_t *server = (named_server_t *)arg; 7280 dns_view_t *view = NULL; 7281 7282 view = ISC_LIST_HEAD(server->viewlist); 7283 while (view != NULL) { 7284 dns_view_dialup(view); 7285 view = ISC_LIST_NEXT(view, link); 7286 } 7287 } 7288 7289 typedef struct { 7290 isc_mem_t *mctx; 7291 isc_loop_t *loop; 7292 dns_fetch_t *fetch; 7293 dns_view_t *view; 7294 dns_fixedname_t tatname; 7295 dns_fixedname_t keyname; 7296 dns_rdataset_t rdataset; 7297 dns_rdataset_t sigrdataset; 7298 } ns_tat_t; 7299 7300 static int 7301 cid(const void *a, const void *b) { 7302 const uint16_t ida = *(const uint16_t *)a; 7303 const uint16_t idb = *(const uint16_t *)b; 7304 if (ida < idb) { 7305 return -1; 7306 } else if (ida > idb) { 7307 return 1; 7308 } else { 7309 return 0; 7310 } 7311 } 7312 7313 static void 7314 tat_done(void *arg) { 7315 dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg; 7316 ns_tat_t *tat = NULL; 7317 7318 INSIST(resp != NULL); 7319 7320 tat = resp->arg; 7321 7322 INSIST(tat != NULL); 7323 7324 /* Free resources which are not of interest */ 7325 if (resp->node != NULL) { 7326 dns_db_detachnode(resp->db, &resp->node); 7327 } 7328 if (resp->db != NULL) { 7329 dns_db_detach(&resp->db); 7330 } 7331 7332 dns_resolver_freefresp(&resp); 7333 dns_resolver_destroyfetch(&tat->fetch); 7334 if (dns_rdataset_isassociated(&tat->rdataset)) { 7335 dns_rdataset_disassociate(&tat->rdataset); 7336 } 7337 if (dns_rdataset_isassociated(&tat->sigrdataset)) { 7338 dns_rdataset_disassociate(&tat->sigrdataset); 7339 } 7340 dns_view_detach(&tat->view); 7341 isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); 7342 } 7343 7344 struct dotat_arg { 7345 dns_view_t *view; 7346 isc_loop_t *loop; 7347 }; 7348 7349 /*% 7350 * Prepare the QNAME for the TAT query to be sent by processing the trust 7351 * anchors present at 'keynode' of 'keytable'. Store the result in 'dst' and 7352 * the domain name which 'keynode' is associated with in 'origin'. 7353 * 7354 * A maximum of 12 key IDs can be reported in a single TAT query due to the 7355 * 63-octet length limit for any single label in a domain name. If there are 7356 * more than 12 keys configured at 'keynode', only the first 12 will be 7357 * reported in the TAT query. 7358 */ 7359 static isc_result_t 7360 get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) { 7361 dns_rdataset_t dsset; 7362 unsigned int i, n = 0; 7363 uint16_t ids[12]; 7364 isc_textregion_t r; 7365 char label[64]; 7366 int m; 7367 7368 dns_rdataset_init(&dsset); 7369 if (dns_keynode_dsset(keynode, &dsset)) { 7370 isc_result_t result; 7371 7372 for (result = dns_rdataset_first(&dsset); 7373 result == ISC_R_SUCCESS; 7374 result = dns_rdataset_next(&dsset)) 7375 { 7376 dns_rdata_t rdata = DNS_RDATA_INIT; 7377 dns_rdata_ds_t ds; 7378 7379 dns_rdata_reset(&rdata); 7380 dns_rdataset_current(&dsset, &rdata); 7381 result = dns_rdata_tostruct(&rdata, &ds, NULL); 7382 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7383 if (n < (sizeof(ids) / sizeof(ids[0]))) { 7384 ids[n] = ds.key_tag; 7385 n++; 7386 } 7387 } 7388 dns_rdataset_disassociate(&dsset); 7389 } 7390 7391 if (n == 0) { 7392 return DNS_R_EMPTYNAME; 7393 } 7394 7395 if (n > 1) { 7396 qsort(ids, n, sizeof(ids[0]), cid); 7397 } 7398 7399 /* 7400 * Encoded as "_ta-xxxx\(-xxxx\)*" where xxxx is the hex version of 7401 * of the keyid. 7402 */ 7403 label[0] = 0; 7404 r.base = label; 7405 r.length = sizeof(label); 7406 m = snprintf(r.base, r.length, "_ta"); 7407 if (m < 0 || (unsigned int)m > r.length) { 7408 return ISC_R_FAILURE; 7409 } 7410 isc_textregion_consume(&r, m); 7411 for (i = 0; i < n; i++) { 7412 m = snprintf(r.base, r.length, "-%04x", ids[i]); 7413 if (m < 0 || (unsigned int)m > r.length) { 7414 return ISC_R_FAILURE; 7415 } 7416 isc_textregion_consume(&r, m); 7417 } 7418 7419 return dns_name_fromstring(target, label, keyname, 0, NULL); 7420 } 7421 7422 static void 7423 tat_send(void *arg) { 7424 ns_tat_t *tat = (ns_tat_t *)arg; 7425 char namebuf[DNS_NAME_FORMATSIZE]; 7426 dns_fixedname_t fdomain; 7427 dns_name_t *domain = NULL; 7428 dns_rdataset_t nameservers; 7429 isc_result_t result; 7430 dns_name_t *keyname = NULL; 7431 dns_name_t *tatname = NULL; 7432 7433 keyname = dns_fixedname_name(&tat->keyname); 7434 tatname = dns_fixedname_name(&tat->tatname); 7435 7436 dns_name_format(tatname, namebuf, sizeof(namebuf)); 7437 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7438 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7439 "%s: sending trust-anchor-telemetry query '%s/NULL'", 7440 tat->view->name, namebuf); 7441 7442 /* 7443 * TAT queries should be sent to the authoritative servers for a given 7444 * zone. If this function is called for a keytable node corresponding 7445 * to a locally served zone, calling dns_resolver_createfetch() with 7446 * NULL 'domain' and 'nameservers' arguments will cause 'tatname' to be 7447 * resolved locally, without sending any TAT queries upstream. 7448 * 7449 * Work around this issue by calling dns_view_findzonecut() first. If 7450 * the zone is served locally, the NS RRset for the given domain name 7451 * will be retrieved from local data; if it is not, the deepest zone 7452 * cut we have for it will be retrieved from cache. In either case, 7453 * passing the results to dns_resolver_createfetch() will prevent it 7454 * from returning NXDOMAIN for 'tatname' while still allowing it to 7455 * chase down any potential delegations returned by upstream servers in 7456 * order to eventually find the destination host to send the TAT query 7457 * to. 7458 * 7459 * After the dns_view_findzonecut() call, 'domain' will hold the 7460 * deepest zone cut we can find for 'keyname' while 'nameservers' will 7461 * hold the NS RRset at that zone cut. 7462 */ 7463 domain = dns_fixedname_initname(&fdomain); 7464 dns_rdataset_init(&nameservers); 7465 result = dns_view_findzonecut(tat->view, keyname, domain, NULL, 0, 0, 7466 true, true, &nameservers, NULL); 7467 if (result == ISC_R_SUCCESS) { 7468 result = dns_resolver_createfetch( 7469 tat->view->resolver, tatname, dns_rdatatype_null, 7470 domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, NULL, 7471 NULL, tat->loop, tat_done, tat, NULL, &tat->rdataset, 7472 &tat->sigrdataset, &tat->fetch); 7473 } 7474 7475 /* 7476 * 'domain' holds the dns_name_t pointer inside a dst_key_t structure. 7477 * dns_resolver_createfetch() creates its own copy of 'domain' if it 7478 * succeeds. Thus, 'domain' is not freed here. 7479 * 7480 * Even if dns_view_findzonecut() returned something else than 7481 * ISC_R_SUCCESS, it still could have associated 'nameservers'. 7482 * dns_resolver_createfetch() creates its own copy of 'nameservers' if 7483 * it succeeds. Thus, we need to check whether 'nameservers' is 7484 * associated and release it if it is. 7485 */ 7486 if (dns_rdataset_isassociated(&nameservers)) { 7487 dns_rdataset_disassociate(&nameservers); 7488 } 7489 7490 if (result != ISC_R_SUCCESS) { 7491 dns_view_detach(&tat->view); 7492 isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); 7493 } 7494 } 7495 7496 static void 7497 dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, dns_name_t *keyname, 7498 void *arg) { 7499 struct dotat_arg *dotat_arg = (struct dotat_arg *)arg; 7500 isc_result_t result; 7501 dns_view_t *view = NULL; 7502 ns_tat_t *tat = NULL; 7503 7504 REQUIRE(keytable != NULL); 7505 REQUIRE(keynode != NULL); 7506 REQUIRE(dotat_arg != NULL); 7507 7508 view = dotat_arg->view; 7509 7510 tat = isc_mem_get(view->mctx, sizeof(*tat)); 7511 *tat = (ns_tat_t){ 0 }; 7512 7513 dns_rdataset_init(&tat->rdataset); 7514 dns_rdataset_init(&tat->sigrdataset); 7515 dns_name_copy(keyname, dns_fixedname_initname(&tat->keyname)); 7516 result = get_tat_qname(dns_fixedname_initname(&tat->tatname), keyname, 7517 keynode); 7518 if (result != ISC_R_SUCCESS) { 7519 isc_mem_put(view->mctx, tat, sizeof(*tat)); 7520 return; 7521 } 7522 isc_mem_attach(view->mctx, &tat->mctx); 7523 tat->loop = dotat_arg->loop; 7524 dns_view_attach(view, &tat->view); 7525 7526 /* 7527 * We don't want to be holding the keytable lock when calling 7528 * dns_view_findzonecut() as it creates a lock order loop so 7529 * call dns_view_findzonecut() in a event handler. 7530 * 7531 * zone->lock (dns_zone_setviewcommit) while holding view->lock 7532 * (dns_view_setviewcommit) 7533 * 7534 * keytable->lock (dns_keytable_find) while holding zone->lock 7535 * (zone_asyncload) 7536 * 7537 * view->lock (dns_view_findzonecut) while holding keytable->lock 7538 * (dns_keytable_forall) 7539 */ 7540 isc_async_run(named_g_mainloop, tat_send, tat); 7541 } 7542 7543 static void 7544 tat_timer_tick(void *arg) { 7545 isc_result_t result; 7546 named_server_t *server = (named_server_t *)arg; 7547 struct dotat_arg dotat_arg = { 0 }; 7548 dns_view_t *view = NULL; 7549 dns_keytable_t *secroots = NULL; 7550 7551 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 7552 view = ISC_LIST_NEXT(view, link)) 7553 { 7554 if (!view->trust_anchor_telemetry || !view->enablevalidation) { 7555 continue; 7556 } 7557 7558 result = dns_view_getsecroots(view, &secroots); 7559 if (result != ISC_R_SUCCESS) { 7560 continue; 7561 } 7562 7563 dotat_arg.view = view; 7564 dotat_arg.loop = named_g_mainloop; 7565 dns_keytable_forall(secroots, dotat, &dotat_arg); 7566 dns_keytable_detach(&secroots); 7567 } 7568 } 7569 7570 static void 7571 pps_timer_tick(void *arg) { 7572 static unsigned int oldrequests = 0; 7573 unsigned int requests = atomic_load_relaxed(&ns_client_requests); 7574 7575 UNUSED(arg); 7576 7577 /* 7578 * Don't worry about wrapping as the overflow result will be right. 7579 */ 7580 dns_pps = (requests - oldrequests) / 1200; 7581 oldrequests = requests; 7582 } 7583 7584 /* 7585 * Replace the current value of '*field', a dynamically allocated 7586 * string or NULL, with a dynamically allocated copy of the 7587 * null-terminated string pointed to by 'value', or NULL. 7588 */ 7589 static void 7590 setstring(named_server_t *server, char **field, const char *value) { 7591 char *copy; 7592 7593 if (value != NULL) { 7594 copy = isc_mem_strdup(server->mctx, value); 7595 } else { 7596 copy = NULL; 7597 } 7598 7599 if (*field != NULL) { 7600 isc_mem_free(server->mctx, *field); 7601 } 7602 7603 *field = copy; 7604 } 7605 7606 /* 7607 * Replace the current value of '*field', a dynamically allocated 7608 * string or NULL, with another dynamically allocated string 7609 * or NULL if whether 'obj' is a string or void value, respectively. 7610 */ 7611 static void 7612 setoptstring(named_server_t *server, char **field, const cfg_obj_t *obj) { 7613 if (cfg_obj_isvoid(obj)) { 7614 setstring(server, field, NULL); 7615 } else { 7616 setstring(server, field, cfg_obj_asstring(obj)); 7617 } 7618 } 7619 7620 static void 7621 portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports, 7622 bool positive) { 7623 const cfg_listelt_t *element; 7624 7625 for (element = cfg_list_first(ports); element != NULL; 7626 element = cfg_list_next(element)) 7627 { 7628 const cfg_obj_t *obj = cfg_listelt_value(element); 7629 7630 if (cfg_obj_isuint32(obj)) { 7631 in_port_t port = (in_port_t)cfg_obj_asuint32(obj); 7632 7633 if (positive) { 7634 isc_portset_add(portset, port); 7635 } else { 7636 isc_portset_remove(portset, port); 7637 } 7638 } else { 7639 const cfg_obj_t *obj_loport, *obj_hiport; 7640 in_port_t loport, hiport; 7641 7642 obj_loport = cfg_tuple_get(obj, "loport"); 7643 loport = (in_port_t)cfg_obj_asuint32(obj_loport); 7644 obj_hiport = cfg_tuple_get(obj, "hiport"); 7645 hiport = (in_port_t)cfg_obj_asuint32(obj_hiport); 7646 7647 if (positive) { 7648 isc_portset_addrange(portset, loport, hiport); 7649 } else { 7650 isc_portset_removerange(portset, loport, 7651 hiport); 7652 } 7653 } 7654 } 7655 } 7656 7657 static isc_result_t 7658 removed(dns_zone_t *zone, void *uap) { 7659 if (dns_zone_getview(zone) != uap) { 7660 return ISC_R_SUCCESS; 7661 } 7662 7663 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", 7664 dns_zonetype_name(dns_zone_gettype(zone))); 7665 return ISC_R_SUCCESS; 7666 } 7667 7668 static void 7669 cleanup_session_key(named_server_t *server, isc_mem_t *mctx) { 7670 if (server->session_keyfile != NULL) { 7671 isc_file_remove(server->session_keyfile); 7672 isc_mem_free(mctx, server->session_keyfile); 7673 server->session_keyfile = NULL; 7674 } 7675 7676 if (server->session_keyname != NULL) { 7677 if (dns_name_dynamic(server->session_keyname)) { 7678 dns_name_free(server->session_keyname, mctx); 7679 } 7680 isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); 7681 server->session_keyname = NULL; 7682 } 7683 7684 if (server->sessionkey != NULL) { 7685 dst_key_free(&server->sessionkey); 7686 } 7687 7688 server->session_keyalg = DST_ALG_UNKNOWN; 7689 server->session_keybits = 0; 7690 } 7691 7692 static isc_result_t 7693 generate_session_key(const char *filename, const char *keynamestr, 7694 const dns_name_t *keyname, dst_algorithm_t alg, 7695 uint16_t bits, isc_mem_t *mctx, bool first_time, 7696 dst_key_t **keyp) { 7697 isc_result_t result = ISC_R_SUCCESS; 7698 dst_key_t *key = NULL; 7699 isc_buffer_t key_txtbuffer; 7700 isc_buffer_t key_rawbuffer; 7701 char key_txtsecret[256]; 7702 char key_rawsecret[64]; 7703 isc_region_t key_rawregion; 7704 FILE *fp = NULL; 7705 7706 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7707 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7708 "generating session key for dynamic DNS"); 7709 7710 /* generate key */ 7711 result = dst_key_generate(keyname, alg, bits, 1, 0, DNS_KEYPROTO_ANY, 7712 dns_rdataclass_in, NULL, mctx, &key, NULL); 7713 if (result != ISC_R_SUCCESS) { 7714 return result; 7715 } 7716 7717 /* 7718 * Dump the key to the buffer for later use. 7719 */ 7720 isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); 7721 CHECK(dst_key_tobuffer(key, &key_rawbuffer)); 7722 7723 isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); 7724 isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); 7725 CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); 7726 7727 /* Dump the key to the key file. */ 7728 fp = named_os_openfile(filename, S_IRUSR | S_IWUSR, first_time); 7729 if (fp == NULL) { 7730 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7731 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7732 "could not create %s", filename); 7733 result = ISC_R_NOPERM; 7734 goto cleanup; 7735 } 7736 7737 fprintf(fp, 7738 "key \"%s\" {\n" 7739 "\talgorithm %s;\n" 7740 "\tsecret \"%.*s\";\n};\n", 7741 keynamestr, dst_hmac_algorithm_totext(alg), 7742 (int)isc_buffer_usedlength(&key_txtbuffer), 7743 (char *)isc_buffer_base(&key_txtbuffer)); 7744 7745 CHECK(isc_stdio_flush(fp)); 7746 result = isc_stdio_close(fp); 7747 if (result != ISC_R_SUCCESS) { 7748 goto cleanup; 7749 } 7750 7751 *keyp = key; 7752 return ISC_R_SUCCESS; 7753 7754 cleanup: 7755 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7756 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7757 "failed to generate session key " 7758 "for dynamic DNS: %s", 7759 isc_result_totext(result)); 7760 if (fp != NULL) { 7761 (void)isc_stdio_close(fp); 7762 (void)isc_file_remove(filename); 7763 } 7764 if (key != NULL) { 7765 dst_key_free(&key); 7766 } 7767 7768 return result; 7769 } 7770 7771 static isc_result_t 7772 configure_session_key(const cfg_obj_t **maps, named_server_t *server, 7773 isc_mem_t *mctx, bool first_time) { 7774 const char *keyfile = NULL, *keynamestr = NULL, *algstr = NULL; 7775 unsigned int algtype; 7776 dns_fixedname_t fname; 7777 dns_name_t *keyname = NULL; 7778 isc_buffer_t buffer; 7779 uint16_t bits; 7780 const cfg_obj_t *obj = NULL; 7781 bool need_deleteold = false; 7782 bool need_createnew = false; 7783 isc_result_t result; 7784 7785 obj = NULL; 7786 result = named_config_get(maps, "session-keyfile", &obj); 7787 if (result == ISC_R_SUCCESS) { 7788 if (cfg_obj_isvoid(obj)) { 7789 keyfile = NULL; /* disable it */ 7790 } else { 7791 keyfile = cfg_obj_asstring(obj); 7792 } 7793 } else { 7794 keyfile = named_g_defaultsessionkeyfile; 7795 } 7796 7797 obj = NULL; 7798 result = named_config_get(maps, "session-keyname", &obj); 7799 INSIST(result == ISC_R_SUCCESS); 7800 keynamestr = cfg_obj_asstring(obj); 7801 isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr)); 7802 isc_buffer_add(&buffer, strlen(keynamestr)); 7803 keyname = dns_fixedname_initname(&fname); 7804 result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); 7805 if (result != ISC_R_SUCCESS) { 7806 return result; 7807 } 7808 7809 obj = NULL; 7810 result = named_config_get(maps, "session-keyalg", &obj); 7811 INSIST(result == ISC_R_SUCCESS); 7812 algstr = cfg_obj_asstring(obj); 7813 result = named_config_getkeyalgorithm(algstr, &algtype, &bits); 7814 if (result != ISC_R_SUCCESS) { 7815 const char *s = " (keeping current key)"; 7816 7817 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7818 "session-keyalg: " 7819 "unsupported or unknown algorithm '%s'%s", 7820 algstr, server->session_keyfile != NULL ? s : ""); 7821 return result; 7822 } 7823 7824 /* See if we need to (re)generate a new key. */ 7825 if (keyfile == NULL) { 7826 if (server->session_keyfile != NULL) { 7827 need_deleteold = true; 7828 } 7829 } else if (server->session_keyfile == NULL) { 7830 need_createnew = true; 7831 } else if (strcmp(keyfile, server->session_keyfile) != 0 || 7832 !dns_name_equal(server->session_keyname, keyname) || 7833 server->session_keyalg != algtype || 7834 server->session_keybits != bits) 7835 { 7836 need_deleteold = true; 7837 need_createnew = true; 7838 } 7839 7840 if (need_deleteold) { 7841 INSIST(server->session_keyfile != NULL); 7842 INSIST(server->session_keyname != NULL); 7843 INSIST(server->sessionkey != NULL); 7844 7845 cleanup_session_key(server, mctx); 7846 } 7847 7848 if (need_createnew) { 7849 INSIST(server->sessionkey == NULL); 7850 INSIST(server->session_keyfile == NULL); 7851 INSIST(server->session_keyname == NULL); 7852 INSIST(server->session_keyalg == DST_ALG_UNKNOWN); 7853 INSIST(server->session_keybits == 0); 7854 7855 server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); 7856 dns_name_init(server->session_keyname, NULL); 7857 dns_name_dup(keyname, mctx, server->session_keyname); 7858 7859 server->session_keyfile = isc_mem_strdup(mctx, keyfile); 7860 7861 server->session_keyalg = algtype; 7862 server->session_keybits = bits; 7863 7864 CHECK(generate_session_key(keyfile, keynamestr, keyname, 7865 algtype, bits, mctx, first_time, 7866 &server->sessionkey)); 7867 } 7868 7869 return result; 7870 7871 cleanup: 7872 cleanup_session_key(server, mctx); 7873 return result; 7874 } 7875 7876 static isc_result_t 7877 setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 7878 cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx) { 7879 isc_result_t result = ISC_R_SUCCESS; 7880 bool allow = false; 7881 ns_cfgctx_t *nzcfg = NULL; 7882 const cfg_obj_t *maps[4]; 7883 const cfg_obj_t *options = NULL, *voptions = NULL; 7884 const cfg_obj_t *nz = NULL; 7885 const cfg_obj_t *nzdir = NULL; 7886 const char *dir = NULL; 7887 const cfg_obj_t *obj = NULL; 7888 int i = 0; 7889 uint64_t mapsize = 0ULL; 7890 7891 REQUIRE(config != NULL); 7892 7893 if (vconfig != NULL) { 7894 voptions = cfg_tuple_get(vconfig, "options"); 7895 } 7896 if (voptions != NULL) { 7897 maps[i++] = voptions; 7898 } 7899 result = cfg_map_get(config, "options", &options); 7900 if (result == ISC_R_SUCCESS) { 7901 maps[i++] = options; 7902 } 7903 maps[i++] = named_g_defaults; 7904 maps[i] = NULL; 7905 7906 result = named_config_get(maps, "allow-new-zones", &nz); 7907 if (result == ISC_R_SUCCESS) { 7908 allow = cfg_obj_asboolean(nz); 7909 } 7910 result = named_config_get(maps, "new-zones-directory", &nzdir); 7911 if (result == ISC_R_SUCCESS) { 7912 dir = cfg_obj_asstring(nzdir); 7913 result = isc_file_isdirectory(dir); 7914 if (result != ISC_R_SUCCESS) { 7915 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 7916 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7917 "invalid new-zones-directory %s: %s", dir, 7918 isc_result_totext(result)); 7919 return result; 7920 } 7921 if (!isc_file_isdirwritable(dir)) { 7922 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7923 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7924 "new-zones-directory '%s' " 7925 "is not writable", 7926 dir); 7927 return ISC_R_NOPERM; 7928 } 7929 7930 dns_view_setnewzonedir(view, dir); 7931 } 7932 7933 #ifdef HAVE_LMDB 7934 result = named_config_get(maps, "lmdb-mapsize", &obj); 7935 if (result == ISC_R_SUCCESS && obj != NULL) { 7936 mapsize = cfg_obj_asuint64(obj); 7937 if (mapsize < (1ULL << 20)) { /* 1 megabyte */ 7938 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7939 "'lmdb-mapsize " 7940 "%" PRId64 "' " 7941 "is too small", 7942 mapsize); 7943 return ISC_R_FAILURE; 7944 } else if (mapsize > (1ULL << 40)) { /* 1 terabyte */ 7945 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7946 "'lmdb-mapsize " 7947 "%" PRId64 "' " 7948 "is too large", 7949 mapsize); 7950 return ISC_R_FAILURE; 7951 } 7952 } 7953 #else /* ifdef HAVE_LMDB */ 7954 UNUSED(obj); 7955 #endif /* HAVE_LMDB */ 7956 7957 /* 7958 * A non-empty catalog-zones statement implies allow-new-zones 7959 */ 7960 if (!allow) { 7961 const cfg_obj_t *cz = NULL; 7962 result = named_config_get(maps, "catalog-zones", &cz); 7963 if (result == ISC_R_SUCCESS) { 7964 const cfg_listelt_t *e = 7965 cfg_list_first(cfg_tuple_get(cz, "zone list")); 7966 if (e != NULL) { 7967 allow = true; 7968 } 7969 } 7970 } 7971 7972 if (!allow) { 7973 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 7974 return ISC_R_SUCCESS; 7975 } 7976 7977 nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg)); 7978 *nzcfg = (ns_cfgctx_t){ 0 }; 7979 7980 /* 7981 * We attach the parser that was used for config as well 7982 * as the one that will be used for added zones, to avoid 7983 * a shutdown race later. 7984 */ 7985 isc_mem_attach(view->mctx, &nzcfg->mctx); 7986 cfg_parser_attach(conf_parser, &nzcfg->conf_parser); 7987 cfg_parser_attach(named_g_addparser, &nzcfg->add_parser); 7988 cfg_aclconfctx_attach(actx, &nzcfg->actx); 7989 7990 result = dns_view_setnewzones(view, true, nzcfg, newzone_cfgctx_destroy, 7991 mapsize); 7992 if (result != ISC_R_SUCCESS) { 7993 cfg_aclconfctx_detach(&nzcfg->actx); 7994 cfg_parser_destroy(&nzcfg->add_parser); 7995 cfg_parser_destroy(&nzcfg->conf_parser); 7996 isc_mem_putanddetach(&nzcfg->mctx, nzcfg, sizeof(*nzcfg)); 7997 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 7998 return result; 7999 } 8000 8001 cfg_obj_attach(config, &nzcfg->config); 8002 if (vconfig != NULL) { 8003 cfg_obj_attach(vconfig, &nzcfg->vconfig); 8004 } 8005 8006 result = load_nzf(view, nzcfg); 8007 return result; 8008 } 8009 8010 static void 8011 configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, 8012 dns_view_t *view) { 8013 const char *zname; 8014 dns_fixedname_t fixorigin; 8015 dns_name_t *origin; 8016 isc_result_t result2; 8017 dns_view_t *pview = NULL; 8018 dns_zone_t *zone = NULL; 8019 8020 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 8021 origin = dns_fixedname_initname(&fixorigin); 8022 8023 result2 = dns_name_fromstring(origin, zname, dns_rootname, 0, NULL); 8024 if (result2 != ISC_R_SUCCESS) { 8025 return; 8026 } 8027 8028 result2 = dns_viewlist_find(&named_g_server->viewlist, view->name, 8029 view->rdclass, &pview); 8030 if (result2 != ISC_R_SUCCESS) { 8031 return; 8032 } 8033 8034 result2 = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, &zone); 8035 if (result2 != ISC_R_SUCCESS) { 8036 dns_view_detach(&pview); 8037 return; 8038 } 8039 8040 if (result == ISC_R_SUCCESS) { 8041 dns_zone_setviewcommit(zone); 8042 } else { 8043 dns_zone_setviewrevert(zone); 8044 } 8045 8046 dns_zone_detach(&zone); 8047 dns_view_detach(&pview); 8048 } 8049 8050 #ifndef HAVE_LMDB 8051 8052 static isc_result_t 8053 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 8054 cfg_aclconfctx_t *actx) { 8055 isc_result_t result; 8056 ns_cfgctx_t *nzctx; 8057 const cfg_obj_t *zonelist; 8058 const cfg_listelt_t *element; 8059 8060 nzctx = view->new_zone_config; 8061 if (nzctx == NULL || nzctx->nzf_config == NULL) { 8062 return ISC_R_SUCCESS; 8063 } 8064 8065 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8066 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8067 "loading additional zones for view '%s'", view->name); 8068 8069 zonelist = NULL; 8070 cfg_map_get(nzctx->nzf_config, "zone", &zonelist); 8071 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 CHECK(configure_zone(config, zconfig, vconfig, view, 8077 &named_g_server->viewlist, 8078 &named_g_server->kasplist, 8079 &named_g_server->keystorelist, actx, true, 8080 false, false, false)); 8081 } 8082 8083 result = ISC_R_SUCCESS; 8084 8085 cleanup: 8086 for (element = cfg_list_first(zonelist); element != NULL; 8087 element = cfg_list_next(element)) 8088 { 8089 const cfg_obj_t *zconfig = cfg_listelt_value(element); 8090 configure_zone_setviewcommit(result, zconfig, view); 8091 } 8092 8093 return result; 8094 } 8095 8096 #else /* HAVE_LMDB */ 8097 8098 static isc_result_t 8099 data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, 8100 cfg_obj_t **zoneconfig) { 8101 isc_result_t result; 8102 const char *zone_name; 8103 size_t zone_name_len; 8104 const char *zone_config; 8105 size_t zone_config_len; 8106 cfg_obj_t *zoneconf = NULL; 8107 char bufname[DNS_NAME_FORMATSIZE]; 8108 8109 REQUIRE(view != NULL); 8110 REQUIRE(key != NULL); 8111 REQUIRE(data != NULL); 8112 REQUIRE(text != NULL); 8113 REQUIRE(zoneconfig != NULL && *zoneconfig == NULL); 8114 8115 if (*text == NULL) { 8116 isc_buffer_allocate(view->mctx, text, 256); 8117 } else { 8118 isc_buffer_clear(*text); 8119 } 8120 8121 zone_name = (const char *)key->mv_data; 8122 zone_name_len = key->mv_size; 8123 INSIST(zone_name != NULL && zone_name_len > 0); 8124 8125 zone_config = (const char *)data->mv_data; 8126 zone_config_len = data->mv_size; 8127 INSIST(zone_config != NULL && zone_config_len > 0); 8128 8129 /* zone zonename { config; }; */ 8130 result = isc_buffer_reserve(*text, 6 + zone_name_len + 2 + 8131 zone_config_len + 2); 8132 if (result != ISC_R_SUCCESS) { 8133 goto cleanup; 8134 } 8135 8136 CHECK(putstr(text, "zone \"")); 8137 CHECK(putmem(text, (const void *)zone_name, zone_name_len)); 8138 CHECK(putstr(text, "\" ")); 8139 CHECK(putmem(text, (const void *)zone_config, zone_config_len)); 8140 CHECK(putstr(text, ";\n")); 8141 8142 snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len, 8143 zone_name); 8144 8145 cfg_parser_reset(named_g_addparser); 8146 result = cfg_parse_buffer(named_g_addparser, *text, bufname, 0, 8147 &cfg_type_addzoneconf, 0, &zoneconf); 8148 if (result != ISC_R_SUCCESS) { 8149 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8150 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8151 "parsing config for zone '%.*s' in " 8152 "NZD database '%s' failed", 8153 (int)zone_name_len, zone_name, view->new_zone_db); 8154 goto cleanup; 8155 } 8156 8157 *zoneconfig = zoneconf; 8158 zoneconf = NULL; 8159 result = ISC_R_SUCCESS; 8160 8161 cleanup: 8162 if (zoneconf != NULL) { 8163 cfg_obj_destroy(named_g_addparser, &zoneconf); 8164 } 8165 8166 return result; 8167 } 8168 8169 /*% 8170 * Prototype for a callback which can be used with for_all_newzone_cfgs(). 8171 */ 8172 typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig, 8173 cfg_obj_t *config, cfg_obj_t *vconfig, 8174 dns_view_t *view, 8175 cfg_aclconfctx_t *actx); 8176 8177 /*% 8178 * For each zone found in a NZD opened by the caller, create an object 8179 * representing its configuration and invoke "callback" with the created 8180 * object, "config", "vconfig", "mctx", "view" and "actx" as arguments (all 8181 * these are non-global variables required to invoke configure_zone()). 8182 * Immediately interrupt processing if an error is encountered while 8183 * transforming NZD data into a zone configuration object or if "callback" 8184 * returns an error. 8185 * 8186 * Caller must hold 'view->new_zone_lock'. 8187 */ 8188 static isc_result_t 8189 for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config, 8190 cfg_obj_t *vconfig, dns_view_t *view, 8191 cfg_aclconfctx_t *actx, MDB_txn *txn, MDB_dbi dbi) { 8192 const cfg_obj_t *zconfig, *zlist; 8193 isc_result_t result = ISC_R_SUCCESS; 8194 cfg_obj_t *zconfigobj = NULL; 8195 isc_buffer_t *text = NULL; 8196 MDB_cursor *cursor = NULL; 8197 MDB_val data, key; 8198 int status; 8199 8200 status = mdb_cursor_open(txn, dbi, &cursor); 8201 if (status != MDB_SUCCESS) { 8202 return ISC_R_FAILURE; 8203 } 8204 8205 for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); 8206 status == MDB_SUCCESS; 8207 status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) 8208 { 8209 /* 8210 * Create a configuration object from data fetched from NZD. 8211 */ 8212 result = data_to_cfg(view, &key, &data, &text, &zconfigobj); 8213 if (result != ISC_R_SUCCESS) { 8214 break; 8215 } 8216 8217 /* 8218 * Extract zone configuration from configuration object. 8219 */ 8220 zlist = NULL; 8221 result = cfg_map_get(zconfigobj, "zone", &zlist); 8222 if (result != ISC_R_SUCCESS) { 8223 break; 8224 } else if (!cfg_obj_islist(zlist)) { 8225 result = ISC_R_FAILURE; 8226 break; 8227 } 8228 zconfig = cfg_listelt_value(cfg_list_first(zlist)); 8229 8230 /* 8231 * Invoke callback. 8232 */ 8233 result = callback(zconfig, config, vconfig, view, actx); 8234 if (result != ISC_R_SUCCESS) { 8235 break; 8236 } 8237 8238 /* 8239 * Destroy the configuration object created in this iteration. 8240 */ 8241 cfg_obj_destroy(named_g_addparser, &zconfigobj); 8242 } 8243 8244 if (text != NULL) { 8245 isc_buffer_free(&text); 8246 } 8247 if (zconfigobj != NULL) { 8248 cfg_obj_destroy(named_g_addparser, &zconfigobj); 8249 } 8250 mdb_cursor_close(cursor); 8251 8252 return result; 8253 } 8254 8255 /*% 8256 * Attempt to configure a zone found in NZD and return the result. 8257 */ 8258 static isc_result_t 8259 configure_newzone(const cfg_obj_t *zconfig, cfg_obj_t *config, 8260 cfg_obj_t *vconfig, dns_view_t *view, 8261 cfg_aclconfctx_t *actx) { 8262 return configure_zone( 8263 config, zconfig, vconfig, view, &named_g_server->viewlist, 8264 &named_g_server->kasplist, &named_g_server->keystorelist, actx, 8265 true, false, false, false); 8266 } 8267 8268 /*% 8269 * Revert new view assignment for a zone found in NZD. 8270 */ 8271 static isc_result_t 8272 configure_newzone_revert(const cfg_obj_t *zconfig, cfg_obj_t *config, 8273 cfg_obj_t *vconfig, dns_view_t *view, 8274 cfg_aclconfctx_t *actx) { 8275 UNUSED(config); 8276 UNUSED(vconfig); 8277 UNUSED(actx); 8278 8279 configure_zone_setviewcommit(ISC_R_FAILURE, zconfig, view); 8280 8281 return ISC_R_SUCCESS; 8282 } 8283 8284 static isc_result_t 8285 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 8286 cfg_aclconfctx_t *actx) { 8287 isc_result_t result; 8288 MDB_txn *txn = NULL; 8289 MDB_dbi dbi; 8290 8291 if (view->new_zone_config == NULL) { 8292 return ISC_R_SUCCESS; 8293 } 8294 8295 LOCK(&view->new_zone_lock); 8296 8297 result = nzd_open(view, MDB_RDONLY, &txn, &dbi); 8298 if (result != ISC_R_SUCCESS) { 8299 UNLOCK(&view->new_zone_lock); 8300 return ISC_R_SUCCESS; 8301 } 8302 8303 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8304 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8305 "loading NZD configs from '%s' " 8306 "for view '%s'", 8307 view->new_zone_db, view->name); 8308 8309 result = for_all_newzone_cfgs(configure_newzone, config, vconfig, view, 8310 actx, txn, dbi); 8311 if (result != ISC_R_SUCCESS) { 8312 /* 8313 * An error was encountered while attempting to configure zones 8314 * found in NZD. As this error may have been caused by a 8315 * configure_zone() failure, try restoring a sane configuration 8316 * by reattaching all zones found in NZD to the old view. If 8317 * this also fails, too bad, there is nothing more we can do in 8318 * terms of trying to make things right. 8319 */ 8320 (void)for_all_newzone_cfgs(configure_newzone_revert, config, 8321 vconfig, view, actx, txn, dbi); 8322 } 8323 8324 (void)nzd_close(&txn, false); 8325 8326 UNLOCK(&view->new_zone_lock); 8327 8328 return result; 8329 } 8330 8331 static isc_result_t 8332 get_newzone_config(dns_view_t *view, const char *zonename, 8333 cfg_obj_t **zoneconfig) { 8334 isc_result_t result; 8335 int status; 8336 cfg_obj_t *zoneconf = NULL; 8337 isc_buffer_t *text = NULL; 8338 MDB_txn *txn = NULL; 8339 MDB_dbi dbi; 8340 MDB_val key, data; 8341 char zname[DNS_NAME_FORMATSIZE]; 8342 dns_fixedname_t fname; 8343 dns_name_t *name; 8344 isc_buffer_t b; 8345 8346 INSIST(zoneconfig != NULL && *zoneconfig == NULL); 8347 8348 LOCK(&view->new_zone_lock); 8349 8350 CHECK(nzd_open(view, MDB_RDONLY, &txn, &dbi)); 8351 8352 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8353 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8354 "loading NZD config from '%s' " 8355 "for zone '%s'", 8356 view->new_zone_db, zonename); 8357 8358 /* Normalize zone name */ 8359 isc_buffer_constinit(&b, zonename, strlen(zonename)); 8360 isc_buffer_add(&b, strlen(zonename)); 8361 name = dns_fixedname_initname(&fname); 8362 CHECK(dns_name_fromtext(name, &b, dns_rootname, DNS_NAME_DOWNCASE, 8363 NULL)); 8364 dns_name_format(name, zname, sizeof(zname)); 8365 8366 key.mv_data = zname; 8367 key.mv_size = strlen(zname); 8368 8369 status = mdb_get(txn, dbi, &key, &data); 8370 if (status != MDB_SUCCESS) { 8371 CHECK(ISC_R_FAILURE); 8372 } 8373 8374 CHECK(data_to_cfg(view, &key, &data, &text, &zoneconf)); 8375 8376 *zoneconfig = zoneconf; 8377 zoneconf = NULL; 8378 result = ISC_R_SUCCESS; 8379 8380 cleanup: 8381 (void)nzd_close(&txn, false); 8382 8383 UNLOCK(&view->new_zone_lock); 8384 8385 if (zoneconf != NULL) { 8386 cfg_obj_destroy(named_g_addparser, &zoneconf); 8387 } 8388 if (text != NULL) { 8389 isc_buffer_free(&text); 8390 } 8391 8392 return result; 8393 } 8394 8395 #endif /* HAVE_LMDB */ 8396 8397 static isc_result_t 8398 load_configuration(const char *filename, named_server_t *server, 8399 bool first_time) { 8400 cfg_obj_t *config = NULL, *bindkeys = NULL; 8401 cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; 8402 const cfg_listelt_t *element; 8403 const cfg_obj_t *builtin_views; 8404 const cfg_obj_t *maps[3]; 8405 const cfg_obj_t *obj; 8406 const cfg_obj_t *options; 8407 const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; 8408 const cfg_obj_t *kasps; 8409 const cfg_obj_t *keystores; 8410 dns_kasp_t *kasp = NULL; 8411 dns_kasp_t *kasp_next = NULL; 8412 dns_kasp_t *default_kasp = NULL; 8413 dns_kasplist_t tmpkasplist, kasplist; 8414 unsigned int kaspopts = (ISCCFG_KASPCONF_CHECK_ALGORITHMS | 8415 ISCCFG_KASPCONF_CHECK_KEYLIST | 8416 ISCCFG_KASPCONF_LOG_ERRORS); 8417 dns_keystore_t *keystore = NULL; 8418 dns_keystore_t *keystore_next = NULL; 8419 dns_keystorelist_t tmpkeystorelist, keystorelist; 8420 const cfg_obj_t *views = NULL; 8421 dns_view_t *view_next = NULL; 8422 dns_viewlist_t tmpviewlist; 8423 dns_viewlist_t viewlist, builtin_viewlist; 8424 in_port_t listen_port, udpport_low, udpport_high; 8425 int i, backlog; 8426 isc_interval_t interval; 8427 isc_logconfig_t *logc = NULL; 8428 isc_portset_t *v4portset = NULL; 8429 isc_portset_t *v6portset = NULL; 8430 isc_result_t result; 8431 uint32_t heartbeat_interval; 8432 uint32_t interface_interval; 8433 uint32_t udpsize; 8434 uint32_t transfer_message_size; 8435 uint32_t recv_tcp_buffer_size; 8436 uint32_t send_tcp_buffer_size; 8437 uint32_t recv_udp_buffer_size; 8438 uint32_t send_udp_buffer_size; 8439 named_cache_t *nsc = NULL; 8440 named_cachelist_t cachelist, tmpcachelist; 8441 ns_altsecret_t *altsecret; 8442 ns_altsecretlist_t altsecrets, tmpaltsecrets; 8443 uint32_t softquota = 0; 8444 uint32_t max; 8445 uint64_t initial, idle, keepalive, advertised; 8446 bool loadbalancesockets; 8447 bool exclusive = true; 8448 dns_aclenv_t *env = 8449 ns_interfacemgr_getaclenv(named_g_server->interfacemgr); 8450 8451 /* 8452 * Require the reconfiguration to happen always on the main loop 8453 */ 8454 REQUIRE(isc_loop() == named_g_mainloop); 8455 8456 ISC_LIST_INIT(kasplist); 8457 ISC_LIST_INIT(keystorelist); 8458 ISC_LIST_INIT(viewlist); 8459 ISC_LIST_INIT(builtin_viewlist); 8460 ISC_LIST_INIT(cachelist); 8461 ISC_LIST_INIT(altsecrets); 8462 8463 /* Ensure exclusive access to configuration data. */ 8464 isc_loopmgr_pause(named_g_loopmgr); 8465 8466 /* Create the ACL configuration context */ 8467 if (named_g_aclconfctx != NULL) { 8468 cfg_aclconfctx_detach(&named_g_aclconfctx); 8469 } 8470 result = cfg_aclconfctx_create(named_g_mctx, &named_g_aclconfctx); 8471 if (result != ISC_R_SUCCESS) { 8472 goto cleanup_exclusive; 8473 } 8474 8475 /* 8476 * Shut down all dyndb instances. 8477 */ 8478 dns_dyndb_cleanup(false); 8479 8480 /* 8481 * Parse the global default pseudo-config file. 8482 */ 8483 if (first_time) { 8484 result = named_config_parsedefaults(named_g_parser, 8485 &named_g_config); 8486 if (result != ISC_R_SUCCESS) { 8487 named_main_earlyfatal("unable to load " 8488 "internal defaults: %s", 8489 isc_result_totext(result)); 8490 } 8491 RUNTIME_CHECK(cfg_map_get(named_g_config, "options", 8492 &named_g_defaults) == ISC_R_SUCCESS); 8493 } 8494 8495 /* 8496 * Log the current working directory. 8497 */ 8498 if (first_time) { 8499 char cwd[PATH_MAX]; 8500 if (getcwd(cwd, sizeof(cwd)) == cwd) { 8501 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8502 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8503 "the initial working directory is '%s'", 8504 cwd); 8505 } 8506 } 8507 8508 /* 8509 * Parse the configuration file using the new config code. 8510 */ 8511 config = NULL; 8512 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8513 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8514 "loading configuration from '%s'", filename); 8515 result = cfg_parser_create(named_g_mctx, named_g_lctx, &conf_parser); 8516 if (result != ISC_R_SUCCESS) { 8517 goto cleanup_exclusive; 8518 } 8519 8520 cfg_parser_setcallback(conf_parser, directory_callback, NULL); 8521 result = cfg_parse_file(conf_parser, filename, &cfg_type_namedconf, 8522 &config); 8523 if (result != ISC_R_SUCCESS) { 8524 goto cleanup_conf_parser; 8525 } 8526 8527 /* 8528 * Check the validity of the configuration. 8529 * 8530 * (Ignore plugin parameters for now; they will be 8531 * checked later when the modules are actually loaded and 8532 * registered.) 8533 */ 8534 result = isccfg_check_namedconf(config, BIND_CHECK_ALGORITHMS, 8535 named_g_lctx, named_g_mctx); 8536 if (result != ISC_R_SUCCESS) { 8537 goto cleanup_config; 8538 } 8539 8540 /* Let's recreate the TLS context cache */ 8541 if (server->tlsctx_server_cache != NULL) { 8542 isc_tlsctx_cache_detach(&server->tlsctx_server_cache); 8543 } 8544 8545 isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_server_cache); 8546 8547 if (server->tlsctx_client_cache != NULL) { 8548 isc_tlsctx_cache_detach(&server->tlsctx_client_cache); 8549 } 8550 8551 isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_client_cache); 8552 8553 dns_zonemgr_set_tlsctx_cache(server->zonemgr, 8554 server->tlsctx_client_cache); 8555 8556 /* 8557 * Fill in the maps array, used for resolving defaults. 8558 */ 8559 i = 0; 8560 options = NULL; 8561 result = cfg_map_get(config, "options", &options); 8562 if (result == ISC_R_SUCCESS) { 8563 maps[i++] = options; 8564 } 8565 maps[i++] = named_g_defaults; 8566 maps[i] = NULL; 8567 8568 #if HAVE_LIBNGHTTP2 8569 obj = NULL; 8570 result = named_config_get(maps, "http-port", &obj); 8571 INSIST(result == ISC_R_SUCCESS); 8572 named_g_httpport = (in_port_t)cfg_obj_asuint32(obj); 8573 8574 obj = NULL; 8575 result = named_config_get(maps, "https-port", &obj); 8576 INSIST(result == ISC_R_SUCCESS); 8577 named_g_httpsport = (in_port_t)cfg_obj_asuint32(obj); 8578 8579 obj = NULL; 8580 result = named_config_get(maps, "http-listener-clients", &obj); 8581 INSIST(result == ISC_R_SUCCESS); 8582 named_g_http_listener_clients = cfg_obj_asuint32(obj); 8583 8584 obj = NULL; 8585 result = named_config_get(maps, "http-streams-per-connection", &obj); 8586 INSIST(result == ISC_R_SUCCESS); 8587 named_g_http_streams_per_conn = cfg_obj_asuint32(obj); 8588 #endif 8589 8590 /* 8591 * If "dnssec-validation auto" is turned on, the root key 8592 * will be used as a default trust anchor. The root key 8593 * is built in, but if bindkeys-file is set, then it will 8594 * be overridden with the key in that file. 8595 */ 8596 obj = NULL; 8597 (void)named_config_get(maps, "bindkeys-file", &obj); 8598 if (obj != NULL) { 8599 setstring(server, &server->bindkeysfile, cfg_obj_asstring(obj)); 8600 INSIST(server->bindkeysfile != NULL); 8601 if (access(server->bindkeysfile, R_OK) != 0) { 8602 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8603 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8604 "unable to open '%s'; using built-in " 8605 "keys instead", 8606 server->bindkeysfile); 8607 } else { 8608 result = cfg_parser_create(named_g_mctx, named_g_lctx, 8609 &bindkeys_parser); 8610 if (result != ISC_R_SUCCESS) { 8611 goto cleanup_config; 8612 } 8613 8614 result = cfg_parse_file(bindkeys_parser, 8615 server->bindkeysfile, 8616 &cfg_type_bindkeys, &bindkeys); 8617 if (result != ISC_R_SUCCESS) { 8618 isc_log_write( 8619 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8620 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8621 "unable to parse '%s' " 8622 "error '%s'; using " 8623 "built-in keys instead", 8624 server->bindkeysfile, 8625 isc_result_totext(result)); 8626 } 8627 } 8628 } else { 8629 setstring(server, &server->bindkeysfile, NULL); 8630 } 8631 8632 #if defined(HAVE_GEOIP2) 8633 /* 8634 * Release any previously opened GeoIP2 databases. 8635 */ 8636 named_geoip_unload(); 8637 8638 /* 8639 * Initialize GeoIP databases from the configured location. 8640 * This should happen before configuring any ACLs, so that we 8641 * know what databases are available and can reject any GeoIP 8642 * ACLs that can't work. 8643 */ 8644 obj = NULL; 8645 result = named_config_get(maps, "geoip-directory", &obj); 8646 INSIST(result == ISC_R_SUCCESS); 8647 if (cfg_obj_isstring(obj)) { 8648 char *dir = UNCONST(cfg_obj_asstring(obj)); 8649 named_geoip_load(dir); 8650 } 8651 named_g_aclconfctx->geoip = named_g_geoip; 8652 #endif /* HAVE_GEOIP2 */ 8653 8654 /* 8655 * Configure various server options. 8656 */ 8657 configure_server_quota(maps, "transfers-out", 8658 &server->sctx->xfroutquota); 8659 configure_server_quota(maps, "tcp-clients", &server->sctx->tcpquota); 8660 configure_server_quota(maps, "recursive-clients", 8661 &server->sctx->recursionquota); 8662 configure_server_quota(maps, "update-quota", &server->sctx->updquota); 8663 configure_server_quota(maps, "sig0checks-quota", 8664 &server->sctx->sig0checksquota); 8665 8666 max = isc_quota_getmax(&server->sctx->recursionquota); 8667 if (max > 1000) { 8668 unsigned int margin = ISC_MAX(100, named_g_cpus + 1); 8669 if (margin + 100 > max) { 8670 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8671 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8672 "'recursive-clients %d' too low when " 8673 "running with %d worker threads", 8674 max, named_g_cpus); 8675 result = ISC_R_RANGE; 8676 8677 goto cleanup_bindkeys_parser; 8678 } 8679 softquota = max - margin; 8680 } else { 8681 softquota = (max * 90) / 100; 8682 } 8683 isc_quota_soft(&server->sctx->recursionquota, softquota); 8684 8685 obj = NULL; 8686 result = named_config_get(maps, "sig0checks-quota-exempt", &obj); 8687 if (result == ISC_R_SUCCESS) { 8688 result = cfg_acl_fromconfig( 8689 obj, config, named_g_lctx, named_g_aclconfctx, 8690 named_g_mctx, 0, &server->sctx->sig0checksquota_exempt); 8691 INSIST(result == ISC_R_SUCCESS); 8692 } 8693 8694 /* 8695 * Set "blackhole". Only legal at options level; there is 8696 * no default. 8697 */ 8698 result = configure_view_acl(NULL, config, NULL, "blackhole", NULL, 8699 named_g_aclconfctx, named_g_mctx, 8700 &server->sctx->blackholeacl); 8701 if (result != ISC_R_SUCCESS) { 8702 goto cleanup_bindkeys_parser; 8703 } 8704 8705 if (server->sctx->blackholeacl != NULL) { 8706 dns_dispatchmgr_setblackhole(named_g_dispatchmgr, 8707 server->sctx->blackholeacl); 8708 } 8709 8710 obj = NULL; 8711 result = named_config_get(maps, "match-mapped-addresses", &obj); 8712 INSIST(result == ISC_R_SUCCESS); 8713 env->match_mapped = cfg_obj_asboolean(obj); 8714 8715 /* 8716 * Configure the network manager 8717 */ 8718 obj = NULL; 8719 result = named_config_get(maps, "tcp-initial-timeout", &obj); 8720 INSIST(result == ISC_R_SUCCESS); 8721 initial = cfg_obj_asuint32(obj) * 100; 8722 if (initial > MAX_INITIAL_TIMEOUT) { 8723 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8724 "tcp-initial-timeout value is out of range: " 8725 "lowering to %" PRIu32, 8726 MAX_INITIAL_TIMEOUT / 100); 8727 initial = MAX_INITIAL_TIMEOUT; 8728 } else if (initial < MIN_INITIAL_TIMEOUT) { 8729 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8730 "tcp-initial-timeout value is out of range: " 8731 "raising to %" PRIu32, 8732 MIN_INITIAL_TIMEOUT / 100); 8733 initial = MIN_INITIAL_TIMEOUT; 8734 } 8735 8736 obj = NULL; 8737 result = named_config_get(maps, "tcp-idle-timeout", &obj); 8738 INSIST(result == ISC_R_SUCCESS); 8739 idle = cfg_obj_asuint32(obj) * 100; 8740 if (idle > MAX_IDLE_TIMEOUT) { 8741 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8742 "tcp-idle-timeout value is out of range: " 8743 "lowering to %" PRIu32, 8744 MAX_IDLE_TIMEOUT / 100); 8745 idle = MAX_IDLE_TIMEOUT; 8746 } else if (idle < MIN_IDLE_TIMEOUT) { 8747 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8748 "tcp-idle-timeout value is out of range: " 8749 "raising to %" PRIu32, 8750 MIN_IDLE_TIMEOUT / 100); 8751 idle = MIN_IDLE_TIMEOUT; 8752 } 8753 8754 obj = NULL; 8755 result = named_config_get(maps, "tcp-keepalive-timeout", &obj); 8756 INSIST(result == ISC_R_SUCCESS); 8757 keepalive = cfg_obj_asuint32(obj) * 100; 8758 if (keepalive > MAX_KEEPALIVE_TIMEOUT) { 8759 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8760 "tcp-keepalive-timeout value is out of range: " 8761 "lowering to %" PRIu32, 8762 MAX_KEEPALIVE_TIMEOUT / 100); 8763 keepalive = MAX_KEEPALIVE_TIMEOUT; 8764 } else if (keepalive < MIN_KEEPALIVE_TIMEOUT) { 8765 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8766 "tcp-keepalive-timeout value is out of range: " 8767 "raising to %" PRIu32, 8768 MIN_KEEPALIVE_TIMEOUT / 100); 8769 keepalive = MIN_KEEPALIVE_TIMEOUT; 8770 } 8771 8772 obj = NULL; 8773 result = named_config_get(maps, "tcp-advertised-timeout", &obj); 8774 INSIST(result == ISC_R_SUCCESS); 8775 advertised = cfg_obj_asuint32(obj) * 100; 8776 if (advertised > MAX_ADVERTISED_TIMEOUT) { 8777 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8778 "tcp-advertized-timeout value is out of range: " 8779 "lowering to %" PRIu32, 8780 MAX_ADVERTISED_TIMEOUT / 100); 8781 advertised = MAX_ADVERTISED_TIMEOUT; 8782 } 8783 8784 isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, 8785 advertised); 8786 8787 #define CAP_IF_NOT_ZERO(v, min, max) \ 8788 if (v > 0 && v < min) { \ 8789 v = min; \ 8790 } else if (v > max) { \ 8791 v = max; \ 8792 } 8793 8794 /* Set the kernel send and receive buffer sizes */ 8795 obj = NULL; 8796 result = named_config_get(maps, "tcp-receive-buffer", &obj); 8797 INSIST(result == ISC_R_SUCCESS); 8798 recv_tcp_buffer_size = cfg_obj_asuint32(obj); 8799 CAP_IF_NOT_ZERO(recv_tcp_buffer_size, 4096, INT32_MAX); 8800 8801 obj = NULL; 8802 result = named_config_get(maps, "tcp-send-buffer", &obj); 8803 INSIST(result == ISC_R_SUCCESS); 8804 send_tcp_buffer_size = cfg_obj_asuint32(obj); 8805 CAP_IF_NOT_ZERO(send_tcp_buffer_size, 4096, INT32_MAX); 8806 8807 obj = NULL; 8808 result = named_config_get(maps, "udp-receive-buffer", &obj); 8809 INSIST(result == ISC_R_SUCCESS); 8810 recv_udp_buffer_size = cfg_obj_asuint32(obj); 8811 CAP_IF_NOT_ZERO(recv_udp_buffer_size, 4096, INT32_MAX); 8812 8813 obj = NULL; 8814 result = named_config_get(maps, "udp-send-buffer", &obj); 8815 INSIST(result == ISC_R_SUCCESS); 8816 send_udp_buffer_size = cfg_obj_asuint32(obj); 8817 CAP_IF_NOT_ZERO(send_udp_buffer_size, 4096, INT32_MAX); 8818 8819 isc_nm_setnetbuffers(named_g_netmgr, recv_tcp_buffer_size, 8820 send_tcp_buffer_size, recv_udp_buffer_size, 8821 send_udp_buffer_size); 8822 8823 #undef CAP_IF_NOT_ZERO 8824 8825 /* 8826 * Configure sets of UDP query source ports. 8827 */ 8828 result = isc_portset_create(named_g_mctx, &v4portset); 8829 if (result != ISC_R_SUCCESS) { 8830 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8831 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8832 "creating UDP/IPv4 port set: %s", 8833 isc_result_totext(result)); 8834 goto cleanup_bindkeys_parser; 8835 } 8836 result = isc_portset_create(named_g_mctx, &v6portset); 8837 if (result != ISC_R_SUCCESS) { 8838 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8839 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8840 "creating UDP/IPv6 port set: %s", 8841 isc_result_totext(result)); 8842 goto cleanup_v4portset; 8843 } 8844 8845 usev4ports = NULL; 8846 usev6ports = NULL; 8847 avoidv4ports = NULL; 8848 avoidv6ports = NULL; 8849 8850 (void)named_config_get(maps, "use-v4-udp-ports", &usev4ports); 8851 if (usev4ports != NULL) { 8852 portset_fromconf(v4portset, usev4ports, true); 8853 } else { 8854 result = isc_net_getudpportrange(AF_INET, &udpport_low, 8855 &udpport_high); 8856 if (result != ISC_R_SUCCESS) { 8857 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8858 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8859 "get the default UDP/IPv4 port range: %s", 8860 isc_result_totext(result)); 8861 goto cleanup_v6portset; 8862 } 8863 8864 if (udpport_low == udpport_high) { 8865 isc_portset_add(v4portset, udpport_low); 8866 } else { 8867 isc_portset_addrange(v4portset, udpport_low, 8868 udpport_high); 8869 } 8870 if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE4)) { 8871 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8872 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8873 "using default UDP/IPv4 port range: " 8874 "[%d, %d]", 8875 udpport_low, udpport_high); 8876 } 8877 } 8878 (void)named_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports); 8879 if (avoidv4ports != NULL) { 8880 portset_fromconf(v4portset, avoidv4ports, false); 8881 } 8882 8883 (void)named_config_get(maps, "use-v6-udp-ports", &usev6ports); 8884 if (usev6ports != NULL) { 8885 portset_fromconf(v6portset, usev6ports, true); 8886 } else { 8887 result = isc_net_getudpportrange(AF_INET6, &udpport_low, 8888 &udpport_high); 8889 if (result != ISC_R_SUCCESS) { 8890 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8891 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8892 "get the default UDP/IPv6 port range: %s", 8893 isc_result_totext(result)); 8894 goto cleanup_v6portset; 8895 } 8896 if (udpport_low == udpport_high) { 8897 isc_portset_add(v6portset, udpport_low); 8898 } else { 8899 isc_portset_addrange(v6portset, udpport_low, 8900 udpport_high); 8901 } 8902 if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE6)) { 8903 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8904 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8905 "using default UDP/IPv6 port range: " 8906 "[%d, %d]", 8907 udpport_low, udpport_high); 8908 } 8909 } 8910 (void)named_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports); 8911 if (avoidv6ports != NULL) { 8912 portset_fromconf(v6portset, avoidv6ports, false); 8913 } 8914 8915 dns_dispatchmgr_setavailports(named_g_dispatchmgr, v4portset, 8916 v6portset); 8917 8918 /* 8919 * Set the EDNS UDP size when we don't match a view. 8920 */ 8921 obj = NULL; 8922 result = named_config_get(maps, "edns-udp-size", &obj); 8923 INSIST(result == ISC_R_SUCCESS); 8924 udpsize = cfg_obj_asuint32(obj); 8925 if (udpsize < 512) { 8926 udpsize = 512; 8927 } 8928 if (udpsize > 4096) { 8929 udpsize = 4096; 8930 } 8931 server->sctx->udpsize = (uint16_t)udpsize; 8932 8933 /* Set the transfer message size for TCP */ 8934 obj = NULL; 8935 result = named_config_get(maps, "transfer-message-size", &obj); 8936 INSIST(result == ISC_R_SUCCESS); 8937 transfer_message_size = cfg_obj_asuint32(obj); 8938 if (transfer_message_size < 512) { 8939 transfer_message_size = 512; 8940 } else if (transfer_message_size > 65535) { 8941 transfer_message_size = 65535; 8942 } 8943 server->sctx->transfer_tcp_message_size = 8944 (uint16_t)transfer_message_size; 8945 8946 /* 8947 * Configure the zone manager. 8948 */ 8949 obj = NULL; 8950 result = named_config_get(maps, "transfers-in", &obj); 8951 INSIST(result == ISC_R_SUCCESS); 8952 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); 8953 8954 obj = NULL; 8955 result = named_config_get(maps, "transfers-per-ns", &obj); 8956 INSIST(result == ISC_R_SUCCESS); 8957 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); 8958 8959 obj = NULL; 8960 result = named_config_get(maps, "notify-rate", &obj); 8961 INSIST(result == ISC_R_SUCCESS); 8962 dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj)); 8963 8964 obj = NULL; 8965 result = named_config_get(maps, "startup-notify-rate", &obj); 8966 INSIST(result == ISC_R_SUCCESS); 8967 dns_zonemgr_setstartupnotifyrate(server->zonemgr, 8968 cfg_obj_asuint32(obj)); 8969 8970 obj = NULL; 8971 result = named_config_get(maps, "serial-query-rate", &obj); 8972 INSIST(result == ISC_R_SUCCESS); 8973 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); 8974 8975 /* 8976 * Determine which port to use for listening for incoming connections. 8977 */ 8978 if (named_g_port != 0) { 8979 listen_port = named_g_port; 8980 } else { 8981 result = named_config_getport(config, "port", &listen_port); 8982 if (result != ISC_R_SUCCESS) { 8983 goto cleanup_v6portset; 8984 } 8985 } 8986 8987 /* 8988 * Find the listen queue depth. 8989 */ 8990 obj = NULL; 8991 result = named_config_get(maps, "tcp-listen-queue", &obj); 8992 INSIST(result == ISC_R_SUCCESS); 8993 backlog = cfg_obj_asuint32(obj); 8994 if ((backlog > 0) && (backlog < 10)) { 8995 backlog = 10; 8996 } 8997 ns_interfacemgr_setbacklog(server->interfacemgr, backlog); 8998 8999 obj = NULL; 9000 result = named_config_get(maps, "reuseport", &obj); 9001 INSIST(result == ISC_R_SUCCESS); 9002 loadbalancesockets = cfg_obj_asboolean(obj); 9003 #if HAVE_SO_REUSEPORT_LB 9004 if (first_time) { 9005 isc_nm_setloadbalancesockets(named_g_netmgr, 9006 cfg_obj_asboolean(obj)); 9007 } else if (loadbalancesockets != 9008 isc_nm_getloadbalancesockets(named_g_netmgr)) 9009 { 9010 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 9011 "changing reuseport value requires server restart"); 9012 } 9013 #else 9014 if (loadbalancesockets) { 9015 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 9016 "reuseport has no effect on this system"); 9017 } 9018 #endif 9019 9020 /* 9021 * Configure the interface manager according to the "listen-on" 9022 * statement. 9023 */ 9024 { 9025 const cfg_obj_t *clistenon = NULL; 9026 ns_listenlist_t *listenon = NULL; 9027 9028 /* 9029 * Even though listen-on is present in the default 9030 * configuration, this way is easier. 9031 */ 9032 if (options != NULL) { 9033 (void)cfg_map_get(options, "listen-on", &clistenon); 9034 } 9035 if (clistenon != NULL) { 9036 result = listenlist_fromconfig( 9037 clistenon, config, named_g_aclconfctx, 9038 named_g_mctx, AF_INET, 9039 server->tlsctx_server_cache, &listenon); 9040 } else { 9041 /* 9042 * Not specified, use default. 9043 */ 9044 result = ns_listenlist_default(named_g_mctx, 9045 listen_port, true, 9046 AF_INET, &listenon); 9047 } 9048 if (result != ISC_R_SUCCESS) { 9049 goto cleanup_v6portset; 9050 } 9051 9052 if (listenon != NULL) { 9053 ns_interfacemgr_setlistenon4(server->interfacemgr, 9054 listenon); 9055 ns_listenlist_detach(&listenon); 9056 } 9057 } 9058 9059 /* 9060 * Ditto for IPv6. 9061 */ 9062 { 9063 const cfg_obj_t *clistenon = NULL; 9064 ns_listenlist_t *listenon = NULL; 9065 9066 if (options != NULL) { 9067 (void)cfg_map_get(options, "listen-on-v6", &clistenon); 9068 } 9069 if (clistenon != NULL) { 9070 result = listenlist_fromconfig( 9071 clistenon, config, named_g_aclconfctx, 9072 named_g_mctx, AF_INET6, 9073 server->tlsctx_server_cache, &listenon); 9074 } else { 9075 /* 9076 * Not specified, use default. 9077 */ 9078 result = ns_listenlist_default(named_g_mctx, 9079 listen_port, true, 9080 AF_INET6, &listenon); 9081 } 9082 if (result != ISC_R_SUCCESS) { 9083 goto cleanup_v6portset; 9084 } 9085 if (listenon != NULL) { 9086 ns_interfacemgr_setlistenon6(server->interfacemgr, 9087 listenon); 9088 ns_listenlist_detach(&listenon); 9089 } 9090 } 9091 9092 if (first_time) { 9093 /* 9094 * Rescan the interface list to pick up changes in the 9095 * listen-on option. This requires the loopmgr to be 9096 * temporarily resumed. 9097 */ 9098 isc_loopmgr_resume(named_g_loopmgr); 9099 result = ns_interfacemgr_scan(server->interfacemgr, true, true); 9100 isc_loopmgr_pause(named_g_loopmgr); 9101 9102 /* 9103 * Check that named is able to TCP listen on at least one 9104 * interface. Otherwise, another named process could be running 9105 * and we should fail. 9106 */ 9107 if (result == ISC_R_ADDRINUSE) { 9108 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9109 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9110 "unable to listen on any configured " 9111 "interfaces"); 9112 result = ISC_R_FAILURE; 9113 goto cleanup_v6portset; 9114 } 9115 } 9116 9117 /* 9118 * Arrange for further interface scanning to occur periodically 9119 * as specified by the "interface-interval" option. 9120 */ 9121 obj = NULL; 9122 result = named_config_get(maps, "interface-interval", &obj); 9123 INSIST(result == ISC_R_SUCCESS); 9124 interface_interval = cfg_obj_asduration(obj); 9125 server->interface_interval = interface_interval; 9126 9127 /* 9128 * Enable automatic interface scans. 9129 */ 9130 obj = NULL; 9131 result = named_config_get(maps, "automatic-interface-scan", &obj); 9132 INSIST(result == ISC_R_SUCCESS); 9133 server->sctx->interface_auto = cfg_obj_asboolean(obj); 9134 9135 if (server->sctx->interface_auto) { 9136 if (ns_interfacemgr_dynamic_updates_are_reliable() && 9137 server->interface_interval != 0) 9138 { 9139 /* 9140 * In some cases the user might expect a certain 9141 * behaviour from the rescan timer, let's try to deduce 9142 * that from the configuration options. 9143 */ 9144 isc_log_write( 9145 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9146 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9147 "Disabling periodic interface re-scans timer"); 9148 server->interface_interval = 0; 9149 } 9150 9151 ns_interfacemgr_routeconnect(server->interfacemgr); 9152 } else { 9153 ns_interfacemgr_routedisconnect(server->interfacemgr); 9154 } 9155 9156 if (server->interface_interval == 0) { 9157 isc_timer_stop(server->interface_timer); 9158 } else { 9159 isc_interval_set(&interval, interface_interval, 0); 9160 isc_timer_start(server->interface_timer, isc_timertype_ticker, 9161 &interval); 9162 } 9163 9164 /* 9165 * Configure the dialup heartbeat timer. 9166 */ 9167 obj = NULL; 9168 result = named_config_get(maps, "heartbeat-interval", &obj); 9169 INSIST(result == ISC_R_SUCCESS); 9170 heartbeat_interval = cfg_obj_asuint32(obj) * 60; 9171 if (heartbeat_interval == 0) { 9172 isc_timer_stop(server->heartbeat_timer); 9173 } else if (server->heartbeat_interval != heartbeat_interval) { 9174 isc_interval_set(&interval, heartbeat_interval, 0); 9175 isc_timer_start(server->heartbeat_timer, isc_timertype_ticker, 9176 &interval); 9177 } 9178 server->heartbeat_interval = heartbeat_interval; 9179 9180 isc_interval_set(&interval, 1200, 0); 9181 isc_timer_start(server->pps_timer, isc_timertype_ticker, &interval); 9182 9183 isc_interval_set(&interval, named_g_tat_interval, 0); 9184 isc_timer_start(server->tat_timer, isc_timertype_ticker, &interval); 9185 9186 /* 9187 * Write the PID file. 9188 */ 9189 obj = NULL; 9190 if (named_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) { 9191 if (cfg_obj_isvoid(obj)) { 9192 named_os_writepidfile(NULL, first_time); 9193 } else { 9194 named_os_writepidfile(cfg_obj_asstring(obj), 9195 first_time); 9196 } 9197 } else { 9198 named_os_writepidfile(named_g_defaultpidfile, first_time); 9199 } 9200 9201 /* 9202 * Configure the server-wide session key. This must be done before 9203 * configure views because zone configuration may need to know 9204 * session-keyname. 9205 * 9206 * Failure of session key generation isn't fatal at this time; if it 9207 * turns out that a session key is really needed but doesn't exist, 9208 * we'll treat it as a fatal error then. 9209 */ 9210 (void)configure_session_key(maps, server, named_g_mctx, first_time); 9211 9212 /* 9213 * Create the built-in key store ("key-directory"). 9214 */ 9215 result = cfg_keystore_fromconfig(NULL, named_g_mctx, named_g_lctx, 9216 named_g_engine, &keystorelist, NULL); 9217 if (result != ISC_R_SUCCESS) { 9218 goto cleanup_keystorelist; 9219 } 9220 9221 /* 9222 * Create the DNSSEC key stores. 9223 */ 9224 keystores = NULL; 9225 (void)cfg_map_get(config, "key-store", &keystores); 9226 for (element = cfg_list_first(keystores); element != NULL; 9227 element = cfg_list_next(element)) 9228 { 9229 cfg_obj_t *kconfig = cfg_listelt_value(element); 9230 keystore = NULL; 9231 result = cfg_keystore_fromconfig(kconfig, named_g_mctx, 9232 named_g_lctx, named_g_engine, 9233 &keystorelist, NULL); 9234 if (result != ISC_R_SUCCESS) { 9235 goto cleanup_keystorelist; 9236 } 9237 } 9238 9239 /* 9240 * Create the built-in kasp policies ("default", "insecure"). 9241 */ 9242 kasps = NULL; 9243 (void)cfg_map_get(named_g_config, "dnssec-policy", &kasps); 9244 for (element = cfg_list_first(kasps); element != NULL; 9245 element = cfg_list_next(element)) 9246 { 9247 cfg_obj_t *kconfig = cfg_listelt_value(element); 9248 9249 kasp = NULL; 9250 result = cfg_kasp_fromconfig(kconfig, default_kasp, kaspopts, 9251 named_g_mctx, named_g_lctx, 9252 &keystorelist, &kasplist, &kasp); 9253 if (result != ISC_R_SUCCESS) { 9254 goto cleanup_kasplist; 9255 } 9256 INSIST(kasp != NULL); 9257 dns_kasp_freeze(kasp); 9258 9259 /* Insist that the first built-in policy is the default one. */ 9260 if (default_kasp == NULL) { 9261 INSIST(strcmp(dns_kasp_getname(kasp), "default") == 0); 9262 dns_kasp_attach(kasp, &default_kasp); 9263 } 9264 9265 dns_kasp_detach(&kasp); 9266 } 9267 INSIST(default_kasp != NULL); 9268 9269 /* 9270 * Create the DNSSEC key and signing policies (KASP). 9271 */ 9272 kasps = NULL; 9273 (void)cfg_map_get(config, "dnssec-policy", &kasps); 9274 for (element = cfg_list_first(kasps); element != NULL; 9275 element = cfg_list_next(element)) 9276 { 9277 cfg_obj_t *kconfig = cfg_listelt_value(element); 9278 kasp = NULL; 9279 result = cfg_kasp_fromconfig(kconfig, default_kasp, kaspopts, 9280 named_g_mctx, named_g_lctx, 9281 &keystorelist, &kasplist, &kasp); 9282 if (result != ISC_R_SUCCESS) { 9283 goto cleanup_kasplist; 9284 } 9285 INSIST(kasp != NULL); 9286 dns_kasp_freeze(kasp); 9287 dns_kasp_detach(&kasp); 9288 } 9289 dns_kasp_detach(&default_kasp); 9290 9291 /* 9292 * Save keystore list and kasp list. 9293 */ 9294 tmpkeystorelist = server->keystorelist; 9295 server->keystorelist = keystorelist; 9296 keystorelist = tmpkeystorelist; 9297 9298 tmpkasplist = server->kasplist; 9299 server->kasplist = kasplist; 9300 kasplist = tmpkasplist; 9301 9302 #ifdef USE_DNSRPS 9303 /* 9304 * Find the path to the DNSRPS implementation library. 9305 */ 9306 obj = NULL; 9307 if (named_config_get(maps, "dnsrps-library", &obj) == ISC_R_SUCCESS) { 9308 if (server->dnsrpslib != NULL) { 9309 dns_dnsrps_server_destroy(); 9310 isc_mem_free(server->mctx, server->dnsrpslib); 9311 server->dnsrpslib = NULL; 9312 } 9313 setstring(server, &server->dnsrpslib, cfg_obj_asstring(obj)); 9314 result = dns_dnsrps_server_create(server->dnsrpslib); 9315 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9316 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9317 "initializing DNSRPS RPZ provider '%s': %s", 9318 server->dnsrpslib, isc_result_totext(result)); 9319 /* 9320 * It's okay if librpz isn't available. We'll complain 9321 * later if it turns out to be needed for a view with 9322 * "dnsrps-enable yes". 9323 */ 9324 if (result == ISC_R_FILENOTFOUND) { 9325 result = ISC_R_SUCCESS; 9326 } 9327 CHECKFATAL(result, "initializing RPZ service interface"); 9328 } 9329 #endif /* ifdef USE_DNSRPS */ 9330 9331 /* 9332 * Configure the views. 9333 */ 9334 views = NULL; 9335 (void)cfg_map_get(config, "view", &views); 9336 9337 /* 9338 * Create the views. 9339 */ 9340 for (element = cfg_list_first(views); element != NULL; 9341 element = cfg_list_next(element)) 9342 { 9343 cfg_obj_t *vconfig = cfg_listelt_value(element); 9344 dns_view_t *view = NULL; 9345 9346 result = create_view(vconfig, &viewlist, &view); 9347 if (result != ISC_R_SUCCESS) { 9348 goto cleanup_viewlist; 9349 } 9350 INSIST(view != NULL); 9351 9352 result = setup_newzones(view, config, vconfig, conf_parser, 9353 named_g_aclconfctx); 9354 dns_view_detach(&view); 9355 9356 if (result != ISC_R_SUCCESS) { 9357 goto cleanup_viewlist; 9358 } 9359 } 9360 9361 /* 9362 * If there were no explicit views then we do the default 9363 * view here. 9364 */ 9365 if (views == NULL) { 9366 dns_view_t *view = NULL; 9367 9368 result = create_view(NULL, &viewlist, &view); 9369 if (result != ISC_R_SUCCESS) { 9370 goto cleanup_viewlist; 9371 } 9372 INSIST(view != NULL); 9373 9374 result = setup_newzones(view, config, NULL, conf_parser, 9375 named_g_aclconfctx); 9376 9377 dns_view_detach(&view); 9378 if (result != ISC_R_SUCCESS) { 9379 goto cleanup_viewlist; 9380 } 9381 } 9382 9383 /* 9384 * Configure and freeze all explicit views. Explicit 9385 * views that have zones were already created at parsing 9386 * time, but views with no zones must be created here. 9387 */ 9388 for (element = cfg_list_first(views); element != NULL; 9389 element = cfg_list_next(element)) 9390 { 9391 cfg_obj_t *vconfig = cfg_listelt_value(element); 9392 dns_view_t *view = NULL; 9393 9394 view = NULL; 9395 result = find_view(vconfig, &viewlist, &view); 9396 if (result != ISC_R_SUCCESS) { 9397 goto cleanup_cachelist; 9398 } 9399 9400 result = configure_view( 9401 view, &viewlist, config, vconfig, &cachelist, 9402 &server->cachelist, &server->kasplist, 9403 &server->keystorelist, bindkeys, named_g_mctx, 9404 named_g_aclconfctx, true, first_time); 9405 if (result != ISC_R_SUCCESS) { 9406 dns_view_detach(&view); 9407 goto cleanup_cachelist; 9408 } 9409 dns_view_freeze(view); 9410 dns_view_detach(&view); 9411 } 9412 9413 /* 9414 * Make sure we have a default view if and only if there 9415 * were no explicit views. 9416 */ 9417 if (views == NULL) { 9418 dns_view_t *view = NULL; 9419 result = find_view(NULL, &viewlist, &view); 9420 if (result != ISC_R_SUCCESS) { 9421 goto cleanup_cachelist; 9422 } 9423 result = configure_view( 9424 view, &viewlist, config, NULL, &cachelist, 9425 &server->cachelist, &server->kasplist, 9426 &server->keystorelist, bindkeys, named_g_mctx, 9427 named_g_aclconfctx, true, first_time); 9428 if (result != ISC_R_SUCCESS) { 9429 dns_view_detach(&view); 9430 goto cleanup_cachelist; 9431 } 9432 dns_view_freeze(view); 9433 dns_view_detach(&view); 9434 } 9435 9436 /* 9437 * Create (or recreate) the built-in views. 9438 */ 9439 builtin_views = NULL; 9440 RUNTIME_CHECK(cfg_map_get(named_g_config, "view", &builtin_views) == 9441 ISC_R_SUCCESS); 9442 for (element = cfg_list_first(builtin_views); element != NULL; 9443 element = cfg_list_next(element)) 9444 { 9445 cfg_obj_t *vconfig = cfg_listelt_value(element); 9446 dns_view_t *view = NULL; 9447 9448 result = create_view(vconfig, &builtin_viewlist, &view); 9449 if (result != ISC_R_SUCCESS) { 9450 goto cleanup_cachelist; 9451 } 9452 9453 result = configure_view( 9454 view, &viewlist, config, vconfig, &cachelist, 9455 &server->cachelist, &server->kasplist, 9456 &server->keystorelist, bindkeys, named_g_mctx, 9457 named_g_aclconfctx, false, first_time); 9458 if (result != ISC_R_SUCCESS) { 9459 dns_view_detach(&view); 9460 goto cleanup_cachelist; 9461 } 9462 dns_view_freeze(view); 9463 dns_view_detach(&view); 9464 } 9465 9466 /* Now combine the two viewlists into one */ 9467 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 9468 9469 /* 9470 * Commit any dns_zone_setview() calls on all zones in the new 9471 * view. 9472 */ 9473 for (dns_view_t *view = ISC_LIST_HEAD(viewlist); view != NULL; 9474 view = ISC_LIST_NEXT(view, link)) 9475 { 9476 dns_view_setviewcommit(view); 9477 } 9478 9479 /* Swap our new view list with the production one. */ 9480 tmpviewlist = server->viewlist; 9481 server->viewlist = viewlist; 9482 viewlist = tmpviewlist; 9483 9484 /* Make the view list available to each of the views */ 9485 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9486 view = ISC_LIST_NEXT(view, link)) 9487 { 9488 view->viewlist = &server->viewlist; 9489 } 9490 9491 /* Swap our new cache list with the production one. */ 9492 tmpcachelist = server->cachelist; 9493 server->cachelist = cachelist; 9494 cachelist = tmpcachelist; 9495 9496 /* Load the TKEY information from the configuration. */ 9497 if (options != NULL) { 9498 dns_tkeyctx_t *tkeyctx = NULL; 9499 9500 result = named_tkeyctx_fromconfig(options, named_g_mctx, 9501 &tkeyctx); 9502 if (result != ISC_R_SUCCESS) { 9503 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9504 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9505 "configuring TKEY: %s", 9506 isc_result_totext(result)); 9507 goto cleanup_cachelist; 9508 } 9509 if (server->sctx->tkeyctx != NULL) { 9510 dns_tkeyctx_destroy(&server->sctx->tkeyctx); 9511 } 9512 server->sctx->tkeyctx = tkeyctx; 9513 } 9514 9515 #ifdef HAVE_LMDB 9516 /* 9517 * If we're using LMDB, we may have created newzones databases 9518 * as root, making it impossible to reopen them later after 9519 * switching to a new userid. We close them now, and reopen 9520 * after relinquishing privileges them. 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_close(view); 9527 } 9528 } 9529 #endif /* HAVE_LMDB */ 9530 9531 /* 9532 * Switch to the effective UID for setting up files. 9533 * Later, after configuring all the listening ports, 9534 * we'll relinquish root privileges permanently. 9535 */ 9536 if (first_time) { 9537 named_os_changeuser(false); 9538 } 9539 9540 /* 9541 * Check that the working directory is writable. 9542 */ 9543 if (!isc_file_isdirwritable(".")) { 9544 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9545 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9546 "the working directory is not writable"); 9547 result = ISC_R_NOPERM; 9548 goto cleanup_cachelist; 9549 } 9550 9551 #ifdef HAVE_LMDB 9552 /* 9553 * Reopen NZD databases. 9554 */ 9555 if (first_time) { 9556 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); 9557 view != NULL; view = ISC_LIST_NEXT(view, link)) 9558 { 9559 nzd_env_reopen(view); 9560 } 9561 } 9562 #endif /* HAVE_LMDB */ 9563 9564 /* 9565 * Configure the logging system. 9566 * 9567 * Do this after changing UID to make sure that any log 9568 * files specified in named.conf get created by the 9569 * unprivileged user, not root. 9570 */ 9571 if (named_g_logstderr) { 9572 const cfg_obj_t *logobj = NULL; 9573 9574 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9575 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9576 "not using config file logging " 9577 "statement for logging due to " 9578 "-g option"); 9579 9580 (void)cfg_map_get(config, "logging", &logobj); 9581 if (logobj != NULL) { 9582 result = named_logconfig(NULL, logobj); 9583 if (result != ISC_R_SUCCESS) { 9584 isc_log_write( 9585 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9586 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9587 "checking logging configuration " 9588 "failed: %s", 9589 isc_result_totext(result)); 9590 goto cleanup_cachelist; 9591 } 9592 } 9593 } else { 9594 const cfg_obj_t *logobj = NULL; 9595 9596 isc_logconfig_create(named_g_lctx, &logc); 9597 9598 logobj = NULL; 9599 (void)cfg_map_get(config, "logging", &logobj); 9600 if (logobj != NULL) { 9601 result = named_logconfig(logc, logobj); 9602 if (result != ISC_R_SUCCESS) { 9603 isc_log_write( 9604 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9605 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9606 "configuring logging: %s", 9607 isc_result_totext(result)); 9608 goto cleanup_logc; 9609 } 9610 } else { 9611 named_log_setdefaultchannels(logc); 9612 named_log_setdefaultsslkeylogfile(logc); 9613 result = named_log_setunmatchedcategory(logc); 9614 if (result != ISC_R_SUCCESS) { 9615 isc_log_write( 9616 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9617 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9618 "setting up default 'category " 9619 "unmatched': %s", 9620 isc_result_totext(result)); 9621 goto cleanup_logc; 9622 } 9623 result = named_log_setdefaultcategory(logc); 9624 if (result != ISC_R_SUCCESS) { 9625 isc_log_write( 9626 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9627 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9628 "setting up default 'category " 9629 "default': %s", 9630 isc_result_totext(result)); 9631 goto cleanup_logc; 9632 } 9633 } 9634 9635 isc_logconfig_use(named_g_lctx, logc); 9636 logc = NULL; 9637 9638 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9639 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9640 "now using logging configuration from " 9641 "config file"); 9642 } 9643 9644 /* 9645 * Set the default value of the query logging flag depending 9646 * whether a "queries" category has been defined. This is 9647 * a disgusting hack, but we need to do this for BIND 8 9648 * compatibility. 9649 */ 9650 if (first_time) { 9651 const cfg_obj_t *logobj = NULL; 9652 const cfg_obj_t *categories = NULL; 9653 9654 obj = NULL; 9655 if (named_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { 9656 ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES, 9657 cfg_obj_asboolean(obj)); 9658 } else { 9659 (void)cfg_map_get(config, "logging", &logobj); 9660 if (logobj != NULL) { 9661 (void)cfg_map_get(logobj, "category", 9662 &categories); 9663 } 9664 if (categories != NULL) { 9665 for (element = cfg_list_first(categories); 9666 element != NULL; 9667 element = cfg_list_next(element)) 9668 { 9669 const cfg_obj_t *catobj; 9670 const char *str; 9671 9672 obj = cfg_listelt_value(element); 9673 catobj = cfg_tuple_get(obj, "name"); 9674 str = cfg_obj_asstring(catobj); 9675 if (strcasecmp(str, "queries") == 0) { 9676 ns_server_setoption( 9677 server->sctx, 9678 NS_SERVER_LOGQUERIES, 9679 true); 9680 } 9681 } 9682 } 9683 } 9684 obj = NULL; 9685 result = named_config_get(maps, "responselog", &obj); 9686 if (result == ISC_R_SUCCESS) { 9687 ns_server_setoption(server->sctx, 9688 NS_SERVER_LOGRESPONSES, 9689 cfg_obj_asboolean(obj)); 9690 } 9691 } 9692 9693 obj = NULL; 9694 if (options != NULL && 9695 cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS) 9696 { 9697 named_g_memstatistics = cfg_obj_asboolean(obj); 9698 } else { 9699 named_g_memstatistics = 9700 ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0); 9701 } 9702 9703 obj = NULL; 9704 if (named_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS) 9705 { 9706 named_main_setmemstats(cfg_obj_asstring(obj)); 9707 } else if (named_g_memstatistics) { 9708 named_main_setmemstats("named.memstats"); 9709 } else { 9710 named_main_setmemstats(NULL); 9711 } 9712 9713 obj = NULL; 9714 result = named_config_get(maps, "statistics-file", &obj); 9715 INSIST(result == ISC_R_SUCCESS); 9716 setstring(server, &server->statsfile, cfg_obj_asstring(obj)); 9717 9718 obj = NULL; 9719 result = named_config_get(maps, "dump-file", &obj); 9720 INSIST(result == ISC_R_SUCCESS); 9721 setstring(server, &server->dumpfile, cfg_obj_asstring(obj)); 9722 9723 obj = NULL; 9724 result = named_config_get(maps, "secroots-file", &obj); 9725 INSIST(result == ISC_R_SUCCESS); 9726 setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)); 9727 9728 obj = NULL; 9729 result = named_config_get(maps, "recursing-file", &obj); 9730 INSIST(result == ISC_R_SUCCESS); 9731 setstring(server, &server->recfile, cfg_obj_asstring(obj)); 9732 9733 obj = NULL; 9734 result = named_config_get(maps, "version", &obj); 9735 if (result == ISC_R_SUCCESS) { 9736 setoptstring(server, &server->version, obj); 9737 server->version_set = true; 9738 } else { 9739 server->version_set = false; 9740 } 9741 9742 obj = NULL; 9743 result = named_config_get(maps, "hostname", &obj); 9744 if (result == ISC_R_SUCCESS) { 9745 setoptstring(server, &server->hostname, obj); 9746 server->hostname_set = true; 9747 } else { 9748 server->hostname_set = false; 9749 } 9750 9751 obj = NULL; 9752 result = named_config_get(maps, "server-id", &obj); 9753 server->sctx->usehostname = false; 9754 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 9755 /* The parser translates "hostname" to true */ 9756 server->sctx->usehostname = true; 9757 result = ns_server_setserverid(server->sctx, NULL); 9758 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 9759 /* Found a quoted string */ 9760 result = ns_server_setserverid(server->sctx, 9761 cfg_obj_asstring(obj)); 9762 } else { 9763 result = ns_server_setserverid(server->sctx, NULL); 9764 } 9765 RUNTIME_CHECK(result == ISC_R_SUCCESS); 9766 9767 obj = NULL; 9768 result = named_config_get(maps, "flush-zones-on-shutdown", &obj); 9769 if (result == ISC_R_SUCCESS) { 9770 server->flushonshutdown = cfg_obj_asboolean(obj); 9771 } else { 9772 server->flushonshutdown = false; 9773 } 9774 9775 obj = NULL; 9776 result = named_config_get(maps, "answer-cookie", &obj); 9777 INSIST(result == ISC_R_SUCCESS); 9778 server->sctx->answercookie = cfg_obj_asboolean(obj); 9779 9780 obj = NULL; 9781 result = named_config_get(maps, "cookie-algorithm", &obj); 9782 INSIST(result == ISC_R_SUCCESS); 9783 if (strcasecmp(cfg_obj_asstring(obj), "siphash24") == 0) { 9784 server->sctx->cookiealg = ns_cookiealg_siphash24; 9785 } else { 9786 UNREACHABLE(); 9787 } 9788 9789 obj = NULL; 9790 result = named_config_get(maps, "cookie-secret", &obj); 9791 if (result == ISC_R_SUCCESS) { 9792 const char *str; 9793 bool first = true; 9794 isc_buffer_t b; 9795 unsigned int usedlength; 9796 unsigned int expectedlength; 9797 9798 for (element = cfg_list_first(obj); element != NULL; 9799 element = cfg_list_next(element)) 9800 { 9801 obj = cfg_listelt_value(element); 9802 str = cfg_obj_asstring(obj); 9803 9804 if (first) { 9805 memset(server->sctx->secret, 0, 9806 sizeof(server->sctx->secret)); 9807 isc_buffer_init(&b, server->sctx->secret, 9808 sizeof(server->sctx->secret)); 9809 result = isc_hex_decodestring(str, &b); 9810 if (result != ISC_R_SUCCESS && 9811 result != ISC_R_NOSPACE) 9812 { 9813 goto cleanup_altsecrets; 9814 } 9815 first = false; 9816 } else { 9817 altsecret = isc_mem_get(server->sctx->mctx, 9818 sizeof(*altsecret)); 9819 isc_buffer_init(&b, altsecret->secret, 9820 sizeof(altsecret->secret)); 9821 result = isc_hex_decodestring(str, &b); 9822 if (result != ISC_R_SUCCESS && 9823 result != ISC_R_NOSPACE) 9824 { 9825 isc_mem_put(server->sctx->mctx, 9826 altsecret, 9827 sizeof(*altsecret)); 9828 goto cleanup_altsecrets; 9829 } 9830 ISC_LIST_INITANDAPPEND(altsecrets, altsecret, 9831 link); 9832 } 9833 9834 usedlength = isc_buffer_usedlength(&b); 9835 switch (server->sctx->cookiealg) { 9836 case ns_cookiealg_siphash24: 9837 expectedlength = ISC_SIPHASH24_KEY_LENGTH; 9838 if (usedlength != expectedlength) { 9839 result = ISC_R_RANGE; 9840 isc_log_write( 9841 named_g_lctx, 9842 NAMED_LOGCATEGORY_GENERAL, 9843 NAMED_LOGMODULE_SERVER, 9844 ISC_LOG_ERROR, 9845 "SipHash-2-4 cookie-secret " 9846 "must be 128 bits: %s", 9847 isc_result_totext(result)); 9848 goto cleanup_altsecrets; 9849 } 9850 break; 9851 } 9852 } 9853 } else { 9854 isc_nonce_buf(server->sctx->secret, 9855 sizeof(server->sctx->secret)); 9856 } 9857 9858 /* 9859 * Swap altsecrets lists. 9860 */ 9861 tmpaltsecrets = server->sctx->altsecrets; 9862 server->sctx->altsecrets = altsecrets; 9863 altsecrets = tmpaltsecrets; 9864 9865 (void)named_server_loadnta(server); 9866 9867 #ifdef USE_DNSRPS 9868 /* 9869 * Start and connect to the DNS Response Policy Service 9870 * daemon, dnsrpzd, for each view that uses DNSRPS. 9871 */ 9872 for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9873 view = ISC_LIST_NEXT(view, link)) 9874 { 9875 result = dns_dnsrps_connect(view->rpzs); 9876 if (result != ISC_R_SUCCESS) { 9877 view = NULL; 9878 goto cleanup_altsecrets; 9879 } 9880 } 9881 #endif /* ifdef USE_DNSRPS */ 9882 9883 /* 9884 * Record the time of most recent configuration 9885 */ 9886 named_g_configtime = isc_time_now(); 9887 9888 isc_loopmgr_resume(named_g_loopmgr); 9889 exclusive = false; 9890 9891 /* Take back root privileges temporarily */ 9892 if (first_time) { 9893 named_os_restoreuser(); 9894 } 9895 9896 /* Configure the statistics channel(s) */ 9897 result = named_statschannels_configure(named_g_server, config, 9898 named_g_aclconfctx); 9899 if (result != ISC_R_SUCCESS) { 9900 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9901 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9902 "configuring statistics server(s): %s", 9903 isc_result_totext(result)); 9904 goto cleanup_altsecrets; 9905 } 9906 9907 /* 9908 * Bind the control port(s). 9909 */ 9910 result = named_controls_configure(named_g_server->controls, config, 9911 named_g_aclconfctx); 9912 if (result != ISC_R_SUCCESS) { 9913 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9914 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9915 "binding control channel(s): %s", 9916 isc_result_totext(result)); 9917 goto cleanup_altsecrets; 9918 } 9919 9920 (void)ns_interfacemgr_scan(server->interfacemgr, true, true); 9921 9922 /* 9923 * Permanently drop root privileges now. 9924 */ 9925 if (first_time) { 9926 named_os_changeuser(true); 9927 } 9928 9929 /* 9930 * These cleans up either the old production view list 9931 * or our temporary list depending on whether they 9932 * were swapped above or not. 9933 */ 9934 cleanup_altsecrets: 9935 while ((altsecret = ISC_LIST_HEAD(altsecrets)) != NULL) { 9936 ISC_LIST_UNLINK(altsecrets, altsecret, link); 9937 isc_mem_put(server->sctx->mctx, altsecret, sizeof(*altsecret)); 9938 } 9939 9940 cleanup_logc: 9941 if (logc != NULL) { 9942 isc_logconfig_destroy(&logc); 9943 } 9944 9945 cleanup_cachelist: 9946 while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { 9947 ISC_LIST_UNLINK(cachelist, nsc, link); 9948 dns_cache_detach(&nsc->cache); 9949 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 9950 } 9951 9952 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 9953 9954 cleanup_viewlist: 9955 for (dns_view_t *view = ISC_LIST_HEAD(viewlist); view != NULL; 9956 view = view_next) 9957 { 9958 view_next = ISC_LIST_NEXT(view, link); 9959 ISC_LIST_UNLINK(viewlist, view, link); 9960 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) 9961 { 9962 dns_view_setviewrevert(view); 9963 (void)dns_view_apply(view, false, NULL, removed, view); 9964 } 9965 dns_view_detach(&view); 9966 } 9967 9968 cleanup_kasplist: 9969 for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) { 9970 kasp_next = ISC_LIST_NEXT(kasp, link); 9971 ISC_LIST_UNLINK(kasplist, kasp, link); 9972 dns_kasp_detach(&kasp); 9973 } 9974 9975 cleanup_keystorelist: 9976 for (keystore = ISC_LIST_HEAD(keystorelist); keystore != NULL; 9977 keystore = keystore_next) 9978 { 9979 keystore_next = ISC_LIST_NEXT(keystore, link); 9980 ISC_LIST_UNLINK(keystorelist, keystore, link); 9981 dns_keystore_detach(&keystore); 9982 } 9983 9984 cleanup_v6portset: 9985 isc_portset_destroy(named_g_mctx, &v6portset); 9986 9987 cleanup_v4portset: 9988 isc_portset_destroy(named_g_mctx, &v4portset); 9989 9990 cleanup_bindkeys_parser: 9991 9992 if (bindkeys_parser != NULL) { 9993 if (bindkeys != NULL) { 9994 cfg_obj_destroy(bindkeys_parser, &bindkeys); 9995 } 9996 cfg_parser_destroy(&bindkeys_parser); 9997 } 9998 9999 cleanup_config: 10000 cfg_obj_destroy(conf_parser, &config); 10001 10002 cleanup_conf_parser: 10003 cfg_parser_destroy(&conf_parser); 10004 10005 cleanup_exclusive: 10006 if (exclusive) { 10007 isc_loopmgr_resume(named_g_loopmgr); 10008 } 10009 10010 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10011 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 10012 "load_configuration: %s", isc_result_totext(result)); 10013 10014 return result; 10015 } 10016 10017 static isc_result_t 10018 view_loaded(void *arg) { 10019 isc_result_t result; 10020 ns_zoneload_t *zl = (ns_zoneload_t *)arg; 10021 10022 /* 10023 * Force zone maintenance. Do this after loading 10024 * so that we know when we need to force AXFR of 10025 * secondary zones whose master files are missing. 10026 * 10027 * We use the zoneload reference counter to let us 10028 * know when all views are finished. 10029 */ 10030 if (isc_refcount_decrement(&zl->refs) == 1) { 10031 named_server_t *server = zl->server; 10032 bool reconfig = zl->reconfig; 10033 dns_view_t *view = NULL; 10034 10035 isc_refcount_destroy(&zl->refs); 10036 isc_mem_put(server->mctx, zl, sizeof(*zl)); 10037 10038 /* 10039 * To maintain compatibility with log parsing tools that might 10040 * be looking for this string after "rndc reconfig", we keep it 10041 * as it is 10042 */ 10043 if (reconfig) { 10044 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10045 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10046 "any newly configured zones are now " 10047 "loaded"); 10048 } else { 10049 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10050 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10051 "all zones loaded"); 10052 } 10053 10054 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10055 view = ISC_LIST_NEXT(view, link)) 10056 { 10057 if (view->managed_keys != NULL) { 10058 result = dns_zone_synckeyzone( 10059 view->managed_keys); 10060 if (result != ISC_R_SUCCESS) { 10061 isc_log_write( 10062 named_g_lctx, 10063 DNS_LOGCATEGORY_DNSSEC, 10064 DNS_LOGMODULE_DNSSEC, 10065 ISC_LOG_ERROR, 10066 "failed to initialize " 10067 "managed-keys for view %s " 10068 "(%s): DNSSEC validation is " 10069 "at risk", 10070 view->name, 10071 isc_result_totext(result)); 10072 } 10073 } 10074 } 10075 10076 CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr), 10077 "forcing zone maintenance"); 10078 10079 named_os_started(); 10080 10081 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10082 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10083 "FIPS mode is %s", 10084 isc_fips_mode() ? "enabled" : "disabled"); 10085 10086 named_os_notify_systemd("READY=1\n" 10087 "STATUS=running\n" 10088 "MAINPID=%" PRId64 "\n", 10089 (int64_t)getpid()); 10090 10091 atomic_store(&server->reload_status, NAMED_RELOAD_DONE); 10092 10093 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10094 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10095 "running"); 10096 } 10097 10098 return ISC_R_SUCCESS; 10099 } 10100 10101 static isc_result_t 10102 load_zones(named_server_t *server, bool reconfig) { 10103 isc_result_t result = ISC_R_SUCCESS; 10104 ns_zoneload_t *zl = NULL; 10105 dns_view_t *view = NULL; 10106 10107 zl = isc_mem_get(server->mctx, sizeof(*zl)); 10108 zl->server = server; 10109 zl->reconfig = reconfig; 10110 10111 isc_loopmgr_pause(named_g_loopmgr); 10112 10113 isc_refcount_init(&zl->refs, 1); 10114 10115 /* 10116 * Schedule zones to be loaded from disk. 10117 */ 10118 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10119 view = ISC_LIST_NEXT(view, link)) 10120 { 10121 if (view->managed_keys != NULL) { 10122 result = dns_zone_load(view->managed_keys, false); 10123 if (result != ISC_R_SUCCESS && 10124 result != DNS_R_UPTODATE && 10125 result != DNS_R_CONTINUE) 10126 { 10127 goto cleanup; 10128 } 10129 } 10130 if (view->redirect != NULL) { 10131 result = dns_zone_load(view->redirect, false); 10132 if (result != ISC_R_SUCCESS && 10133 result != DNS_R_UPTODATE && 10134 result != DNS_R_CONTINUE) 10135 { 10136 goto cleanup; 10137 } 10138 } 10139 10140 /* 10141 * 'dns_view_asyncload' calls view_loaded if there are no 10142 * zones. 10143 */ 10144 isc_refcount_increment(&zl->refs); 10145 result = dns_view_asyncload(view, reconfig, view_loaded, zl); 10146 if (result != ISC_R_SUCCESS) { 10147 isc_refcount_decrement1(&zl->refs); 10148 goto cleanup; 10149 } 10150 } 10151 10152 cleanup: 10153 if (isc_refcount_decrement(&zl->refs) == 1) { 10154 isc_refcount_destroy(&zl->refs); 10155 isc_mem_put(server->mctx, zl, sizeof(*zl)); 10156 } 10157 10158 isc_loopmgr_resume(named_g_loopmgr); 10159 10160 return result; 10161 } 10162 10163 static void 10164 run_server(void *arg) { 10165 isc_result_t result; 10166 named_server_t *server = (named_server_t *)arg; 10167 dns_geoip_databases_t *geoip = NULL; 10168 10169 dns_zonemgr_create(named_g_mctx, named_g_netmgr, &server->zonemgr); 10170 10171 CHECKFATAL(dns_dispatchmgr_create(named_g_mctx, named_g_loopmgr, 10172 named_g_netmgr, &named_g_dispatchmgr), 10173 "creating dispatch manager"); 10174 10175 dns_dispatchmgr_setstats(named_g_dispatchmgr, server->resolverstats); 10176 10177 #if defined(HAVE_GEOIP2) 10178 geoip = named_g_geoip; 10179 #else /* if defined(HAVE_GEOIP2) */ 10180 geoip = NULL; 10181 #endif /* if defined(HAVE_GEOIP2) */ 10182 10183 CHECKFATAL(ns_interfacemgr_create(named_g_mctx, server->sctx, 10184 named_g_loopmgr, named_g_netmgr, 10185 named_g_dispatchmgr, geoip, 10186 &server->interfacemgr), 10187 "creating interface manager"); 10188 10189 isc_timer_create(named_g_mainloop, interface_timer_tick, server, 10190 &server->interface_timer); 10191 10192 isc_timer_create(named_g_mainloop, heartbeat_timer_tick, server, 10193 &server->heartbeat_timer); 10194 10195 isc_timer_create(named_g_mainloop, tat_timer_tick, server, 10196 &server->tat_timer); 10197 10198 isc_timer_create(named_g_mainloop, pps_timer_tick, server, 10199 &server->pps_timer); 10200 10201 CHECKFATAL( 10202 cfg_parser_create(named_g_mctx, named_g_lctx, &named_g_parser), 10203 "creating default configuration parser"); 10204 10205 CHECKFATAL(cfg_parser_create(named_g_mctx, named_g_lctx, 10206 &named_g_addparser), 10207 "creating additional configuration parser"); 10208 10209 CHECKFATAL(load_configuration(named_g_conffile, server, true), 10210 "loading configuration"); 10211 10212 CHECKFATAL(load_zones(server, false), "loading zones"); 10213 #ifdef ENABLE_AFL 10214 named_g_run_done = true; 10215 #endif /* ifdef ENABLE_AFL */ 10216 } 10217 10218 void 10219 named_server_flushonshutdown(named_server_t *server, bool flush) { 10220 REQUIRE(NAMED_SERVER_VALID(server)); 10221 10222 server->flushonshutdown = flush; 10223 } 10224 10225 static void 10226 shutdown_server(void *arg) { 10227 named_server_t *server = (named_server_t *)arg; 10228 dns_view_t *view = NULL, *view_next = NULL; 10229 dns_kasp_t *kasp = NULL, *kasp_next = NULL; 10230 dns_keystore_t *keystore = NULL, *keystore_next = NULL; 10231 bool flush = server->flushonshutdown; 10232 named_cache_t *nsc = NULL; 10233 10234 named_os_notify_systemd("STOPPING=1\n"); 10235 named_os_notify_close(); 10236 10237 isc_signal_stop(server->sighup); 10238 isc_signal_destroy(&server->sighup); 10239 10240 /* 10241 * We need to shutdown the interface before going 10242 * exclusive (which would pause the netmgr). 10243 */ 10244 ns_interfacemgr_shutdown(server->interfacemgr); 10245 10246 named_controls_shutdown(server->controls); 10247 10248 named_statschannels_shutdown(server); 10249 10250 isc_loopmgr_pause(named_g_loopmgr); 10251 10252 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10253 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "shutting down%s", 10254 flush ? ": flushing changes" : ""); 10255 10256 cleanup_session_key(server, server->mctx); 10257 10258 if (named_g_aclconfctx != NULL) { 10259 cfg_aclconfctx_detach(&named_g_aclconfctx); 10260 } 10261 10262 cfg_obj_destroy(named_g_parser, &named_g_config); 10263 cfg_parser_destroy(&named_g_parser); 10264 cfg_parser_destroy(&named_g_addparser); 10265 10266 (void)named_server_saventa(server); 10267 10268 for (kasp = ISC_LIST_HEAD(server->kasplist); kasp != NULL; 10269 kasp = kasp_next) 10270 { 10271 kasp_next = ISC_LIST_NEXT(kasp, link); 10272 ISC_LIST_UNLINK(server->kasplist, kasp, link); 10273 dns_kasp_detach(&kasp); 10274 } 10275 10276 for (keystore = ISC_LIST_HEAD(server->keystorelist); keystore != NULL; 10277 keystore = keystore_next) 10278 { 10279 keystore_next = ISC_LIST_NEXT(keystore, link); 10280 ISC_LIST_UNLINK(server->keystorelist, keystore, link); 10281 dns_keystore_detach(&keystore); 10282 } 10283 10284 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10285 view = view_next) 10286 { 10287 view_next = ISC_LIST_NEXT(view, link); 10288 ISC_LIST_UNLINK(server->viewlist, view, link); 10289 dns_view_flushonshutdown(view, flush); 10290 dns_view_detach(&view); 10291 } 10292 10293 /* 10294 * Shut down all dyndb instances. 10295 */ 10296 dns_dyndb_cleanup(true); 10297 10298 while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { 10299 ISC_LIST_UNLINK(server->cachelist, nsc, link); 10300 dns_cache_detach(&nsc->cache); 10301 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 10302 } 10303 10304 isc_timer_destroy(&server->interface_timer); 10305 isc_timer_destroy(&server->heartbeat_timer); 10306 isc_timer_destroy(&server->pps_timer); 10307 isc_timer_destroy(&server->tat_timer); 10308 10309 ns_interfacemgr_detach(&server->interfacemgr); 10310 10311 dns_dispatchmgr_detach(&named_g_dispatchmgr); 10312 10313 dns_zonemgr_shutdown(server->zonemgr); 10314 10315 #if defined(HAVE_GEOIP2) 10316 named_geoip_shutdown(); 10317 #endif /* HAVE_GEOIP2 */ 10318 10319 dns_db_detach(&server->in_roothints); 10320 10321 isc_loopmgr_resume(named_g_loopmgr); 10322 } 10323 10324 static isc_result_t 10325 get_matching_view_sync(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, 10326 dns_message_t *message, dns_aclenv_t *env, 10327 isc_result_t *sigresult, dns_view_t **viewp) { 10328 dns_view_t *view; 10329 10330 /* 10331 * We should not be running synchronous view matching if signature 10332 * checking involves SIG(0). TSIG has priority of SIG(0), so if TSIG 10333 * is set then we proceed anyway. 10334 */ 10335 INSIST(message->tsigkey != NULL || message->tsig != NULL || 10336 message->sig0 == NULL); 10337 10338 for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL; 10339 view = ISC_LIST_NEXT(view, link)) 10340 { 10341 if (message->rdclass == view->rdclass || 10342 message->rdclass == dns_rdataclass_any) 10343 { 10344 const dns_name_t *tsig = NULL; 10345 10346 dns_message_resetsig(message); 10347 *sigresult = dns_message_checksig(message, view); 10348 if (*sigresult == ISC_R_SUCCESS) { 10349 tsig = dns_tsigkey_identity(message->tsigkey); 10350 } 10351 10352 if (dns_acl_allowed(srcaddr, tsig, view->matchclients, 10353 env) && 10354 dns_acl_allowed(destaddr, tsig, 10355 view->matchdestinations, env) && 10356 !(view->matchrecursiveonly && 10357 (message->flags & DNS_MESSAGEFLAG_RD) == 0)) 10358 { 10359 dns_view_attach(view, viewp); 10360 return ISC_R_SUCCESS; 10361 } 10362 } 10363 } 10364 10365 return ISC_R_NOTFOUND; 10366 } 10367 10368 static void 10369 get_matching_view_done(void *cbarg) { 10370 matching_view_ctx_t *mvctx = cbarg; 10371 dns_message_t *message = mvctx->message; 10372 10373 if (*mvctx->viewmatchresult == ISC_R_SUCCESS) { 10374 INSIST(mvctx->view != NULL); 10375 dns_view_attach(mvctx->view, mvctx->viewp); 10376 } 10377 10378 mvctx->cb(mvctx->cbarg); 10379 10380 if (mvctx->quota_result == ISC_R_SUCCESS) { 10381 isc_quota_release(&mvctx->sctx->sig0checksquota); 10382 } 10383 if (mvctx->view != NULL) { 10384 dns_view_detach(&mvctx->view); 10385 } 10386 isc_loop_detach(&mvctx->loop); 10387 ns_server_detach(&mvctx->sctx); 10388 isc_mem_put(message->mctx, mvctx, sizeof(*mvctx)); 10389 dns_message_detach(&message); 10390 } 10391 10392 static dns_view_t * 10393 get_matching_view_next(dns_view_t *view, dns_rdataclass_t rdclass) { 10394 if (view == NULL) { 10395 view = ISC_LIST_HEAD(named_g_server->viewlist); 10396 } else { 10397 view = ISC_LIST_NEXT(view, link); 10398 } 10399 while (true) { 10400 if (view == NULL || rdclass == view->rdclass || 10401 rdclass == dns_rdataclass_any) 10402 { 10403 return view; 10404 } 10405 view = ISC_LIST_NEXT(view, link); 10406 }; 10407 } 10408 10409 static void 10410 get_matching_view_continue(void *cbarg, isc_result_t result) { 10411 matching_view_ctx_t *mvctx = cbarg; 10412 dns_view_t *view = NULL; 10413 const dns_name_t *tsig = NULL; 10414 10415 *mvctx->sigresult = result; 10416 10417 if (result == ISC_R_SUCCESS) { 10418 tsig = dns_tsigkey_identity(mvctx->message->tsigkey); 10419 } 10420 10421 if (dns_acl_allowed(mvctx->srcaddr, tsig, mvctx->view->matchclients, 10422 mvctx->env) && 10423 dns_acl_allowed(mvctx->destaddr, tsig, 10424 mvctx->view->matchdestinations, mvctx->env) && 10425 !(mvctx->view->matchrecursiveonly && 10426 (mvctx->message->flags & DNS_MESSAGEFLAG_RD) == 0)) 10427 { 10428 /* 10429 * A matching view is found. 10430 */ 10431 *mvctx->viewmatchresult = ISC_R_SUCCESS; 10432 get_matching_view_done(cbarg); 10433 return; 10434 } 10435 10436 dns_message_resetsig(mvctx->message); 10437 10438 view = get_matching_view_next(mvctx->view, mvctx->message->rdclass); 10439 dns_view_detach(&mvctx->view); 10440 if (view != NULL) { 10441 /* 10442 * Try the next view. 10443 */ 10444 dns_view_attach(view, &mvctx->view); 10445 result = dns_message_checksig_async( 10446 mvctx->message, view, mvctx->loop, 10447 get_matching_view_continue, mvctx); 10448 INSIST(result == DNS_R_WAIT); 10449 return; 10450 } 10451 10452 /* 10453 * No matching view is found. 10454 */ 10455 *mvctx->viewmatchresult = ISC_R_NOTFOUND; 10456 get_matching_view_done(cbarg); 10457 } 10458 10459 /*% 10460 * Find a view that matches the source and destination addresses of a query. 10461 */ 10462 static isc_result_t 10463 get_matching_view(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, 10464 dns_message_t *message, dns_aclenv_t *env, ns_server_t *sctx, 10465 isc_loop_t *loop, isc_job_cb cb, void *cbarg, 10466 isc_result_t *sigresult, isc_result_t *viewmatchresult, 10467 dns_view_t **viewp) { 10468 dns_view_t *view = NULL; 10469 isc_result_t result; 10470 10471 REQUIRE(message != NULL); 10472 REQUIRE(sctx != NULL); 10473 REQUIRE(loop == NULL || cb != NULL); 10474 REQUIRE(sigresult != NULL); 10475 REQUIRE(viewmatchresult != NULL); 10476 REQUIRE(viewp != NULL && *viewp == NULL); 10477 10478 /* No offloading is requested if the loop is unset. */ 10479 if (loop == NULL) { 10480 *viewmatchresult = get_matching_view_sync( 10481 srcaddr, destaddr, message, env, sigresult, viewp); 10482 return *viewmatchresult; 10483 } 10484 10485 /* Also no offloading when there is no view at all to match against. */ 10486 view = get_matching_view_next(NULL, message->rdclass); 10487 if (view == NULL) { 10488 *viewmatchresult = ISC_R_NOTFOUND; 10489 return *viewmatchresult; 10490 } 10491 10492 dns_message_resetsig(message); 10493 10494 matching_view_ctx_t *mvctx = isc_mem_get(message->mctx, sizeof(*mvctx)); 10495 *mvctx = (matching_view_ctx_t){ 10496 .srcaddr = srcaddr, 10497 .destaddr = destaddr, 10498 .env = env, 10499 .cb = cb, 10500 .cbarg = cbarg, 10501 .sigresult = sigresult, 10502 .viewmatchresult = viewmatchresult, 10503 .quota_result = ISC_R_UNSET, 10504 .viewp = viewp, 10505 }; 10506 ns_server_attach(sctx, &mvctx->sctx); 10507 isc_loop_attach(loop, &mvctx->loop); 10508 dns_message_attach(message, &mvctx->message); 10509 10510 /* 10511 * If the message has a SIG0 signature which we are going to 10512 * check, and the client is not exempt from the SIG(0) quota, 10513 * then acquire a quota. TSIG has priority over SIG(0), so if 10514 * TSIG is set then we don't care. 10515 */ 10516 if (message->tsigkey == NULL && message->tsig == NULL && 10517 message->sig0 != NULL) 10518 { 10519 if (sctx->sig0checksquota_exempt != NULL) { 10520 int exempt_match; 10521 10522 result = dns_acl_match(srcaddr, NULL, 10523 sctx->sig0checksquota_exempt, 10524 env, &exempt_match, NULL); 10525 if (result == ISC_R_SUCCESS && exempt_match > 0) { 10526 mvctx->quota_result = ISC_R_EXISTS; 10527 } 10528 } 10529 if (mvctx->quota_result == ISC_R_UNSET) { 10530 mvctx->quota_result = 10531 isc_quota_acquire(&sctx->sig0checksquota); 10532 } 10533 if (mvctx->quota_result == ISC_R_SOFTQUOTA) { 10534 isc_quota_release(&sctx->sig0checksquota); 10535 } 10536 if (mvctx->quota_result != ISC_R_SUCCESS && 10537 mvctx->quota_result != ISC_R_EXISTS) 10538 { 10539 *mvctx->viewmatchresult = ISC_R_QUOTA; 10540 isc_async_run(loop, get_matching_view_done, mvctx); 10541 return DNS_R_WAIT; 10542 } 10543 } 10544 10545 dns_view_attach(view, &mvctx->view); 10546 result = dns_message_checksig_async(message, view, loop, 10547 get_matching_view_continue, mvctx); 10548 INSIST(result == DNS_R_WAIT); 10549 10550 return DNS_R_WAIT; 10551 } 10552 10553 void 10554 named_server_create(isc_mem_t *mctx, named_server_t **serverp) { 10555 isc_result_t result; 10556 named_server_t *server = isc_mem_get(mctx, sizeof(*server)); 10557 10558 *server = (named_server_t){ 10559 .mctx = mctx, 10560 .statsfile = isc_mem_strdup(mctx, "named.stats"), 10561 .dumpfile = isc_mem_strdup(mctx, "named_dump.db"), 10562 .secrootsfile = isc_mem_strdup(mctx, "named.secroots"), 10563 .recfile = isc_mem_strdup(mctx, "named.recursing"), 10564 }; 10565 10566 /* Initialize server data structures. */ 10567 ISC_LIST_INIT(server->kasplist); 10568 ISC_LIST_INIT(server->keystorelist); 10569 ISC_LIST_INIT(server->viewlist); 10570 10571 /* Must be first. */ 10572 CHECKFATAL(dst_lib_init(named_g_mctx, named_g_engine), 10573 "initializing DST"); 10574 10575 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, 10576 &server->in_roothints), 10577 "setting up root hints"); 10578 10579 atomic_init(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 10580 10581 ns_server_create(mctx, get_matching_view, &server->sctx); 10582 10583 #if defined(HAVE_GEOIP2) 10584 /* 10585 * GeoIP must be initialized before the interface 10586 * manager (which includes the ACL environment) 10587 * is created. 10588 */ 10589 named_geoip_init(); 10590 #endif /* HAVE_GEOIP2 */ 10591 10592 #ifdef ENABLE_AFL 10593 server->sctx->fuzztype = named_g_fuzz_type; 10594 server->sctx->fuzznotify = named_fuzz_notify; 10595 #endif /* ifdef ENABLE_AFL */ 10596 10597 named_g_mainloop = isc_loop_main(named_g_loopmgr); 10598 10599 isc_loop_setup(named_g_mainloop, run_server, server); 10600 isc_loop_teardown(named_g_mainloop, shutdown_server, server); 10601 10602 /* Add SIGHUP reload handler */ 10603 server->sighup = isc_signal_new( 10604 named_g_loopmgr, named_server_reloadwanted, server, SIGHUP); 10605 10606 isc_stats_create(server->mctx, &server->sockstats, 10607 isc_sockstatscounter_max); 10608 isc_nm_setstats(named_g_netmgr, server->sockstats); 10609 10610 isc_stats_create(named_g_mctx, &server->zonestats, 10611 dns_zonestatscounter_max); 10612 10613 isc_stats_create(named_g_mctx, &server->resolverstats, 10614 dns_resstatscounter_max); 10615 10616 CHECKFATAL(named_controls_create(server, &server->controls), 10617 "named_controls_create"); 10618 10619 ISC_LIST_INIT(server->statschannels); 10620 10621 ISC_LIST_INIT(server->cachelist); 10622 10623 server->magic = NAMED_SERVER_MAGIC; 10624 10625 *serverp = server; 10626 } 10627 10628 void 10629 named_server_destroy(named_server_t **serverp) { 10630 named_server_t *server = *serverp; 10631 REQUIRE(NAMED_SERVER_VALID(server)); 10632 10633 #ifdef HAVE_DNSTAP 10634 if (server->dtenv != NULL) { 10635 dns_dt_detach(&server->dtenv); 10636 } 10637 #endif /* HAVE_DNSTAP */ 10638 10639 #ifdef USE_DNSRPS 10640 dns_dnsrps_server_destroy(); 10641 isc_mem_free(server->mctx, server->dnsrpslib); 10642 #endif /* ifdef USE_DNSRPS */ 10643 10644 named_controls_destroy(&server->controls); 10645 10646 isc_stats_detach(&server->zonestats); 10647 isc_stats_detach(&server->sockstats); 10648 isc_stats_detach(&server->resolverstats); 10649 10650 if (server->sctx != NULL) { 10651 ns_server_detach(&server->sctx); 10652 } 10653 10654 isc_mem_free(server->mctx, server->statsfile); 10655 isc_mem_free(server->mctx, server->dumpfile); 10656 isc_mem_free(server->mctx, server->secrootsfile); 10657 isc_mem_free(server->mctx, server->recfile); 10658 10659 if (server->bindkeysfile != NULL) { 10660 isc_mem_free(server->mctx, server->bindkeysfile); 10661 } 10662 10663 if (server->version != NULL) { 10664 isc_mem_free(server->mctx, server->version); 10665 } 10666 if (server->hostname != NULL) { 10667 isc_mem_free(server->mctx, server->hostname); 10668 } 10669 10670 if (server->zonemgr != NULL) { 10671 dns_zonemgr_detach(&server->zonemgr); 10672 } 10673 10674 dst_lib_destroy(); 10675 10676 INSIST(ISC_LIST_EMPTY(server->kasplist)); 10677 INSIST(ISC_LIST_EMPTY(server->keystorelist)); 10678 INSIST(ISC_LIST_EMPTY(server->viewlist)); 10679 INSIST(ISC_LIST_EMPTY(server->cachelist)); 10680 10681 if (server->tlsctx_server_cache != NULL) { 10682 isc_tlsctx_cache_detach(&server->tlsctx_server_cache); 10683 } 10684 10685 if (server->tlsctx_client_cache != NULL) { 10686 isc_tlsctx_cache_detach(&server->tlsctx_client_cache); 10687 } 10688 10689 server->magic = 0; 10690 isc_mem_put(server->mctx, server, sizeof(*server)); 10691 *serverp = NULL; 10692 } 10693 10694 static void 10695 fatal(const char *msg, isc_result_t result) { 10696 if (named_g_loopmgr_running) { 10697 isc_loopmgr_pause(named_g_loopmgr); 10698 } 10699 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10700 NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "%s: %s", msg, 10701 isc_result_totext(result)); 10702 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10703 NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, 10704 "exiting (due to fatal error)"); 10705 named_os_shutdown(); 10706 _exit(EXIT_FAILURE); 10707 } 10708 10709 static isc_result_t 10710 loadconfig(named_server_t *server) { 10711 isc_result_t result; 10712 result = load_configuration(named_g_conffile, server, false); 10713 if (result == ISC_R_SUCCESS) { 10714 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10715 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10716 "reloading configuration succeeded"); 10717 } else { 10718 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10719 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 10720 "reloading configuration failed: %s", 10721 isc_result_totext(result)); 10722 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 10723 } 10724 10725 return result; 10726 } 10727 10728 static isc_result_t 10729 reload(named_server_t *server) { 10730 isc_result_t result; 10731 10732 atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 10733 10734 named_os_notify_systemd("RELOADING=1\n" 10735 "MONOTONIC_USEC=%" PRIu64 "\n" 10736 "STATUS=reload command received\n", 10737 (uint64_t)isc_time_monotonic() / NS_PER_US); 10738 10739 CHECK(loadconfig(server)); 10740 10741 result = load_zones(server, false); 10742 if (result == ISC_R_SUCCESS) { 10743 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10744 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10745 "reloading zones succeeded"); 10746 } else { 10747 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10748 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 10749 "reloading zones failed: %s", 10750 isc_result_totext(result)); 10751 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 10752 } 10753 cleanup: 10754 named_os_notify_systemd("READY=1\n" 10755 "STATUS=reload command finished: %s\n", 10756 isc_result_totext(result)); 10757 10758 return result; 10759 } 10760 10761 /* 10762 * Handle a reload event (from SIGHUP). 10763 */ 10764 static void 10765 named_server_reload(void *arg) { 10766 named_server_t *server = (named_server_t *)arg; 10767 10768 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10769 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10770 "received SIGHUP signal to reload zones"); 10771 (void)reload(server); 10772 } 10773 10774 void 10775 named_server_reloadwanted(void *arg, int signum) { 10776 named_server_t *server = (named_server_t *)arg; 10777 10778 REQUIRE(signum == SIGHUP); 10779 10780 isc_async_run(named_g_mainloop, named_server_reload, server); 10781 } 10782 10783 #ifdef JEMALLOC_API_SUPPORTED 10784 static isc_result_t 10785 memprof_toggle(bool active) { 10786 if (mallctl("prof.active", NULL, NULL, &active, sizeof(active)) != 0) { 10787 return ISC_R_FAILURE; 10788 } 10789 10790 return ISC_R_SUCCESS; 10791 } 10792 10793 static isc_result_t 10794 memprof_dump(void) { 10795 if (mallctl("prof.dump", NULL, NULL, NULL, 0) != 0) { 10796 return ISC_R_FAILURE; 10797 } 10798 10799 return ISC_R_SUCCESS; 10800 } 10801 #else 10802 static isc_result_t 10803 memprof_toggle(bool active) { 10804 UNUSED(active); 10805 10806 return ISC_R_NOTIMPLEMENTED; 10807 } 10808 10809 static isc_result_t 10810 memprof_dump(void) { 10811 return ISC_R_NOTIMPLEMENTED; 10812 } 10813 10814 #endif /* JEMALLOC_API_SUPPORTED */ 10815 10816 void 10817 named_server_scan_interfaces(named_server_t *server) { 10818 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10819 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 10820 "automatic interface rescan"); 10821 10822 ns_interfacemgr_scan(server->interfacemgr, true, false); 10823 } 10824 10825 /* 10826 * Get the next token from lexer 'lex'. 10827 * 10828 * NOTE: the token value for string tokens always uses the same pointer 10829 * value. Multiple calls to this function on the same lexer will always 10830 * return either that value (lex->data) or NULL. It is necessary to copy 10831 * the token into local storage if it needs to be referenced after the next 10832 * call to next_token(). 10833 */ 10834 static char * 10835 next_token(isc_lex_t *lex, isc_buffer_t **text) { 10836 isc_result_t result; 10837 isc_token_t token; 10838 10839 token.type = isc_tokentype_unknown; 10840 result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF | ISC_LEXOPT_QSTRING, 10841 &token); 10842 10843 switch (result) { 10844 case ISC_R_NOMORE: 10845 (void)isc_lex_close(lex); 10846 break; 10847 case ISC_R_SUCCESS: 10848 if (token.type == isc_tokentype_eof) { 10849 (void)isc_lex_close(lex); 10850 } 10851 break; 10852 case ISC_R_NOSPACE: 10853 if (text != NULL) { 10854 (void)putstr(text, "token too large"); 10855 (void)putnull(text); 10856 } 10857 return NULL; 10858 default: 10859 if (text != NULL) { 10860 (void)putstr(text, isc_result_totext(result)); 10861 (void)putnull(text); 10862 } 10863 return NULL; 10864 } 10865 10866 if (token.type == isc_tokentype_string || 10867 token.type == isc_tokentype_qstring) 10868 { 10869 return token.value.as_textregion.base; 10870 } 10871 10872 return NULL; 10873 } 10874 10875 /* 10876 * Find the zone specified in the control channel command, if any. 10877 * If a zone is specified, point '*zonep' at it, otherwise 10878 * set '*zonep' to NULL, and f 'zonename' is not NULL, copy 10879 * the zone name into it (N.B. 'zonename' must have space to hold 10880 * a full DNS name). 10881 * 10882 * If 'zonetxt' is set, the caller has already pulled a token 10883 * off the command line that is to be used as the zone name. (This 10884 * is sometimes done when it's necessary to check for an optional 10885 * argument before the zone name, as in "rndc sync [-clean] zone".) 10886 */ 10887 static isc_result_t 10888 zone_from_args(named_server_t *server, isc_lex_t *lex, const char *zonetxt, 10889 dns_zone_t **zonep, char *zonename, isc_buffer_t **text, 10890 bool skip) { 10891 char *ptr; 10892 char *classtxt; 10893 const char *viewtxt = NULL; 10894 dns_fixedname_t fname; 10895 dns_name_t *name; 10896 isc_result_t result; 10897 dns_view_t *view = NULL; 10898 dns_rdataclass_t rdclass; 10899 char problem[DNS_NAME_FORMATSIZE + 500] = ""; 10900 char zonebuf[DNS_NAME_FORMATSIZE]; 10901 bool redirect = false; 10902 10903 REQUIRE(zonep != NULL && *zonep == NULL); 10904 10905 if (skip) { 10906 /* Skip the command name. */ 10907 ptr = next_token(lex, text); 10908 if (ptr == NULL) { 10909 return ISC_R_UNEXPECTEDEND; 10910 } 10911 } 10912 10913 /* Look for the zone name. */ 10914 if (zonetxt == NULL) { 10915 zonetxt = next_token(lex, text); 10916 } 10917 if (zonetxt == NULL) { 10918 return ISC_R_SUCCESS; 10919 } 10920 10921 /* Copy zonetxt because it'll be overwritten by next_token() */ 10922 /* To locate a zone named "-redirect" use "-redirect." */ 10923 if (strcmp(zonetxt, "-redirect") == 0) { 10924 redirect = true; 10925 strlcpy(zonebuf, ".", DNS_NAME_FORMATSIZE); 10926 } else { 10927 strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE); 10928 } 10929 if (zonename != NULL) { 10930 strlcpy(zonename, redirect ? "." : zonetxt, 10931 DNS_NAME_FORMATSIZE); 10932 } 10933 10934 name = dns_fixedname_initname(&fname); 10935 CHECK(dns_name_fromstring(name, zonebuf, dns_rootname, 0, NULL)); 10936 10937 /* Look for the optional class name. */ 10938 classtxt = next_token(lex, text); 10939 if (classtxt != NULL) { 10940 isc_textregion_t r; 10941 r.base = classtxt; 10942 r.length = strlen(classtxt); 10943 CHECK(dns_rdataclass_fromtext(&rdclass, &r)); 10944 10945 /* Look for the optional view name. */ 10946 viewtxt = next_token(lex, text); 10947 } else { 10948 rdclass = dns_rdataclass_in; 10949 } 10950 10951 if (viewtxt == NULL) { 10952 if (redirect) { 10953 result = dns_viewlist_find(&server->viewlist, 10954 "_default", 10955 dns_rdataclass_in, &view); 10956 if (result != ISC_R_SUCCESS || view->redirect == NULL) { 10957 result = ISC_R_NOTFOUND; 10958 snprintf(problem, sizeof(problem), 10959 "redirect zone not found in " 10960 "_default view"); 10961 } else { 10962 dns_zone_attach(view->redirect, zonep); 10963 result = ISC_R_SUCCESS; 10964 } 10965 } else { 10966 result = dns_viewlist_findzone(&server->viewlist, name, 10967 classtxt == NULL, 10968 rdclass, zonep); 10969 if (result == ISC_R_NOTFOUND) { 10970 snprintf(problem, sizeof(problem), 10971 "no matching zone '%s' in any view", 10972 zonebuf); 10973 } else if (result == ISC_R_MULTIPLE) { 10974 snprintf(problem, sizeof(problem), 10975 "zone '%s' was found in multiple " 10976 "views", 10977 zonebuf); 10978 } 10979 } 10980 } else { 10981 result = dns_viewlist_find(&server->viewlist, viewtxt, rdclass, 10982 &view); 10983 if (result != ISC_R_SUCCESS) { 10984 snprintf(problem, sizeof(problem), 10985 "no matching view '%s'", viewtxt); 10986 goto report; 10987 } 10988 10989 if (redirect) { 10990 if (view->redirect != NULL) { 10991 dns_zone_attach(view->redirect, zonep); 10992 result = ISC_R_SUCCESS; 10993 } else { 10994 result = ISC_R_NOTFOUND; 10995 } 10996 } else { 10997 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, 10998 zonep); 10999 } 11000 if (result != ISC_R_SUCCESS) { 11001 snprintf(problem, sizeof(problem), 11002 "no matching zone '%s' in view '%s'", zonebuf, 11003 viewtxt); 11004 } 11005 } 11006 11007 /* Partial match? */ 11008 if (result != ISC_R_SUCCESS && *zonep != NULL) { 11009 dns_zone_detach(zonep); 11010 } 11011 if (result == DNS_R_PARTIALMATCH) { 11012 result = ISC_R_NOTFOUND; 11013 } 11014 report: 11015 if (result != ISC_R_SUCCESS) { 11016 isc_result_t tresult; 11017 11018 tresult = putstr(text, problem); 11019 if (tresult == ISC_R_SUCCESS) { 11020 (void)putnull(text); 11021 } 11022 } 11023 11024 cleanup: 11025 if (view != NULL) { 11026 dns_view_detach(&view); 11027 } 11028 11029 return result; 11030 } 11031 11032 /* 11033 * Act on a "retransfer" command from the command channel. 11034 */ 11035 isc_result_t 11036 named_server_retransfercommand(named_server_t *server, isc_lex_t *lex, 11037 isc_buffer_t **text) { 11038 isc_result_t result; 11039 const char *arg = NULL; 11040 dns_zone_t *zone = NULL; 11041 dns_zone_t *raw = NULL; 11042 dns_zonetype_t type; 11043 bool force = false; 11044 11045 REQUIRE(text != NULL); 11046 11047 /* Skip the command name. */ 11048 (void)next_token(lex, text); 11049 11050 arg = next_token(lex, text); 11051 if (arg != NULL && (strcmp(arg, "-force") == 0)) { 11052 force = true; 11053 arg = next_token(lex, text); 11054 } 11055 11056 result = zone_from_args(server, lex, arg, &zone, NULL, text, false); 11057 if (result != ISC_R_SUCCESS) { 11058 return result; 11059 } 11060 if (zone == NULL) { 11061 return ISC_R_UNEXPECTEDEND; 11062 } 11063 dns_zone_getraw(zone, &raw); 11064 if (raw != NULL) { 11065 dns_zone_detach(&zone); 11066 dns_zone_attach(raw, &zone); 11067 dns_zone_detach(&raw); 11068 } 11069 type = dns_zone_gettype(zone); 11070 if (type == dns_zone_secondary || type == dns_zone_mirror || 11071 type == dns_zone_stub || 11072 (type == dns_zone_redirect && 11073 dns_zone_getredirecttype(zone) == dns_zone_secondary)) 11074 { 11075 if (force) { 11076 dns_zone_stopxfr(zone); 11077 } 11078 dns_zone_forcexfr(zone); 11079 } else { 11080 (void)putstr(text, "retransfer: inappropriate zone type: "); 11081 (void)putstr(text, dns_zonetype_name(type)); 11082 if (type == dns_zone_redirect) { 11083 type = dns_zone_getredirecttype(zone); 11084 (void)putstr(text, "("); 11085 (void)putstr(text, dns_zonetype_name(type)); 11086 (void)putstr(text, ")"); 11087 } 11088 (void)putnull(text); 11089 result = ISC_R_FAILURE; 11090 } 11091 dns_zone_detach(&zone); 11092 return result; 11093 } 11094 11095 /* 11096 * Act on a "reload" command from the command channel. 11097 */ 11098 isc_result_t 11099 named_server_reloadcommand(named_server_t *server, isc_lex_t *lex, 11100 isc_buffer_t **text) { 11101 isc_result_t result; 11102 dns_zone_t *zone = NULL; 11103 dns_zonetype_t type; 11104 const char *msg = NULL; 11105 11106 REQUIRE(text != NULL); 11107 11108 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11109 if (result != ISC_R_SUCCESS) { 11110 return result; 11111 } 11112 if (zone == NULL) { 11113 result = reload(server); 11114 if (result == ISC_R_SUCCESS) { 11115 msg = "server reload successful"; 11116 } 11117 } else { 11118 type = dns_zone_gettype(zone); 11119 if (type == dns_zone_secondary || type == dns_zone_mirror || 11120 type == dns_zone_stub) 11121 { 11122 dns_zone_refresh(zone); 11123 dns_zone_detach(&zone); 11124 msg = "zone refresh queued"; 11125 } else { 11126 result = dns_zone_load(zone, false); 11127 dns_zone_detach(&zone); 11128 switch (result) { 11129 case ISC_R_SUCCESS: 11130 msg = "zone reload successful"; 11131 break; 11132 case DNS_R_CONTINUE: 11133 msg = "zone reload queued"; 11134 result = ISC_R_SUCCESS; 11135 break; 11136 case DNS_R_UPTODATE: 11137 msg = "zone reload up-to-date"; 11138 result = ISC_R_SUCCESS; 11139 break; 11140 default: 11141 /* failure message will be generated by rndc */ 11142 break; 11143 } 11144 } 11145 } 11146 if (msg != NULL) { 11147 (void)putstr(text, msg); 11148 (void)putnull(text); 11149 } 11150 return result; 11151 } 11152 11153 /* 11154 * Act on a "reset-stats" command from the command channel. 11155 */ 11156 isc_result_t 11157 named_server_resetstatscommand(named_server_t *server, isc_lex_t *lex, 11158 isc_buffer_t **text) { 11159 const char *arg = NULL; 11160 bool recursive_high_water = false; 11161 bool tcp_high_water = false; 11162 11163 REQUIRE(text != NULL); 11164 11165 /* Skip the command name. */ 11166 (void)next_token(lex, text); 11167 11168 arg = next_token(lex, text); 11169 if (arg == NULL) { 11170 (void)putstr(text, "reset-stats: argument expected"); 11171 (void)putnull(text); 11172 return ISC_R_UNEXPECTEDEND; 11173 } 11174 while (arg != NULL) { 11175 if (strcmp(arg, "recursive-high-water") == 0) { 11176 recursive_high_water = true; 11177 } else if (strcmp(arg, "tcp-high-water") == 0) { 11178 tcp_high_water = true; 11179 } else { 11180 (void)putstr(text, "reset-stats: " 11181 "unrecognized argument: "); 11182 (void)putstr(text, arg); 11183 (void)putnull(text); 11184 return ISC_R_FAILURE; 11185 } 11186 arg = next_token(lex, text); 11187 } 11188 11189 if (recursive_high_water) { 11190 isc_stats_set(ns_stats_get(server->sctx->nsstats), 0, 11191 ns_statscounter_recurshighwater); 11192 } 11193 if (tcp_high_water) { 11194 isc_stats_set(ns_stats_get(server->sctx->nsstats), 0, 11195 ns_statscounter_tcphighwater); 11196 } 11197 11198 return ISC_R_SUCCESS; 11199 } 11200 11201 /* 11202 * Act on a "reconfig" command from the command channel. 11203 */ 11204 isc_result_t 11205 named_server_reconfigcommand(named_server_t *server) { 11206 isc_result_t result; 11207 atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 11208 11209 named_os_notify_systemd("RELOADING=1\n" 11210 "MONOTONIC_USEC=%" PRIu64 "\n" 11211 "STATUS=reconfig command received\n", 11212 (uint64_t)isc_time_monotonic() / NS_PER_US); 11213 11214 CHECK(loadconfig(server)); 11215 11216 result = load_zones(server, true); 11217 if (result == ISC_R_SUCCESS) { 11218 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11219 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11220 "scheduled loading new zones"); 11221 } else { 11222 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11223 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11224 "loading new zones failed: %s", 11225 isc_result_totext(result)); 11226 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 11227 } 11228 cleanup: 11229 named_os_notify_systemd("READY=1\n" 11230 "STATUS=reconfig command finished: %s\n", 11231 isc_result_totext(result)); 11232 11233 return result; 11234 } 11235 11236 /* 11237 * Act on a "notify" command from the command channel. 11238 */ 11239 isc_result_t 11240 named_server_notifycommand(named_server_t *server, isc_lex_t *lex, 11241 isc_buffer_t **text) { 11242 isc_result_t result; 11243 dns_zone_t *zone = NULL; 11244 const char msg[] = "zone notify queued"; 11245 11246 REQUIRE(text != NULL); 11247 11248 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11249 if (result != ISC_R_SUCCESS) { 11250 return result; 11251 } 11252 if (zone == NULL) { 11253 return ISC_R_UNEXPECTEDEND; 11254 } 11255 11256 dns_zone_notify(zone, true); 11257 dns_zone_detach(&zone); 11258 (void)putstr(text, msg); 11259 (void)putnull(text); 11260 11261 return ISC_R_SUCCESS; 11262 } 11263 11264 /* 11265 * Act on a "refresh" command from the command channel. 11266 */ 11267 isc_result_t 11268 named_server_refreshcommand(named_server_t *server, isc_lex_t *lex, 11269 isc_buffer_t **text) { 11270 isc_result_t result; 11271 dns_zone_t *zone = NULL, *raw = NULL; 11272 const char msg1[] = "zone refresh queued"; 11273 const char msg2[] = "not a secondary, mirror, or stub zone"; 11274 dns_zonetype_t type; 11275 11276 REQUIRE(text != NULL); 11277 11278 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11279 if (result != ISC_R_SUCCESS) { 11280 return result; 11281 } 11282 if (zone == NULL) { 11283 return ISC_R_UNEXPECTEDEND; 11284 } 11285 11286 dns_zone_getraw(zone, &raw); 11287 if (raw != NULL) { 11288 dns_zone_detach(&zone); 11289 dns_zone_attach(raw, &zone); 11290 dns_zone_detach(&raw); 11291 } 11292 11293 type = dns_zone_gettype(zone); 11294 if (type == dns_zone_secondary || type == dns_zone_mirror || 11295 type == dns_zone_stub) 11296 { 11297 dns_zone_refresh(zone); 11298 dns_zone_detach(&zone); 11299 (void)putstr(text, msg1); 11300 (void)putnull(text); 11301 return ISC_R_SUCCESS; 11302 } 11303 11304 dns_zone_detach(&zone); 11305 (void)putstr(text, msg2); 11306 (void)putnull(text); 11307 return ISC_R_FAILURE; 11308 } 11309 11310 isc_result_t 11311 named_server_setortoggle(named_server_t *server, const char *optname, 11312 unsigned int option, isc_lex_t *lex) { 11313 bool prev, value; 11314 char *ptr = NULL; 11315 11316 /* Skip the command name. */ 11317 ptr = next_token(lex, NULL); 11318 if (ptr == NULL) { 11319 return ISC_R_UNEXPECTEDEND; 11320 } 11321 11322 prev = ns_server_getoption(server->sctx, option); 11323 11324 ptr = next_token(lex, NULL); 11325 if (ptr == NULL) { 11326 value = !prev; 11327 } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 11328 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 11329 { 11330 value = true; 11331 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 11332 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 11333 { 11334 value = false; 11335 } else { 11336 return DNS_R_SYNTAX; 11337 } 11338 11339 if (value == prev) { 11340 return ISC_R_SUCCESS; 11341 } 11342 11343 ns_server_setoption(server->sctx, option, value); 11344 11345 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11346 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "%s is now %s", 11347 optname, value ? "on" : "off"); 11348 return ISC_R_SUCCESS; 11349 } 11350 11351 static isc_result_t 11352 listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 11353 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 11354 isc_tlsctx_cache_t *tlsctx_cache, 11355 ns_listenlist_t **target) { 11356 isc_result_t result; 11357 const cfg_listelt_t *element; 11358 ns_listenlist_t *dlist = NULL; 11359 11360 REQUIRE(target != NULL && *target == NULL); 11361 11362 result = ns_listenlist_create(mctx, &dlist); 11363 if (result != ISC_R_SUCCESS) { 11364 return result; 11365 } 11366 11367 for (element = cfg_list_first(listenlist); element != NULL; 11368 element = cfg_list_next(element)) 11369 { 11370 ns_listenelt_t *delt = NULL; 11371 const cfg_obj_t *listener = cfg_listelt_value(element); 11372 result = listenelt_fromconfig(listener, config, actx, mctx, 11373 family, tlsctx_cache, &delt); 11374 if (result != ISC_R_SUCCESS) { 11375 goto cleanup; 11376 } 11377 ISC_LIST_APPEND(dlist->elts, delt, link); 11378 } 11379 *target = dlist; 11380 return ISC_R_SUCCESS; 11381 11382 cleanup: 11383 ns_listenlist_detach(&dlist); 11384 return result; 11385 } 11386 11387 static const cfg_obj_t * 11388 find_maplist(const cfg_obj_t *config, const char *listname, const char *name) { 11389 isc_result_t result; 11390 const cfg_obj_t *maplist = NULL; 11391 const cfg_listelt_t *elt = NULL; 11392 11393 REQUIRE(config != NULL); 11394 REQUIRE(name != NULL); 11395 11396 result = cfg_map_get(config, listname, &maplist); 11397 if (result != ISC_R_SUCCESS) { 11398 return NULL; 11399 } 11400 11401 for (elt = cfg_list_first(maplist); elt != NULL; 11402 elt = cfg_list_next(elt)) 11403 { 11404 const cfg_obj_t *map = cfg_listelt_value(elt); 11405 if (strcasecmp(cfg_obj_asstring(cfg_map_getname(map)), name) == 11406 0) 11407 { 11408 return map; 11409 } 11410 } 11411 11412 return NULL; 11413 } 11414 11415 /* 11416 * Create a listen list from the corresponding configuration 11417 * data structure. 11418 */ 11419 static isc_result_t 11420 listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 11421 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 11422 isc_tlsctx_cache_t *tlsctx_cache, 11423 ns_listenelt_t **target) { 11424 isc_result_t result; 11425 const cfg_obj_t *ltup = NULL; 11426 const cfg_obj_t *tlsobj = NULL, *httpobj = NULL; 11427 const cfg_obj_t *portobj = NULL; 11428 const cfg_obj_t *http_server = NULL; 11429 const cfg_obj_t *proxyobj = NULL; 11430 in_port_t port = 0; 11431 const char *key = NULL, *cert = NULL, *ca_file = NULL, 11432 *dhparam_file = NULL, *ciphers = NULL, *cipher_suites = NULL; 11433 bool tls_prefer_server_ciphers = false, 11434 tls_prefer_server_ciphers_set = false; 11435 bool tls_session_tickets = false, tls_session_tickets_set = false; 11436 bool do_tls = false, no_tls = false, http = false; 11437 ns_listenelt_t *delt = NULL; 11438 uint32_t tls_protos = 0; 11439 ns_listen_tls_params_t tls_params = { 0 }; 11440 const char *tlsname = NULL; 11441 isc_nm_proxy_type_t proxy = ISC_NM_PROXY_NONE; 11442 11443 REQUIRE(target != NULL && *target == NULL); 11444 11445 ltup = cfg_tuple_get(listener, "tuple"); 11446 RUNTIME_CHECK(ltup != NULL); 11447 11448 tlsobj = cfg_tuple_get(ltup, "tls"); 11449 if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) { 11450 tlsname = cfg_obj_asstring(tlsobj); 11451 11452 if (strcasecmp(tlsname, "none") == 0) { 11453 no_tls = true; 11454 } else if (strcasecmp(tlsname, "ephemeral") == 0) { 11455 do_tls = true; 11456 } else { 11457 const cfg_obj_t *keyobj = NULL, *certobj = NULL, 11458 *ca_obj = NULL, *dhparam_obj = NULL; 11459 const cfg_obj_t *tlsmap = NULL; 11460 const cfg_obj_t *tls_proto_list = NULL; 11461 const cfg_obj_t *ciphers_obj = NULL; 11462 const cfg_obj_t *cipher_suites_obj = NULL; 11463 const cfg_obj_t *prefer_server_ciphers_obj = NULL; 11464 const cfg_obj_t *session_tickets_obj = NULL; 11465 11466 do_tls = true; 11467 11468 tlsmap = find_maplist(config, "tls", tlsname); 11469 if (tlsmap == NULL) { 11470 cfg_obj_log(tlsobj, named_g_lctx, ISC_LOG_ERROR, 11471 "tls '%s' is not defined", 11472 cfg_obj_asstring(tlsobj)); 11473 return ISC_R_FAILURE; 11474 } 11475 11476 CHECK(cfg_map_get(tlsmap, "key-file", &keyobj)); 11477 key = cfg_obj_asstring(keyobj); 11478 11479 CHECK(cfg_map_get(tlsmap, "cert-file", &certobj)); 11480 cert = cfg_obj_asstring(certobj); 11481 11482 if (cfg_map_get(tlsmap, "ca-file", &ca_obj) == 11483 ISC_R_SUCCESS) 11484 { 11485 ca_file = cfg_obj_asstring(ca_obj); 11486 } 11487 11488 if (cfg_map_get(tlsmap, "protocols", &tls_proto_list) == 11489 ISC_R_SUCCESS) 11490 { 11491 const cfg_listelt_t *proto = NULL; 11492 INSIST(tls_proto_list != NULL); 11493 for (proto = cfg_list_first(tls_proto_list); 11494 proto != 0; proto = cfg_list_next(proto)) 11495 { 11496 const cfg_obj_t *tls_proto_obj = 11497 cfg_listelt_value(proto); 11498 const char *tls_sver = 11499 cfg_obj_asstring(tls_proto_obj); 11500 const isc_tls_protocol_version_t ver = 11501 isc_tls_protocol_name_to_version( 11502 tls_sver); 11503 11504 INSIST(ver != 11505 ISC_TLS_PROTO_VER_UNDEFINED); 11506 INSIST(isc_tls_protocol_supported(ver)); 11507 tls_protos |= ver; 11508 } 11509 } 11510 11511 if (cfg_map_get(tlsmap, "dhparam-file", &dhparam_obj) == 11512 ISC_R_SUCCESS) 11513 { 11514 dhparam_file = cfg_obj_asstring(dhparam_obj); 11515 } 11516 11517 if (cfg_map_get(tlsmap, "ciphers", &ciphers_obj) == 11518 ISC_R_SUCCESS) 11519 { 11520 ciphers = cfg_obj_asstring(ciphers_obj); 11521 } 11522 11523 if (cfg_map_get(tlsmap, "cipher-suites", 11524 &cipher_suites_obj) == ISC_R_SUCCESS) 11525 { 11526 cipher_suites = 11527 cfg_obj_asstring(cipher_suites_obj); 11528 } 11529 11530 if (cfg_map_get(tlsmap, "prefer-server-ciphers", 11531 &prefer_server_ciphers_obj) == 11532 ISC_R_SUCCESS) 11533 { 11534 tls_prefer_server_ciphers = cfg_obj_asboolean( 11535 prefer_server_ciphers_obj); 11536 tls_prefer_server_ciphers_set = true; 11537 } 11538 11539 if (cfg_map_get(tlsmap, "session-tickets", 11540 &session_tickets_obj) == ISC_R_SUCCESS) 11541 { 11542 tls_session_tickets = 11543 cfg_obj_asboolean(session_tickets_obj); 11544 tls_session_tickets_set = true; 11545 } 11546 } 11547 } 11548 11549 tls_params = (ns_listen_tls_params_t){ 11550 .name = tlsname, 11551 .key = key, 11552 .cert = cert, 11553 .ca_file = ca_file, 11554 .protocols = tls_protos, 11555 .dhparam_file = dhparam_file, 11556 .ciphers = ciphers, 11557 .cipher_suites = cipher_suites, 11558 .prefer_server_ciphers = tls_prefer_server_ciphers, 11559 .prefer_server_ciphers_set = tls_prefer_server_ciphers_set, 11560 .session_tickets = tls_session_tickets, 11561 .session_tickets_set = tls_session_tickets_set 11562 }; 11563 11564 httpobj = cfg_tuple_get(ltup, "http"); 11565 if (httpobj != NULL && cfg_obj_isstring(httpobj)) { 11566 const char *httpname = cfg_obj_asstring(httpobj); 11567 11568 if (!do_tls && !no_tls) { 11569 return ISC_R_FAILURE; 11570 } 11571 11572 http_server = find_maplist(config, "http", httpname); 11573 if (http_server == NULL && strcasecmp(httpname, "default") != 0) 11574 { 11575 cfg_obj_log(httpobj, named_g_lctx, ISC_LOG_ERROR, 11576 "http '%s' is not defined", 11577 cfg_obj_asstring(httpobj)); 11578 return ISC_R_FAILURE; 11579 } 11580 11581 http = true; 11582 } 11583 11584 portobj = cfg_tuple_get(ltup, "port"); 11585 if (!cfg_obj_isuint32(portobj)) { 11586 if (http && do_tls) { 11587 if (named_g_httpsport != 0) { 11588 port = named_g_httpsport; 11589 } else { 11590 result = named_config_getport( 11591 config, "https-port", &port); 11592 if (result != ISC_R_SUCCESS) { 11593 return result; 11594 } 11595 } 11596 } else if (http && !do_tls) { 11597 if (named_g_httpport != 0) { 11598 port = named_g_httpport; 11599 } else { 11600 result = named_config_getport( 11601 config, "http-port", &port); 11602 if (result != ISC_R_SUCCESS) { 11603 return result; 11604 } 11605 } 11606 } else if (do_tls) { 11607 if (named_g_tlsport != 0) { 11608 port = named_g_tlsport; 11609 } else { 11610 result = named_config_getport( 11611 config, "tls-port", &port); 11612 if (result != ISC_R_SUCCESS) { 11613 return result; 11614 } 11615 } 11616 } else { 11617 if (named_g_port != 0) { 11618 port = named_g_port; 11619 } else { 11620 result = named_config_getport(config, "port", 11621 &port); 11622 if (result != ISC_R_SUCCESS) { 11623 return result; 11624 } 11625 } 11626 } 11627 } else { 11628 if (cfg_obj_asuint32(portobj) >= UINT16_MAX) { 11629 return ISC_R_RANGE; 11630 } 11631 port = (in_port_t)cfg_obj_asuint32(portobj); 11632 } 11633 11634 proxyobj = cfg_tuple_get(ltup, "proxy"); 11635 if (proxyobj != NULL && cfg_obj_isstring(proxyobj)) { 11636 const char *proxyval = cfg_obj_asstring(proxyobj); 11637 11638 if (strcasecmp(proxyval, "encrypted") == 0) { 11639 INSIST(do_tls == true); 11640 proxy = ISC_NM_PROXY_ENCRYPTED; 11641 } else if (strcasecmp(proxyval, "plain") == 0) { 11642 proxy = ISC_NM_PROXY_PLAIN; 11643 } else { 11644 UNREACHABLE(); 11645 } 11646 } 11647 11648 #ifdef HAVE_LIBNGHTTP2 11649 if (http) { 11650 CHECK(listenelt_http(http_server, family, do_tls, &tls_params, 11651 tlsctx_cache, port, mctx, proxy, &delt)); 11652 } 11653 #endif /* HAVE_LIBNGHTTP2 */ 11654 11655 if (!http) { 11656 CHECK(ns_listenelt_create(mctx, port, NULL, family, do_tls, 11657 &tls_params, tlsctx_cache, proxy, 11658 &delt)); 11659 } 11660 11661 result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"), config, 11662 named_g_lctx, actx, mctx, family, 11663 &delt->acl); 11664 if (result != ISC_R_SUCCESS) { 11665 ns_listenelt_destroy(delt); 11666 return result; 11667 } 11668 *target = delt; 11669 11670 cleanup: 11671 return result; 11672 } 11673 11674 #ifdef HAVE_LIBNGHTTP2 11675 static isc_result_t 11676 listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, 11677 const ns_listen_tls_params_t *tls_params, 11678 isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, 11679 isc_mem_t *mctx, isc_nm_proxy_type_t proxy, 11680 ns_listenelt_t **target) { 11681 isc_result_t result = ISC_R_SUCCESS; 11682 ns_listenelt_t *delt = NULL; 11683 char **endpoints = NULL; 11684 const cfg_obj_t *eplist = NULL; 11685 const cfg_listelt_t *elt = NULL; 11686 size_t len = 1, i = 0; 11687 uint32_t max_clients = named_g_http_listener_clients; 11688 uint32_t max_streams = named_g_http_streams_per_conn; 11689 11690 REQUIRE(target != NULL && *target == NULL); 11691 11692 if (tls) { 11693 INSIST(tls_params != NULL); 11694 INSIST((tls_params->key == NULL) == (tls_params->cert == NULL)); 11695 } 11696 11697 if (port == 0) { 11698 port = tls ? named_g_httpsport : named_g_httpport; 11699 } 11700 11701 /* 11702 * If "default" was used, we set up the default endpoint 11703 * of "/dns-query". 11704 */ 11705 if (http != NULL) { 11706 const cfg_obj_t *cfg_max_clients = NULL; 11707 const cfg_obj_t *cfg_max_streams = NULL; 11708 11709 if (cfg_map_get(http, "endpoints", &eplist) == ISC_R_SUCCESS) { 11710 INSIST(eplist != NULL); 11711 len = cfg_list_length(eplist, false); 11712 } 11713 11714 if (cfg_map_get(http, "listener-clients", &cfg_max_clients) == 11715 ISC_R_SUCCESS) 11716 { 11717 INSIST(cfg_max_clients != NULL); 11718 max_clients = cfg_obj_asuint32(cfg_max_clients); 11719 } 11720 11721 if (cfg_map_get(http, "streams-per-connection", 11722 &cfg_max_streams) == ISC_R_SUCCESS) 11723 { 11724 INSIST(cfg_max_streams != NULL); 11725 max_streams = cfg_obj_asuint32(cfg_max_streams); 11726 } 11727 } 11728 11729 endpoints = isc_mem_allocate(mctx, sizeof(endpoints[0]) * len); 11730 11731 if (http != NULL && eplist != NULL) { 11732 for (elt = cfg_list_first(eplist); elt != NULL; 11733 elt = cfg_list_next(elt)) 11734 { 11735 const cfg_obj_t *ep = cfg_listelt_value(elt); 11736 const char *path = cfg_obj_asstring(ep); 11737 endpoints[i++] = isc_mem_strdup(mctx, path); 11738 } 11739 } else { 11740 endpoints[i++] = isc_mem_strdup(mctx, ISC_NM_HTTP_DEFAULT_PATH); 11741 } 11742 11743 INSIST(i == len); 11744 11745 result = ns_listenelt_create_http( 11746 mctx, port, NULL, family, tls, tls_params, tlsctx_cache, proxy, 11747 endpoints, len, max_clients, max_streams, &delt); 11748 if (result != ISC_R_SUCCESS) { 11749 goto error; 11750 } 11751 11752 *target = delt; 11753 11754 return result; 11755 error: 11756 if (delt != NULL) { 11757 ns_listenelt_destroy(delt); 11758 } 11759 return result; 11760 } 11761 #endif /* HAVE_LIBNGHTTP2 */ 11762 11763 isc_result_t 11764 named_server_dumpstats(named_server_t *server) { 11765 isc_result_t result; 11766 FILE *fp = NULL; 11767 11768 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), 11769 "could not open statistics dump file", server->statsfile); 11770 11771 result = named_stats_dump(server, fp); 11772 11773 cleanup: 11774 if (fp != NULL) { 11775 (void)isc_stdio_close(fp); 11776 } 11777 if (result == ISC_R_SUCCESS) { 11778 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11779 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11780 "dumpstats complete"); 11781 } else { 11782 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11783 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11784 "dumpstats failed: %s", 11785 isc_result_totext(result)); 11786 } 11787 return result; 11788 } 11789 11790 static isc_result_t 11791 add_zone_tolist(dns_zone_t *zone, void *uap) { 11792 struct dumpcontext *dctx = uap; 11793 struct zonelistentry *zle; 11794 11795 zle = isc_mem_get(dctx->mctx, sizeof *zle); 11796 zle->zone = NULL; 11797 dns_zone_attach(zone, &zle->zone); 11798 ISC_LINK_INIT(zle, link); 11799 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); 11800 return ISC_R_SUCCESS; 11801 } 11802 11803 static isc_result_t 11804 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { 11805 struct viewlistentry *vle; 11806 isc_result_t result = ISC_R_SUCCESS; 11807 11808 /* 11809 * Prevent duplicate views. 11810 */ 11811 for (vle = ISC_LIST_HEAD(dctx->viewlist); vle != NULL; 11812 vle = ISC_LIST_NEXT(vle, link)) 11813 { 11814 if (vle->view == view) { 11815 return ISC_R_SUCCESS; 11816 } 11817 } 11818 11819 vle = isc_mem_get(dctx->mctx, sizeof *vle); 11820 vle->view = NULL; 11821 dns_view_attach(view, &vle->view); 11822 ISC_LINK_INIT(vle, link); 11823 ISC_LIST_INIT(vle->zonelist); 11824 ISC_LIST_APPEND(dctx->viewlist, vle, link); 11825 if (dctx->dumpzones) { 11826 result = dns_view_apply(view, true, NULL, add_zone_tolist, 11827 dctx); 11828 } 11829 return result; 11830 } 11831 11832 static void 11833 dumpcontext_destroy(struct dumpcontext *dctx) { 11834 struct viewlistentry *vle; 11835 struct zonelistentry *zle; 11836 11837 vle = ISC_LIST_HEAD(dctx->viewlist); 11838 while (vle != NULL) { 11839 ISC_LIST_UNLINK(dctx->viewlist, vle, link); 11840 zle = ISC_LIST_HEAD(vle->zonelist); 11841 while (zle != NULL) { 11842 ISC_LIST_UNLINK(vle->zonelist, zle, link); 11843 dns_zone_detach(&zle->zone); 11844 isc_mem_put(dctx->mctx, zle, sizeof *zle); 11845 zle = ISC_LIST_HEAD(vle->zonelist); 11846 } 11847 dns_view_detach(&vle->view); 11848 isc_mem_put(dctx->mctx, vle, sizeof *vle); 11849 vle = ISC_LIST_HEAD(dctx->viewlist); 11850 } 11851 if (dctx->version != NULL) { 11852 dns_db_closeversion(dctx->db, &dctx->version, false); 11853 } 11854 if (dctx->db != NULL) { 11855 dns_db_detach(&dctx->db); 11856 } 11857 if (dctx->cache != NULL) { 11858 dns_db_detach(&dctx->cache); 11859 } 11860 if (dctx->fp != NULL) { 11861 (void)isc_stdio_close(dctx->fp); 11862 } 11863 if (dctx->mdctx != NULL) { 11864 dns_dumpctx_detach(&dctx->mdctx); 11865 } 11866 isc_mem_put(dctx->mctx, dctx, sizeof *dctx); 11867 } 11868 11869 static void 11870 dumpdone(void *arg, isc_result_t result) { 11871 struct dumpcontext *dctx = arg; 11872 char buf[1024 + 32]; 11873 const dns_master_style_t *style; 11874 11875 if (result != ISC_R_SUCCESS) { 11876 goto cleanup; 11877 } 11878 if (dctx->mdctx != NULL) { 11879 dns_dumpctx_detach(&dctx->mdctx); 11880 } 11881 if (dctx->view == NULL) { 11882 dctx->view = ISC_LIST_HEAD(dctx->viewlist); 11883 if (dctx->view == NULL) { 11884 goto done; 11885 } 11886 INSIST(dctx->zone == NULL); 11887 } else { 11888 goto resume; 11889 } 11890 nextview: 11891 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); 11892 resume: 11893 if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { 11894 fprintf(dctx->fp, ";\n; Cache of view '%s' is shared as '%s'\n", 11895 dctx->view->view->name, 11896 dns_cache_getname(dctx->view->view->cache)); 11897 } else if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) 11898 { 11899 if (dctx->dumpexpired) { 11900 style = &dns_master_style_cache_with_expired; 11901 } else { 11902 style = &dns_master_style_cache; 11903 } 11904 /* start cache dump */ 11905 if (dctx->view->view->cachedb != NULL) { 11906 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 11907 } 11908 if (dctx->cache != NULL) { 11909 fprintf(dctx->fp, 11910 ";\n; Cache dump of view '%s' (cache %s)\n;\n", 11911 dctx->view->view->name, 11912 dns_cache_getname(dctx->view->view->cache)); 11913 result = dns_master_dumptostreamasync( 11914 dctx->mctx, dctx->cache, NULL, style, dctx->fp, 11915 named_g_mainloop, dumpdone, dctx, &dctx->mdctx); 11916 if (result == ISC_R_SUCCESS) { 11917 return; 11918 } 11919 if (result == ISC_R_NOTIMPLEMENTED) { 11920 fprintf(dctx->fp, "; %s\n", 11921 isc_result_totext(result)); 11922 } else if (result != ISC_R_SUCCESS) { 11923 goto cleanup; 11924 } 11925 } 11926 } 11927 11928 if ((dctx->dumpadb || dctx->dumpfail) && dctx->cache == NULL && 11929 dctx->view->view->cachedb != NULL) 11930 { 11931 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 11932 } 11933 11934 if (dctx->cache != NULL) { 11935 if (dctx->dumpadb) { 11936 dns_adb_t *adb = NULL; 11937 dns_view_getadb(dctx->view->view, &adb); 11938 if (adb != NULL) { 11939 dns_adb_dump(adb, dctx->fp); 11940 dns_adb_detach(&adb); 11941 } 11942 } 11943 if (dctx->dumpfail) { 11944 dns_badcache_print(dctx->view->view->failcache, 11945 "SERVFAIL cache", dctx->fp); 11946 } 11947 dns_db_detach(&dctx->cache); 11948 } 11949 if (dctx->dumpzones) { 11950 style = &dns_master_style_full; 11951 nextzone: 11952 if (dctx->version != NULL) { 11953 dns_db_closeversion(dctx->db, &dctx->version, false); 11954 } 11955 if (dctx->db != NULL) { 11956 dns_db_detach(&dctx->db); 11957 } 11958 if (dctx->zone == NULL) { 11959 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); 11960 } else { 11961 dctx->zone = ISC_LIST_NEXT(dctx->zone, link); 11962 } 11963 if (dctx->zone != NULL) { 11964 /* start zone dump */ 11965 dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); 11966 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); 11967 result = dns_zone_getdb(dctx->zone->zone, &dctx->db); 11968 if (result != ISC_R_SUCCESS) { 11969 fprintf(dctx->fp, "; %s\n", 11970 isc_result_totext(result)); 11971 goto nextzone; 11972 } 11973 dns_db_currentversion(dctx->db, &dctx->version); 11974 result = dns_master_dumptostreamasync( 11975 dctx->mctx, dctx->db, dctx->version, style, 11976 dctx->fp, dns_zone_getloop(dctx->zone->zone), 11977 dumpdone, dctx, &dctx->mdctx); 11978 if (result == ISC_R_SUCCESS) { 11979 return; 11980 } 11981 if (result == ISC_R_NOTIMPLEMENTED) { 11982 fprintf(dctx->fp, "; %s\n", 11983 isc_result_totext(result)); 11984 result = ISC_R_SUCCESS; 11985 POST(result); 11986 goto nextzone; 11987 } 11988 if (result != ISC_R_SUCCESS) { 11989 goto cleanup; 11990 } 11991 } 11992 } 11993 if (dctx->view != NULL) { 11994 dctx->view = ISC_LIST_NEXT(dctx->view, link); 11995 if (dctx->view != NULL) { 11996 goto nextview; 11997 } 11998 } 11999 done: 12000 fprintf(dctx->fp, "; Dump complete\n"); 12001 result = isc_stdio_flush(dctx->fp); 12002 if (result == ISC_R_SUCCESS) { 12003 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12004 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12005 "dumpdb complete"); 12006 } 12007 cleanup: 12008 if (result != ISC_R_SUCCESS) { 12009 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12010 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12011 "dumpdb failed: %s", isc_result_totext(result)); 12012 } 12013 dumpcontext_destroy(dctx); 12014 } 12015 12016 isc_result_t 12017 named_server_dumpdb(named_server_t *server, isc_lex_t *lex, 12018 isc_buffer_t **text) { 12019 struct dumpcontext *dctx = NULL; 12020 dns_view_t *view; 12021 isc_result_t result; 12022 char *ptr; 12023 const char *sep; 12024 bool found; 12025 12026 REQUIRE(text != NULL); 12027 12028 /* Skip the command name. */ 12029 ptr = next_token(lex, NULL); 12030 if (ptr == NULL) { 12031 return ISC_R_UNEXPECTEDEND; 12032 } 12033 12034 dctx = isc_mem_get(server->mctx, sizeof(*dctx)); 12035 *dctx = (struct dumpcontext){ 12036 .mctx = server->mctx, 12037 .dumpcache = true, 12038 .dumpadb = true, 12039 .dumpfail = true, 12040 .viewlist = ISC_LIST_INITIALIZER, 12041 }; 12042 12043 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), 12044 "could not open dump file", server->dumpfile); 12045 12046 ptr = next_token(lex, NULL); 12047 sep = (ptr == NULL) ? "" : ": "; 12048 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12049 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12050 "dumpdb started%s%s", sep, (ptr != NULL) ? ptr : ""); 12051 12052 if (ptr != NULL && strcmp(ptr, "-all") == 0) { 12053 /* also dump zones */ 12054 dctx->dumpzones = true; 12055 ptr = next_token(lex, NULL); 12056 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { 12057 /* this is the default */ 12058 ptr = next_token(lex, NULL); 12059 } else if (ptr != NULL && strcmp(ptr, "-expired") == 0) { 12060 /* this is the same as -cache but includes expired data */ 12061 dctx->dumpexpired = true; 12062 ptr = next_token(lex, NULL); 12063 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { 12064 /* only dump zones, suppress caches */ 12065 dctx->dumpadb = false; 12066 dctx->dumpcache = false; 12067 dctx->dumpfail = false; 12068 dctx->dumpzones = true; 12069 ptr = next_token(lex, NULL); 12070 } else if (ptr != NULL && strcmp(ptr, "-adb") == 0) { 12071 /* only dump adb, suppress other caches */ 12072 dctx->dumpcache = false; 12073 dctx->dumpfail = false; 12074 ptr = next_token(lex, NULL); 12075 } else if (ptr != NULL && strcmp(ptr, "-bad") == 0) { 12076 /* only dump badcache, suppress other caches */ 12077 dctx->dumpadb = false; 12078 dctx->dumpcache = false; 12079 dctx->dumpfail = false; 12080 ptr = next_token(lex, NULL); 12081 } else if (ptr != NULL && strcmp(ptr, "-fail") == 0) { 12082 /* only dump servfail cache, suppress other caches */ 12083 dctx->dumpadb = false; 12084 dctx->dumpcache = false; 12085 ptr = next_token(lex, NULL); 12086 } 12087 12088 nextview: 12089 found = false; 12090 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12091 view = ISC_LIST_NEXT(view, link)) 12092 { 12093 if (ptr != NULL && strcmp(view->name, ptr) != 0) { 12094 continue; 12095 } 12096 found = true; 12097 CHECK(add_view_tolist(dctx, view)); 12098 } 12099 if (ptr != NULL) { 12100 if (!found) { 12101 CHECK(putstr(text, "view '")); 12102 CHECK(putstr(text, ptr)); 12103 CHECK(putstr(text, "' not found")); 12104 CHECK(putnull(text)); 12105 result = ISC_R_NOTFOUND; 12106 dumpdone(dctx, result); 12107 return result; 12108 } 12109 ptr = next_token(lex, NULL); 12110 if (ptr != NULL) { 12111 goto nextview; 12112 } 12113 } 12114 dumpdone(dctx, ISC_R_SUCCESS); 12115 return ISC_R_SUCCESS; 12116 12117 cleanup: 12118 dumpcontext_destroy(dctx); 12119 return result; 12120 } 12121 12122 isc_result_t 12123 named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex, 12124 isc_buffer_t **text) { 12125 dns_view_t *view; 12126 dns_keytable_t *secroots = NULL; 12127 dns_ntatable_t *ntatable = NULL; 12128 isc_result_t result; 12129 char *ptr; 12130 FILE *fp = NULL; 12131 isc_time_t now; 12132 char tbuf[64]; 12133 unsigned int used = isc_buffer_usedlength(*text); 12134 bool first = true; 12135 12136 REQUIRE(text != NULL); 12137 12138 /* Skip the command name. */ 12139 ptr = next_token(lex, text); 12140 if (ptr == NULL) { 12141 return ISC_R_UNEXPECTEDEND; 12142 } 12143 12144 /* "-" here means print the output instead of dumping to file */ 12145 ptr = next_token(lex, text); 12146 if (ptr != NULL && strcmp(ptr, "-") == 0) { 12147 ptr = next_token(lex, text); 12148 } else { 12149 result = isc_stdio_open(server->secrootsfile, "w", &fp); 12150 if (result != ISC_R_SUCCESS) { 12151 (void)putstr(text, "could not open "); 12152 (void)putstr(text, server->secrootsfile); 12153 CHECKMF(result, "could not open secroots dump file", 12154 server->secrootsfile); 12155 } 12156 } 12157 12158 now = isc_time_now(); 12159 isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); 12160 CHECK(putstr(text, "secure roots as of ")); 12161 CHECK(putstr(text, tbuf)); 12162 CHECK(putstr(text, ":\n")); 12163 used = isc_buffer_usedlength(*text); 12164 12165 do { 12166 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12167 view = ISC_LIST_NEXT(view, link)) 12168 { 12169 if (ptr != NULL && strcmp(view->name, ptr) != 0) { 12170 continue; 12171 } 12172 if (secroots != NULL) { 12173 dns_keytable_detach(&secroots); 12174 } 12175 result = dns_view_getsecroots(view, &secroots); 12176 if (result == ISC_R_NOTFOUND) { 12177 result = ISC_R_SUCCESS; 12178 continue; 12179 } 12180 if (first || used != isc_buffer_usedlength(*text)) { 12181 CHECK(putstr(text, "\n")); 12182 first = false; 12183 } 12184 CHECK(putstr(text, " Start view ")); 12185 CHECK(putstr(text, view->name)); 12186 CHECK(putstr(text, "\n Secure roots:\n\n")); 12187 used = isc_buffer_usedlength(*text); 12188 CHECK(dns_keytable_totext(secroots, text)); 12189 12190 if (ntatable != NULL) { 12191 dns_ntatable_detach(&ntatable); 12192 } 12193 result = dns_view_getntatable(view, &ntatable); 12194 if (result == ISC_R_NOTFOUND) { 12195 result = ISC_R_SUCCESS; 12196 continue; 12197 } 12198 if (used != isc_buffer_usedlength(*text)) { 12199 CHECK(putstr(text, "\n")); 12200 } 12201 CHECK(putstr(text, " Negative trust anchors:\n\n")); 12202 used = isc_buffer_usedlength(*text); 12203 CHECK(dns_ntatable_totext(ntatable, NULL, text)); 12204 } 12205 12206 if (ptr != NULL) { 12207 ptr = next_token(lex, text); 12208 } 12209 } while (ptr != NULL); 12210 12211 cleanup: 12212 if (secroots != NULL) { 12213 dns_keytable_detach(&secroots); 12214 } 12215 if (ntatable != NULL) { 12216 dns_ntatable_detach(&ntatable); 12217 } 12218 12219 if (fp != NULL) { 12220 if (used != isc_buffer_usedlength(*text)) { 12221 (void)putstr(text, "\n"); 12222 } 12223 fprintf(fp, "%.*s", (int)isc_buffer_usedlength(*text), 12224 (char *)isc_buffer_base(*text)); 12225 isc_buffer_clear(*text); 12226 (void)isc_stdio_close(fp); 12227 } else if (isc_buffer_usedlength(*text) > 0) { 12228 (void)putnull(text); 12229 } 12230 12231 if (result == ISC_R_SUCCESS) { 12232 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12233 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12234 "dumpsecroots complete"); 12235 } else { 12236 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12237 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12238 "dumpsecroots failed: %s", 12239 isc_result_totext(result)); 12240 } 12241 return result; 12242 } 12243 12244 isc_result_t 12245 named_server_dumprecursing(named_server_t *server) { 12246 FILE *fp = NULL; 12247 dns_view_t *view; 12248 isc_result_t result; 12249 12250 CHECKMF(isc_stdio_open(server->recfile, "w", &fp), 12251 "could not open dump file", server->recfile); 12252 fprintf(fp, ";\n; Recursing Queries\n;\n"); 12253 ns_interfacemgr_dumprecursing(fp, server->interfacemgr); 12254 12255 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12256 view = ISC_LIST_NEXT(view, link)) 12257 { 12258 fprintf(fp, ";\n; Active fetch domains [view: %s]\n;\n", 12259 view->name); 12260 dns_resolver_dumpfetches(view->resolver, isc_statsformat_file, 12261 fp); 12262 } 12263 12264 fprintf(fp, "; Dump complete\n"); 12265 12266 cleanup: 12267 if (fp != NULL) { 12268 result = isc_stdio_close(fp); 12269 } 12270 if (result == ISC_R_SUCCESS) { 12271 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12272 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12273 "dumprecursing complete"); 12274 } else { 12275 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12276 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12277 "dumprecursing failed: %s", 12278 isc_result_totext(result)); 12279 } 12280 return result; 12281 } 12282 12283 isc_result_t 12284 named_server_setdebuglevel(named_server_t *server, isc_lex_t *lex) { 12285 char *ptr; 12286 char *endp; 12287 long newlevel; 12288 12289 UNUSED(server); 12290 12291 /* Skip the command name. */ 12292 ptr = next_token(lex, NULL); 12293 if (ptr == NULL) { 12294 return ISC_R_UNEXPECTEDEND; 12295 } 12296 12297 /* Look for the new level name. */ 12298 ptr = next_token(lex, NULL); 12299 if (ptr == NULL) { 12300 if (named_g_debuglevel < 99) { 12301 named_g_debuglevel++; 12302 } 12303 } else { 12304 newlevel = strtol(ptr, &endp, 10); 12305 if (*endp != '\0' || newlevel < 0 || newlevel > 99) { 12306 return ISC_R_RANGE; 12307 } 12308 named_g_debuglevel = (unsigned int)newlevel; 12309 } 12310 isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel); 12311 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12312 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12313 "debug level is now %u", named_g_debuglevel); 12314 return ISC_R_SUCCESS; 12315 } 12316 12317 isc_result_t 12318 named_server_validation(named_server_t *server, isc_lex_t *lex, 12319 isc_buffer_t **text) { 12320 char *ptr; 12321 dns_view_t *view; 12322 bool changed = false; 12323 isc_result_t result; 12324 bool enable = true, set = true, first = true; 12325 12326 REQUIRE(text != NULL); 12327 12328 /* Skip the command name. */ 12329 ptr = next_token(lex, text); 12330 if (ptr == NULL) { 12331 return ISC_R_UNEXPECTEDEND; 12332 } 12333 12334 /* Find out what we are to do. */ 12335 ptr = next_token(lex, text); 12336 if (ptr == NULL) { 12337 return ISC_R_UNEXPECTEDEND; 12338 } 12339 12340 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 12341 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 12342 { 12343 enable = true; 12344 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 12345 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 12346 { 12347 enable = false; 12348 } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { 12349 set = false; 12350 } else { 12351 return DNS_R_SYNTAX; 12352 } 12353 12354 /* Look for the view name. */ 12355 ptr = next_token(lex, text); 12356 12357 isc_loopmgr_pause(named_g_loopmgr); 12358 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12359 view = ISC_LIST_NEXT(view, link)) 12360 { 12361 if ((ptr != NULL && strcasecmp(ptr, view->name) != 0) || 12362 strcasecmp("_bind", view->name) == 0) 12363 { 12364 continue; 12365 } 12366 12367 if (set) { 12368 CHECK(dns_view_flushcache(view, false)); 12369 view->enablevalidation = enable; 12370 changed = true; 12371 } else { 12372 if (!first) { 12373 CHECK(putstr(text, "\n")); 12374 } 12375 CHECK(putstr(text, "DNSSEC validation is ")); 12376 CHECK(putstr(text, view->enablevalidation 12377 ? "enabled" 12378 : "disabled")); 12379 CHECK(putstr(text, " (view ")); 12380 CHECK(putstr(text, view->name)); 12381 CHECK(putstr(text, ")")); 12382 first = false; 12383 } 12384 } 12385 CHECK(putnull(text)); 12386 12387 if (!set) { 12388 result = ISC_R_SUCCESS; 12389 } else if (changed) { 12390 result = ISC_R_SUCCESS; 12391 } else { 12392 result = ISC_R_FAILURE; 12393 } 12394 cleanup: 12395 isc_loopmgr_resume(named_g_loopmgr); 12396 return result; 12397 } 12398 12399 isc_result_t 12400 named_server_flushcache(named_server_t *server, isc_lex_t *lex) { 12401 char *ptr; 12402 dns_view_t *view; 12403 bool flushed; 12404 bool found; 12405 isc_result_t result; 12406 named_cache_t *nsc; 12407 12408 /* Skip the command name. */ 12409 ptr = next_token(lex, NULL); 12410 if (ptr == NULL) { 12411 return ISC_R_UNEXPECTEDEND; 12412 } 12413 12414 /* Look for the view name. */ 12415 ptr = next_token(lex, NULL); 12416 12417 isc_loopmgr_pause(named_g_loopmgr); 12418 flushed = true; 12419 found = false; 12420 12421 /* 12422 * Flushing a cache is tricky when caches are shared by multiple views. 12423 * We first identify which caches should be flushed in the local cache 12424 * list, flush these caches, and then update other views that refer to 12425 * the flushed cache DB. 12426 */ 12427 if (ptr != NULL) { 12428 /* 12429 * Mark caches that need to be flushed. This is an O(#view^2) 12430 * operation in the very worst case, but should be normally 12431 * much more lightweight because only a few (most typically just 12432 * one) views will match. 12433 */ 12434 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12435 view = ISC_LIST_NEXT(view, link)) 12436 { 12437 if (strcasecmp(ptr, view->name) != 0) { 12438 continue; 12439 } 12440 found = true; 12441 for (nsc = ISC_LIST_HEAD(server->cachelist); 12442 nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) 12443 { 12444 if (nsc->cache == view->cache) { 12445 break; 12446 } 12447 } 12448 INSIST(nsc != NULL); 12449 nsc->needflush = true; 12450 } 12451 } else { 12452 found = true; 12453 } 12454 12455 /* Perform flush */ 12456 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12457 nsc = ISC_LIST_NEXT(nsc, link)) 12458 { 12459 if (ptr != NULL && !nsc->needflush) { 12460 continue; 12461 } 12462 nsc->needflush = true; 12463 result = dns_view_flushcache(nsc->primaryview, false); 12464 if (result != ISC_R_SUCCESS) { 12465 flushed = false; 12466 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12467 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12468 "flushing cache in view '%s' failed: %s", 12469 nsc->primaryview->name, 12470 isc_result_totext(result)); 12471 } 12472 } 12473 12474 /* 12475 * Fix up views that share a flushed cache: let the views update the 12476 * cache DB they're referring to. This could also be an expensive 12477 * operation, but should typically be marginal: the inner loop is only 12478 * necessary for views that share a cache, and if there are many such 12479 * views the number of shared cache should normally be small. 12480 * A worst case is that we have n views and n/2 caches, each shared by 12481 * two views. Then this will be a O(n^2/4) operation. 12482 */ 12483 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12484 view = ISC_LIST_NEXT(view, link)) 12485 { 12486 if (!dns_view_iscacheshared(view)) { 12487 continue; 12488 } 12489 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12490 nsc = ISC_LIST_NEXT(nsc, link)) 12491 { 12492 if (!nsc->needflush || nsc->cache != view->cache) { 12493 continue; 12494 } 12495 result = dns_view_flushcache(view, true); 12496 if (result != ISC_R_SUCCESS) { 12497 flushed = false; 12498 isc_log_write( 12499 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12500 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12501 "fixing cache in view '%s' " 12502 "failed: %s", 12503 view->name, isc_result_totext(result)); 12504 } 12505 } 12506 } 12507 12508 /* Cleanup the cache list. */ 12509 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12510 nsc = ISC_LIST_NEXT(nsc, link)) 12511 { 12512 nsc->needflush = false; 12513 } 12514 12515 if (flushed && found) { 12516 if (ptr != NULL) { 12517 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12518 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12519 "flushing cache in view '%s' succeeded", 12520 ptr); 12521 } else { 12522 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12523 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12524 "flushing caches in all views succeeded"); 12525 } 12526 result = ISC_R_SUCCESS; 12527 } else { 12528 if (!found) { 12529 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12530 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12531 "flushing cache in view '%s' failed: " 12532 "view not found", 12533 ptr); 12534 result = ISC_R_NOTFOUND; 12535 } else { 12536 result = ISC_R_FAILURE; 12537 } 12538 } 12539 isc_loopmgr_resume(named_g_loopmgr); 12540 return result; 12541 } 12542 12543 isc_result_t 12544 named_server_flushnode(named_server_t *server, isc_lex_t *lex, bool tree) { 12545 char *ptr, *viewname; 12546 char target[DNS_NAME_FORMATSIZE]; 12547 dns_view_t *view; 12548 bool flushed; 12549 bool found; 12550 isc_result_t result; 12551 isc_buffer_t b; 12552 dns_fixedname_t fixed; 12553 dns_name_t *name; 12554 12555 /* Skip the command name. */ 12556 ptr = next_token(lex, NULL); 12557 if (ptr == NULL) { 12558 return ISC_R_UNEXPECTEDEND; 12559 } 12560 12561 /* Find the domain name to flush. */ 12562 ptr = next_token(lex, NULL); 12563 if (ptr == NULL) { 12564 return ISC_R_UNEXPECTEDEND; 12565 } 12566 12567 strlcpy(target, ptr, DNS_NAME_FORMATSIZE); 12568 isc_buffer_constinit(&b, target, strlen(target)); 12569 isc_buffer_add(&b, strlen(target)); 12570 name = dns_fixedname_initname(&fixed); 12571 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 12572 if (result != ISC_R_SUCCESS) { 12573 return result; 12574 } 12575 12576 /* Look for the view name. */ 12577 viewname = next_token(lex, NULL); 12578 12579 isc_loopmgr_pause(named_g_loopmgr); 12580 flushed = true; 12581 found = false; 12582 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12583 view = ISC_LIST_NEXT(view, link)) 12584 { 12585 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) { 12586 continue; 12587 } 12588 found = true; 12589 /* 12590 * It's a little inefficient to try flushing name for all views 12591 * if some of the views share a single cache. But since the 12592 * operation is lightweight we prefer simplicity here. 12593 */ 12594 result = dns_view_flushnode(view, name, tree); 12595 if (result != ISC_R_SUCCESS) { 12596 flushed = false; 12597 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12598 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12599 "flushing %s '%s' in cache view '%s' " 12600 "failed: %s", 12601 tree ? "tree" : "name", target, 12602 view->name, isc_result_totext(result)); 12603 } 12604 } 12605 if (flushed && found) { 12606 if (viewname != NULL) { 12607 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12608 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12609 "flushing %s '%s' in cache view '%s' " 12610 "succeeded", 12611 tree ? "tree" : "name", target, viewname); 12612 } else { 12613 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12614 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12615 "flushing %s '%s' in all cache views " 12616 "succeeded", 12617 tree ? "tree" : "name", target); 12618 } 12619 result = ISC_R_SUCCESS; 12620 } else { 12621 if (!found) { 12622 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12623 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12624 "flushing %s '%s' in cache view '%s' " 12625 "failed: view not found", 12626 tree ? "tree" : "name", target, viewname); 12627 } 12628 result = ISC_R_FAILURE; 12629 } 12630 isc_loopmgr_resume(named_g_loopmgr); 12631 return result; 12632 } 12633 12634 isc_result_t 12635 named_server_status(named_server_t *server, isc_buffer_t **text) { 12636 isc_result_t result; 12637 unsigned int zonecount, xferrunning, xferdeferred, xferfirstrefresh; 12638 unsigned int soaqueries, automatic; 12639 const char *ob = "", *cb = "", *alt = ""; 12640 char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE]; 12641 char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE]; 12642 char line[1024], hostname[256]; 12643 named_reload_t reload_status; 12644 12645 REQUIRE(text != NULL); 12646 12647 if (named_g_server->version_set) { 12648 ob = " ("; 12649 cb = ")"; 12650 if (named_g_server->version == NULL) { 12651 alt = "version.bind/txt/ch disabled"; 12652 } else { 12653 alt = named_g_server->version; 12654 } 12655 } 12656 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); 12657 xferrunning = dns_zonemgr_getcount(server->zonemgr, 12658 DNS_ZONESTATE_XFERRUNNING); 12659 xferdeferred = dns_zonemgr_getcount(server->zonemgr, 12660 DNS_ZONESTATE_XFERDEFERRED); 12661 xferfirstrefresh = dns_zonemgr_getcount(server->zonemgr, 12662 DNS_ZONESTATE_XFERFIRSTREFRESH); 12663 soaqueries = dns_zonemgr_getcount(server->zonemgr, 12664 DNS_ZONESTATE_SOAQUERY); 12665 automatic = dns_zonemgr_getcount(server->zonemgr, 12666 DNS_ZONESTATE_AUTOMATIC); 12667 12668 isc_time_formathttptimestamp(&named_g_boottime, boottime, 12669 sizeof(boottime)); 12670 isc_time_formathttptimestamp(&named_g_configtime, configtime, 12671 sizeof(configtime)); 12672 12673 snprintf(line, sizeof(line), "version: %s%s <id:%s>%s%s%s\n", 12674 PACKAGE_STRING, PACKAGE_DESCRIPTION, PACKAGE_SRCID, ob, alt, 12675 cb); 12676 CHECK(putstr(text, line)); 12677 12678 if (gethostname(hostname, sizeof(hostname)) == 0) { 12679 strlcpy(hostname, "localhost", sizeof(hostname)); 12680 } 12681 snprintf(line, sizeof(line), "running on %s: %s\n", hostname, 12682 named_os_uname()); 12683 CHECK(putstr(text, line)); 12684 12685 snprintf(line, sizeof(line), "boot time: %s\n", boottime); 12686 CHECK(putstr(text, line)); 12687 12688 snprintf(line, sizeof(line), "last configured: %s\n", configtime); 12689 CHECK(putstr(text, line)); 12690 12691 if (named_g_chrootdir != NULL) { 12692 snprintf(line, sizeof(line), "configuration file: %s (%s%s)\n", 12693 named_g_conffile, named_g_chrootdir, named_g_conffile); 12694 } else { 12695 snprintf(line, sizeof(line), "configuration file: %s\n", 12696 named_g_conffile); 12697 } 12698 CHECK(putstr(text, line)); 12699 12700 snprintf(line, sizeof(line), "CPUs found: %u\n", named_g_cpus_detected); 12701 CHECK(putstr(text, line)); 12702 12703 snprintf(line, sizeof(line), "worker threads: %u\n", named_g_cpus); 12704 CHECK(putstr(text, line)); 12705 12706 snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n", 12707 zonecount, automatic); 12708 CHECK(putstr(text, line)); 12709 12710 snprintf(line, sizeof(line), "debug level: %u\n", named_g_debuglevel); 12711 CHECK(putstr(text, line)); 12712 12713 snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning); 12714 CHECK(putstr(text, line)); 12715 12716 snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred); 12717 CHECK(putstr(text, line)); 12718 12719 snprintf(line, sizeof(line), "xfers first refresh: %u\n", 12720 xferfirstrefresh); 12721 CHECK(putstr(text, line)); 12722 12723 snprintf(line, sizeof(line), "soa queries in progress: %u\n", 12724 soaqueries); 12725 CHECK(putstr(text, line)); 12726 12727 snprintf(line, sizeof(line), "query logging is %s\n", 12728 ns_server_getoption(server->sctx, NS_SERVER_LOGQUERIES) 12729 ? "ON" 12730 : "OFF"); 12731 CHECK(putstr(text, line)); 12732 12733 snprintf(line, sizeof(line), "response logging is %s\n", 12734 ns_server_getoption(server->sctx, NS_SERVER_LOGRESPONSES) 12735 ? "ON" 12736 : "OFF"); 12737 CHECK(putstr(text, line)); 12738 12739 snprintf(line, sizeof(line), "memory profiling is %s\n", 12740 named_server_getmemprof()); 12741 CHECK(putstr(text, line)); 12742 12743 snprintf(line, sizeof(line), "recursive clients: %u/%u/%u\n", 12744 isc_quota_getused(&server->sctx->recursionquota), 12745 isc_quota_getsoft(&server->sctx->recursionquota), 12746 isc_quota_getmax(&server->sctx->recursionquota)); 12747 CHECK(putstr(text, line)); 12748 12749 snprintf(line, sizeof(line), "recursive high-water: %u\n", 12750 (unsigned int)ns_stats_get_counter( 12751 server->sctx->nsstats, 12752 ns_statscounter_recurshighwater)); 12753 CHECK(putstr(text, line)); 12754 12755 snprintf(line, sizeof(line), "tcp clients: %u/%u\n", 12756 isc_quota_getused(&server->sctx->tcpquota), 12757 isc_quota_getmax(&server->sctx->tcpquota)); 12758 CHECK(putstr(text, line)); 12759 12760 snprintf(line, sizeof(line), "TCP high-water: %u\n", 12761 (unsigned int)ns_stats_get_counter( 12762 server->sctx->nsstats, ns_statscounter_tcphighwater)); 12763 CHECK(putstr(text, line)); 12764 12765 reload_status = atomic_load(&server->reload_status); 12766 if (reload_status != NAMED_RELOAD_DONE) { 12767 snprintf(line, sizeof(line), "reload/reconfig %s\n", 12768 reload_status == NAMED_RELOAD_FAILED ? "failed" 12769 : "in progress"); 12770 CHECK(putstr(text, line)); 12771 } 12772 12773 CHECK(putstr(text, "server is up and running")); 12774 CHECK(putnull(text)); 12775 12776 return ISC_R_SUCCESS; 12777 cleanup: 12778 return result; 12779 } 12780 12781 isc_result_t 12782 named_server_testgen(isc_lex_t *lex, isc_buffer_t **text) { 12783 isc_result_t result; 12784 char *ptr; 12785 unsigned long count; 12786 unsigned long i; 12787 const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; 12788 12789 REQUIRE(text != NULL); 12790 12791 /* Skip the command name. */ 12792 ptr = next_token(lex, text); 12793 if (ptr == NULL) { 12794 return ISC_R_UNEXPECTEDEND; 12795 } 12796 12797 ptr = next_token(lex, text); 12798 if (ptr == NULL) { 12799 count = 26; 12800 } else { 12801 count = strtoul(ptr, NULL, 10); 12802 } 12803 12804 CHECK(isc_buffer_reserve(*text, count)); 12805 for (i = 0; i < count; i++) { 12806 CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)])); 12807 } 12808 12809 CHECK(putnull(text)); 12810 12811 cleanup: 12812 return result; 12813 } 12814 12815 /* 12816 * Act on a "sign" or "loadkeys" command from the command channel. 12817 */ 12818 isc_result_t 12819 named_server_rekey(named_server_t *server, isc_lex_t *lex, 12820 isc_buffer_t **text) { 12821 isc_result_t result; 12822 dns_zone_t *zone = NULL; 12823 dns_zonetype_t type; 12824 uint16_t keyopts; 12825 bool fullsign = false; 12826 char *ptr; 12827 12828 REQUIRE(text != NULL); 12829 12830 ptr = next_token(lex, text); 12831 if (ptr == NULL) { 12832 return ISC_R_UNEXPECTEDEND; 12833 } 12834 12835 if (strcasecmp(ptr, NAMED_COMMAND_SIGN) == 0) { 12836 fullsign = true; 12837 } 12838 12839 REQUIRE(text != NULL); 12840 12841 result = zone_from_args(server, lex, NULL, &zone, NULL, text, false); 12842 if (result != ISC_R_SUCCESS) { 12843 return result; 12844 } 12845 if (zone == NULL) { 12846 return ISC_R_UNEXPECTEDEND; /* XXX: or do all zones? */ 12847 } 12848 12849 type = dns_zone_gettype(zone); 12850 if (type != dns_zone_primary) { 12851 dns_zone_detach(&zone); 12852 return DNS_R_NOTPRIMARY; 12853 } 12854 12855 keyopts = dns_zone_getkeyopts(zone); 12856 12857 /* 12858 * "rndc loadkeys" requires a "dnssec-policy". 12859 */ 12860 if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) { 12861 result = ISC_R_NOPERM; 12862 } else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) { 12863 result = ISC_R_NOPERM; 12864 } else { 12865 dns_zone_rekey(zone, fullsign, false); 12866 } 12867 12868 dns_zone_detach(&zone); 12869 return result; 12870 } 12871 12872 /* 12873 * Act on a "sync" command from the command channel. 12874 */ 12875 static isc_result_t 12876 synczone(dns_zone_t *zone, void *uap) { 12877 bool cleanup = *(bool *)uap; 12878 isc_result_t result; 12879 dns_zone_t *raw = NULL; 12880 char *journal; 12881 12882 dns_zone_getraw(zone, &raw); 12883 if (raw != NULL) { 12884 synczone(raw, uap); 12885 dns_zone_detach(&raw); 12886 } 12887 12888 result = dns_zone_flush(zone); 12889 if (result != ISC_R_SUCCESS) { 12890 cleanup = false; 12891 } 12892 if (cleanup) { 12893 journal = dns_zone_getjournal(zone); 12894 if (journal != NULL) { 12895 (void)isc_file_remove(journal); 12896 } 12897 } 12898 12899 return result; 12900 } 12901 12902 isc_result_t 12903 named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { 12904 isc_result_t result, tresult; 12905 dns_view_t *view = NULL; 12906 dns_zone_t *zone = NULL; 12907 char classstr[DNS_RDATACLASS_FORMATSIZE]; 12908 char zonename[DNS_NAME_FORMATSIZE]; 12909 const char *vname = NULL, *sep = NULL, *arg = NULL; 12910 bool cleanup = false; 12911 12912 REQUIRE(text != NULL); 12913 12914 (void)next_token(lex, text); 12915 12916 arg = next_token(lex, text); 12917 if (arg != NULL && 12918 (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) 12919 { 12920 cleanup = true; 12921 arg = next_token(lex, text); 12922 } 12923 12924 REQUIRE(text != NULL); 12925 12926 result = zone_from_args(server, lex, arg, &zone, NULL, text, false); 12927 if (result != ISC_R_SUCCESS) { 12928 return result; 12929 } 12930 12931 if (zone == NULL) { 12932 isc_loopmgr_pause(named_g_loopmgr); 12933 tresult = ISC_R_SUCCESS; 12934 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12935 view = ISC_LIST_NEXT(view, link)) 12936 { 12937 result = dns_view_apply(view, false, NULL, synczone, 12938 &cleanup); 12939 if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) 12940 { 12941 tresult = result; 12942 } 12943 } 12944 isc_loopmgr_resume(named_g_loopmgr); 12945 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12946 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12947 "dumping all zones%s: %s", 12948 cleanup ? ", removing journal files" : "", 12949 isc_result_totext(result)); 12950 return tresult; 12951 } 12952 12953 isc_loopmgr_pause(named_g_loopmgr); 12954 result = synczone(zone, &cleanup); 12955 isc_loopmgr_resume(named_g_loopmgr); 12956 12957 view = dns_zone_getview(zone); 12958 if (strcmp(view->name, "_default") == 0 || 12959 strcmp(view->name, "_bind") == 0) 12960 { 12961 vname = ""; 12962 sep = ""; 12963 } else { 12964 vname = view->name; 12965 sep = " "; 12966 } 12967 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 12968 sizeof(classstr)); 12969 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 12970 isc_log_write( 12971 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, 12972 ISC_LOG_INFO, "sync: dumping zone '%s/%s'%s%s%s: %s", zonename, 12973 classstr, sep, vname, cleanup ? ", removing journal file" : "", 12974 isc_result_totext(result)); 12975 dns_zone_detach(&zone); 12976 return result; 12977 } 12978 12979 /* 12980 * Act on a "freeze" or "thaw" command from the command channel. 12981 */ 12982 isc_result_t 12983 named_server_freeze(named_server_t *server, bool freeze, isc_lex_t *lex, 12984 isc_buffer_t **text) { 12985 isc_result_t result, tresult; 12986 dns_zone_t *mayberaw = NULL, *raw = NULL; 12987 dns_zonetype_t type; 12988 char classstr[DNS_RDATACLASS_FORMATSIZE]; 12989 char zonename[DNS_NAME_FORMATSIZE]; 12990 dns_view_t *view; 12991 const char *vname, *sep; 12992 bool frozen; 12993 const char *msg = NULL; 12994 12995 REQUIRE(text != NULL); 12996 12997 result = zone_from_args(server, lex, NULL, &mayberaw, NULL, text, true); 12998 if (result != ISC_R_SUCCESS) { 12999 return result; 13000 } 13001 if (mayberaw == NULL) { 13002 isc_loopmgr_pause(named_g_loopmgr); 13003 tresult = ISC_R_SUCCESS; 13004 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 13005 view = ISC_LIST_NEXT(view, link)) 13006 { 13007 result = dns_view_freezezones(view, freeze); 13008 if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) 13009 { 13010 tresult = result; 13011 } 13012 } 13013 isc_loopmgr_resume(named_g_loopmgr); 13014 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13015 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13016 "%s all zones: %s", 13017 freeze ? "freezing" : "thawing", 13018 isc_result_totext(tresult)); 13019 return tresult; 13020 } 13021 dns_zone_getraw(mayberaw, &raw); 13022 if (raw != NULL) { 13023 dns_zone_detach(&mayberaw); 13024 dns_zone_attach(raw, &mayberaw); 13025 dns_zone_detach(&raw); 13026 } 13027 type = dns_zone_gettype(mayberaw); 13028 if (type != dns_zone_primary) { 13029 dns_zone_detach(&mayberaw); 13030 return DNS_R_NOTPRIMARY; 13031 } 13032 13033 if (freeze && !dns_zone_isdynamic(mayberaw, true)) { 13034 dns_zone_detach(&mayberaw); 13035 return DNS_R_NOTDYNAMIC; 13036 } 13037 13038 isc_loopmgr_pause(named_g_loopmgr); 13039 frozen = dns_zone_getupdatedisabled(mayberaw); 13040 if (freeze) { 13041 if (frozen) { 13042 msg = "WARNING: The zone was already frozen.\n" 13043 "Someone else may be editing it or " 13044 "it may still be re-loading."; 13045 result = DNS_R_FROZEN; 13046 } 13047 if (result == ISC_R_SUCCESS) { 13048 result = dns_zone_flush(mayberaw); 13049 if (result != ISC_R_SUCCESS) { 13050 msg = "Flushing the zone updates to " 13051 "disk failed."; 13052 } 13053 } 13054 if (result == ISC_R_SUCCESS) { 13055 dns_zone_setupdatedisabled(mayberaw, freeze); 13056 } 13057 } else { 13058 if (frozen) { 13059 result = dns_zone_loadandthaw(mayberaw); 13060 switch (result) { 13061 case ISC_R_SUCCESS: 13062 case DNS_R_UPTODATE: 13063 msg = "The zone reload and thaw was " 13064 "successful."; 13065 result = ISC_R_SUCCESS; 13066 break; 13067 case DNS_R_CONTINUE: 13068 msg = "A zone reload and thaw was started.\n" 13069 "Check the logs to see the result."; 13070 result = ISC_R_SUCCESS; 13071 break; 13072 default: 13073 break; 13074 } 13075 } 13076 } 13077 isc_loopmgr_resume(named_g_loopmgr); 13078 13079 if (msg != NULL) { 13080 (void)putstr(text, msg); 13081 (void)putnull(text); 13082 } 13083 13084 view = dns_zone_getview(mayberaw); 13085 if (strcmp(view->name, "_default") == 0 || 13086 strcmp(view->name, "_bind") == 0) 13087 { 13088 vname = ""; 13089 sep = ""; 13090 } else { 13091 vname = view->name; 13092 sep = " "; 13093 } 13094 dns_rdataclass_format(dns_zone_getclass(mayberaw), classstr, 13095 sizeof(classstr)); 13096 dns_name_format(dns_zone_getorigin(mayberaw), zonename, 13097 sizeof(zonename)); 13098 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13099 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13100 "%s zone '%s/%s'%s%s: %s", 13101 freeze ? "freezing" : "thawing", zonename, classstr, sep, 13102 vname, isc_result_totext(result)); 13103 dns_zone_detach(&mayberaw); 13104 return result; 13105 } 13106 13107 #ifdef HAVE_LIBSCF 13108 /* 13109 * This function adds a message for rndc to echo if named 13110 * is managed by smf and is also running chroot. 13111 */ 13112 isc_result_t 13113 named_smf_add_message(isc_buffer_t **text) { 13114 REQUIRE(text != NULL); 13115 13116 return putstr(text, "use svcadm(1M) to manage named"); 13117 } 13118 #endif /* HAVE_LIBSCF */ 13119 13120 #ifndef HAVE_LMDB 13121 13122 /* 13123 * Emit a comment at the top of the nzf file containing the viewname 13124 * Expects the fp to already be open for writing 13125 */ 13126 #define HEADER1 "# New zone file for view: " 13127 #define HEADER2 \ 13128 "\n# This file contains configuration for zones added by\n" \ 13129 "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n" 13130 static isc_result_t 13131 add_comment(FILE *fp, const char *viewname) { 13132 isc_result_t result; 13133 CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL)); 13134 CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL)); 13135 CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL)); 13136 cleanup: 13137 return result; 13138 } 13139 13140 static void 13141 dumpzone(void *arg, const char *buf, int len) { 13142 FILE *fp = arg; 13143 13144 (void)isc_stdio_write(buf, len, 1, fp, NULL); 13145 } 13146 13147 static isc_result_t 13148 nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) { 13149 isc_result_t result; 13150 off_t offset; 13151 FILE *fp = NULL; 13152 bool offsetok = false; 13153 13154 LOCK(&view->new_zone_lock); 13155 13156 CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); 13157 CHECK(isc_stdio_seek(fp, 0, SEEK_END)); 13158 13159 CHECK(isc_stdio_tell(fp, &offset)); 13160 offsetok = true; 13161 if (offset == 0) { 13162 CHECK(add_comment(fp, view->name)); 13163 } 13164 13165 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 13166 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); 13167 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); 13168 CHECK(isc_stdio_flush(fp)); 13169 result = isc_stdio_close(fp); 13170 fp = NULL; 13171 13172 cleanup: 13173 if (fp != NULL) { 13174 (void)isc_stdio_close(fp); 13175 if (offsetok) { 13176 isc_result_t result2; 13177 13178 result2 = isc_file_truncate(view->new_zone_file, 13179 offset); 13180 if (result2 != ISC_R_SUCCESS) { 13181 isc_log_write( 13182 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13183 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13184 "Error truncating NZF file '%s' " 13185 "during rollback from append: " 13186 "%s", 13187 view->new_zone_file, 13188 isc_result_totext(result2)); 13189 } 13190 } 13191 } 13192 UNLOCK(&view->new_zone_lock); 13193 return result; 13194 } 13195 13196 static isc_result_t 13197 nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { 13198 const cfg_obj_t *zl = NULL; 13199 cfg_list_t *list; 13200 const cfg_listelt_t *elt; 13201 13202 FILE *fp = NULL; 13203 char tmp[1024]; 13204 isc_result_t result; 13205 13206 result = isc_file_template(view->new_zone_file, "nzf-XXXXXXXX", tmp, 13207 sizeof(tmp)); 13208 if (result == ISC_R_SUCCESS) { 13209 result = isc_file_openunique(tmp, &fp); 13210 } 13211 if (result != ISC_R_SUCCESS) { 13212 return result; 13213 } 13214 13215 cfg_map_get(config, "zone", &zl); 13216 if (!cfg_obj_islist(zl)) { 13217 CHECK(ISC_R_FAILURE); 13218 } 13219 13220 list = UNCONST(&zl->value.list); 13221 13222 CHECK(add_comment(fp, view->name)); /* force a comment */ 13223 13224 for (elt = ISC_LIST_HEAD(*list); elt != NULL; 13225 elt = ISC_LIST_NEXT(elt, link)) 13226 { 13227 const cfg_obj_t *zconfig = cfg_listelt_value(elt); 13228 13229 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 13230 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); 13231 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); 13232 } 13233 13234 CHECK(isc_stdio_flush(fp)); 13235 result = isc_stdio_close(fp); 13236 fp = NULL; 13237 if (result != ISC_R_SUCCESS) { 13238 goto cleanup; 13239 } 13240 CHECK(isc_file_rename(tmp, view->new_zone_file)); 13241 return result; 13242 13243 cleanup: 13244 if (fp != NULL) { 13245 (void)isc_stdio_close(fp); 13246 } 13247 (void)isc_file_remove(tmp); 13248 return result; 13249 } 13250 13251 static isc_result_t 13252 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { 13253 isc_result_t result; 13254 13255 /* The new zone file may not exist. That is OK. */ 13256 if (!isc_file_exists(view->new_zone_file)) { 13257 return ISC_R_SUCCESS; 13258 } 13259 13260 /* 13261 * Parse the configuration in the NZF file. This may be called in 13262 * multiple views, so we reset the parser each time. 13263 */ 13264 cfg_parser_reset(named_g_addparser); 13265 result = cfg_parse_file(named_g_addparser, view->new_zone_file, 13266 &cfg_type_addzoneconf, &nzcfg->nzf_config); 13267 if (result != ISC_R_SUCCESS) { 13268 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13269 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13270 "Error parsing NZF file '%s': %s", 13271 view->new_zone_file, isc_result_totext(result)); 13272 } 13273 13274 return result; 13275 } 13276 #else /* HAVE_LMDB */ 13277 13278 static void 13279 nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) { 13280 dns_fixedname_t fixed; 13281 13282 dns_fixedname_init(&fixed); 13283 dns_name_downcase(name, dns_fixedname_name(&fixed), NULL); 13284 dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen); 13285 13286 key->mv_data = namebuf; 13287 key->mv_size = strlen(namebuf); 13288 } 13289 13290 static void 13291 dumpzone(void *arg, const char *buf, int len) { 13292 ns_dzarg_t *dzarg = arg; 13293 isc_result_t result; 13294 13295 REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); 13296 13297 result = putmem(dzarg->text, buf, len); 13298 if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { 13299 dzarg->result = result; 13300 } 13301 } 13302 13303 static isc_result_t 13304 nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone, 13305 const cfg_obj_t *zconfig) { 13306 isc_result_t result; 13307 int status; 13308 dns_view_t *view; 13309 bool commit = false; 13310 isc_buffer_t *text = NULL; 13311 char namebuf[1024]; 13312 MDB_val key, data; 13313 ns_dzarg_t dzarg; 13314 13315 view = dns_zone_getview(zone); 13316 13317 nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf)); 13318 13319 if (zconfig == NULL) { 13320 /* We're deleting the zone from the database */ 13321 status = mdb_del(*txnp, dbi, &key, NULL); 13322 if (status != MDB_SUCCESS && status != MDB_NOTFOUND) { 13323 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13324 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13325 "Error deleting zone %s " 13326 "from NZD database: %s", 13327 namebuf, mdb_strerror(status)); 13328 result = ISC_R_FAILURE; 13329 goto cleanup; 13330 } else if (status != MDB_NOTFOUND) { 13331 commit = true; 13332 } 13333 } else { 13334 /* We're creating or overwriting the zone */ 13335 const cfg_obj_t *zoptions; 13336 13337 isc_buffer_allocate(view->mctx, &text, 256); 13338 13339 zoptions = cfg_tuple_get(zconfig, "options"); 13340 if (zoptions == NULL) { 13341 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13342 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13343 "Unable to get options from config in " 13344 "nzd_save()"); 13345 result = ISC_R_FAILURE; 13346 goto cleanup; 13347 } 13348 13349 dzarg.magic = DZARG_MAGIC; 13350 dzarg.text = &text; 13351 dzarg.result = ISC_R_SUCCESS; 13352 cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); 13353 if (dzarg.result != ISC_R_SUCCESS) { 13354 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13355 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13356 "Error writing zone config to " 13357 "buffer in nzd_save(): %s", 13358 isc_result_totext(dzarg.result)); 13359 result = dzarg.result; 13360 goto cleanup; 13361 } 13362 13363 data.mv_data = isc_buffer_base(text); 13364 data.mv_size = isc_buffer_usedlength(text); 13365 13366 status = mdb_put(*txnp, dbi, &key, &data, 0); 13367 if (status != MDB_SUCCESS) { 13368 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13369 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13370 "Error inserting zone in " 13371 "NZD database: %s", 13372 mdb_strerror(status)); 13373 result = ISC_R_FAILURE; 13374 goto cleanup; 13375 } 13376 13377 commit = true; 13378 } 13379 13380 result = ISC_R_SUCCESS; 13381 13382 cleanup: 13383 if (!commit || result != ISC_R_SUCCESS) { 13384 (void)mdb_txn_abort(*txnp); 13385 } else { 13386 status = mdb_txn_commit(*txnp); 13387 if (status != MDB_SUCCESS) { 13388 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13389 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13390 "Error committing " 13391 "NZD database: %s", 13392 mdb_strerror(status)); 13393 result = ISC_R_FAILURE; 13394 } 13395 } 13396 *txnp = NULL; 13397 13398 if (text != NULL) { 13399 isc_buffer_free(&text); 13400 } 13401 13402 return result; 13403 } 13404 13405 /* 13406 * Check whether the new zone database for 'view' can be opened for writing. 13407 * 13408 * Caller must hold 'view->new_zone_lock'. 13409 */ 13410 static isc_result_t 13411 nzd_writable(dns_view_t *view) { 13412 isc_result_t result = ISC_R_SUCCESS; 13413 int status; 13414 MDB_dbi dbi; 13415 MDB_txn *txn = NULL; 13416 13417 REQUIRE(view != NULL); 13418 13419 status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, 0, &txn); 13420 if (status != MDB_SUCCESS) { 13421 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13422 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13423 "mdb_txn_begin: %s", mdb_strerror(status)); 13424 return ISC_R_FAILURE; 13425 } 13426 13427 status = mdb_dbi_open(txn, NULL, 0, &dbi); 13428 if (status != MDB_SUCCESS) { 13429 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13430 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13431 "mdb_dbi_open: %s", mdb_strerror(status)); 13432 result = ISC_R_FAILURE; 13433 } 13434 13435 mdb_txn_abort(txn); 13436 return result; 13437 } 13438 13439 /* 13440 * Open the new zone database for 'view' and start a transaction for it. 13441 * 13442 * Caller must hold 'view->new_zone_lock'. 13443 */ 13444 static isc_result_t 13445 nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { 13446 int status; 13447 MDB_txn *txn = NULL; 13448 13449 REQUIRE(view != NULL); 13450 REQUIRE(txnp != NULL && *txnp == NULL); 13451 REQUIRE(dbi != NULL); 13452 13453 status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, flags, &txn); 13454 if (status != MDB_SUCCESS) { 13455 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13456 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13457 "mdb_txn_begin: %s", mdb_strerror(status)); 13458 goto cleanup; 13459 } 13460 13461 status = mdb_dbi_open(txn, NULL, 0, dbi); 13462 if (status != MDB_SUCCESS) { 13463 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13464 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13465 "mdb_dbi_open: %s", mdb_strerror(status)); 13466 goto cleanup; 13467 } 13468 13469 *txnp = txn; 13470 13471 cleanup: 13472 if (status != MDB_SUCCESS) { 13473 if (txn != NULL) { 13474 mdb_txn_abort(txn); 13475 } 13476 return ISC_R_FAILURE; 13477 } 13478 13479 return ISC_R_SUCCESS; 13480 } 13481 13482 /* 13483 * nzd_env_close() and nzd_env_reopen are a kluge to address the 13484 * problem of an NZD file possibly being created before we drop 13485 * root privileges. 13486 */ 13487 static void 13488 nzd_env_close(dns_view_t *view) { 13489 const char *dbpath = NULL; 13490 char dbpath_copy[PATH_MAX]; 13491 char lockpath[PATH_MAX]; 13492 int status, ret; 13493 13494 if (view->new_zone_dbenv == NULL) { 13495 return; 13496 } 13497 13498 status = mdb_env_get_path(view->new_zone_dbenv, &dbpath); 13499 INSIST(status == MDB_SUCCESS); 13500 snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath); 13501 strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy)); 13502 mdb_env_close((MDB_env *)view->new_zone_dbenv); 13503 13504 /* 13505 * Database files must be owned by the eventual user, not by root. 13506 */ 13507 ret = chown(dbpath_copy, named_os_uid(), -1); 13508 UNUSED(ret); 13509 13510 /* 13511 * Some platforms need the lockfile not to exist when we reopen the 13512 * environment. 13513 */ 13514 (void)isc_file_remove(lockpath); 13515 13516 view->new_zone_dbenv = NULL; 13517 } 13518 13519 static isc_result_t 13520 nzd_env_reopen(dns_view_t *view) { 13521 isc_result_t result; 13522 MDB_env *env = NULL; 13523 int status; 13524 13525 if (view->new_zone_db == NULL) { 13526 return ISC_R_SUCCESS; 13527 } 13528 13529 nzd_env_close(view); 13530 13531 status = mdb_env_create(&env); 13532 if (status != MDB_SUCCESS) { 13533 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13534 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13535 "mdb_env_create failed: %s", 13536 mdb_strerror(status)); 13537 CHECK(ISC_R_FAILURE); 13538 } 13539 13540 if (view->new_zone_mapsize != 0ULL) { 13541 status = mdb_env_set_mapsize(env, view->new_zone_mapsize); 13542 if (status != MDB_SUCCESS) { 13543 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13544 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13545 "mdb_env_set_mapsize failed: %s", 13546 mdb_strerror(status)); 13547 CHECK(ISC_R_FAILURE); 13548 } 13549 } 13550 13551 status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); 13552 if (status != MDB_SUCCESS) { 13553 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13554 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13555 "mdb_env_open of '%s' failed: %s", 13556 view->new_zone_db, mdb_strerror(status)); 13557 CHECK(ISC_R_FAILURE); 13558 } 13559 13560 view->new_zone_dbenv = env; 13561 env = NULL; 13562 result = ISC_R_SUCCESS; 13563 13564 cleanup: 13565 if (env != NULL) { 13566 mdb_env_close(env); 13567 } 13568 return result; 13569 } 13570 13571 /* 13572 * If 'commit' is true, commit the new zone database transaction pointed to by 13573 * 'txnp'; otherwise, abort that transaction. 13574 * 13575 * Caller must hold 'view->new_zone_lock' for the view that the transaction 13576 * pointed to by 'txnp' was started for. 13577 */ 13578 static isc_result_t 13579 nzd_close(MDB_txn **txnp, bool commit) { 13580 isc_result_t result = ISC_R_SUCCESS; 13581 int status; 13582 13583 REQUIRE(txnp != NULL); 13584 13585 if (*txnp != NULL) { 13586 if (commit) { 13587 status = mdb_txn_commit(*txnp); 13588 if (status != MDB_SUCCESS) { 13589 result = ISC_R_FAILURE; 13590 } 13591 } else { 13592 mdb_txn_abort(*txnp); 13593 } 13594 *txnp = NULL; 13595 } 13596 13597 return result; 13598 } 13599 13600 /* 13601 * If there's an existing NZF file, load it and migrate its data 13602 * to the NZD. 13603 * 13604 * Caller must hold view->new_zone_lock. 13605 */ 13606 static isc_result_t 13607 load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { 13608 isc_result_t result; 13609 cfg_obj_t *nzf_config = NULL; 13610 int status; 13611 isc_buffer_t *text = NULL; 13612 bool commit = false; 13613 const cfg_obj_t *zonelist; 13614 const cfg_listelt_t *element; 13615 char tempname[PATH_MAX]; 13616 MDB_txn *txn = NULL; 13617 MDB_dbi dbi; 13618 MDB_val key, data; 13619 ns_dzarg_t dzarg; 13620 13621 UNUSED(nzcfg); 13622 13623 /* 13624 * If NZF file doesn't exist, or NZD DB exists and already 13625 * has data, return without attempting migration. 13626 */ 13627 if (!isc_file_exists(view->new_zone_file)) { 13628 result = ISC_R_SUCCESS; 13629 goto cleanup; 13630 } 13631 13632 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13633 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13634 "Migrating zones from NZF file '%s' to " 13635 "NZD database '%s'", 13636 view->new_zone_file, view->new_zone_db); 13637 /* 13638 * Instead of blindly copying lines, we parse the NZF file using 13639 * the configuration parser, because it validates it against the 13640 * config type, giving us a guarantee that valid configuration 13641 * will be written to DB. 13642 */ 13643 cfg_parser_reset(named_g_addparser); 13644 result = cfg_parse_file(named_g_addparser, view->new_zone_file, 13645 &cfg_type_addzoneconf, &nzf_config); 13646 if (result != ISC_R_SUCCESS) { 13647 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13648 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13649 "Error parsing NZF file '%s': %s", 13650 view->new_zone_file, isc_result_totext(result)); 13651 goto cleanup; 13652 } 13653 13654 zonelist = NULL; 13655 CHECK(cfg_map_get(nzf_config, "zone", &zonelist)); 13656 if (!cfg_obj_islist(zonelist)) { 13657 CHECK(ISC_R_FAILURE); 13658 } 13659 13660 CHECK(nzd_open(view, 0, &txn, &dbi)); 13661 13662 isc_buffer_allocate(view->mctx, &text, 256); 13663 13664 for (element = cfg_list_first(zonelist); element != NULL; 13665 element = cfg_list_next(element)) 13666 { 13667 const cfg_obj_t *zconfig; 13668 const cfg_obj_t *zoptions; 13669 char zname[DNS_NAME_FORMATSIZE]; 13670 dns_fixedname_t fname; 13671 dns_name_t *name; 13672 const char *origin; 13673 isc_buffer_t b; 13674 13675 zconfig = cfg_listelt_value(element); 13676 13677 origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 13678 if (origin == NULL) { 13679 result = ISC_R_FAILURE; 13680 goto cleanup; 13681 } 13682 13683 /* Normalize zone name */ 13684 isc_buffer_constinit(&b, origin, strlen(origin)); 13685 isc_buffer_add(&b, strlen(origin)); 13686 name = dns_fixedname_initname(&fname); 13687 CHECK(dns_name_fromtext(name, &b, dns_rootname, 13688 DNS_NAME_DOWNCASE, NULL)); 13689 dns_name_format(name, zname, sizeof(zname)); 13690 13691 key.mv_data = zname; 13692 key.mv_size = strlen(zname); 13693 13694 zoptions = cfg_tuple_get(zconfig, "options"); 13695 if (zoptions == NULL) { 13696 result = ISC_R_FAILURE; 13697 goto cleanup; 13698 } 13699 13700 isc_buffer_clear(text); 13701 dzarg.magic = DZARG_MAGIC; 13702 dzarg.text = &text; 13703 dzarg.result = ISC_R_SUCCESS; 13704 cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); 13705 if (dzarg.result != ISC_R_SUCCESS) { 13706 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13707 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13708 "Error writing zone config to " 13709 "buffer in load_nzf(): %s", 13710 isc_result_totext(result)); 13711 result = dzarg.result; 13712 goto cleanup; 13713 } 13714 13715 data.mv_data = isc_buffer_base(text); 13716 data.mv_size = isc_buffer_usedlength(text); 13717 13718 status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE); 13719 if (status != MDB_SUCCESS) { 13720 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13721 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13722 "Error inserting zone in " 13723 "NZD database: %s", 13724 mdb_strerror(status)); 13725 result = ISC_R_FAILURE; 13726 goto cleanup; 13727 } 13728 13729 commit = true; 13730 } 13731 13732 result = ISC_R_SUCCESS; 13733 13734 /* 13735 * Leaving the NZF file in place is harmless as we won't use it 13736 * if an NZD database is found for the view. But we rename NZF file 13737 * to a backup name here. 13738 */ 13739 strlcpy(tempname, view->new_zone_file, sizeof(tempname)); 13740 if (strlen(tempname) < sizeof(tempname) - 1) { 13741 strlcat(tempname, "~", sizeof(tempname)); 13742 isc_file_rename(view->new_zone_file, tempname); 13743 } 13744 13745 cleanup: 13746 if (result != ISC_R_SUCCESS) { 13747 (void)nzd_close(&txn, false); 13748 } else { 13749 result = nzd_close(&txn, commit); 13750 } 13751 13752 if (text != NULL) { 13753 isc_buffer_free(&text); 13754 } 13755 13756 if (nzf_config != NULL) { 13757 cfg_obj_destroy(named_g_addparser, &nzf_config); 13758 } 13759 13760 return result; 13761 } 13762 #endif /* HAVE_LMDB */ 13763 13764 static isc_result_t 13765 newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, 13766 cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp, 13767 bool *redirectp, isc_buffer_t **text) { 13768 isc_result_t result; 13769 isc_buffer_t argbuf; 13770 bool redirect = false; 13771 cfg_obj_t *zoneconf = NULL; 13772 const cfg_obj_t *zlist = NULL; 13773 const cfg_obj_t *zoneobj = NULL; 13774 const cfg_obj_t *zoptions = NULL; 13775 const cfg_obj_t *obj = NULL; 13776 const char *viewname = NULL; 13777 dns_rdataclass_t rdclass; 13778 dns_view_t *view = NULL; 13779 const char *bn = NULL; 13780 13781 REQUIRE(viewp != NULL && *viewp == NULL); 13782 REQUIRE(zoneobjp != NULL && *zoneobjp == NULL); 13783 REQUIRE(zoneconfp != NULL && *zoneconfp == NULL); 13784 REQUIRE(redirectp != NULL); 13785 13786 /* Try to parse the argument string */ 13787 isc_buffer_init(&argbuf, command, (unsigned int)strlen(command)); 13788 isc_buffer_add(&argbuf, strlen(command)); 13789 13790 if (strncasecmp(command, "add", 3) == 0) { 13791 bn = "addzone"; 13792 } else if (strncasecmp(command, "mod", 3) == 0) { 13793 bn = "modzone"; 13794 } else { 13795 UNREACHABLE(); 13796 } 13797 13798 /* 13799 * Convert the "addzone" or "modzone" to just "zone", for 13800 * the benefit of the parser 13801 */ 13802 isc_buffer_forward(&argbuf, 3); 13803 13804 cfg_parser_reset(named_g_addparser); 13805 CHECK(cfg_parse_buffer(named_g_addparser, &argbuf, bn, 0, 13806 &cfg_type_addzoneconf, 0, &zoneconf)); 13807 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 13808 if (!cfg_obj_islist(zlist)) { 13809 CHECK(ISC_R_FAILURE); 13810 } 13811 13812 /* For now we only support adding one zone at a time */ 13813 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 13814 13815 /* Check the zone type for ones that are not supported by addzone. */ 13816 zoptions = cfg_tuple_get(zoneobj, "options"); 13817 13818 obj = NULL; 13819 (void)cfg_map_get(zoptions, "type", &obj); 13820 if (obj == NULL) { 13821 (void)cfg_map_get(zoptions, "in-view", &obj); 13822 if (obj != NULL) { 13823 (void)putstr(text, "'in-view' zones not supported by "); 13824 (void)putstr(text, bn); 13825 } else { 13826 (void)putstr(text, "zone type not specified"); 13827 } 13828 CHECK(ISC_R_FAILURE); 13829 } 13830 13831 if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 || 13832 strcasecmp(cfg_obj_asstring(obj), "forward") == 0) 13833 { 13834 (void)putstr(text, "'"); 13835 (void)putstr(text, cfg_obj_asstring(obj)); 13836 (void)putstr(text, "' zones not supported by "); 13837 (void)putstr(text, bn); 13838 CHECK(ISC_R_FAILURE); 13839 } 13840 13841 if (strcasecmp(cfg_obj_asstring(obj), "redirect") == 0) { 13842 redirect = true; 13843 } 13844 13845 /* Make sense of optional class argument */ 13846 obj = cfg_tuple_get(zoneobj, "class"); 13847 CHECK(named_config_getclass(obj, dns_rdataclass_in, &rdclass)); 13848 13849 /* Make sense of optional view argument */ 13850 obj = cfg_tuple_get(zoneobj, "view"); 13851 if (obj && cfg_obj_isstring(obj)) { 13852 viewname = cfg_obj_asstring(obj); 13853 } 13854 if (viewname == NULL || *viewname == '\0') { 13855 viewname = "_default"; 13856 } 13857 result = dns_viewlist_find(&server->viewlist, viewname, rdclass, &view); 13858 if (result == ISC_R_NOTFOUND) { 13859 (void)putstr(text, "no matching view found for '"); 13860 (void)putstr(text, viewname); 13861 (void)putstr(text, "'"); 13862 goto cleanup; 13863 } else if (result != ISC_R_SUCCESS) { 13864 goto cleanup; 13865 } 13866 13867 *viewp = view; 13868 *zoneobjp = zoneobj; 13869 *zoneconfp = zoneconf; 13870 *redirectp = redirect; 13871 13872 return ISC_R_SUCCESS; 13873 13874 cleanup: 13875 if (zoneconf != NULL) { 13876 cfg_obj_destroy(named_g_addparser, &zoneconf); 13877 } 13878 if (view != NULL) { 13879 dns_view_detach(&view); 13880 } 13881 13882 return result; 13883 } 13884 13885 static isc_result_t 13886 delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config, 13887 const dns_name_t *zname, nzfwriter_t nzfwriter) { 13888 isc_result_t result = ISC_R_NOTFOUND; 13889 const cfg_listelt_t *elt = NULL; 13890 const cfg_obj_t *zl = NULL; 13891 cfg_list_t *list; 13892 dns_fixedname_t myfixed; 13893 dns_name_t *myname; 13894 13895 REQUIRE(view != NULL); 13896 REQUIRE(pctx != NULL); 13897 REQUIRE(config != NULL); 13898 REQUIRE(zname != NULL); 13899 13900 LOCK(&view->new_zone_lock); 13901 13902 cfg_map_get(config, "zone", &zl); 13903 13904 if (!cfg_obj_islist(zl)) { 13905 CHECK(ISC_R_FAILURE); 13906 } 13907 13908 list = UNCONST(&zl->value.list); 13909 13910 myname = dns_fixedname_initname(&myfixed); 13911 13912 for (elt = ISC_LIST_HEAD(*list); elt != NULL; 13913 elt = ISC_LIST_NEXT(elt, link)) 13914 { 13915 const cfg_obj_t *zconf = cfg_listelt_value(elt); 13916 const char *zn; 13917 cfg_listelt_t *e; 13918 13919 zn = cfg_obj_asstring(cfg_tuple_get(zconf, "name")); 13920 result = dns_name_fromstring(myname, zn, dns_rootname, 0, NULL); 13921 if (result != ISC_R_SUCCESS || !dns_name_equal(zname, myname)) { 13922 continue; 13923 } 13924 13925 e = UNCONST(elt); 13926 ISC_LIST_UNLINK(*list, e, link); 13927 cfg_obj_destroy(pctx, &e->obj); 13928 isc_mem_put(pctx->mctx, e, sizeof(*e)); 13929 result = ISC_R_SUCCESS; 13930 break; 13931 } 13932 13933 /* 13934 * Write config to NZF file if appropriate 13935 */ 13936 if (nzfwriter != NULL && view->new_zone_file != NULL) { 13937 result = nzfwriter(config, view); 13938 } 13939 13940 cleanup: 13941 UNLOCK(&view->new_zone_lock); 13942 return result; 13943 } 13944 13945 static isc_result_t 13946 do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, 13947 dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj, 13948 bool redirect, isc_buffer_t **text) { 13949 isc_result_t result, tresult; 13950 dns_zone_t *zone = NULL; 13951 #ifndef HAVE_LMDB 13952 FILE *fp = NULL; 13953 bool cleanup_config = false; 13954 #else /* HAVE_LMDB */ 13955 MDB_txn *txn = NULL; 13956 MDB_dbi dbi; 13957 bool locked = false; 13958 13959 UNUSED(zoneconf); 13960 #endif 13961 13962 /* Zone shouldn't already exist */ 13963 if (redirect) { 13964 result = (view->redirect == NULL) ? ISC_R_NOTFOUND 13965 : ISC_R_EXISTS; 13966 } else { 13967 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 13968 if (result == ISC_R_SUCCESS) { 13969 result = ISC_R_EXISTS; 13970 } 13971 } 13972 if (result != ISC_R_NOTFOUND) { 13973 goto cleanup; 13974 } 13975 13976 isc_loopmgr_pause(named_g_loopmgr); 13977 13978 #ifndef HAVE_LMDB 13979 /* 13980 * Make sure we can open the configuration save file 13981 */ 13982 result = isc_stdio_open(view->new_zone_file, "a", &fp); 13983 if (result != ISC_R_SUCCESS) { 13984 isc_loopmgr_resume(named_g_loopmgr); 13985 TCHECK(putstr(text, "unable to create '")); 13986 TCHECK(putstr(text, view->new_zone_file)); 13987 TCHECK(putstr(text, "': ")); 13988 TCHECK(putstr(text, isc_result_totext(result))); 13989 goto cleanup; 13990 } 13991 13992 (void)isc_stdio_close(fp); 13993 fp = NULL; 13994 #else /* HAVE_LMDB */ 13995 LOCK(&view->new_zone_lock); 13996 locked = true; 13997 /* Make sure we can open the NZD database */ 13998 result = nzd_writable(view); 13999 if (result != ISC_R_SUCCESS) { 14000 isc_loopmgr_resume(named_g_loopmgr); 14001 TCHECK(putstr(text, "unable to open NZD database for '")); 14002 TCHECK(putstr(text, view->new_zone_db)); 14003 TCHECK(putstr(text, "'")); 14004 result = ISC_R_FAILURE; 14005 goto cleanup; 14006 } 14007 #endif /* HAVE_LMDB */ 14008 14009 /* Mark view unfrozen and configure zone */ 14010 dns_view_thaw(view); 14011 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, 14012 &server->viewlist, &server->kasplist, 14013 &server->keystorelist, cfg->actx, true, false, 14014 false, false); 14015 dns_view_freeze(view); 14016 14017 isc_loopmgr_resume(named_g_loopmgr); 14018 14019 if (result != ISC_R_SUCCESS) { 14020 TCHECK(putstr(text, "configure_zone failed: ")); 14021 TCHECK(putstr(text, isc_result_totext(result))); 14022 goto cleanup; 14023 } 14024 14025 /* Is it there yet? */ 14026 if (redirect) { 14027 if (view->redirect == NULL) { 14028 CHECK(ISC_R_NOTFOUND); 14029 } 14030 dns_zone_attach(view->redirect, &zone); 14031 } else { 14032 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 14033 if (result != ISC_R_SUCCESS) { 14034 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14035 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14036 "added new zone was not found: %s", 14037 isc_result_totext(result)); 14038 goto cleanup; 14039 } 14040 } 14041 14042 #ifndef HAVE_LMDB 14043 /* 14044 * If there wasn't a previous newzone config, just save the one 14045 * we've created. If there was a previous one, merge the new 14046 * zone into it. 14047 */ 14048 if (cfg->nzf_config == NULL) { 14049 cfg_obj_attach(zoneconf, &cfg->nzf_config); 14050 } else { 14051 cfg_obj_t *z = UNCONST(zoneobj); 14052 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, 14053 "zone")); 14054 } 14055 cleanup_config = true; 14056 #endif /* HAVE_LMDB */ 14057 14058 /* 14059 * Load the zone from the master file. If this fails, we'll 14060 * need to undo the configuration we've done already. 14061 */ 14062 result = dns_zone_load(zone, true); 14063 if (result != ISC_R_SUCCESS) { 14064 dns_db_t *dbp = NULL; 14065 14066 TCHECK(putstr(text, "dns_zone_loadnew failed: ")); 14067 TCHECK(putstr(text, isc_result_totext(result))); 14068 14069 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14070 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14071 "addzone failed; reverting."); 14072 14073 /* If the zone loaded partially, unload it */ 14074 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14075 dns_db_detach(&dbp); 14076 dns_zone_unload(zone); 14077 } 14078 14079 /* Remove the zone from the zone table */ 14080 dns_view_delzone(view, zone); 14081 goto cleanup; 14082 } 14083 14084 /* Flag the zone as having been added at runtime */ 14085 dns_zone_setadded(zone, true); 14086 14087 #ifdef HAVE_LMDB 14088 /* Save the new zone configuration into the NZD */ 14089 CHECK(nzd_open(view, 0, &txn, &dbi)); 14090 CHECK(nzd_save(&txn, dbi, zone, zoneobj)); 14091 #else /* ifdef HAVE_LMDB */ 14092 /* Append the zone configuration to the NZF */ 14093 result = nzf_append(view, zoneobj); 14094 #endif /* HAVE_LMDB */ 14095 14096 cleanup: 14097 14098 #ifndef HAVE_LMDB 14099 if (fp != NULL) { 14100 (void)isc_stdio_close(fp); 14101 } 14102 if (result != ISC_R_SUCCESS && cleanup_config) { 14103 tresult = delete_zoneconf(view, cfg->add_parser, 14104 cfg->nzf_config, name, NULL); 14105 RUNTIME_CHECK(tresult == ISC_R_SUCCESS); 14106 } 14107 #else /* HAVE_LMDB */ 14108 if (txn != NULL) { 14109 (void)nzd_close(&txn, false); 14110 } 14111 if (locked) { 14112 UNLOCK(&view->new_zone_lock); 14113 } 14114 #endif /* HAVE_LMDB */ 14115 14116 if (zone != NULL) { 14117 dns_zone_detach(&zone); 14118 } 14119 14120 return result; 14121 } 14122 14123 static isc_result_t 14124 do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, 14125 dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj, 14126 bool redirect, isc_buffer_t **text) { 14127 isc_result_t result, tresult; 14128 dns_zone_t *zone = NULL; 14129 bool added; 14130 #ifndef HAVE_LMDB 14131 FILE *fp = NULL; 14132 cfg_obj_t *z; 14133 #else /* HAVE_LMDB */ 14134 MDB_txn *txn = NULL; 14135 MDB_dbi dbi; 14136 bool locked = false; 14137 #endif /* HAVE_LMDB */ 14138 14139 /* Zone must already exist */ 14140 if (redirect) { 14141 if (view->redirect != NULL) { 14142 dns_zone_attach(view->redirect, &zone); 14143 result = ISC_R_SUCCESS; 14144 } else { 14145 result = ISC_R_NOTFOUND; 14146 } 14147 } else { 14148 result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); 14149 } 14150 if (result != ISC_R_SUCCESS) { 14151 goto cleanup; 14152 } 14153 14154 added = dns_zone_getadded(zone); 14155 dns_zone_detach(&zone); 14156 14157 #ifndef HAVE_LMDB 14158 cfg = (ns_cfgctx_t *)view->new_zone_config; 14159 if (cfg == NULL) { 14160 TCHECK(putstr(text, "new zone config is not set")); 14161 CHECK(ISC_R_FAILURE); 14162 } 14163 #endif /* ifndef HAVE_LMDB */ 14164 14165 isc_loopmgr_pause(named_g_loopmgr); 14166 14167 #ifndef HAVE_LMDB 14168 /* Make sure we can open the configuration save file */ 14169 result = isc_stdio_open(view->new_zone_file, "a", &fp); 14170 if (result != ISC_R_SUCCESS) { 14171 TCHECK(putstr(text, "unable to open '")); 14172 TCHECK(putstr(text, view->new_zone_file)); 14173 TCHECK(putstr(text, "': ")); 14174 TCHECK(putstr(text, isc_result_totext(result))); 14175 isc_loopmgr_resume(named_g_loopmgr); 14176 goto cleanup; 14177 } 14178 (void)isc_stdio_close(fp); 14179 fp = NULL; 14180 #else /* HAVE_LMDB */ 14181 LOCK(&view->new_zone_lock); 14182 locked = true; 14183 /* Make sure we can open the NZD database */ 14184 result = nzd_writable(view); 14185 if (result != ISC_R_SUCCESS) { 14186 TCHECK(putstr(text, "unable to open NZD database for '")); 14187 TCHECK(putstr(text, view->new_zone_db)); 14188 TCHECK(putstr(text, "'")); 14189 result = ISC_R_FAILURE; 14190 isc_loopmgr_resume(named_g_loopmgr); 14191 goto cleanup; 14192 } 14193 #endif /* HAVE_LMDB */ 14194 14195 /* Reconfigure the zone */ 14196 dns_view_thaw(view); 14197 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, 14198 &server->viewlist, &server->kasplist, 14199 &server->keystorelist, cfg->actx, true, false, 14200 false, true); 14201 dns_view_freeze(view); 14202 14203 isc_loopmgr_resume(named_g_loopmgr); 14204 14205 if (result != ISC_R_SUCCESS) { 14206 TCHECK(putstr(text, "configure_zone failed: ")); 14207 TCHECK(putstr(text, isc_result_totext(result))); 14208 goto cleanup; 14209 } 14210 14211 /* Is it there yet? */ 14212 if (redirect) { 14213 if (view->redirect == NULL) { 14214 CHECK(ISC_R_NOTFOUND); 14215 } 14216 dns_zone_attach(view->redirect, &zone); 14217 } else { 14218 CHECK(dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone)); 14219 } 14220 14221 #ifndef HAVE_LMDB 14222 /* Remove old zone from configuration (and NZF file if applicable) */ 14223 if (added) { 14224 result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, 14225 dns_zone_getorigin(zone), 14226 nzf_writeconf); 14227 if (result != ISC_R_SUCCESS) { 14228 TCHECK(putstr(text, "former zone configuration " 14229 "not deleted: ")); 14230 TCHECK(putstr(text, isc_result_totext(result))); 14231 goto cleanup; 14232 } 14233 } 14234 #endif /* HAVE_LMDB */ 14235 14236 if (!added) { 14237 if (cfg->vconfig == NULL) { 14238 result = delete_zoneconf( 14239 view, cfg->conf_parser, cfg->config, 14240 dns_zone_getorigin(zone), NULL); 14241 } else { 14242 const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, 14243 "options"); 14244 result = delete_zoneconf( 14245 view, cfg->conf_parser, voptions, 14246 dns_zone_getorigin(zone), NULL); 14247 } 14248 14249 if (result != ISC_R_SUCCESS) { 14250 TCHECK(putstr(text, "former zone configuration " 14251 "not deleted: ")); 14252 TCHECK(putstr(text, isc_result_totext(result))); 14253 goto cleanup; 14254 } 14255 } 14256 14257 /* Load the zone from the master file if it needs reloading. */ 14258 result = dns_zone_load(zone, true); 14259 14260 /* 14261 * Dynamic zones need no reloading, so we can pass this result. 14262 */ 14263 if (result == DNS_R_DYNAMIC) { 14264 result = ISC_R_SUCCESS; 14265 } 14266 14267 if (result != ISC_R_SUCCESS) { 14268 dns_db_t *dbp = NULL; 14269 14270 TCHECK(putstr(text, "failed to load zone '")); 14271 TCHECK(putstr(text, zname)); 14272 TCHECK(putstr(text, "': ")); 14273 TCHECK(putstr(text, isc_result_totext(result))); 14274 TCHECK(putstr(text, "\nThe zone is no longer being served. ")); 14275 TCHECK(putstr(text, "Use 'rndc addzone' to correct\n")); 14276 TCHECK(putstr(text, "the problem and restore service.")); 14277 14278 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14279 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14280 "modzone failed; removing zone."); 14281 14282 /* If the zone loaded partially, unload it */ 14283 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14284 dns_db_detach(&dbp); 14285 dns_zone_unload(zone); 14286 } 14287 14288 /* Remove the zone from the zone table */ 14289 dns_view_delzone(view, zone); 14290 goto cleanup; 14291 } 14292 14293 #ifndef HAVE_LMDB 14294 /* Store the new zone configuration; also in NZF if applicable */ 14295 z = UNCONST(zoneobj); 14296 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone")); 14297 #endif /* HAVE_LMDB */ 14298 14299 if (added) { 14300 #ifdef HAVE_LMDB 14301 CHECK(nzd_open(view, 0, &txn, &dbi)); 14302 CHECK(nzd_save(&txn, dbi, zone, zoneobj)); 14303 #else /* ifdef HAVE_LMDB */ 14304 result = nzf_append(view, zoneobj); 14305 if (result != ISC_R_SUCCESS) { 14306 TCHECK(putstr(text, "\nNew zone config not saved: ")); 14307 TCHECK(putstr(text, isc_result_totext(result))); 14308 goto cleanup; 14309 } 14310 #endif /* HAVE_LMDB */ 14311 14312 TCHECK(putstr(text, "zone '")); 14313 TCHECK(putstr(text, zname)); 14314 TCHECK(putstr(text, "' reconfigured.")); 14315 } else { 14316 TCHECK(putstr(text, "zone '")); 14317 TCHECK(putstr(text, zname)); 14318 TCHECK(putstr(text, "' must also be reconfigured in\n")); 14319 TCHECK(putstr(text, "named.conf to make changes permanent.")); 14320 } 14321 14322 cleanup: 14323 14324 #ifndef HAVE_LMDB 14325 if (fp != NULL) { 14326 (void)isc_stdio_close(fp); 14327 } 14328 #else /* HAVE_LMDB */ 14329 if (txn != NULL) { 14330 (void)nzd_close(&txn, false); 14331 } 14332 if (locked) { 14333 UNLOCK(&view->new_zone_lock); 14334 } 14335 #endif /* HAVE_LMDB */ 14336 14337 if (zone != NULL) { 14338 dns_zone_detach(&zone); 14339 } 14340 14341 return result; 14342 } 14343 14344 /* 14345 * Act on an "addzone" or "modzone" command from the command channel. 14346 */ 14347 isc_result_t 14348 named_server_changezone(named_server_t *server, char *command, 14349 isc_buffer_t **text) { 14350 isc_result_t result; 14351 bool addzone; 14352 bool redirect = false; 14353 ns_cfgctx_t *cfg = NULL; 14354 cfg_obj_t *zoneconf = NULL; 14355 const cfg_obj_t *zoneobj = NULL; 14356 const char *zonename; 14357 dns_view_t *view = NULL; 14358 isc_buffer_t buf; 14359 dns_fixedname_t fname; 14360 dns_name_t *dnsname; 14361 14362 REQUIRE(text != NULL); 14363 14364 if (strncasecmp(command, "add", 3) == 0) { 14365 addzone = true; 14366 } else { 14367 INSIST(strncasecmp(command, "mod", 3) == 0); 14368 addzone = false; 14369 } 14370 14371 CHECK(newzone_parse(server, command, &view, &zoneconf, &zoneobj, 14372 &redirect, text)); 14373 14374 /* Are we accepting new zones in this view? */ 14375 #ifdef HAVE_LMDB 14376 if (view->new_zone_db == NULL) 14377 #else /* ifdef HAVE_LMDB */ 14378 if (view->new_zone_file == NULL) 14379 #endif /* HAVE_LMDB */ 14380 { 14381 (void)putstr(text, "Not allowing new zones in view '"); 14382 (void)putstr(text, view->name); 14383 (void)putstr(text, "'"); 14384 result = ISC_R_NOPERM; 14385 goto cleanup; 14386 } 14387 14388 cfg = (ns_cfgctx_t *)view->new_zone_config; 14389 if (cfg == NULL) { 14390 result = ISC_R_FAILURE; 14391 goto cleanup; 14392 } 14393 14394 zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name")); 14395 isc_buffer_constinit(&buf, zonename, strlen(zonename)); 14396 isc_buffer_add(&buf, strlen(zonename)); 14397 14398 dnsname = dns_fixedname_initname(&fname); 14399 CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, 0, NULL)); 14400 14401 if (redirect) { 14402 if (!dns_name_equal(dnsname, dns_rootname)) { 14403 (void)putstr(text, "redirect zones must be called " 14404 "\".\""); 14405 CHECK(ISC_R_FAILURE); 14406 } 14407 } 14408 14409 if (addzone) { 14410 CHECK(do_addzone(server, cfg, view, dnsname, zoneconf, zoneobj, 14411 redirect, text)); 14412 } else { 14413 CHECK(do_modzone(server, cfg, view, dnsname, zonename, zoneobj, 14414 redirect, text)); 14415 } 14416 14417 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14418 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14419 "%s zone %s in view %s via %s", 14420 addzone ? "added" : "updated", zonename, view->name, 14421 addzone ? NAMED_COMMAND_ADDZONE : NAMED_COMMAND_MODZONE); 14422 14423 /* Changing a zone counts as reconfiguration */ 14424 named_g_configtime = isc_time_now(); 14425 14426 cleanup: 14427 if (isc_buffer_usedlength(*text) > 0) { 14428 (void)putnull(text); 14429 } 14430 if (zoneconf != NULL) { 14431 cfg_obj_destroy(named_g_addparser, &zoneconf); 14432 } 14433 if (view != NULL) { 14434 dns_view_detach(&view); 14435 } 14436 14437 return result; 14438 } 14439 14440 static bool 14441 inuse(const char *file, bool first, isc_buffer_t **text) { 14442 if (file != NULL && isc_file_exists(file)) { 14443 if (first) { 14444 (void)putstr(text, "The following files were in use " 14445 "and may now be removed:\n"); 14446 } else { 14447 (void)putstr(text, "\n"); 14448 } 14449 (void)putstr(text, file); 14450 (void)putnull(text); 14451 return false; 14452 } 14453 return first; 14454 } 14455 14456 typedef struct { 14457 dns_zone_t *zone; 14458 bool cleanup; 14459 } ns_dzctx_t; 14460 14461 /* 14462 * Carry out a zone deletion scheduled by named_server_delzone(). 14463 */ 14464 static void 14465 rmzone(void *arg) { 14466 ns_dzctx_t *dz = (ns_dzctx_t *)arg; 14467 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; 14468 dns_catz_zone_t *catz = NULL; 14469 char zonename[DNS_NAME_FORMATSIZE]; 14470 dns_view_t *view = NULL; 14471 ns_cfgctx_t *cfg = NULL; 14472 dns_db_t *dbp = NULL; 14473 bool added; 14474 isc_result_t result; 14475 #ifdef HAVE_LMDB 14476 MDB_txn *txn = NULL; 14477 MDB_dbi dbi; 14478 #endif /* ifdef HAVE_LMDB */ 14479 14480 REQUIRE(dz != NULL); 14481 14482 /* Dig out configuration for this zone */ 14483 zone = dz->zone; 14484 view = dns_zone_getview(zone); 14485 cfg = (ns_cfgctx_t *)view->new_zone_config; 14486 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 14487 14488 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14489 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14490 "deleting zone %s in view %s via delzone", zonename, 14491 view->name); 14492 14493 /* 14494 * Remove the zone from configuration (and NZF file if applicable) 14495 * (If this is a catalog zone member then nzf_config can be NULL) 14496 */ 14497 added = dns_zone_getadded(zone); 14498 catz = dns_zone_get_parentcatz(zone); 14499 14500 if (added && catz == NULL && cfg != NULL) { 14501 #ifdef HAVE_LMDB 14502 /* Make sure we can open the NZD database */ 14503 LOCK(&view->new_zone_lock); 14504 result = nzd_open(view, 0, &txn, &dbi); 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 open NZD database for '%s'", 14509 view->new_zone_db); 14510 } else { 14511 result = nzd_save(&txn, dbi, zone, NULL); 14512 } 14513 14514 if (result != ISC_R_SUCCESS) { 14515 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14516 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14517 "unable to delete zone configuration: %s", 14518 isc_result_totext(result)); 14519 } 14520 14521 if (txn != NULL) { 14522 (void)nzd_close(&txn, false); 14523 } 14524 UNLOCK(&view->new_zone_lock); 14525 #else /* ifdef HAVE_LMDB */ 14526 result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, 14527 dns_zone_getorigin(zone), 14528 nzf_writeconf); 14529 if (result != ISC_R_SUCCESS) { 14530 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14531 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14532 "unable to delete zone configuration: %s", 14533 isc_result_totext(result)); 14534 } 14535 #endif /* HAVE_LMDB */ 14536 } 14537 14538 if (!added && cfg != NULL) { 14539 if (cfg->vconfig != NULL) { 14540 const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, 14541 "options"); 14542 result = delete_zoneconf( 14543 view, cfg->conf_parser, voptions, 14544 dns_zone_getorigin(zone), NULL); 14545 } else { 14546 result = delete_zoneconf( 14547 view, cfg->conf_parser, cfg->config, 14548 dns_zone_getorigin(zone), NULL); 14549 } 14550 if (result != ISC_R_SUCCESS) { 14551 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14552 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14553 "unable to delete zone configuration: %s", 14554 isc_result_totext(result)); 14555 } 14556 } 14557 14558 /* Unload zone database */ 14559 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14560 dns_db_detach(&dbp); 14561 dns_zone_unload(zone); 14562 } 14563 14564 /* Clean up stub/secondary zone files if requested to do so */ 14565 dns_zone_getraw(zone, &raw); 14566 mayberaw = (raw != NULL) ? raw : zone; 14567 14568 if (added && dz->cleanup) { 14569 const char *file; 14570 14571 file = dns_zone_getfile(mayberaw); 14572 result = isc_file_remove(file); 14573 if (result != ISC_R_SUCCESS) { 14574 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14575 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14576 "file %s not removed: %s", file, 14577 isc_result_totext(result)); 14578 } 14579 14580 file = dns_zone_getjournal(mayberaw); 14581 result = isc_file_remove(file); 14582 if (result != ISC_R_SUCCESS) { 14583 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14584 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14585 "file %s not removed: %s", file, 14586 isc_result_totext(result)); 14587 } 14588 14589 if (zone != mayberaw) { 14590 file = dns_zone_getfile(zone); 14591 result = isc_file_remove(file); 14592 if (result != ISC_R_SUCCESS) { 14593 isc_log_write( 14594 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14595 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14596 "file %s not removed: %s", file, 14597 isc_result_totext(result)); 14598 } 14599 14600 file = dns_zone_getjournal(zone); 14601 result = isc_file_remove(file); 14602 if (result != ISC_R_SUCCESS) { 14603 isc_log_write( 14604 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14605 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14606 "file %s not removed: %s", file, 14607 isc_result_totext(result)); 14608 } 14609 } 14610 } 14611 14612 if (raw != NULL) { 14613 dns_zone_detach(&raw); 14614 } 14615 dns_zone_detach(&zone); 14616 isc_mem_put(named_g_mctx, dz, sizeof(*dz)); 14617 } 14618 14619 /* 14620 * Act on a "delzone" command from the command channel. 14621 */ 14622 isc_result_t 14623 named_server_delzone(named_server_t *server, isc_lex_t *lex, 14624 isc_buffer_t **text) { 14625 isc_result_t result, tresult; 14626 dns_zone_t *zone = NULL; 14627 dns_zone_t *raw = NULL; 14628 dns_zone_t *mayberaw; 14629 dns_view_t *view = NULL; 14630 char zonename[DNS_NAME_FORMATSIZE]; 14631 bool cleanup = false; 14632 const char *ptr; 14633 bool added; 14634 ns_dzctx_t *dz = NULL; 14635 14636 REQUIRE(text != NULL); 14637 14638 /* Skip the command name. */ 14639 ptr = next_token(lex, text); 14640 if (ptr == NULL) { 14641 return ISC_R_UNEXPECTEDEND; 14642 } 14643 14644 /* Find out what we are to do. */ 14645 ptr = next_token(lex, text); 14646 if (ptr == NULL) { 14647 return ISC_R_UNEXPECTEDEND; 14648 } 14649 14650 if (strcmp(ptr, "-clean") == 0 || strcmp(ptr, "-clear") == 0) { 14651 cleanup = true; 14652 ptr = next_token(lex, text); 14653 } 14654 14655 CHECK(zone_from_args(server, lex, ptr, &zone, zonename, text, false)); 14656 if (zone == NULL) { 14657 result = ISC_R_UNEXPECTEDEND; 14658 goto cleanup; 14659 } 14660 14661 INSIST(zonename != NULL); 14662 14663 /* Is this a policy zone? */ 14664 if (dns_zone_get_rpz_num(zone) != DNS_RPZ_INVALID_NUM) { 14665 TCHECK(putstr(text, "zone '")); 14666 TCHECK(putstr(text, zonename)); 14667 TCHECK(putstr(text, 14668 "' cannot be deleted: response-policy zone.")); 14669 result = ISC_R_FAILURE; 14670 goto cleanup; 14671 } 14672 14673 view = dns_zone_getview(zone); 14674 if (dns_zone_gettype(zone) == dns_zone_redirect) { 14675 dns_zone_detach(&view->redirect); 14676 } else { 14677 CHECK(dns_view_delzone(view, zone)); 14678 } 14679 14680 /* Send cleanup event */ 14681 dz = isc_mem_get(named_g_mctx, sizeof(*dz)); 14682 *dz = (ns_dzctx_t){ 14683 .cleanup = cleanup, 14684 }; 14685 dns_zone_attach(zone, &dz->zone); 14686 isc_async_run(dns_zone_getloop(zone), rmzone, dz); 14687 14688 /* Inform user about cleaning up stub/secondary zone files */ 14689 dns_zone_getraw(zone, &raw); 14690 mayberaw = (raw != NULL) ? raw : zone; 14691 14692 added = dns_zone_getadded(zone); 14693 if (!added) { 14694 TCHECK(putstr(text, "zone '")); 14695 TCHECK(putstr(text, zonename)); 14696 TCHECK(putstr(text, "' is no longer active and will be " 14697 "deleted.\n")); 14698 TCHECK(putstr(text, "To keep it from returning ")); 14699 TCHECK(putstr(text, "when the server is restarted, it\n")); 14700 TCHECK(putstr(text, "must also be removed from named.conf.")); 14701 } else if (cleanup) { 14702 TCHECK(putstr(text, "zone '")); 14703 TCHECK(putstr(text, zonename)); 14704 TCHECK(putstr(text, "' and associated files will be deleted.")); 14705 } else if (dns_zone_gettype(mayberaw) == dns_zone_secondary || 14706 dns_zone_gettype(mayberaw) == dns_zone_mirror || 14707 dns_zone_gettype(mayberaw) == dns_zone_stub) 14708 { 14709 bool first; 14710 const char *file; 14711 14712 TCHECK(putstr(text, "zone '")); 14713 TCHECK(putstr(text, zonename)); 14714 TCHECK(putstr(text, "' will be deleted.")); 14715 14716 file = dns_zone_getfile(mayberaw); 14717 first = inuse(file, true, text); 14718 14719 file = dns_zone_getjournal(mayberaw); 14720 first = inuse(file, first, text); 14721 14722 if (zone != mayberaw) { 14723 file = dns_zone_getfile(zone); 14724 first = inuse(file, first, text); 14725 14726 file = dns_zone_getjournal(zone); 14727 (void)inuse(file, first, text); 14728 } 14729 } 14730 14731 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14732 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14733 "zone %s scheduled for removal via delzone", zonename); 14734 14735 /* Removing a zone counts as reconfiguration */ 14736 named_g_configtime = isc_time_now(); 14737 14738 result = ISC_R_SUCCESS; 14739 14740 cleanup: 14741 if (isc_buffer_usedlength(*text) > 0) { 14742 (void)putnull(text); 14743 } 14744 if (raw != NULL) { 14745 dns_zone_detach(&raw); 14746 } 14747 if (zone != NULL) { 14748 dns_zone_detach(&zone); 14749 } 14750 14751 return result; 14752 } 14753 14754 static const cfg_obj_t * 14755 find_name_in_list_from_map(const cfg_obj_t *config, 14756 const char *map_key_for_list, const char *name, 14757 bool redirect) { 14758 const cfg_obj_t *list = NULL; 14759 const cfg_listelt_t *element; 14760 const cfg_obj_t *obj = NULL; 14761 dns_fixedname_t fixed1, fixed2; 14762 dns_name_t *name1 = NULL, *name2 = NULL; 14763 isc_result_t result; 14764 14765 if (strcmp(map_key_for_list, "zone") == 0) { 14766 name1 = dns_fixedname_initname(&fixed1); 14767 name2 = dns_fixedname_initname(&fixed2); 14768 result = dns_name_fromstring(name1, name, dns_rootname, 0, 14769 NULL); 14770 RUNTIME_CHECK(result == ISC_R_SUCCESS); 14771 } 14772 14773 cfg_map_get(config, map_key_for_list, &list); 14774 for (element = cfg_list_first(list); element != NULL; 14775 element = cfg_list_next(element)) 14776 { 14777 const char *vname; 14778 14779 obj = cfg_listelt_value(element); 14780 INSIST(obj != NULL); 14781 vname = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 14782 if (vname == NULL) { 14783 obj = NULL; 14784 continue; 14785 } 14786 14787 if (name1 != NULL) { 14788 result = dns_name_fromstring(name2, vname, dns_rootname, 14789 0, NULL); 14790 if (result == ISC_R_SUCCESS && 14791 dns_name_equal(name1, name2)) 14792 { 14793 const cfg_obj_t *zoptions; 14794 const cfg_obj_t *typeobj = NULL; 14795 zoptions = cfg_tuple_get(obj, "options"); 14796 14797 if (zoptions != NULL) { 14798 cfg_map_get(zoptions, "type", &typeobj); 14799 } 14800 if (redirect && typeobj != NULL && 14801 strcasecmp(cfg_obj_asstring(typeobj), 14802 "redirect") == 0) 14803 { 14804 break; 14805 } else if (!redirect) { 14806 break; 14807 } 14808 } 14809 } else if (strcasecmp(vname, name) == 0) { 14810 break; 14811 } 14812 14813 obj = NULL; 14814 } 14815 14816 return obj; 14817 } 14818 14819 static void 14820 emitzone(void *arg, const char *buf, int len) { 14821 ns_dzarg_t *dzarg = arg; 14822 isc_result_t result; 14823 14824 REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); 14825 result = putmem(dzarg->text, buf, len); 14826 if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { 14827 dzarg->result = result; 14828 } 14829 } 14830 14831 /* 14832 * Act on a "showzone" command from the command channel. 14833 */ 14834 isc_result_t 14835 named_server_showzone(named_server_t *server, isc_lex_t *lex, 14836 isc_buffer_t **text) { 14837 isc_result_t result; 14838 const cfg_obj_t *vconfig = NULL, *zconfig = NULL; 14839 char zonename[DNS_NAME_FORMATSIZE]; 14840 const cfg_obj_t *map; 14841 dns_view_t *view = NULL; 14842 dns_zone_t *zone = NULL; 14843 ns_cfgctx_t *cfg = NULL; 14844 #ifdef HAVE_LMDB 14845 cfg_obj_t *nzconfig = NULL; 14846 #endif /* HAVE_LMDB */ 14847 bool added, redirect; 14848 ns_dzarg_t dzarg; 14849 14850 REQUIRE(text != NULL); 14851 14852 /* Parse parameters */ 14853 CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); 14854 if (zone == NULL) { 14855 result = ISC_R_UNEXPECTEDEND; 14856 goto cleanup; 14857 } 14858 14859 redirect = dns_zone_gettype(zone) == dns_zone_redirect; 14860 added = dns_zone_getadded(zone); 14861 view = dns_zone_getview(zone); 14862 dns_zone_detach(&zone); 14863 14864 cfg = (ns_cfgctx_t *)view->new_zone_config; 14865 if (cfg == NULL) { 14866 result = ISC_R_FAILURE; 14867 goto cleanup; 14868 } 14869 14870 if (!added) { 14871 /* Find the view statement */ 14872 vconfig = find_name_in_list_from_map(cfg->config, "view", 14873 view->name, false); 14874 14875 /* Find the zone statement */ 14876 if (vconfig != NULL) { 14877 map = cfg_tuple_get(vconfig, "options"); 14878 } else { 14879 map = cfg->config; 14880 } 14881 14882 zconfig = find_name_in_list_from_map(map, "zone", zonename, 14883 redirect); 14884 } 14885 14886 #ifndef HAVE_LMDB 14887 if (zconfig == NULL && cfg->nzf_config != NULL) { 14888 zconfig = find_name_in_list_from_map(cfg->nzf_config, "zone", 14889 zonename, redirect); 14890 } 14891 #else /* HAVE_LMDB */ 14892 if (zconfig == NULL) { 14893 const cfg_obj_t *zlist = NULL; 14894 CHECK(get_newzone_config(view, zonename, &nzconfig)); 14895 CHECK(cfg_map_get(nzconfig, "zone", &zlist)); 14896 if (!cfg_obj_islist(zlist)) { 14897 CHECK(ISC_R_FAILURE); 14898 } 14899 14900 zconfig = cfg_listelt_value(cfg_list_first(zlist)); 14901 } 14902 #endif /* HAVE_LMDB */ 14903 14904 if (zconfig == NULL) { 14905 CHECK(ISC_R_NOTFOUND); 14906 } 14907 14908 CHECK(putstr(text, "zone ")); 14909 dzarg.magic = DZARG_MAGIC; 14910 dzarg.text = text; 14911 dzarg.result = ISC_R_SUCCESS; 14912 cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, &dzarg); 14913 CHECK(dzarg.result); 14914 14915 CHECK(putstr(text, ";")); 14916 14917 result = ISC_R_SUCCESS; 14918 14919 cleanup: 14920 #ifdef HAVE_LMDB 14921 if (nzconfig != NULL) { 14922 cfg_obj_destroy(named_g_addparser, &nzconfig); 14923 } 14924 #endif /* HAVE_LMDB */ 14925 if (isc_buffer_usedlength(*text) > 0) { 14926 (void)putnull(text); 14927 } 14928 14929 return result; 14930 } 14931 14932 static void 14933 newzone_cfgctx_destroy(void **cfgp) { 14934 ns_cfgctx_t *cfg; 14935 14936 REQUIRE(cfgp != NULL && *cfgp != NULL); 14937 14938 cfg = *cfgp; 14939 14940 if (cfg->conf_parser != NULL) { 14941 if (cfg->config != NULL) { 14942 cfg_obj_destroy(cfg->conf_parser, &cfg->config); 14943 } 14944 if (cfg->vconfig != NULL) { 14945 cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig); 14946 } 14947 cfg_parser_destroy(&cfg->conf_parser); 14948 } 14949 if (cfg->add_parser != NULL) { 14950 if (cfg->nzf_config != NULL) { 14951 cfg_obj_destroy(cfg->add_parser, &cfg->nzf_config); 14952 } 14953 cfg_parser_destroy(&cfg->add_parser); 14954 } 14955 14956 if (cfg->actx != NULL) { 14957 cfg_aclconfctx_detach(&cfg->actx); 14958 } 14959 14960 isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); 14961 *cfgp = NULL; 14962 } 14963 14964 isc_result_t 14965 named_server_signing(named_server_t *server, isc_lex_t *lex, 14966 isc_buffer_t **text) { 14967 isc_result_t result = ISC_R_SUCCESS; 14968 dns_zone_t *zone = NULL; 14969 dns_name_t *origin; 14970 dns_db_t *db = NULL; 14971 dns_dbnode_t *node = NULL; 14972 dns_dbversion_t *version = NULL; 14973 dns_rdatatype_t privatetype; 14974 dns_rdataset_t privset; 14975 bool first = true; 14976 bool list = false, clear = false; 14977 bool chain = false; 14978 bool setserial = false; 14979 bool resalt = false; 14980 uint32_t serial = 0; 14981 char keystr[DNS_SECALG_FORMATSIZE + 7]; /* <5-digit keyid>/<alg> */ 14982 unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0; 14983 unsigned char salt[255]; 14984 const char *ptr; 14985 size_t n; 14986 bool kasp = false; 14987 14988 REQUIRE(text != NULL); 14989 14990 dns_rdataset_init(&privset); 14991 14992 /* Skip the command name. */ 14993 ptr = next_token(lex, text); 14994 if (ptr == NULL) { 14995 return ISC_R_UNEXPECTEDEND; 14996 } 14997 14998 /* Find out what we are to do. */ 14999 ptr = next_token(lex, text); 15000 if (ptr == NULL) { 15001 return ISC_R_UNEXPECTEDEND; 15002 } 15003 15004 if (strcasecmp(ptr, "-list") == 0) { 15005 list = true; 15006 } else if ((strcasecmp(ptr, "-clear") == 0) || 15007 (strcasecmp(ptr, "-clean") == 0)) 15008 { 15009 clear = true; 15010 ptr = next_token(lex, text); 15011 if (ptr == NULL) { 15012 return ISC_R_UNEXPECTEDEND; 15013 } 15014 strlcpy(keystr, ptr, sizeof(keystr)); 15015 } else if (strcasecmp(ptr, "-nsec3param") == 0) { 15016 char hashbuf[64], flagbuf[64], iterbuf[64]; 15017 char nbuf[256]; 15018 15019 chain = true; 15020 ptr = next_token(lex, text); 15021 if (ptr == NULL) { 15022 return ISC_R_UNEXPECTEDEND; 15023 } 15024 15025 if (strcasecmp(ptr, "none") == 0) { 15026 hash = 0; 15027 } else { 15028 strlcpy(hashbuf, ptr, sizeof(hashbuf)); 15029 15030 ptr = next_token(lex, text); 15031 if (ptr == NULL) { 15032 return ISC_R_UNEXPECTEDEND; 15033 } 15034 strlcpy(flagbuf, ptr, sizeof(flagbuf)); 15035 15036 ptr = next_token(lex, text); 15037 if (ptr == NULL) { 15038 return ISC_R_UNEXPECTEDEND; 15039 } 15040 strlcpy(iterbuf, ptr, sizeof(iterbuf)); 15041 n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", hashbuf, 15042 flagbuf, iterbuf); 15043 if (n == sizeof(nbuf)) { 15044 return ISC_R_NOSPACE; 15045 } 15046 n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); 15047 if (n != 3U) { 15048 return ISC_R_BADNUMBER; 15049 } 15050 15051 if (hash > 0xffU || flags > 0xffU || 15052 iter > dns_nsec3_maxiterations()) 15053 { 15054 return ISC_R_RANGE; 15055 } 15056 15057 ptr = next_token(lex, text); 15058 if (ptr == NULL) { 15059 return ISC_R_UNEXPECTEDEND; 15060 } else if (strcasecmp(ptr, "auto") == 0) { 15061 /* Auto-generate a random salt. 15062 * XXXMUKS: This currently uses the 15063 * minimum recommended length by RFC 15064 * 5155 (64 bits). It should be made 15065 * configurable. 15066 */ 15067 saltlen = 8; 15068 resalt = true; 15069 } else if (strcmp(ptr, "-") != 0) { 15070 isc_buffer_t buf; 15071 15072 isc_buffer_init(&buf, salt, sizeof(salt)); 15073 CHECK(isc_hex_decodestring(ptr, &buf)); 15074 saltlen = isc_buffer_usedlength(&buf); 15075 } 15076 } 15077 } else if (strcasecmp(ptr, "-serial") == 0) { 15078 ptr = next_token(lex, text); 15079 if (ptr == NULL) { 15080 return ISC_R_UNEXPECTEDEND; 15081 } 15082 CHECK(isc_parse_uint32(&serial, ptr, 10)); 15083 setserial = true; 15084 } else { 15085 CHECK(DNS_R_SYNTAX); 15086 } 15087 15088 CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); 15089 if (zone == NULL) { 15090 CHECK(ISC_R_UNEXPECTEDEND); 15091 } 15092 15093 if (dns_zone_getkasp(zone) != NULL) { 15094 kasp = true; 15095 } 15096 15097 if (clear) { 15098 CHECK(dns_zone_keydone(zone, keystr)); 15099 (void)putstr(text, "request queued"); 15100 (void)putnull(text); 15101 } else if (chain && !kasp) { 15102 CHECK(dns_zone_setnsec3param( 15103 zone, (uint8_t)hash, (uint8_t)flags, iter, 15104 (uint8_t)saltlen, salt, true, resalt)); 15105 (void)putstr(text, "nsec3param request queued"); 15106 (void)putnull(text); 15107 } else if (setserial) { 15108 CHECK(dns_zone_setserial(zone, serial)); 15109 (void)putstr(text, "serial request queued"); 15110 (void)putnull(text); 15111 } else if (list) { 15112 privatetype = dns_zone_getprivatetype(zone); 15113 origin = dns_zone_getorigin(zone); 15114 CHECK(dns_zone_getdb(zone, &db)); 15115 CHECK(dns_db_findnode(db, origin, false, &node)); 15116 dns_db_currentversion(db, &version); 15117 15118 result = dns_db_findrdataset(db, node, version, privatetype, 15119 dns_rdatatype_none, 0, &privset, 15120 NULL); 15121 if (result == ISC_R_NOTFOUND) { 15122 (void)putstr(text, "No signing records found"); 15123 (void)putnull(text); 15124 result = ISC_R_SUCCESS; 15125 goto cleanup; 15126 } 15127 15128 for (result = dns_rdataset_first(&privset); 15129 result == ISC_R_SUCCESS; 15130 result = dns_rdataset_next(&privset)) 15131 { 15132 dns_rdata_t priv = DNS_RDATA_INIT; 15133 /* 15134 * In theory, the output buffer could hold a full RDATA 15135 * record which is 16-bit and then some text around 15136 * it 15137 */ 15138 char output[UINT16_MAX + BUFSIZ]; 15139 isc_buffer_t buf; 15140 15141 dns_rdataset_current(&privset, &priv); 15142 15143 isc_buffer_init(&buf, output, sizeof(output)); 15144 CHECK(dns_private_totext(&priv, &buf)); 15145 if (!first) { 15146 CHECK(putstr(text, "\n")); 15147 } 15148 CHECK(putstr(text, output)); 15149 first = false; 15150 } 15151 if (!first) { 15152 CHECK(putnull(text)); 15153 } 15154 15155 if (result == ISC_R_NOMORE) { 15156 result = ISC_R_SUCCESS; 15157 } 15158 } else if (kasp) { 15159 (void)putstr(text, "zone uses dnssec-policy, use rndc dnssec " 15160 "command instead"); 15161 (void)putnull(text); 15162 } 15163 15164 cleanup: 15165 if (dns_rdataset_isassociated(&privset)) { 15166 dns_rdataset_disassociate(&privset); 15167 } 15168 if (node != NULL) { 15169 dns_db_detachnode(db, &node); 15170 } 15171 if (version != NULL) { 15172 dns_db_closeversion(db, &version, false); 15173 } 15174 if (db != NULL) { 15175 dns_db_detach(&db); 15176 } 15177 if (zone != NULL) { 15178 dns_zone_detach(&zone); 15179 } 15180 15181 return result; 15182 } 15183 15184 static bool 15185 argcheck(char *cmd, const char *full) { 15186 size_t l; 15187 15188 if (cmd == NULL || cmd[0] != '-') { 15189 return false; 15190 } 15191 15192 cmd++; 15193 l = strlen(cmd); 15194 if (l > strlen(full) || strncasecmp(cmd, full, l) != 0) { 15195 return false; 15196 } 15197 15198 return true; 15199 } 15200 15201 isc_result_t 15202 named_server_dnssec(named_server_t *server, isc_lex_t *lex, 15203 isc_buffer_t **text) { 15204 isc_result_t result = ISC_R_SUCCESS; 15205 dns_zone_t *zone = NULL; 15206 dns_kasp_t *kasp = NULL; 15207 dns_dnsseckeylist_t keys; 15208 dns_dnsseckey_t *key; 15209 char *ptr, *zonetext = NULL; 15210 const char *msg = NULL; 15211 /* variables for -step */ 15212 bool forcestep = false; 15213 /* variables for -checkds */ 15214 bool checkds = false, dspublish = false; 15215 /* variables for -rollover */ 15216 bool rollover = false; 15217 /* variables for -key */ 15218 bool use_keyid = false; 15219 dns_keytag_t keyid = 0; 15220 uint8_t algorithm = 0; 15221 /* variables for -status */ 15222 bool status = false; 15223 char output[4096]; 15224 isc_stdtime_t now, when; 15225 isc_time_t timenow, timewhen; 15226 dns_db_t *db = NULL; 15227 dns_dbversion_t *version = NULL; 15228 15229 REQUIRE(text != NULL); 15230 15231 /* Skip the command name. */ 15232 ptr = next_token(lex, text); 15233 if (ptr == NULL) { 15234 return ISC_R_UNEXPECTEDEND; 15235 } 15236 15237 /* Find out what we are to do. */ 15238 ptr = next_token(lex, text); 15239 if (ptr == NULL) { 15240 return ISC_R_UNEXPECTEDEND; 15241 } 15242 15243 /* Initialize current time and key list. */ 15244 timenow = isc_time_now(); 15245 now = isc_time_seconds(&timenow); 15246 when = now; 15247 15248 ISC_LIST_INIT(keys); 15249 15250 if (strcasecmp(ptr, "-status") == 0) { 15251 status = true; 15252 } else if (strcasecmp(ptr, "-rollover") == 0) { 15253 rollover = true; 15254 } else if (strcasecmp(ptr, "-checkds") == 0) { 15255 checkds = true; 15256 } else if (strcasecmp(ptr, "-step") == 0) { 15257 forcestep = true; 15258 } else { 15259 CHECK(DNS_R_SYNTAX); 15260 } 15261 15262 if (rollover || checkds) { 15263 /* Check for options */ 15264 for (;;) { 15265 ptr = next_token(lex, text); 15266 if (ptr == NULL) { 15267 msg = "Bad format"; 15268 CHECK(ISC_R_UNEXPECTEDEND); 15269 } else if (argcheck(ptr, "alg")) { 15270 isc_consttextregion_t alg; 15271 ptr = next_token(lex, text); 15272 if (ptr == NULL) { 15273 msg = "No key algorithm specified"; 15274 CHECK(ISC_R_UNEXPECTEDEND); 15275 } 15276 alg.base = ptr; 15277 alg.length = strlen(alg.base); 15278 result = dns_secalg_fromtext( 15279 &algorithm, (isc_textregion_t *)&alg); 15280 if (result != ISC_R_SUCCESS) { 15281 msg = "Bad algorithm"; 15282 CHECK(DNS_R_SYNTAX); 15283 } 15284 continue; 15285 } else if (argcheck(ptr, "key")) { 15286 uint16_t id; 15287 ptr = next_token(lex, text); 15288 if (ptr == NULL) { 15289 msg = "No key identifier specified"; 15290 CHECK(ISC_R_UNEXPECTEDEND); 15291 } 15292 CHECK(isc_parse_uint16(&id, ptr, 10)); 15293 keyid = (dns_keytag_t)id; 15294 use_keyid = true; 15295 continue; 15296 } else if (argcheck(ptr, "when")) { 15297 uint32_t tw; 15298 ptr = next_token(lex, text); 15299 if (ptr == NULL) { 15300 msg = "No time specified"; 15301 CHECK(ISC_R_UNEXPECTEDEND); 15302 } 15303 CHECK(dns_time32_fromtext(ptr, &tw)); 15304 when = (isc_stdtime_t)tw; 15305 continue; 15306 } else if (ptr[0] == '-') { 15307 msg = "Unknown option"; 15308 CHECK(DNS_R_SYNTAX); 15309 } else if (checkds) { 15310 /* 15311 * No arguments provided, so we must be 15312 * parsing "published|withdrawn". 15313 */ 15314 if (strcasecmp(ptr, "published") == 0) { 15315 dspublish = true; 15316 } else if (strcasecmp(ptr, "withdrawn") != 0) { 15317 CHECK(DNS_R_SYNTAX); 15318 } 15319 } else if (rollover) { 15320 /* 15321 * No arguments provided, so we must be 15322 * parsing the zone. 15323 */ 15324 zonetext = ptr; 15325 } 15326 break; 15327 } 15328 15329 if (rollover && !use_keyid) { 15330 msg = "Key id is required when scheduling rollover"; 15331 CHECK(DNS_R_SYNTAX); 15332 } 15333 15334 if (algorithm > 0 && !use_keyid) { 15335 msg = "Key id is required when setting algorithm"; 15336 CHECK(DNS_R_SYNTAX); 15337 } 15338 } 15339 15340 /* Get zone. */ 15341 CHECK(zone_from_args(server, lex, zonetext, &zone, NULL, text, false)); 15342 if (zone == NULL) { 15343 msg = "Zone not found"; 15344 CHECK(ISC_R_UNEXPECTEDEND); 15345 } 15346 15347 /* Trailing garbage? */ 15348 ptr = next_token(lex, text); 15349 if (ptr != NULL) { 15350 msg = "Too many arguments"; 15351 CHECK(DNS_R_SYNTAX); 15352 } 15353 15354 /* Get dnssec-policy. */ 15355 kasp = dns_zone_getkasp(zone); 15356 if (kasp == NULL) { 15357 msg = "Zone does not have dnssec-policy"; 15358 goto cleanup; 15359 } 15360 15361 /* Get DNSSEC keys. */ 15362 CHECK(dns_zone_getdb(zone, &db)); 15363 dns_db_currentversion(db, &version); 15364 LOCK(&kasp->lock); 15365 result = dns_zone_getdnsseckeys(zone, db, version, now, &keys); 15366 UNLOCK(&kasp->lock); 15367 if (result != ISC_R_SUCCESS) { 15368 if (result != ISC_R_NOTFOUND) { 15369 goto cleanup; 15370 } 15371 } 15372 15373 if (status) { 15374 /* 15375 * Output the DNSSEC status of the key and signing policy. 15376 */ 15377 isc_result_t r; 15378 LOCK(&kasp->lock); 15379 r = dns_keymgr_status(kasp, &keys, now, &output[0], 15380 sizeof(output)); 15381 UNLOCK(&kasp->lock); 15382 CHECK(putstr(text, output)); 15383 if (r != ISC_R_SUCCESS) { 15384 CHECK(putstr(text, 15385 "\n\nStatus output is truncated...")); 15386 } 15387 } else if (checkds) { 15388 /* 15389 * Mark DS record has been seen, so it may move to the 15390 * rumoured state. 15391 */ 15392 char whenbuf[80]; 15393 isc_time_set(&timewhen, when, 0); 15394 isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); 15395 isc_result_t ret; 15396 15397 LOCK(&kasp->lock); 15398 if (use_keyid) { 15399 result = dns_keymgr_checkds_id(kasp, &keys, now, when, 15400 dspublish, keyid, 15401 (unsigned int)algorithm); 15402 } else { 15403 result = dns_keymgr_checkds(kasp, &keys, now, when, 15404 dspublish); 15405 } 15406 UNLOCK(&kasp->lock); 15407 15408 switch (result) { 15409 case ISC_R_SUCCESS: 15410 /* 15411 * Rekey after checkds command because the next key 15412 * event may have changed. 15413 */ 15414 dns_zone_rekey(zone, false, false); 15415 15416 if (use_keyid) { 15417 char tagbuf[6]; 15418 snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); 15419 CHECK(putstr(text, "KSK ")); 15420 CHECK(putstr(text, tagbuf)); 15421 CHECK(putstr(text, ": ")); 15422 } 15423 CHECK(putstr(text, "Marked DS as ")); 15424 if (dspublish) { 15425 CHECK(putstr(text, "published ")); 15426 } else { 15427 CHECK(putstr(text, "withdrawn ")); 15428 } 15429 CHECK(putstr(text, "since ")); 15430 CHECK(putstr(text, whenbuf)); 15431 break; 15432 case DNS_R_TOOMANYKEYS: 15433 CHECK(putstr(text, 15434 "Error: multiple possible keys found, " 15435 "retry command with -key id")); 15436 break; 15437 default: 15438 ret = result; 15439 CHECK(putstr(text, 15440 "Error executing checkds command: ")); 15441 CHECK(putstr(text, isc_result_totext(ret))); 15442 break; 15443 } 15444 } else if (rollover) { 15445 /* 15446 * Manually rollover a key. 15447 */ 15448 char whenbuf[80]; 15449 isc_time_set(&timewhen, when, 0); 15450 isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); 15451 isc_result_t ret; 15452 15453 LOCK(&kasp->lock); 15454 result = dns_keymgr_rollover(kasp, &keys, now, when, keyid, 15455 (unsigned int)algorithm); 15456 UNLOCK(&kasp->lock); 15457 15458 switch (result) { 15459 case ISC_R_SUCCESS: 15460 /* 15461 * Rekey after rollover command because the next key 15462 * event may have changed. 15463 */ 15464 dns_zone_rekey(zone, false, false); 15465 15466 if (use_keyid) { 15467 char tagbuf[6]; 15468 snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); 15469 CHECK(putstr(text, "Key ")); 15470 CHECK(putstr(text, tagbuf)); 15471 CHECK(putstr(text, ": ")); 15472 } 15473 CHECK(putstr(text, "Rollover scheduled on ")); 15474 CHECK(putstr(text, whenbuf)); 15475 break; 15476 case DNS_R_TOOMANYKEYS: 15477 CHECK(putstr(text, 15478 "Error: multiple possible keys found, " 15479 "retry command with -alg algorithm")); 15480 break; 15481 default: 15482 ret = result; 15483 CHECK(putstr(text, 15484 "Error executing rollover command: ")); 15485 CHECK(putstr(text, isc_result_totext(ret))); 15486 break; 15487 } 15488 } else if (forcestep) { 15489 dns_zone_rekey(zone, false, true); 15490 } 15491 15492 CHECK(putnull(text)); 15493 15494 cleanup: 15495 if (msg != NULL) { 15496 (void)putstr(text, msg); 15497 (void)putnull(text); 15498 } 15499 15500 if (version != NULL) { 15501 dns_db_closeversion(db, &version, false); 15502 } 15503 if (db != NULL) { 15504 dns_db_detach(&db); 15505 } 15506 15507 while (!ISC_LIST_EMPTY(keys)) { 15508 key = ISC_LIST_HEAD(keys); 15509 ISC_LIST_UNLINK(keys, key, link); 15510 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key); 15511 } 15512 15513 if (zone != NULL) { 15514 dns_zone_detach(&zone); 15515 } 15516 15517 return result; 15518 } 15519 15520 static isc_result_t 15521 putmem(isc_buffer_t **b, const char *str, size_t len) { 15522 isc_result_t result; 15523 15524 result = isc_buffer_reserve(*b, (unsigned int)len); 15525 if (result != ISC_R_SUCCESS) { 15526 return ISC_R_NOSPACE; 15527 } 15528 15529 isc_buffer_putmem(*b, (const unsigned char *)str, (unsigned int)len); 15530 return ISC_R_SUCCESS; 15531 } 15532 15533 static isc_result_t 15534 putstr(isc_buffer_t **b, const char *str) { 15535 return putmem(b, str, strlen(str)); 15536 } 15537 15538 static isc_result_t 15539 putuint8(isc_buffer_t **b, uint8_t val) { 15540 isc_result_t result; 15541 15542 result = isc_buffer_reserve(*b, 1); 15543 if (result != ISC_R_SUCCESS) { 15544 return ISC_R_NOSPACE; 15545 } 15546 15547 isc_buffer_putuint8(*b, val); 15548 return ISC_R_SUCCESS; 15549 } 15550 15551 static isc_result_t 15552 putnull(isc_buffer_t **b) { 15553 return putuint8(b, 0); 15554 } 15555 15556 isc_result_t 15557 named_server_zonestatus(named_server_t *server, isc_lex_t *lex, 15558 isc_buffer_t **text) { 15559 isc_result_t result = ISC_R_SUCCESS; 15560 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; 15561 const char *type, *file; 15562 char zonename[DNS_NAME_FORMATSIZE]; 15563 uint32_t serial, signed_serial, nodes; 15564 char serbuf[16], sserbuf[16], nodebuf[16]; 15565 char resignbuf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 2]; 15566 char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15567 char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15568 char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15569 char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15570 char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15571 isc_time_t loadtime, expiretime, refreshtime; 15572 isc_time_t refreshkeytime, resigntime; 15573 dns_zonetype_t zonetype; 15574 bool dynamic = false, frozen = false; 15575 bool hasraw = false; 15576 bool secure, maintain, allow; 15577 dns_db_t *db = NULL, *rawdb = NULL; 15578 char **incfiles = NULL; 15579 int nfiles = 0; 15580 15581 REQUIRE(text != NULL); 15582 15583 isc_time_settoepoch(&loadtime); 15584 isc_time_settoepoch(&refreshtime); 15585 isc_time_settoepoch(&expiretime); 15586 isc_time_settoepoch(&refreshkeytime); 15587 isc_time_settoepoch(&resigntime); 15588 15589 CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); 15590 if (zone == NULL) { 15591 result = ISC_R_UNEXPECTEDEND; 15592 goto cleanup; 15593 } 15594 15595 /* Inline signing? */ 15596 CHECK(dns_zone_getdb(zone, &db)); 15597 dns_zone_getraw(zone, &raw); 15598 hasraw = (raw != NULL); 15599 if (hasraw) { 15600 mayberaw = raw; 15601 zonetype = dns_zone_gettype(raw); 15602 CHECK(dns_zone_getdb(raw, &rawdb)); 15603 } else { 15604 mayberaw = zone; 15605 zonetype = dns_zone_gettype(zone); 15606 } 15607 15608 type = dns_zonetype_name(zonetype); 15609 15610 /* Serial number */ 15611 result = dns_zone_getserial(mayberaw, &serial); 15612 15613 /* This is to mirror old behavior with dns_zone_getserial */ 15614 if (result != ISC_R_SUCCESS) { 15615 serial = 0; 15616 } 15617 15618 snprintf(serbuf, sizeof(serbuf), "%u", serial); 15619 if (hasraw) { 15620 result = dns_zone_getserial(zone, &signed_serial); 15621 if (result != ISC_R_SUCCESS) { 15622 serial = 0; 15623 } 15624 snprintf(sserbuf, sizeof(sserbuf), "%u", signed_serial); 15625 } 15626 15627 /* Database node count */ 15628 nodes = dns_db_nodecount(hasraw ? rawdb : db, dns_dbtree_main); 15629 snprintf(nodebuf, sizeof(nodebuf), "%u", nodes); 15630 15631 /* Security */ 15632 secure = dns_db_issecure(db); 15633 allow = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW) != 0); 15634 maintain = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0); 15635 15636 /* Master files */ 15637 file = dns_zone_getfile(mayberaw); 15638 nfiles = dns_zone_getincludes(mayberaw, &incfiles); 15639 15640 /* Load time */ 15641 dns_zone_getloadtime(zone, &loadtime); 15642 isc_time_formathttptimestamp(&loadtime, lbuf, sizeof(lbuf)); 15643 15644 /* Refresh/expire times */ 15645 if (zonetype == dns_zone_secondary || zonetype == dns_zone_mirror || 15646 zonetype == dns_zone_stub || zonetype == dns_zone_redirect) 15647 { 15648 dns_zone_getexpiretime(mayberaw, &expiretime); 15649 isc_time_formathttptimestamp(&expiretime, xbuf, sizeof(xbuf)); 15650 dns_zone_getrefreshtime(mayberaw, &refreshtime); 15651 isc_time_formathttptimestamp(&refreshtime, rbuf, sizeof(rbuf)); 15652 } 15653 15654 /* Key refresh time */ 15655 if (zonetype == dns_zone_primary || 15656 (zonetype == dns_zone_secondary && hasraw)) 15657 { 15658 dns_zone_getrefreshkeytime(zone, &refreshkeytime); 15659 isc_time_formathttptimestamp(&refreshkeytime, kbuf, 15660 sizeof(kbuf)); 15661 } 15662 15663 /* Dynamic? */ 15664 if (zonetype == dns_zone_primary) { 15665 dynamic = dns_zone_isdynamic(mayberaw, true); 15666 frozen = dynamic && !dns_zone_isdynamic(mayberaw, false); 15667 } 15668 15669 /* Next resign event */ 15670 if (secure && (zonetype == dns_zone_primary || 15671 (zonetype == dns_zone_secondary && hasraw))) 15672 { 15673 dns_name_t *name; 15674 dns_fixedname_t fixed; 15675 isc_stdtime_t resign; 15676 dns_typepair_t typepair; 15677 15678 name = dns_fixedname_initname(&fixed); 15679 15680 result = dns_db_getsigningtime(db, &resign, name, &typepair); 15681 if (result == ISC_R_SUCCESS) { 15682 char namebuf[DNS_NAME_FORMATSIZE]; 15683 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 15684 15685 resign -= dns_zone_getsigresigninginterval(zone); 15686 15687 dns_name_format(name, namebuf, sizeof(namebuf)); 15688 dns_rdatatype_format(DNS_TYPEPAIR_COVERS(typepair), 15689 typebuf, sizeof(typebuf)); 15690 snprintf(resignbuf, sizeof(resignbuf), "%s/%s", namebuf, 15691 typebuf); 15692 isc_time_set(&resigntime, resign, 0); 15693 isc_time_formathttptimestamp(&resigntime, rtbuf, 15694 sizeof(rtbuf)); 15695 } 15696 } 15697 15698 /* Create text */ 15699 CHECK(putstr(text, "name: ")); 15700 CHECK(putstr(text, zonename)); 15701 15702 CHECK(putstr(text, "\ntype: ")); 15703 CHECK(putstr(text, type)); 15704 15705 if (file != NULL) { 15706 int i; 15707 CHECK(putstr(text, "\nfiles: ")); 15708 CHECK(putstr(text, file)); 15709 for (i = 0; i < nfiles; i++) { 15710 CHECK(putstr(text, ", ")); 15711 if (incfiles[i] != NULL) { 15712 CHECK(putstr(text, incfiles[i])); 15713 } 15714 } 15715 } 15716 15717 CHECK(putstr(text, "\nserial: ")); 15718 CHECK(putstr(text, serbuf)); 15719 if (hasraw) { 15720 CHECK(putstr(text, "\nsigned serial: ")); 15721 CHECK(putstr(text, sserbuf)); 15722 } 15723 15724 CHECK(putstr(text, "\nnodes: ")); 15725 CHECK(putstr(text, nodebuf)); 15726 15727 if (!isc_time_isepoch(&loadtime)) { 15728 CHECK(putstr(text, "\nlast loaded: ")); 15729 CHECK(putstr(text, lbuf)); 15730 } 15731 15732 if (!isc_time_isepoch(&refreshtime)) { 15733 CHECK(putstr(text, "\nnext refresh: ")); 15734 CHECK(putstr(text, rbuf)); 15735 } 15736 15737 if (!isc_time_isepoch(&expiretime)) { 15738 CHECK(putstr(text, "\nexpires: ")); 15739 CHECK(putstr(text, xbuf)); 15740 } 15741 15742 if (secure) { 15743 CHECK(putstr(text, "\nsecure: yes")); 15744 if (hasraw) { 15745 CHECK(putstr(text, "\ninline signing: yes")); 15746 } else { 15747 CHECK(putstr(text, "\ninline signing: no")); 15748 } 15749 } else { 15750 CHECK(putstr(text, "\nsecure: no")); 15751 } 15752 15753 if (maintain) { 15754 CHECK(putstr(text, "\nkey maintenance: automatic")); 15755 if (!isc_time_isepoch(&refreshkeytime)) { 15756 CHECK(putstr(text, "\nnext key event: ")); 15757 CHECK(putstr(text, kbuf)); 15758 } 15759 } else if (allow) { 15760 CHECK(putstr(text, "\nkey maintenance: on command")); 15761 } else if (secure || hasraw) { 15762 CHECK(putstr(text, "\nkey maintenance: none")); 15763 } 15764 15765 if (!isc_time_isepoch(&resigntime)) { 15766 CHECK(putstr(text, "\nnext resign node: ")); 15767 CHECK(putstr(text, resignbuf)); 15768 CHECK(putstr(text, "\nnext resign time: ")); 15769 CHECK(putstr(text, rtbuf)); 15770 } 15771 15772 if (dynamic) { 15773 CHECK(putstr(text, "\ndynamic: yes")); 15774 if (frozen) { 15775 CHECK(putstr(text, "\nfrozen: yes")); 15776 } else { 15777 CHECK(putstr(text, "\nfrozen: no")); 15778 } 15779 } else { 15780 CHECK(putstr(text, "\ndynamic: no")); 15781 } 15782 15783 CHECK(putstr(text, "\nreconfigurable via modzone: ")); 15784 CHECK(putstr(text, dns_zone_getadded(zone) ? "yes" : "no")); 15785 15786 cleanup: 15787 /* Indicate truncated output if possible. */ 15788 if (result == ISC_R_NOSPACE) { 15789 (void)putstr(text, "\n..."); 15790 } 15791 if (result == ISC_R_SUCCESS || result == ISC_R_NOSPACE) { 15792 (void)putnull(text); 15793 } 15794 15795 if (db != NULL) { 15796 dns_db_detach(&db); 15797 } 15798 if (rawdb != NULL) { 15799 dns_db_detach(&rawdb); 15800 } 15801 if (incfiles != NULL && mayberaw != NULL) { 15802 int i; 15803 isc_mem_t *mctx = dns_zone_getmctx(mayberaw); 15804 15805 for (i = 0; i < nfiles; i++) { 15806 if (incfiles[i] != NULL) { 15807 isc_mem_free(mctx, incfiles[i]); 15808 } 15809 } 15810 isc_mem_free(mctx, incfiles); 15811 } 15812 if (raw != NULL) { 15813 dns_zone_detach(&raw); 15814 } 15815 if (zone != NULL) { 15816 dns_zone_detach(&zone); 15817 } 15818 return result; 15819 } 15820 15821 isc_result_t 15822 named_server_nta(named_server_t *server, isc_lex_t *lex, bool readonly, 15823 isc_buffer_t **text) { 15824 dns_view_t *view; 15825 dns_ntatable_t *ntatable = NULL; 15826 isc_result_t result = ISC_R_SUCCESS; 15827 char *ptr, *nametext = NULL, *viewname; 15828 char namebuf[DNS_NAME_FORMATSIZE]; 15829 char viewbuf[DNS_NAME_FORMATSIZE]; 15830 isc_stdtime_t now, when; 15831 isc_time_t t; 15832 char tbuf[64]; 15833 const char *msg = NULL; 15834 bool dump = false, force = false; 15835 dns_fixedname_t fn; 15836 const dns_name_t *ntaname; 15837 dns_name_t *fname; 15838 dns_ttl_t ntattl; 15839 bool ttlset = false, viewfound = false; 15840 dns_rdataclass_t rdclass = dns_rdataclass_in; 15841 bool first = true; 15842 15843 REQUIRE(text != NULL); 15844 15845 UNUSED(force); 15846 15847 fname = dns_fixedname_initname(&fn); 15848 15849 /* Skip the command name. */ 15850 ptr = next_token(lex, text); 15851 if (ptr == NULL) { 15852 return ISC_R_UNEXPECTEDEND; 15853 } 15854 15855 for (;;) { 15856 /* Check for options */ 15857 ptr = next_token(lex, text); 15858 if (ptr == NULL) { 15859 return ISC_R_UNEXPECTEDEND; 15860 } 15861 15862 if (strcmp(ptr, "--") == 0) { 15863 break; 15864 } else if (argcheck(ptr, "dump")) { 15865 dump = true; 15866 } else if (argcheck(ptr, "remove")) { 15867 ntattl = 0; 15868 ttlset = true; 15869 } else if (argcheck(ptr, "force")) { 15870 force = true; 15871 continue; 15872 } else if (argcheck(ptr, "lifetime")) { 15873 isc_textregion_t tr; 15874 15875 ptr = next_token(lex, text); 15876 if (ptr == NULL) { 15877 msg = "No lifetime specified"; 15878 CHECK(ISC_R_UNEXPECTEDEND); 15879 } 15880 15881 tr.base = ptr; 15882 tr.length = strlen(ptr); 15883 result = dns_ttl_fromtext(&tr, &ntattl); 15884 if (result != ISC_R_SUCCESS) { 15885 msg = "could not parse NTA lifetime"; 15886 CHECK(result); 15887 } 15888 15889 if (ntattl > 604800) { 15890 msg = "NTA lifetime cannot exceed one week"; 15891 CHECK(ISC_R_RANGE); 15892 } 15893 15894 ttlset = true; 15895 continue; 15896 } else if (argcheck(ptr, "class")) { 15897 isc_textregion_t tr; 15898 15899 ptr = next_token(lex, text); 15900 if (ptr == NULL) { 15901 msg = "No class specified"; 15902 CHECK(ISC_R_UNEXPECTEDEND); 15903 } 15904 15905 tr.base = ptr; 15906 tr.length = strlen(ptr); 15907 CHECK(dns_rdataclass_fromtext(&rdclass, &tr)); 15908 continue; 15909 } else if (ptr[0] == '-') { 15910 msg = "Unknown option"; 15911 CHECK(DNS_R_SYNTAX); 15912 } else { 15913 nametext = ptr; 15914 } 15915 15916 break; 15917 } 15918 15919 /* 15920 * If -dump was specified, list NTA's and return 15921 */ 15922 if (dump) { 15923 size_t last = 0; 15924 15925 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15926 view = ISC_LIST_NEXT(view, link)) 15927 { 15928 if (ntatable != NULL) { 15929 dns_ntatable_detach(&ntatable); 15930 } 15931 result = dns_view_getntatable(view, &ntatable); 15932 if (result == ISC_R_NOTFOUND) { 15933 continue; 15934 } 15935 15936 if (last != isc_buffer_usedlength(*text)) { 15937 CHECK(putstr(text, "\n")); 15938 } 15939 15940 last = isc_buffer_usedlength(*text); 15941 15942 CHECK(dns_ntatable_totext(ntatable, view->name, text)); 15943 } 15944 CHECK(putnull(text)); 15945 15946 goto cleanup; 15947 } 15948 15949 if (readonly) { 15950 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 15951 NAMED_LOGMODULE_CONTROL, ISC_LOG_INFO, 15952 "rejecting restricted control channel " 15953 "NTA command"); 15954 CHECK(ISC_R_FAILURE); 15955 } 15956 15957 /* Get the NTA name if not found above. */ 15958 if (nametext == NULL) { 15959 nametext = next_token(lex, text); 15960 } 15961 if (nametext == NULL) { 15962 return ISC_R_UNEXPECTEDEND; 15963 } 15964 15965 /* Copy nametext as it'll be overwritten by next_token() */ 15966 strlcpy(namebuf, nametext, DNS_NAME_FORMATSIZE); 15967 15968 if (strcmp(namebuf, ".") == 0) { 15969 ntaname = dns_rootname; 15970 } else { 15971 isc_buffer_t b; 15972 isc_buffer_init(&b, namebuf, strlen(namebuf)); 15973 isc_buffer_add(&b, strlen(namebuf)); 15974 CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0, NULL)); 15975 ntaname = fname; 15976 } 15977 15978 /* Look for the view name. */ 15979 viewname = next_token(lex, text); 15980 if (viewname != NULL) { 15981 strlcpy(viewbuf, viewname, DNS_NAME_FORMATSIZE); 15982 viewname = viewbuf; 15983 } 15984 15985 if (next_token(lex, text) != NULL) { 15986 CHECK(DNS_R_SYNTAX); 15987 } 15988 15989 now = isc_stdtime_now(); 15990 15991 isc_loopmgr_pause(named_g_loopmgr); 15992 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15993 view = ISC_LIST_NEXT(view, link)) 15994 { 15995 if (viewname != NULL && strcmp(view->name, viewname) != 0) { 15996 continue; 15997 } 15998 viewfound = true; 15999 16000 if (view->rdclass != rdclass && rdclass != dns_rdataclass_any) { 16001 continue; 16002 } 16003 16004 if (view->nta_lifetime == 0) { 16005 continue; 16006 } 16007 16008 if (!ttlset) { 16009 ntattl = view->nta_lifetime; 16010 } 16011 16012 if (ntatable != NULL) { 16013 dns_ntatable_detach(&ntatable); 16014 } 16015 16016 result = dns_view_getntatable(view, &ntatable); 16017 if (result == ISC_R_NOTFOUND) { 16018 result = ISC_R_SUCCESS; 16019 continue; 16020 } 16021 16022 result = dns_view_flushnode(view, ntaname, true); 16023 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16024 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16025 "flush tree '%s' in cache view '%s': %s", namebuf, 16026 view->name, isc_result_totext(result)); 16027 16028 if (ntattl != 0) { 16029 CHECK(dns_ntatable_add(ntatable, ntaname, force, now, 16030 ntattl)); 16031 16032 when = now + ntattl; 16033 isc_time_set(&t, when, 0); 16034 isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); 16035 16036 if (!first) { 16037 CHECK(putstr(text, "\n")); 16038 } 16039 first = false; 16040 16041 CHECK(putstr(text, "Negative trust anchor added: ")); 16042 CHECK(putstr(text, namebuf)); 16043 CHECK(putstr(text, "/")); 16044 CHECK(putstr(text, view->name)); 16045 CHECK(putstr(text, ", expires ")); 16046 CHECK(putstr(text, tbuf)); 16047 16048 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16049 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16050 "added NTA '%s' (%d sec) in view '%s'", 16051 namebuf, ntattl, view->name); 16052 } else { 16053 bool wasremoved; 16054 16055 result = dns_ntatable_delete(ntatable, ntaname); 16056 if (result == ISC_R_SUCCESS) { 16057 wasremoved = true; 16058 } else if (result == ISC_R_NOTFOUND) { 16059 wasremoved = false; 16060 } else { 16061 goto cleanup_exclusive; 16062 } 16063 16064 if (!first) { 16065 CHECK(putstr(text, "\n")); 16066 } 16067 first = false; 16068 16069 CHECK(putstr(text, "Negative trust anchor ")); 16070 CHECK(putstr(text, 16071 wasremoved ? "removed: " : "not found: ")); 16072 CHECK(putstr(text, namebuf)); 16073 CHECK(putstr(text, "/")); 16074 CHECK(putstr(text, view->name)); 16075 16076 if (wasremoved) { 16077 isc_log_write( 16078 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16079 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16080 "removed NTA '%s' in view %s", namebuf, 16081 view->name); 16082 } 16083 } 16084 16085 result = dns_view_saventa(view); 16086 if (result != ISC_R_SUCCESS) { 16087 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16088 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16089 "error writing NTA file " 16090 "for view '%s': %s", 16091 view->name, isc_result_totext(result)); 16092 } 16093 } 16094 16095 if (!viewfound) { 16096 msg = "No such view"; 16097 result = ISC_R_NOTFOUND; 16098 } else { 16099 (void)putnull(text); 16100 } 16101 16102 cleanup_exclusive: 16103 isc_loopmgr_resume(named_g_loopmgr); 16104 16105 cleanup: 16106 16107 if (msg != NULL) { 16108 (void)putstr(text, msg); 16109 (void)putnull(text); 16110 } 16111 16112 if (ntatable != NULL) { 16113 dns_ntatable_detach(&ntatable); 16114 } 16115 return result; 16116 } 16117 16118 isc_result_t 16119 named_server_saventa(named_server_t *server) { 16120 dns_view_t *view; 16121 16122 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16123 view = ISC_LIST_NEXT(view, link)) 16124 { 16125 isc_result_t result = dns_view_saventa(view); 16126 16127 if (result != ISC_R_SUCCESS) { 16128 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16129 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16130 "error writing 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 isc_result_t 16140 named_server_loadnta(named_server_t *server) { 16141 dns_view_t *view; 16142 16143 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16144 view = ISC_LIST_NEXT(view, link)) 16145 { 16146 isc_result_t result = dns_view_loadnta(view); 16147 16148 if ((result != ISC_R_SUCCESS) && 16149 (result != ISC_R_FILENOTFOUND) && 16150 (result != ISC_R_NOTFOUND)) 16151 { 16152 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16153 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16154 "error loading NTA file " 16155 "for view '%s': %s", 16156 view->name, isc_result_totext(result)); 16157 } 16158 } 16159 16160 return ISC_R_SUCCESS; 16161 } 16162 16163 static isc_result_t 16164 mkey_refresh(dns_view_t *view, isc_buffer_t **text) { 16165 isc_result_t result; 16166 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16167 16168 snprintf(msg, sizeof(msg), "refreshing managed keys for '%s'", 16169 view->name); 16170 CHECK(putstr(text, msg)); 16171 CHECK(dns_zone_synckeyzone(view->managed_keys)); 16172 16173 cleanup: 16174 return result; 16175 } 16176 16177 static isc_result_t 16178 mkey_destroy(dns_view_t *view, isc_buffer_t **text) { 16179 isc_result_t result; 16180 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16181 const char *file = NULL; 16182 dns_db_t *dbp = NULL; 16183 dns_zone_t *mkzone = NULL; 16184 bool removed_a_file = false; 16185 16186 if (view->managed_keys == NULL) { 16187 CHECK(ISC_R_NOTFOUND); 16188 } 16189 16190 snprintf(msg, sizeof(msg), "destroying managed-keys database for '%s'", 16191 view->name); 16192 CHECK(putstr(text, msg)); 16193 16194 isc_loopmgr_pause(named_g_loopmgr); 16195 16196 /* Remove and clean up managed keys zone from view */ 16197 mkzone = view->managed_keys; 16198 view->managed_keys = NULL; 16199 (void)dns_zone_flush(mkzone); 16200 16201 /* Unload zone database */ 16202 if (dns_zone_getdb(mkzone, &dbp) == ISC_R_SUCCESS) { 16203 dns_db_detach(&dbp); 16204 dns_zone_unload(mkzone); 16205 } 16206 16207 /* Delete files */ 16208 file = dns_zone_getfile(mkzone); 16209 result = isc_file_remove(file); 16210 if (result == ISC_R_SUCCESS) { 16211 removed_a_file = true; 16212 } else { 16213 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16214 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 16215 "file %s not removed: %s", file, 16216 isc_result_totext(result)); 16217 } 16218 16219 file = dns_zone_getjournal(mkzone); 16220 result = isc_file_remove(file); 16221 if (result == ISC_R_SUCCESS) { 16222 removed_a_file = true; 16223 } else { 16224 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16225 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 16226 "file %s not removed: %s", file, 16227 isc_result_totext(result)); 16228 } 16229 16230 if (!removed_a_file) { 16231 CHECK(putstr(text, "error: no files could be removed")); 16232 CHECK(ISC_R_FAILURE); 16233 } 16234 16235 dns_zone_detach(&mkzone); 16236 result = ISC_R_SUCCESS; 16237 16238 cleanup: 16239 isc_loopmgr_resume(named_g_loopmgr); 16240 return result; 16241 } 16242 16243 static isc_result_t 16244 mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) { 16245 isc_result_t result; 16246 dns_db_t *db = NULL; 16247 dns_dbversion_t *ver = NULL; 16248 dns_rriterator_t rrit; 16249 isc_stdtime_t now = isc_stdtime_now(); 16250 dns_name_t *prevname = NULL; 16251 16252 CHECK(dns_zone_getdb(view->managed_keys, &db)); 16253 dns_db_currentversion(db, &ver); 16254 dns_rriterator_init(&rrit, db, ver, 0); 16255 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS; 16256 result = dns_rriterator_nextrrset(&rrit)) 16257 { 16258 char buf[DNS_NAME_FORMATSIZE + 500]; 16259 dns_name_t *name = NULL; 16260 dns_rdataset_t *kdset = NULL; 16261 dns_rdata_t rdata = DNS_RDATA_INIT; 16262 dns_rdata_keydata_t kd; 16263 uint32_t ttl; 16264 16265 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL); 16266 if (kdset == NULL || kdset->type != dns_rdatatype_keydata || 16267 !dns_rdataset_isassociated(kdset)) 16268 { 16269 continue; 16270 } 16271 16272 if (name != prevname) { 16273 char nbuf[DNS_NAME_FORMATSIZE]; 16274 dns_name_format(name, nbuf, sizeof(nbuf)); 16275 snprintf(buf, sizeof(buf), "\n\n name: %s", nbuf); 16276 CHECK(putstr(text, buf)); 16277 } 16278 16279 for (result = dns_rdataset_first(kdset); 16280 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset)) 16281 { 16282 char alg[DNS_SECALG_FORMATSIZE]; 16283 char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 16284 dns_keytag_t keyid; 16285 isc_region_t r; 16286 isc_time_t t; 16287 bool revoked; 16288 16289 dns_rdata_reset(&rdata); 16290 dns_rdataset_current(kdset, &rdata); 16291 result = dns_rdata_tostruct(&rdata, &kd, NULL); 16292 RUNTIME_CHECK(result == ISC_R_SUCCESS); 16293 16294 dns_rdata_toregion(&rdata, &r); 16295 isc_region_consume(&r, 12); 16296 keyid = dst_region_computeid(&r); 16297 16298 snprintf(buf, sizeof(buf), "\n keyid: %u", keyid); 16299 CHECK(putstr(text, buf)); 16300 16301 dns_secalg_format(kd.algorithm, alg, sizeof(alg)); 16302 snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg); 16303 CHECK(putstr(text, buf)); 16304 16305 revoked = ((kd.flags & DNS_KEYFLAG_REVOKE) != 0); 16306 snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s", 16307 revoked ? " REVOKE" : "", 16308 ((kd.flags & DNS_KEYFLAG_KSK) != 0) ? " SEP" 16309 : "", 16310 (kd.flags == 0) ? " (none)" : ""); 16311 CHECK(putstr(text, buf)); 16312 16313 isc_time_set(&t, kd.refresh, 0); 16314 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); 16315 snprintf(buf, sizeof(buf), "\n\tnext refresh: %s", 16316 tbuf); 16317 CHECK(putstr(text, buf)); 16318 16319 if (kd.removehd != 0) { 16320 isc_time_set(&t, kd.removehd, 0); 16321 isc_time_formathttptimestamp(&t, tbuf, 16322 sizeof(tbuf)); 16323 snprintf(buf, sizeof(buf), "\n\tremove at: %s", 16324 tbuf); 16325 CHECK(putstr(text, buf)); 16326 } 16327 16328 isc_time_set(&t, kd.addhd, 0); 16329 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); 16330 if (kd.addhd == 0) { 16331 snprintf(buf, sizeof(buf), "\n\tno trust"); 16332 } else if (revoked) { 16333 snprintf(buf, sizeof(buf), "\n\ttrust revoked"); 16334 } else if (kd.addhd <= now) { 16335 snprintf(buf, sizeof(buf), 16336 "\n\ttrusted since: %s", tbuf); 16337 } else if (kd.addhd > now) { 16338 snprintf(buf, sizeof(buf), 16339 "\n\ttrust pending: %s", tbuf); 16340 } 16341 CHECK(putstr(text, buf)); 16342 } 16343 } 16344 16345 if (result == ISC_R_NOMORE) { 16346 result = ISC_R_SUCCESS; 16347 } 16348 16349 cleanup: 16350 if (ver != NULL) { 16351 dns_rriterator_destroy(&rrit); 16352 dns_db_closeversion(db, &ver, false); 16353 } 16354 if (db != NULL) { 16355 dns_db_detach(&db); 16356 } 16357 16358 return result; 16359 } 16360 16361 static isc_result_t 16362 mkey_status(dns_view_t *view, isc_buffer_t **text) { 16363 isc_result_t result; 16364 char msg[ISC_FORMATHTTPTIMESTAMP_SIZE]; 16365 isc_time_t t; 16366 16367 CHECK(putstr(text, "view: ")); 16368 CHECK(putstr(text, view->name)); 16369 16370 CHECK(putstr(text, "\nnext scheduled event: ")); 16371 16372 dns_zone_getrefreshkeytime(view->managed_keys, &t); 16373 if (isc_time_isepoch(&t)) { 16374 CHECK(putstr(text, "never")); 16375 } else { 16376 isc_time_formathttptimestamp(&t, msg, sizeof(msg)); 16377 CHECK(putstr(text, msg)); 16378 } 16379 16380 CHECK(mkey_dumpzone(view, text)); 16381 16382 cleanup: 16383 return result; 16384 } 16385 16386 isc_result_t 16387 named_server_mkeys(named_server_t *server, isc_lex_t *lex, 16388 isc_buffer_t **text) { 16389 char *cmd, *classtxt, *viewtxt = NULL; 16390 isc_result_t result = ISC_R_SUCCESS; 16391 dns_view_t *view = NULL; 16392 dns_rdataclass_t rdclass; 16393 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16394 enum { NONE, STAT, REFRESH, SYNC, DESTROY } opt = NONE; 16395 bool found = false; 16396 bool first = true; 16397 16398 REQUIRE(text != NULL); 16399 16400 /* Skip rndc command name */ 16401 cmd = next_token(lex, text); 16402 if (cmd == NULL) { 16403 return ISC_R_UNEXPECTEDEND; 16404 } 16405 16406 /* Get managed-keys subcommand */ 16407 cmd = next_token(lex, text); 16408 if (cmd == NULL) { 16409 return ISC_R_UNEXPECTEDEND; 16410 } 16411 16412 if (strcasecmp(cmd, "status") == 0) { 16413 opt = STAT; 16414 } else if (strcasecmp(cmd, "refresh") == 0) { 16415 opt = REFRESH; 16416 } else if (strcasecmp(cmd, "sync") == 0) { 16417 opt = SYNC; 16418 } else if (strcasecmp(cmd, "destroy") == 0) { 16419 opt = DESTROY; 16420 } else { 16421 snprintf(msg, sizeof(msg), "unknown command '%s'", cmd); 16422 (void)putstr(text, msg); 16423 result = ISC_R_UNEXPECTED; 16424 goto cleanup; 16425 } 16426 16427 /* Look for the optional class name. */ 16428 classtxt = next_token(lex, text); 16429 if (classtxt != NULL) { 16430 isc_textregion_t r; 16431 r.base = classtxt; 16432 r.length = strlen(classtxt); 16433 result = dns_rdataclass_fromtext(&rdclass, &r); 16434 if (result != ISC_R_SUCCESS) { 16435 snprintf(msg, sizeof(msg), "unknown class '%s'", 16436 classtxt); 16437 (void)putstr(text, msg); 16438 goto cleanup; 16439 } 16440 viewtxt = next_token(lex, text); 16441 } 16442 16443 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16444 view = ISC_LIST_NEXT(view, link)) 16445 { 16446 if (viewtxt != NULL && (rdclass != view->rdclass || 16447 strcmp(view->name, viewtxt) != 0)) 16448 { 16449 continue; 16450 } 16451 16452 if (view->managed_keys == NULL) { 16453 if (viewtxt != NULL) { 16454 snprintf(msg, sizeof(msg), 16455 "view '%s': no managed keys", viewtxt); 16456 CHECK(putstr(text, msg)); 16457 goto cleanup; 16458 } else { 16459 continue; 16460 } 16461 } 16462 16463 found = true; 16464 16465 switch (opt) { 16466 case REFRESH: 16467 if (!first) { 16468 CHECK(putstr(text, "\n")); 16469 } 16470 CHECK(mkey_refresh(view, text)); 16471 break; 16472 case STAT: 16473 if (!first) { 16474 CHECK(putstr(text, "\n\n")); 16475 } 16476 CHECK(mkey_status(view, text)); 16477 break; 16478 case SYNC: 16479 CHECK(dns_zone_flush(view->managed_keys)); 16480 break; 16481 case DESTROY: 16482 if (!first) { 16483 CHECK(putstr(text, "\n")); 16484 } 16485 CHECK(mkey_destroy(view, text)); 16486 break; 16487 default: 16488 UNREACHABLE(); 16489 } 16490 16491 if (viewtxt != NULL) { 16492 break; 16493 } 16494 first = false; 16495 } 16496 16497 if (!found) { 16498 CHECK(putstr(text, "no views with managed keys")); 16499 } 16500 16501 cleanup: 16502 if (isc_buffer_usedlength(*text) > 0) { 16503 (void)putnull(text); 16504 } 16505 16506 return result; 16507 } 16508 16509 isc_result_t 16510 named_server_dnstap(named_server_t *server, isc_lex_t *lex, 16511 isc_buffer_t **text) { 16512 #ifdef HAVE_DNSTAP 16513 char *ptr; 16514 isc_result_t result; 16515 bool reopen = false; 16516 int backups = 0; 16517 16518 REQUIRE(text != NULL); 16519 16520 if (server->dtenv == NULL) { 16521 return ISC_R_NOTFOUND; 16522 } 16523 16524 /* Check the command name. */ 16525 ptr = next_token(lex, text); 16526 if (ptr == NULL) { 16527 return ISC_R_UNEXPECTEDEND; 16528 } 16529 16530 /* "dnstap-reopen" was used in 9.11.0b1 */ 16531 if (strcasecmp(ptr, "dnstap-reopen") == 0) { 16532 reopen = true; 16533 } else { 16534 ptr = next_token(lex, text); 16535 if (ptr == NULL) { 16536 return ISC_R_UNEXPECTEDEND; 16537 } 16538 } 16539 16540 if (reopen || strcasecmp(ptr, "-reopen") == 0) { 16541 backups = ISC_LOG_ROLLNEVER; 16542 } else if (strcasecmp(ptr, "-roll") == 0) { 16543 unsigned int n; 16544 ptr = next_token(lex, text); 16545 if (ptr != NULL) { 16546 unsigned int u; 16547 n = sscanf(ptr, "%u", &u); 16548 if (n != 1U || u > INT_MAX) { 16549 return ISC_R_BADNUMBER; 16550 } 16551 backups = u; 16552 } else { 16553 backups = ISC_LOG_ROLLINFINITE; 16554 } 16555 } else { 16556 return DNS_R_SYNTAX; 16557 } 16558 16559 result = dns_dt_reopen(server->dtenv, backups); 16560 return result; 16561 #else /* ifdef HAVE_DNSTAP */ 16562 UNUSED(server); 16563 UNUSED(lex); 16564 UNUSED(text); 16565 return ISC_R_NOTIMPLEMENTED; 16566 #endif /* ifdef HAVE_DNSTAP */ 16567 } 16568 16569 isc_result_t 16570 named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) { 16571 char *ptr; 16572 isc_result_t result = ISC_R_SUCCESS; 16573 uint32_t initial, idle, keepalive, advertised; 16574 char msg[128]; 16575 16576 /* Skip the command name. */ 16577 ptr = next_token(lex, text); 16578 if (ptr == NULL) { 16579 return ISC_R_UNEXPECTEDEND; 16580 } 16581 16582 isc_nm_gettimeouts(named_g_netmgr, &initial, &idle, &keepalive, 16583 &advertised); 16584 16585 /* Look for optional arguments. */ 16586 ptr = next_token(lex, NULL); 16587 if (ptr != NULL) { 16588 CHECK(isc_parse_uint32(&initial, ptr, 10)); 16589 initial *= 100; 16590 if (initial > MAX_INITIAL_TIMEOUT) { 16591 CHECK(ISC_R_RANGE); 16592 } 16593 if (initial < MIN_INITIAL_TIMEOUT) { 16594 CHECK(ISC_R_RANGE); 16595 } 16596 16597 ptr = next_token(lex, text); 16598 if (ptr == NULL) { 16599 return ISC_R_UNEXPECTEDEND; 16600 } 16601 CHECK(isc_parse_uint32(&idle, ptr, 10)); 16602 idle *= 100; 16603 if (idle > MAX_IDLE_TIMEOUT) { 16604 CHECK(ISC_R_RANGE); 16605 } 16606 if (idle < MIN_IDLE_TIMEOUT) { 16607 CHECK(ISC_R_RANGE); 16608 } 16609 16610 ptr = next_token(lex, text); 16611 if (ptr == NULL) { 16612 return ISC_R_UNEXPECTEDEND; 16613 } 16614 CHECK(isc_parse_uint32(&keepalive, ptr, 10)); 16615 keepalive *= 100; 16616 if (keepalive > MAX_KEEPALIVE_TIMEOUT) { 16617 CHECK(ISC_R_RANGE); 16618 } 16619 if (keepalive < MIN_KEEPALIVE_TIMEOUT) { 16620 CHECK(ISC_R_RANGE); 16621 } 16622 16623 ptr = next_token(lex, text); 16624 if (ptr == NULL) { 16625 return ISC_R_UNEXPECTEDEND; 16626 } 16627 CHECK(isc_parse_uint32(&advertised, ptr, 10)); 16628 advertised *= 100; 16629 if (advertised > MAX_ADVERTISED_TIMEOUT) { 16630 CHECK(ISC_R_RANGE); 16631 } 16632 16633 isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, 16634 advertised); 16635 } 16636 16637 snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial / 100); 16638 CHECK(putstr(text, msg)); 16639 snprintf(msg, sizeof(msg), "tcp-idle-timeout=%u\n", idle / 100); 16640 CHECK(putstr(text, msg)); 16641 snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n", 16642 keepalive / 100); 16643 CHECK(putstr(text, msg)); 16644 snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u", 16645 advertised / 100); 16646 CHECK(putstr(text, msg)); 16647 16648 cleanup: 16649 if (isc_buffer_usedlength(*text) > 0) { 16650 (void)putnull(text); 16651 } 16652 16653 return result; 16654 } 16655 16656 isc_result_t 16657 named_server_servestale(named_server_t *server, isc_lex_t *lex, 16658 isc_buffer_t **text) { 16659 char *ptr, *classtxt, *viewtxt = NULL; 16660 char msg[128]; 16661 dns_rdataclass_t rdclass = dns_rdataclass_in; 16662 dns_view_t *view; 16663 bool found = false; 16664 dns_stale_answer_t staleanswersok = dns_stale_answer_conf; 16665 bool wantstatus = false; 16666 isc_result_t result = ISC_R_SUCCESS; 16667 16668 REQUIRE(text != NULL); 16669 16670 /* Skip the command name. */ 16671 ptr = next_token(lex, text); 16672 if (ptr == NULL) { 16673 return ISC_R_UNEXPECTEDEND; 16674 } 16675 16676 ptr = next_token(lex, NULL); 16677 if (ptr == NULL) { 16678 return ISC_R_UNEXPECTEDEND; 16679 } 16680 16681 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 16682 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 16683 { 16684 staleanswersok = dns_stale_answer_yes; 16685 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 16686 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 16687 { 16688 staleanswersok = dns_stale_answer_no; 16689 } else if (strcasecmp(ptr, "reset") == 0) { 16690 staleanswersok = dns_stale_answer_conf; 16691 } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { 16692 wantstatus = true; 16693 } else { 16694 return DNS_R_SYNTAX; 16695 } 16696 16697 /* Look for the optional class name. */ 16698 classtxt = next_token(lex, text); 16699 if (classtxt != NULL) { 16700 isc_textregion_t r; 16701 16702 /* Look for the optional view name. */ 16703 viewtxt = next_token(lex, text); 16704 16705 /* 16706 * If 'classtext' is not a valid class then it us a view name. 16707 */ 16708 r.base = classtxt; 16709 r.length = strlen(classtxt); 16710 result = dns_rdataclass_fromtext(&rdclass, &r); 16711 if (result != ISC_R_SUCCESS) { 16712 if (viewtxt != NULL) { 16713 snprintf(msg, sizeof(msg), "unknown class '%s'", 16714 classtxt); 16715 (void)putstr(text, msg); 16716 goto cleanup; 16717 } 16718 16719 viewtxt = classtxt; 16720 classtxt = NULL; 16721 } 16722 } 16723 16724 isc_loopmgr_pause(named_g_loopmgr); 16725 16726 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16727 view = ISC_LIST_NEXT(view, link)) 16728 { 16729 dns_ttl_t stale_ttl = 0; 16730 uint32_t stale_refresh = 0; 16731 dns_db_t *db = NULL; 16732 16733 if (classtxt != NULL && rdclass != view->rdclass) { 16734 continue; 16735 } 16736 16737 if (viewtxt != NULL && strcmp(view->name, viewtxt) != 0) { 16738 continue; 16739 } 16740 16741 if (!wantstatus) { 16742 view->staleanswersok = staleanswersok; 16743 found = true; 16744 continue; 16745 } 16746 16747 db = NULL; 16748 dns_db_attach(view->cachedb, &db); 16749 (void)dns_db_getservestalettl(db, &stale_ttl); 16750 (void)dns_db_getservestalerefresh(db, &stale_refresh); 16751 dns_db_detach(&db); 16752 if (found) { 16753 CHECK(putstr(text, "\n")); 16754 } 16755 CHECK(putstr(text, view->name)); 16756 CHECK(putstr(text, ": ")); 16757 switch (view->staleanswersok) { 16758 case dns_stale_answer_yes: 16759 if (stale_ttl > 0) { 16760 CHECK(putstr(text, "stale cache " 16761 "enabled; stale " 16762 "answers enabled")); 16763 } else { 16764 CHECK(putstr(text, "stale cache disabled; " 16765 "stale " 16766 "answers unavailable")); 16767 } 16768 break; 16769 case dns_stale_answer_no: 16770 if (stale_ttl > 0) { 16771 CHECK(putstr(text, "stale cache " 16772 "enabled; stale " 16773 "answers disabled")); 16774 } else { 16775 CHECK(putstr(text, "stale cache disabled; " 16776 "stale " 16777 "answers unavailable")); 16778 } 16779 break; 16780 case dns_stale_answer_conf: 16781 if (view->staleanswersenable && stale_ttl > 0) { 16782 CHECK(putstr(text, "stale cache " 16783 "enabled; stale " 16784 "answers enabled")); 16785 } else if (stale_ttl > 0) { 16786 CHECK(putstr(text, "stale cache " 16787 "enabled; stale " 16788 "answers disabled")); 16789 } else { 16790 CHECK(putstr(text, "stale cache disabled; " 16791 "stale " 16792 "answers unavailable")); 16793 } 16794 break; 16795 } 16796 if (stale_ttl > 0) { 16797 snprintf(msg, sizeof(msg), 16798 " (stale-answer-ttl=%u " 16799 "max-stale-ttl=%u " 16800 "stale-refresh-time=%u)", 16801 view->staleanswerttl, stale_ttl, 16802 stale_refresh); 16803 CHECK(putstr(text, msg)); 16804 } 16805 found = true; 16806 } 16807 16808 if (!found) { 16809 result = ISC_R_NOTFOUND; 16810 } 16811 16812 cleanup: 16813 isc_loopmgr_resume(named_g_loopmgr); 16814 16815 if (isc_buffer_usedlength(*text) > 0) { 16816 (void)putnull(text); 16817 } 16818 16819 return result; 16820 } 16821 16822 isc_result_t 16823 named_server_fetchlimit(named_server_t *server, isc_lex_t *lex, 16824 isc_buffer_t **text) { 16825 isc_result_t result = ISC_R_SUCCESS; 16826 dns_view_t *view = NULL; 16827 char *ptr = NULL, *viewname = NULL; 16828 bool first = true; 16829 dns_adb_t *adb = NULL; 16830 16831 REQUIRE(text != NULL); 16832 16833 /* Skip the command name. */ 16834 ptr = next_token(lex, text); 16835 if (ptr == NULL) { 16836 return ISC_R_UNEXPECTEDEND; 16837 } 16838 16839 /* Look for the view name. */ 16840 viewname = next_token(lex, text); 16841 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16842 view = ISC_LIST_NEXT(view, link)) 16843 { 16844 char tbuf[100]; 16845 unsigned int used; 16846 uint32_t val; 16847 int s; 16848 16849 if (view->rdclass != dns_rdataclass_in) { 16850 continue; 16851 } 16852 16853 if (viewname != NULL && strcasecmp(view->name, viewname) != 0) { 16854 continue; 16855 } 16856 16857 dns_view_getadb(view, &adb); 16858 if (adb == NULL) { 16859 continue; 16860 } 16861 16862 if (!first) { 16863 CHECK(putstr(text, "\n")); 16864 } 16865 CHECK(putstr(text, "Rate limited servers, view ")); 16866 CHECK(putstr(text, view->name)); 16867 16868 dns_adb_getquota(adb, &val, NULL, NULL, NULL, NULL); 16869 s = snprintf(tbuf, sizeof(tbuf), 16870 " (fetches-per-server %u):", val); 16871 if (s < 0 || (unsigned int)s > sizeof(tbuf)) { 16872 CHECK(ISC_R_NOSPACE); 16873 } 16874 first = false; 16875 CHECK(putstr(text, tbuf)); 16876 used = isc_buffer_usedlength(*text); 16877 CHECK(dns_adb_dumpquota(adb, text)); 16878 if (used == isc_buffer_usedlength(*text)) { 16879 CHECK(putstr(text, "\n None.")); 16880 } 16881 16882 CHECK(putstr(text, "\nRate limited servers, view ")); 16883 CHECK(putstr(text, view->name)); 16884 val = dns_resolver_getfetchesperzone(view->resolver); 16885 s = snprintf(tbuf, sizeof(tbuf), 16886 " (fetches-per-zone %u):", val); 16887 if (s < 0 || (unsigned int)s > sizeof(tbuf)) { 16888 CHECK(ISC_R_NOSPACE); 16889 } 16890 CHECK(putstr(text, tbuf)); 16891 used = isc_buffer_usedlength(*text); 16892 CHECK(dns_resolver_dumpquota(view->resolver, text)); 16893 if (used == isc_buffer_usedlength(*text)) { 16894 CHECK(putstr(text, "\n None.")); 16895 } 16896 dns_adb_detach(&adb); 16897 } 16898 cleanup: 16899 if (adb != NULL) { 16900 dns_adb_detach(&adb); 16901 } 16902 if (isc_buffer_usedlength(*text) > 0) { 16903 (void)putnull(text); 16904 } 16905 16906 return result; 16907 } 16908 16909 isc_result_t 16910 named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { 16911 isc_result_t result = ISC_R_SUCCESS; 16912 dns_zone_t *zone = NULL; 16913 dns_kasp_t *kasp = NULL; 16914 const char *ptr; 16915 char skrfile[PATH_MAX]; 16916 16917 /* Skip the command name. */ 16918 ptr = next_token(lex, text); 16919 if (ptr == NULL) { 16920 return ISC_R_UNEXPECTEDEND; 16921 } 16922 16923 /* Find out what we are to do. */ 16924 ptr = next_token(lex, text); 16925 if (ptr == NULL) { 16926 return ISC_R_UNEXPECTEDEND; 16927 } 16928 16929 if (strcasecmp(ptr, "-import") != 0) { 16930 CHECK(DNS_R_SYNTAX); 16931 } 16932 16933 ptr = next_token(lex, NULL); 16934 if (ptr == NULL) { 16935 return ISC_R_UNEXPECTEDEND; 16936 } 16937 (void)snprintf(skrfile, sizeof(skrfile), "%s", ptr); 16938 16939 CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); 16940 if (zone == NULL) { 16941 CHECK(ISC_R_UNEXPECTEDEND); 16942 } 16943 kasp = dns_zone_getkasp(zone); 16944 if (kasp == NULL) { 16945 CHECK(putstr(text, "zone does not have a dnssec-policy")); 16946 CHECK(putnull(text)); 16947 goto cleanup; 16948 } 16949 16950 if (!dns_kasp_offlineksk(kasp)) { 16951 CHECK(putstr(text, "zone does not have offline-ksk enabled")); 16952 CHECK(putnull(text)); 16953 goto cleanup; 16954 } 16955 16956 result = dns_zone_import_skr(zone, skrfile); 16957 if (result != ISC_R_SUCCESS) { 16958 CHECK(putstr(text, "import failed: ")); 16959 CHECK(putstr(text, isc_result_totext(result))); 16960 CHECK(putnull(text)); 16961 } else { 16962 /* Schedule a rekey */ 16963 dns_zone_rekey(zone, false, false); 16964 } 16965 16966 cleanup: 16967 if (zone != NULL) { 16968 dns_zone_detach(&zone); 16969 } 16970 16971 return result; 16972 } 16973 16974 isc_result_t 16975 named_server_togglememprof(isc_lex_t *lex) { 16976 isc_result_t result = ISC_R_FAILURE; 16977 bool active; 16978 char *ptr; 16979 16980 /* Skip the command name. */ 16981 ptr = next_token(lex, NULL); 16982 if (ptr == NULL) { 16983 return ISC_R_UNEXPECTEDEND; 16984 } 16985 16986 ptr = next_token(lex, NULL); 16987 if (ptr == NULL) { 16988 return ISC_R_UNEXPECTEDEND; 16989 } else if (!strcasecmp(ptr, "dump")) { 16990 result = memprof_dump(); 16991 if (result != ISC_R_SUCCESS) { 16992 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16993 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16994 "failed to dump memory profile"); 16995 16996 } else { 16997 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16998 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16999 "memory profile dumped"); 17000 } 17001 17002 goto done; 17003 } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 17004 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 17005 { 17006 active = true; 17007 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 17008 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 17009 { 17010 active = false; 17011 } else { 17012 return DNS_R_SYNTAX; 17013 } 17014 17015 result = memprof_toggle(active); 17016 if (result != ISC_R_SUCCESS) { 17017 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 17018 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 17019 "failed to toggle memory profiling"); 17020 } else { 17021 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 17022 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 17023 "memory profiling %s", 17024 active ? "enabled" : "disabled"); 17025 } 17026 17027 done: 17028 return result; 17029 } 17030 17031 #ifdef JEMALLOC_API_SUPPORTED 17032 const char * 17033 named_server_getmemprof(void) { 17034 memprof_status status = MEMPROF_ON; 17035 bool is_enabled; 17036 size_t len = sizeof(is_enabled); 17037 17038 if (mallctl("config.prof", &is_enabled, &len, NULL, 0) != 0) { 17039 status = MEMPROF_FAILING; 17040 goto done; 17041 } 17042 17043 INSIST(len == sizeof(is_enabled)); 17044 17045 if (!is_enabled) { 17046 status = MEMPROF_UNSUPPORTED; 17047 goto done; 17048 } 17049 17050 if (mallctl("opt.prof", &is_enabled, &len, NULL, 0) != 0) { 17051 status = MEMPROF_FAILING; 17052 goto done; 17053 } 17054 17055 INSIST(len == sizeof(is_enabled)); 17056 17057 if (!is_enabled) { 17058 status = MEMPROF_INACTIVE; 17059 goto done; 17060 } 17061 17062 len = sizeof(is_enabled); 17063 if (mallctl("prof.active", &is_enabled, &len, NULL, 0) != 0) { 17064 status = MEMPROF_FAILING; 17065 goto done; 17066 } 17067 17068 INSIST(len == sizeof(is_enabled)); 17069 17070 if (!is_enabled) { 17071 status = MEMPROF_OFF; 17072 } 17073 17074 done: 17075 return memprof_status_text[status]; 17076 } 17077 17078 #else /* JEMALLOC_API_SUPPORTED */ 17079 const char * 17080 named_server_getmemprof(void) { 17081 return memprof_status_text[MEMPROF_UNSUPPORTED]; 17082 } 17083 #endif /* JEMALLOC_API_SUPPORTED */ 17084