1 /* $NetBSD: server.c,v 1.22 2024/09/22 00:13:56 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 <stdbool.h> 22 #include <stdlib.h> 23 #include <sys/stat.h> 24 #include <sys/types.h> 25 #include <unistd.h> 26 27 #ifdef HAVE_DNSTAP 28 #include <fstrm.h> 29 #endif 30 31 #include <isc/aes.h> 32 #include <isc/app.h> 33 #include <isc/attributes.h> 34 #include <isc/base64.h> 35 #include <isc/commandline.h> 36 #include <isc/dir.h> 37 #include <isc/file.h> 38 #include <isc/hash.h> 39 #include <isc/hex.h> 40 #include <isc/hmac.h> 41 #include <isc/httpd.h> 42 #include <isc/lex.h> 43 #include <isc/meminfo.h> 44 #include <isc/netmgr.h> 45 #include <isc/nonce.h> 46 #include <isc/parseint.h> 47 #include <isc/portset.h> 48 #include <isc/print.h> 49 #include <isc/refcount.h> 50 #include <isc/resource.h> 51 #include <isc/result.h> 52 #include <isc/siphash.h> 53 #include <isc/stat.h> 54 #include <isc/stats.h> 55 #include <isc/stdio.h> 56 #include <isc/string.h> 57 #include <isc/task.h> 58 #include <isc/timer.h> 59 #include <isc/util.h> 60 61 #include <dns/adb.h> 62 #include <dns/badcache.h> 63 #include <dns/cache.h> 64 #include <dns/catz.h> 65 #include <dns/db.h> 66 #include <dns/dispatch.h> 67 #include <dns/dlz.h> 68 #include <dns/dns64.h> 69 #include <dns/dnsrps.h> 70 #include <dns/dnssec.h> 71 #include <dns/dyndb.h> 72 #include <dns/events.h> 73 #include <dns/fixedname.h> 74 #include <dns/forward.h> 75 #include <dns/geoip.h> 76 #include <dns/journal.h> 77 #include <dns/kasp.h> 78 #include <dns/keymgr.h> 79 #include <dns/keytable.h> 80 #include <dns/keyvalues.h> 81 #include <dns/master.h> 82 #include <dns/masterdump.h> 83 #include <dns/nsec3.h> 84 #include <dns/nta.h> 85 #include <dns/order.h> 86 #include <dns/peer.h> 87 #include <dns/private.h> 88 #include <dns/rbt.h> 89 #include <dns/rdataclass.h> 90 #include <dns/rdatalist.h> 91 #include <dns/rdataset.h> 92 #include <dns/rdatastruct.h> 93 #include <dns/resolver.h> 94 #include <dns/rootns.h> 95 #include <dns/rriterator.h> 96 #include <dns/secalg.h> 97 #include <dns/soa.h> 98 #include <dns/stats.h> 99 #include <dns/time.h> 100 #include <dns/tkey.h> 101 #include <dns/tsig.h> 102 #include <dns/ttl.h> 103 #include <dns/view.h> 104 #include <dns/zone.h> 105 #include <dns/zt.h> 106 107 #include <dst/dst.h> 108 109 #include <isccfg/grammar.h> 110 #include <isccfg/kaspconf.h> 111 #include <isccfg/namedconf.h> 112 113 #include <ns/client.h> 114 #include <ns/hooks.h> 115 #include <ns/interfacemgr.h> 116 #include <ns/listenlist.h> 117 118 #include <bind9/check.h> 119 120 #include <named/config.h> 121 #include <named/control.h> 122 #if defined(HAVE_GEOIP2) 123 #include <named/geoip.h> 124 #endif /* HAVE_GEOIP2 */ 125 #include <named/log.h> 126 #include <named/logconf.h> 127 #include <named/main.h> 128 #include <named/os.h> 129 #include <named/server.h> 130 #include <named/statschannel.h> 131 #include <named/tkeyconf.h> 132 #include <named/transportconf.h> 133 #include <named/tsigconf.h> 134 #include <named/zoneconf.h> 135 #ifdef HAVE_LIBSCF 136 #include <stdlib.h> 137 138 #include <named/smf_globals.h> 139 #endif /* ifdef HAVE_LIBSCF */ 140 141 #ifdef HAVE_LMDB 142 #include <lmdb.h> 143 #define count_newzones count_newzones_db 144 #define configure_newzones configure_newzones_db 145 #define dumpzone dumpzone_db 146 #else /* HAVE_LMDB */ 147 #define count_newzones count_newzones_file 148 #define configure_newzones configure_newzones_file 149 #define dumpzone dumpzone_file 150 #endif /* HAVE_LMDB */ 151 152 #ifndef SIZE_MAX 153 #define SIZE_MAX ((size_t)-1) 154 #endif /* ifndef SIZE_MAX */ 155 156 #ifndef SIZE_AS_PERCENT 157 #define SIZE_AS_PERCENT ((size_t)-2) 158 #endif /* ifndef SIZE_AS_PERCENT */ 159 160 #ifdef TUNE_LARGE 161 #define RESOLVER_NTASKS_PERCPU 32 162 #else 163 #define RESOLVER_NTASKS_PERCPU 8 164 #endif /* TUNE_LARGE */ 165 166 /* RFC7828 defines timeout as 16-bit value specified in units of 100 167 * milliseconds, so the maximum and minimum advertised and keepalive 168 * timeouts are capped by the data type (it's ~109 minutes) 169 */ 170 #define MIN_INITIAL_TIMEOUT UINT32_C(2500) /* 2.5 seconds */ 171 #define MAX_INITIAL_TIMEOUT UINT32_C(120000) /* 2 minutes */ 172 #define MIN_IDLE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ 173 #define MAX_IDLE_TIMEOUT UINT32_C(120000) /* 2 minutes */ 174 #define MIN_KEEPALIVE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ 175 #define MAX_KEEPALIVE_TIMEOUT UINT32_C(UINT16_MAX * 100) 176 #define MIN_ADVERTISED_TIMEOUT UINT32_C(0) /* No minimum */ 177 #define MAX_ADVERTISED_TIMEOUT UINT32_C(UINT16_MAX * 100) 178 179 /*% 180 * Check an operation for failure. Assumes that the function 181 * using it has a 'result' variable and a 'cleanup' label. 182 */ 183 #define CHECK(op) \ 184 do { \ 185 result = (op); \ 186 if (result != ISC_R_SUCCESS) \ 187 goto cleanup; \ 188 } while (0) 189 190 #define TCHECK(op) \ 191 do { \ 192 tresult = (op); \ 193 if (tresult != ISC_R_SUCCESS) { \ 194 isc_buffer_clear(*text); \ 195 goto cleanup; \ 196 } \ 197 } while (0) 198 199 #define CHECKM(op, msg) \ 200 do { \ 201 result = (op); \ 202 if (result != ISC_R_SUCCESS) { \ 203 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ 204 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \ 205 "%s: %s", msg, \ 206 isc_result_totext(result)); \ 207 goto cleanup; \ 208 } \ 209 } while (0) 210 211 #define CHECKMF(op, msg, file) \ 212 do { \ 213 result = (op); \ 214 if (result != ISC_R_SUCCESS) { \ 215 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ 216 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \ 217 "%s '%s': %s", msg, file, \ 218 isc_result_totext(result)); \ 219 goto cleanup; \ 220 } \ 221 } while (0) 222 223 #define CHECKFATAL(op, msg) \ 224 do { \ 225 result = (op); \ 226 if (result != ISC_R_SUCCESS) { \ 227 fatal(server, msg, result); \ 228 } \ 229 } while (0) 230 231 /*% 232 * Maximum ADB size for views that share a cache. Use this limit to suppress 233 * the total of memory footprint, which should be the main reason for sharing 234 * a cache. Only effective when a finite max-cache-size is specified. 235 * This is currently defined to be 8MB. 236 */ 237 #define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U 238 239 struct named_dispatch { 240 isc_sockaddr_t addr; 241 unsigned int dispatchgen; 242 dns_dispatch_t *dispatch; 243 ISC_LINK(struct named_dispatch) link; 244 }; 245 246 struct named_cache { 247 dns_cache_t *cache; 248 dns_view_t *primaryview; 249 bool needflush; 250 bool adbsizeadjusted; 251 dns_rdataclass_t rdclass; 252 ISC_LINK(named_cache_t) link; 253 }; 254 255 struct dumpcontext { 256 isc_mem_t *mctx; 257 bool dumpcache; 258 bool dumpzones; 259 bool dumpadb; 260 bool dumpbad; 261 bool dumpexpired; 262 bool dumpfail; 263 FILE *fp; 264 ISC_LIST(struct viewlistentry) viewlist; 265 struct viewlistentry *view; 266 struct zonelistentry *zone; 267 dns_dumpctx_t *mdctx; 268 dns_db_t *db; 269 dns_db_t *cache; 270 isc_task_t *task; 271 dns_dbversion_t *version; 272 }; 273 274 struct viewlistentry { 275 dns_view_t *view; 276 ISC_LINK(struct viewlistentry) link; 277 ISC_LIST(struct zonelistentry) zonelist; 278 }; 279 280 struct zonelistentry { 281 dns_zone_t *zone; 282 ISC_LINK(struct zonelistentry) link; 283 }; 284 285 /*% 286 * Configuration context to retain for each view that allows 287 * new zones to be added at runtime. 288 */ 289 typedef struct ns_cfgctx { 290 isc_mem_t *mctx; 291 cfg_parser_t *conf_parser; 292 cfg_parser_t *add_parser; 293 cfg_obj_t *config; 294 cfg_obj_t *vconfig; 295 cfg_obj_t *nzf_config; 296 cfg_aclconfctx_t *actx; 297 } ns_cfgctx_t; 298 299 /*% 300 * A function to write out added-zone configuration to the new_zone_file 301 * specified in 'view'. Maybe called by delete_zoneconf(). 302 */ 303 typedef isc_result_t (*nzfwriter_t)(const cfg_obj_t *config, dns_view_t *view); 304 305 /*% 306 * Holds state information for the initial zone loading process. 307 * Uses the isc_refcount structure to count the number of views 308 * with pending zone loads, dereferencing as each view finishes. 309 */ 310 typedef struct { 311 named_server_t *server; 312 bool reconfig; 313 isc_refcount_t refs; 314 } ns_zoneload_t; 315 316 typedef struct { 317 named_server_t *server; 318 } catz_cb_data_t; 319 320 typedef struct catz_chgzone_event { 321 ISC_EVENT_COMMON(struct catz_chgzone_event); 322 dns_catz_entry_t *entry; 323 dns_catz_zone_t *origin; 324 dns_view_t *view; 325 catz_cb_data_t *cbd; 326 bool mod; 327 } catz_chgzone_event_t; 328 329 typedef struct catz_reconfig_data { 330 dns_catz_zone_t *catz; 331 const cfg_obj_t *config; 332 catz_cb_data_t *cbd; 333 } catz_reconfig_data_t; 334 335 typedef struct { 336 unsigned int magic; 337 #define DZARG_MAGIC ISC_MAGIC('D', 'z', 'a', 'r') 338 isc_buffer_t **text; 339 isc_result_t result; 340 } ns_dzarg_t; 341 342 /* 343 * These zones should not leak onto the Internet. 344 */ 345 const char *empty_zones[] = { 346 /* RFC 1918 */ 347 "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA", 348 "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA", 349 "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA", 350 "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA", 351 "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA", 352 "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA", 353 354 /* RFC 6598 */ 355 "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA", 356 "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA", 357 "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA", 358 "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA", 359 "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA", 360 "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA", 361 "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA", 362 "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA", 363 "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA", 364 "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA", 365 "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA", 366 "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA", 367 "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA", "102.100.IN-ADDR.ARPA", 368 "103.100.IN-ADDR.ARPA", "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA", 369 "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA", "108.100.IN-ADDR.ARPA", 370 "109.100.IN-ADDR.ARPA", "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA", 371 "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA", "114.100.IN-ADDR.ARPA", 372 "115.100.IN-ADDR.ARPA", "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA", 373 "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA", "120.100.IN-ADDR.ARPA", 374 "121.100.IN-ADDR.ARPA", "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA", 375 "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA", "126.100.IN-ADDR.ARPA", 376 "127.100.IN-ADDR.ARPA", 377 378 /* RFC 5735 and RFC 5737 */ 379 "0.IN-ADDR.ARPA", /* THIS NETWORK */ 380 "127.IN-ADDR.ARPA", /* LOOPBACK */ 381 "254.169.IN-ADDR.ARPA", /* LINK LOCAL */ 382 "2.0.192.IN-ADDR.ARPA", /* TEST NET */ 383 "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */ 384 "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */ 385 "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */ 386 387 /* Local IPv6 Unicast Addresses */ 388 "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." 389 "ARPA", 390 "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." 391 "ARPA", 392 /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ 393 "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", /* LINK LOCAL */ 394 "9.E.F.IP6.ARPA", /* LINK LOCAL */ 395 "A.E.F.IP6.ARPA", /* LINK LOCAL */ 396 "B.E.F.IP6.ARPA", /* LINK LOCAL */ 397 398 /* Example Prefix, RFC 3849. */ 399 "8.B.D.0.1.0.0.2.IP6.ARPA", 400 401 /* RFC 7534 */ 402 "EMPTY.AS112.ARPA", 403 404 /* RFC 8375 */ 405 "HOME.ARPA", 406 407 /* RFC 9462 */ 408 "RESOLVER.ARPA", 409 410 NULL 411 }; 412 413 noreturn static void 414 fatal(named_server_t *server, const char *msg, isc_result_t result); 415 416 static void 417 named_server_reload(isc_task_t *task, isc_event_t *event); 418 419 #ifdef HAVE_LIBNGHTTP2 420 static isc_result_t 421 listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, 422 const ns_listen_tls_params_t *tls_params, 423 isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, 424 isc_mem_t *mctx, ns_listenelt_t **target); 425 #endif 426 427 static isc_result_t 428 listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 429 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 430 isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target); 431 432 static isc_result_t 433 listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 434 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 435 isc_tlsctx_cache_t *tlsctx_cache, 436 ns_listenlist_t **target); 437 438 static isc_result_t 439 configure_forward(const cfg_obj_t *config, dns_view_t *view, 440 const dns_name_t *origin, const cfg_obj_t *forwarders, 441 const cfg_obj_t *forwardtype); 442 443 static isc_result_t 444 configure_alternates(const cfg_obj_t *config, dns_view_t *view, 445 const cfg_obj_t *alternates); 446 447 static isc_result_t 448 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 449 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 450 dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, 451 cfg_aclconfctx_t *aclconf, bool added, bool old_rpz_ok, 452 bool is_catz_member, bool modify); 453 454 static void 455 configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, 456 dns_view_t *view); 457 458 static isc_result_t 459 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 460 isc_mem_t *mctx, cfg_aclconfctx_t *actx); 461 462 static isc_result_t 463 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); 464 465 static void 466 end_reserved_dispatches(named_server_t *server, bool all); 467 468 static void 469 newzone_cfgctx_destroy(void **cfgp); 470 471 static isc_result_t 472 putstr(isc_buffer_t **b, const char *str); 473 474 static isc_result_t 475 putmem(isc_buffer_t **b, const char *str, size_t len); 476 477 static isc_result_t 478 putuint8(isc_buffer_t **b, uint8_t val); 479 480 static isc_result_t 481 putnull(isc_buffer_t **b); 482 483 static int 484 count_zones(const cfg_obj_t *conf); 485 486 #ifdef HAVE_LMDB 487 static isc_result_t 488 migrate_nzf(dns_view_t *view); 489 490 static isc_result_t 491 nzd_writable(dns_view_t *view); 492 493 static isc_result_t 494 nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi); 495 496 static isc_result_t 497 nzd_env_reopen(dns_view_t *view); 498 499 static void 500 nzd_env_close(dns_view_t *view); 501 502 static isc_result_t 503 nzd_close(MDB_txn **txnp, bool commit); 504 505 static isc_result_t 506 nzd_count(dns_view_t *view, int *countp); 507 #else /* ifdef HAVE_LMDB */ 508 static isc_result_t 509 nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); 510 #endif /* ifdef HAVE_LMDB */ 511 512 /*% 513 * Configure a single view ACL at '*aclp'. Get its configuration from 514 * 'vconfig' (for per-view configuration) and maybe from 'config' 515 */ 516 static isc_result_t 517 configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, 518 const cfg_obj_t *gconfig, const char *aclname, 519 const char *acltuplename, cfg_aclconfctx_t *actx, 520 isc_mem_t *mctx, dns_acl_t **aclp) { 521 isc_result_t result; 522 const cfg_obj_t *maps[4]; 523 const cfg_obj_t *aclobj = NULL; 524 int i = 0; 525 526 if (*aclp != NULL) { 527 dns_acl_detach(aclp); 528 } 529 if (vconfig != NULL) { 530 maps[i++] = cfg_tuple_get(vconfig, "options"); 531 } 532 if (config != NULL) { 533 const cfg_obj_t *options = NULL; 534 (void)cfg_map_get(config, "options", &options); 535 if (options != NULL) { 536 maps[i++] = options; 537 } 538 } 539 if (gconfig != NULL) { 540 const cfg_obj_t *options = NULL; 541 (void)cfg_map_get(gconfig, "options", &options); 542 if (options != NULL) { 543 maps[i++] = options; 544 } 545 } 546 maps[i] = NULL; 547 548 (void)named_config_get(maps, aclname, &aclobj); 549 if (aclobj == NULL) { 550 /* 551 * No value available. *aclp == NULL. 552 */ 553 return (ISC_R_SUCCESS); 554 } 555 556 if (acltuplename != NULL) { 557 /* 558 * If the ACL is given in an optional tuple, retrieve it. 559 * The parser should have ensured that a valid object be 560 * returned. 561 */ 562 aclobj = cfg_tuple_get(aclobj, acltuplename); 563 } 564 565 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 0, 566 aclp); 567 568 return (result); 569 } 570 571 /*% 572 * Configure a sortlist at '*aclp'. Essentially the same as 573 * configure_view_acl() except it calls cfg_acl_fromconfig with a 574 * nest_level value of 2. 575 */ 576 static isc_result_t 577 configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, 578 cfg_aclconfctx_t *actx, isc_mem_t *mctx, 579 dns_acl_t **aclp) { 580 isc_result_t result; 581 const cfg_obj_t *maps[3]; 582 const cfg_obj_t *aclobj = NULL; 583 int i = 0; 584 585 if (*aclp != NULL) { 586 dns_acl_detach(aclp); 587 } 588 if (vconfig != NULL) { 589 maps[i++] = cfg_tuple_get(vconfig, "options"); 590 } 591 if (config != NULL) { 592 const cfg_obj_t *options = NULL; 593 (void)cfg_map_get(config, "options", &options); 594 if (options != NULL) { 595 maps[i++] = options; 596 } 597 } 598 maps[i] = NULL; 599 600 (void)named_config_get(maps, "sortlist", &aclobj); 601 if (aclobj == NULL) { 602 return (ISC_R_SUCCESS); 603 } 604 605 /* 606 * Use a nest level of 3 for the "top level" of the sortlist; 607 * this means each entry in the top three levels will be stored 608 * as lists of separate, nested ACLs, rather than merged together 609 * into IP tables as is usually done with ACLs. 610 */ 611 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 3, 612 aclp); 613 614 return (result); 615 } 616 617 static isc_result_t 618 configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, 619 const char *confname, const char *conftuplename, 620 isc_mem_t *mctx, dns_rbt_t **rbtp) { 621 isc_result_t result; 622 const cfg_obj_t *maps[3]; 623 const cfg_obj_t *obj = NULL; 624 const cfg_listelt_t *element; 625 int i = 0; 626 dns_fixedname_t fixed; 627 dns_name_t *name; 628 isc_buffer_t b; 629 const char *str; 630 const cfg_obj_t *nameobj; 631 632 if (*rbtp != NULL) { 633 dns_rbt_destroy(rbtp); 634 } 635 if (vconfig != NULL) { 636 maps[i++] = cfg_tuple_get(vconfig, "options"); 637 } 638 if (config != NULL) { 639 const cfg_obj_t *options = NULL; 640 (void)cfg_map_get(config, "options", &options); 641 if (options != NULL) { 642 maps[i++] = options; 643 } 644 } 645 maps[i] = NULL; 646 647 (void)named_config_get(maps, confname, &obj); 648 if (obj == NULL) { 649 /* 650 * No value available. *rbtp == NULL. 651 */ 652 return (ISC_R_SUCCESS); 653 } 654 655 if (conftuplename != NULL) { 656 obj = cfg_tuple_get(obj, conftuplename); 657 if (cfg_obj_isvoid(obj)) { 658 return (ISC_R_SUCCESS); 659 } 660 } 661 662 result = dns_rbt_create(mctx, NULL, NULL, rbtp); 663 if (result != ISC_R_SUCCESS) { 664 return (result); 665 } 666 667 name = dns_fixedname_initname(&fixed); 668 for (element = cfg_list_first(obj); element != NULL; 669 element = cfg_list_next(element)) 670 { 671 nameobj = cfg_listelt_value(element); 672 str = cfg_obj_asstring(nameobj); 673 isc_buffer_constinit(&b, str, strlen(str)); 674 isc_buffer_add(&b, strlen(str)); 675 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 676 /* 677 * We don't need the node data, but need to set dummy data to 678 * avoid a partial match with an empty node. For example, if 679 * we have foo.example.com and bar.example.com, we'd get a match 680 * for baz.example.com, which is not the expected result. 681 * We simply use (void *)1 as the dummy data. 682 */ 683 result = dns_rbt_addname(*rbtp, name, (void *)1); 684 if (result != ISC_R_SUCCESS) { 685 cfg_obj_log(nameobj, named_g_lctx, ISC_LOG_ERROR, 686 "failed to add %s for %s: %s", str, 687 confname, isc_result_totext(result)); 688 goto cleanup; 689 } 690 } 691 692 return (result); 693 694 cleanup: 695 dns_rbt_destroy(rbtp); 696 return (result); 697 } 698 699 static isc_result_t 700 ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp, 701 unsigned char *digest, dns_rdata_ds_t *ds) { 702 isc_result_t result; 703 dns_rdata_dnskey_t keystruct; 704 dns_rdata_t rdata = DNS_RDATA_INIT; 705 uint32_t rdata1, rdata2, rdata3; 706 const char *datastr = NULL, *namestr = NULL; 707 unsigned char data[4096]; 708 isc_buffer_t databuf; 709 unsigned char rrdata[4096]; 710 isc_buffer_t rrdatabuf; 711 isc_region_t r; 712 dns_fixedname_t fname; 713 dns_name_t *name = NULL; 714 isc_buffer_t namebuf; 715 const char *atstr = NULL; 716 enum { 717 INIT_DNSKEY, 718 STATIC_DNSKEY, 719 INIT_DS, 720 STATIC_DS, 721 TRUSTED 722 } anchortype; 723 724 REQUIRE(namestrp != NULL && *namestrp == NULL); 725 REQUIRE(ds != NULL); 726 727 /* if DNSKEY, flags; if DS, key tag */ 728 rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1")); 729 730 /* if DNSKEY, protocol; if DS, algorithm */ 731 rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2")); 732 733 /* if DNSKEY, algorithm; if DS, digest type */ 734 rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3")); 735 736 namestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 737 *namestrp = namestr; 738 739 name = dns_fixedname_initname(&fname); 740 isc_buffer_constinit(&namebuf, namestr, strlen(namestr)); 741 isc_buffer_add(&namebuf, strlen(namestr)); 742 CHECK(dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL)); 743 744 if (*initialp) { 745 atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype")); 746 747 if (strcasecmp(atstr, "static-key") == 0) { 748 *initialp = false; 749 anchortype = STATIC_DNSKEY; 750 } else if (strcasecmp(atstr, "static-ds") == 0) { 751 *initialp = false; 752 anchortype = STATIC_DS; 753 } else if (strcasecmp(atstr, "initial-key") == 0) { 754 anchortype = INIT_DNSKEY; 755 } else if (strcasecmp(atstr, "initial-ds") == 0) { 756 anchortype = INIT_DS; 757 } else { 758 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 759 "key '%s': " 760 "invalid initialization method '%s'", 761 namestr, atstr); 762 result = ISC_R_FAILURE; 763 goto cleanup; 764 } 765 } else { 766 anchortype = TRUSTED; 767 } 768 769 isc_buffer_init(&databuf, data, sizeof(data)); 770 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 771 772 *ds = (dns_rdata_ds_t){ .common.rdclass = dns_rdataclass_in, 773 .common.rdtype = dns_rdatatype_ds }; 774 775 ISC_LINK_INIT(&ds->common, link); 776 777 switch (anchortype) { 778 case INIT_DNSKEY: 779 case STATIC_DNSKEY: 780 case TRUSTED: 781 /* 782 * This function should never be reached for view 783 * class other than IN 784 */ 785 keystruct.common.rdclass = dns_rdataclass_in; 786 keystruct.common.rdtype = dns_rdatatype_dnskey; 787 788 /* 789 * The key data in keystruct is not dynamically allocated. 790 */ 791 keystruct.mctx = NULL; 792 793 ISC_LINK_INIT(&keystruct.common, link); 794 795 if (rdata1 > 0xffff) { 796 CHECKM(ISC_R_RANGE, "key flags"); 797 } 798 if (rdata1 & DNS_KEYFLAG_REVOKE) { 799 CHECKM(DST_R_BADKEYTYPE, "key flags revoke bit set"); 800 } 801 if (rdata2 > 0xff) { 802 CHECKM(ISC_R_RANGE, "key protocol"); 803 } 804 if (rdata3 > 0xff) { 805 CHECKM(ISC_R_RANGE, "key algorithm"); 806 } 807 808 keystruct.flags = (uint16_t)rdata1; 809 keystruct.protocol = (uint8_t)rdata2; 810 keystruct.algorithm = (uint8_t)rdata3; 811 812 if (!dst_algorithm_supported(keystruct.algorithm)) { 813 CHECK(DST_R_UNSUPPORTEDALG); 814 } 815 816 datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); 817 CHECK(isc_base64_decodestring(datastr, &databuf)); 818 isc_buffer_usedregion(&databuf, &r); 819 keystruct.datalen = r.length; 820 keystruct.data = r.base; 821 822 CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass, 823 keystruct.common.rdtype, &keystruct, 824 &rrdatabuf)); 825 CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, 826 digest, ds)); 827 break; 828 829 case INIT_DS: 830 case STATIC_DS: 831 if (rdata1 > 0xffff) { 832 CHECKM(ISC_R_RANGE, "key tag"); 833 } 834 if (rdata2 > 0xff) { 835 CHECKM(ISC_R_RANGE, "key algorithm"); 836 } 837 if (rdata3 > 0xff) { 838 CHECKM(ISC_R_RANGE, "digest type"); 839 } 840 841 ds->key_tag = (uint16_t)rdata1; 842 ds->algorithm = (uint8_t)rdata2; 843 ds->digest_type = (uint8_t)rdata3; 844 845 datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); 846 CHECK(isc_hex_decodestring(datastr, &databuf)); 847 isc_buffer_usedregion(&databuf, &r); 848 849 switch (ds->digest_type) { 850 case DNS_DSDIGEST_SHA1: 851 if (r.length != ISC_SHA1_DIGESTLENGTH) { 852 CHECK(ISC_R_UNEXPECTEDEND); 853 } 854 break; 855 case DNS_DSDIGEST_SHA256: 856 if (r.length != ISC_SHA256_DIGESTLENGTH) { 857 CHECK(ISC_R_UNEXPECTEDEND); 858 } 859 break; 860 case DNS_DSDIGEST_SHA384: 861 if (r.length != ISC_SHA384_DIGESTLENGTH) { 862 CHECK(ISC_R_UNEXPECTEDEND); 863 } 864 break; 865 default: 866 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 867 "key '%s': " 868 "unknown ds digest type %u", 869 namestr, ds->digest_type); 870 result = ISC_R_FAILURE; 871 goto cleanup; 872 break; 873 } 874 875 ds->length = r.length; 876 ds->digest = digest; 877 memmove(ds->digest, r.base, r.length); 878 879 break; 880 881 default: 882 UNREACHABLE(); 883 } 884 885 return (ISC_R_SUCCESS); 886 887 cleanup: 888 return (result); 889 } 890 891 static void 892 sfd_add(const dns_name_t *name, void *arg) { 893 if (arg != NULL) { 894 dns_view_sfd_add(arg, name); 895 } 896 } 897 898 /*% 899 * Parse 'key' in the context of view configuration 'vconfig'. If successful, 900 * add the key to 'secroots' if both of the following conditions are true: 901 * 902 * - 'keyname_match' is NULL or it matches the owner name of 'key', 903 * - support for the algorithm used by 'key' is not disabled by 'resolver' 904 * for the owner name of 'key'. 905 * 906 * 'managed' is true for managed keys and false for trusted keys. 'mctx' is 907 * the memory context to use for allocating memory. 908 */ 909 static isc_result_t 910 process_key(const cfg_obj_t *key, dns_keytable_t *secroots, 911 const dns_name_t *keyname_match, dns_view_t *view, bool managed) { 912 dns_fixedname_t fkeyname; 913 dns_name_t *keyname = NULL; 914 const char *namestr = NULL; 915 dns_rdata_ds_t ds; 916 isc_result_t result; 917 bool initializing = managed; 918 unsigned char digest[ISC_MAX_MD_SIZE]; 919 isc_buffer_t b; 920 921 result = ta_fromconfig(key, &initializing, &namestr, digest, &ds); 922 923 switch (result) { 924 case ISC_R_SUCCESS: 925 /* 926 * Trust anchor was parsed correctly. 927 */ 928 isc_buffer_constinit(&b, namestr, strlen(namestr)); 929 isc_buffer_add(&b, strlen(namestr)); 930 keyname = dns_fixedname_initname(&fkeyname); 931 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); 932 if (result != ISC_R_SUCCESS) { 933 return (result); 934 } 935 break; 936 case DST_R_UNSUPPORTEDALG: 937 case DST_R_BADKEYTYPE: 938 /* 939 * Key was parsed correctly, but it cannot be used; this is not 940 * a fatal error - log a warning about this key being ignored, 941 * but do not prevent any further ones from being processed. 942 */ 943 cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, 944 "ignoring %s for '%s': %s", 945 initializing ? "initial-key" : "static-key", 946 namestr, isc_result_totext(result)); 947 return (ISC_R_SUCCESS); 948 case DST_R_NOCRYPTO: 949 /* 950 * Crypto support is not available. 951 */ 952 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 953 "ignoring %s for '%s': no crypto support", 954 initializing ? "initial-key" : "static-key", 955 namestr); 956 return (result); 957 default: 958 /* 959 * Something unexpected happened; we have no choice but to 960 * indicate an error so that the configuration loading process 961 * is interrupted. 962 */ 963 cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, 964 "configuring %s for '%s': %s", 965 initializing ? "initial-key" : "static-key", 966 namestr, isc_result_totext(result)); 967 return (ISC_R_FAILURE); 968 } 969 970 /* 971 * If the caller requested to only load keys for a specific name and 972 * the owner name of this key does not match the requested name, do not 973 * load it. 974 */ 975 if (keyname_match != NULL && !dns_name_equal(keyname_match, keyname)) { 976 goto done; 977 } 978 979 /* 980 * Ensure that 'resolver' allows using the algorithm of this key for 981 * its owner name. If it does not, do not load the key and log a 982 * warning, but do not prevent further keys from being processed. 983 */ 984 if (!dns_resolver_algorithm_supported(view->resolver, keyname, 985 ds.algorithm)) 986 { 987 cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, 988 "ignoring %s for '%s': algorithm is disabled", 989 initializing ? "initial-key" : "static-key", 990 namestr); 991 goto done; 992 } 993 994 /* 995 * Add the key to 'secroots'. Keys from a "trust-anchors" or 996 * "managed-keys" statement may be either static or initializing 997 * keys. If it's not initializing, we don't want to treat it as 998 * managed, so we use 'initializing' twice here, for both the 999 * 'managed' and 'initializing' arguments to dns_keytable_add(). 1000 */ 1001 result = dns_keytable_add(secroots, initializing, initializing, keyname, 1002 &ds, sfd_add, view); 1003 1004 done: 1005 return (result); 1006 } 1007 1008 /* 1009 * Load keys from configuration into key table. If 'keyname' is specified, 1010 * only load keys matching that name. If 'managed' is true, load the key as 1011 * an initializing key. 1012 */ 1013 static isc_result_t 1014 load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, 1015 const dns_name_t *keyname) { 1016 const cfg_listelt_t *elt, *elt2; 1017 const cfg_obj_t *keylist; 1018 isc_result_t result; 1019 dns_keytable_t *secroots = NULL; 1020 1021 CHECK(dns_view_getsecroots(view, &secroots)); 1022 1023 for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) 1024 { 1025 keylist = cfg_listelt_value(elt); 1026 1027 for (elt2 = cfg_list_first(keylist); elt2 != NULL; 1028 elt2 = cfg_list_next(elt2)) 1029 { 1030 CHECK(process_key(cfg_listelt_value(elt2), secroots, 1031 keyname, view, managed)); 1032 } 1033 } 1034 1035 cleanup: 1036 if (secroots != NULL) { 1037 dns_keytable_detach(&secroots); 1038 } 1039 if (result == DST_R_NOCRYPTO) { 1040 result = ISC_R_SUCCESS; 1041 } 1042 return (result); 1043 } 1044 1045 /*% 1046 * Check whether a key has been successfully loaded. 1047 */ 1048 static bool 1049 keyloaded(dns_view_t *view, const dns_name_t *name) { 1050 isc_result_t result; 1051 dns_keytable_t *secroots = NULL; 1052 dns_keynode_t *keynode = NULL; 1053 1054 result = dns_view_getsecroots(view, &secroots); 1055 if (result != ISC_R_SUCCESS) { 1056 return (false); 1057 } 1058 1059 result = dns_keytable_find(secroots, name, &keynode); 1060 1061 if (keynode != NULL) { 1062 dns_keytable_detachkeynode(secroots, &keynode); 1063 } 1064 if (secroots != NULL) { 1065 dns_keytable_detach(&secroots); 1066 } 1067 1068 return (result == ISC_R_SUCCESS); 1069 } 1070 1071 /*% 1072 * Configure DNSSEC keys for a view. 1073 * 1074 * The per-view configuration values and the server-global defaults are read 1075 * from 'vconfig' and 'config'. 1076 */ 1077 static isc_result_t 1078 configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, 1079 const cfg_obj_t *config, const cfg_obj_t *bindkeys, 1080 bool auto_root, isc_mem_t *mctx) { 1081 isc_result_t result = ISC_R_SUCCESS; 1082 const cfg_obj_t *view_keys = NULL; 1083 const cfg_obj_t *global_keys = NULL; 1084 const cfg_obj_t *view_managed_keys = NULL; 1085 const cfg_obj_t *view_trust_anchors = NULL; 1086 const cfg_obj_t *global_managed_keys = NULL; 1087 const cfg_obj_t *global_trust_anchors = NULL; 1088 const cfg_obj_t *maps[4]; 1089 const cfg_obj_t *voptions = NULL; 1090 const cfg_obj_t *options = NULL; 1091 const cfg_obj_t *obj = NULL; 1092 const char *directory; 1093 int i = 0; 1094 1095 /* We don't need trust anchors for the _bind view */ 1096 if (strcmp(view->name, "_bind") == 0 && 1097 view->rdclass == dns_rdataclass_chaos) 1098 { 1099 return (ISC_R_SUCCESS); 1100 } 1101 1102 if (vconfig != NULL) { 1103 voptions = cfg_tuple_get(vconfig, "options"); 1104 if (voptions != NULL) { 1105 (void)cfg_map_get(voptions, "trusted-keys", &view_keys); 1106 1107 /* managed-keys and trust-anchors are synonyms. */ 1108 (void)cfg_map_get(voptions, "managed-keys", 1109 &view_managed_keys); 1110 (void)cfg_map_get(voptions, "trust-anchors", 1111 &view_trust_anchors); 1112 1113 maps[i++] = voptions; 1114 } 1115 } 1116 1117 if (config != NULL) { 1118 (void)cfg_map_get(config, "trusted-keys", &global_keys); 1119 1120 /* managed-keys and trust-anchors are synonyms. */ 1121 (void)cfg_map_get(config, "managed-keys", &global_managed_keys); 1122 (void)cfg_map_get(config, "trust-anchors", 1123 &global_trust_anchors); 1124 1125 (void)cfg_map_get(config, "options", &options); 1126 if (options != NULL) { 1127 maps[i++] = options; 1128 } 1129 } 1130 1131 maps[i++] = named_g_defaults; 1132 maps[i] = NULL; 1133 1134 result = dns_view_initsecroots(view, mctx); 1135 if (result != ISC_R_SUCCESS) { 1136 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1137 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1138 "couldn't create keytable"); 1139 return (ISC_R_UNEXPECTED); 1140 } 1141 1142 result = dns_view_initntatable(view, named_g_taskmgr, named_g_timermgr); 1143 if (result != ISC_R_SUCCESS) { 1144 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1145 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1146 "couldn't create NTA table"); 1147 return (ISC_R_UNEXPECTED); 1148 } 1149 1150 if (auto_root && view->rdclass == dns_rdataclass_in) { 1151 const cfg_obj_t *builtin_keys = NULL; 1152 1153 /* 1154 * If bind.keys exists and is populated, it overrides 1155 * the trust-anchors clause hard-coded in named_g_config. 1156 */ 1157 if (bindkeys != NULL) { 1158 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1159 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1160 "obtaining root key for view %s " 1161 "from '%s'", 1162 view->name, named_g_server->bindkeysfile); 1163 1164 (void)cfg_map_get(bindkeys, "trust-anchors", 1165 &builtin_keys); 1166 1167 if (builtin_keys == NULL) { 1168 isc_log_write( 1169 named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1170 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 1171 "dnssec-validation auto: " 1172 "WARNING: root zone key " 1173 "not found"); 1174 } 1175 } 1176 1177 if (builtin_keys == NULL) { 1178 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1179 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1180 "using built-in root key for view %s", 1181 view->name); 1182 1183 (void)cfg_map_get(named_g_config, "trust-anchors", 1184 &builtin_keys); 1185 } 1186 1187 if (builtin_keys != NULL) { 1188 CHECK(load_view_keys(builtin_keys, view, true, 1189 dns_rootname)); 1190 } 1191 1192 if (!keyloaded(view, dns_rootname)) { 1193 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1194 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1195 "root key not loaded"); 1196 result = ISC_R_FAILURE; 1197 goto cleanup; 1198 } 1199 } 1200 1201 if (view->rdclass == dns_rdataclass_in) { 1202 CHECK(load_view_keys(view_keys, view, false, NULL)); 1203 CHECK(load_view_keys(view_trust_anchors, view, true, NULL)); 1204 CHECK(load_view_keys(view_managed_keys, view, true, NULL)); 1205 1206 CHECK(load_view_keys(global_keys, view, false, NULL)); 1207 CHECK(load_view_keys(global_trust_anchors, view, true, NULL)); 1208 CHECK(load_view_keys(global_managed_keys, view, true, NULL)); 1209 } 1210 1211 /* 1212 * Add key zone for managed keys. 1213 */ 1214 obj = NULL; 1215 (void)named_config_get(maps, "managed-keys-directory", &obj); 1216 directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL); 1217 if (directory != NULL) { 1218 result = isc_file_isdirectory(directory); 1219 } 1220 if (result != ISC_R_SUCCESS) { 1221 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 1222 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1223 "invalid managed-keys-directory %s: %s", 1224 directory, isc_result_totext(result)); 1225 goto cleanup; 1226 } else if (directory != NULL) { 1227 if (!isc_file_isdirwritable(directory)) { 1228 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1229 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1230 "managed-keys-directory '%s' " 1231 "is not writable", 1232 directory); 1233 result = ISC_R_NOPERM; 1234 goto cleanup; 1235 } 1236 } 1237 1238 CHECK(add_keydata_zone(view, directory, named_g_mctx)); 1239 1240 cleanup: 1241 return (result); 1242 } 1243 1244 static isc_result_t 1245 mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { 1246 const cfg_listelt_t *element; 1247 const cfg_obj_t *obj; 1248 const char *str; 1249 dns_fixedname_t fixed; 1250 dns_name_t *name; 1251 bool value; 1252 isc_result_t result; 1253 isc_buffer_t b; 1254 1255 name = dns_fixedname_initname(&fixed); 1256 for (element = cfg_list_first(mbs); element != NULL; 1257 element = cfg_list_next(element)) 1258 { 1259 obj = cfg_listelt_value(element); 1260 str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 1261 isc_buffer_constinit(&b, str, strlen(str)); 1262 isc_buffer_add(&b, strlen(str)); 1263 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1264 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); 1265 CHECK(dns_resolver_setmustbesecure(resolver, name, value)); 1266 } 1267 1268 result = ISC_R_SUCCESS; 1269 1270 cleanup: 1271 return (result); 1272 } 1273 1274 /*% 1275 * Get a dispatch appropriate for the resolver of a given view. 1276 */ 1277 static isc_result_t 1278 get_view_querysource_dispatch(const cfg_obj_t **maps, int af, 1279 dns_dispatch_t **dispatchp, bool is_firstview) { 1280 isc_result_t result = ISC_R_FAILURE; 1281 dns_dispatch_t *disp = NULL; 1282 isc_sockaddr_t sa; 1283 const cfg_obj_t *obj = NULL; 1284 1285 switch (af) { 1286 case AF_INET: 1287 result = named_config_get(maps, "query-source", &obj); 1288 INSIST(result == ISC_R_SUCCESS); 1289 break; 1290 case AF_INET6: 1291 result = named_config_get(maps, "query-source-v6", &obj); 1292 INSIST(result == ISC_R_SUCCESS); 1293 break; 1294 default: 1295 UNREACHABLE(); 1296 } 1297 1298 sa = *(cfg_obj_assockaddr(obj)); 1299 INSIST(isc_sockaddr_pf(&sa) == af); 1300 1301 /* 1302 * If we don't support this address family, we're done! 1303 */ 1304 switch (af) { 1305 case AF_INET: 1306 result = isc_net_probeipv4(); 1307 break; 1308 case AF_INET6: 1309 result = isc_net_probeipv6(); 1310 break; 1311 default: 1312 UNREACHABLE(); 1313 } 1314 if (result != ISC_R_SUCCESS) { 1315 return (ISC_R_SUCCESS); 1316 } 1317 1318 /* 1319 * Try to find a dispatcher that we can share. 1320 */ 1321 if (isc_sockaddr_getport(&sa) != 0) { 1322 INSIST(obj != NULL); 1323 if (is_firstview) { 1324 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 1325 "using specific query-source port " 1326 "suppresses port randomization and can be " 1327 "insecure."); 1328 } 1329 } 1330 1331 result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, &disp); 1332 if (result != ISC_R_SUCCESS) { 1333 isc_sockaddr_t any; 1334 char buf[ISC_SOCKADDR_FORMATSIZE]; 1335 1336 switch (af) { 1337 case AF_INET: 1338 isc_sockaddr_any(&any); 1339 break; 1340 case AF_INET6: 1341 isc_sockaddr_any6(&any); 1342 break; 1343 } 1344 if (isc_sockaddr_equal(&sa, &any)) { 1345 return (ISC_R_SUCCESS); 1346 } 1347 isc_sockaddr_format(&sa, buf, sizeof(buf)); 1348 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1349 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1350 "could not get query source dispatcher (%s)", 1351 buf); 1352 return (result); 1353 } 1354 1355 *dispatchp = disp; 1356 1357 return (ISC_R_SUCCESS); 1358 } 1359 1360 static isc_result_t 1361 configure_order(dns_order_t *order, const cfg_obj_t *ent) { 1362 dns_rdataclass_t rdclass; 1363 dns_rdatatype_t rdtype; 1364 const cfg_obj_t *obj; 1365 dns_fixedname_t fixed; 1366 unsigned int mode = 0; 1367 const char *str; 1368 isc_buffer_t b; 1369 isc_result_t result; 1370 bool addroot; 1371 1372 result = named_config_getclass(cfg_tuple_get(ent, "class"), 1373 dns_rdataclass_any, &rdclass); 1374 if (result != ISC_R_SUCCESS) { 1375 return (result); 1376 } 1377 1378 result = named_config_gettype(cfg_tuple_get(ent, "type"), 1379 dns_rdatatype_any, &rdtype); 1380 if (result != ISC_R_SUCCESS) { 1381 return (result); 1382 } 1383 1384 obj = cfg_tuple_get(ent, "name"); 1385 if (cfg_obj_isstring(obj)) { 1386 str = cfg_obj_asstring(obj); 1387 } else { 1388 str = "*"; 1389 } 1390 addroot = (strcmp(str, "*") == 0); 1391 isc_buffer_constinit(&b, str, strlen(str)); 1392 isc_buffer_add(&b, strlen(str)); 1393 dns_fixedname_init(&fixed); 1394 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, dns_rootname, 1395 0, NULL); 1396 if (result != ISC_R_SUCCESS) { 1397 return (result); 1398 } 1399 1400 obj = cfg_tuple_get(ent, "ordering"); 1401 INSIST(cfg_obj_isstring(obj)); 1402 str = cfg_obj_asstring(obj); 1403 if (!strcasecmp(str, "fixed")) { 1404 #if DNS_RDATASET_FIXED 1405 mode = DNS_RDATASETATTR_FIXEDORDER; 1406 #else /* if DNS_RDATASET_FIXED */ 1407 mode = DNS_RDATASETATTR_CYCLIC; 1408 #endif /* DNS_RDATASET_FIXED */ 1409 } else if (!strcasecmp(str, "random")) { 1410 mode = DNS_RDATASETATTR_RANDOMIZE; 1411 } else if (!strcasecmp(str, "cyclic")) { 1412 mode = DNS_RDATASETATTR_CYCLIC; 1413 } else if (!strcasecmp(str, "none")) { 1414 mode = DNS_RDATASETATTR_NONE; 1415 } else { 1416 UNREACHABLE(); 1417 } 1418 1419 /* 1420 * "*" should match everything including the root (BIND 8 compat). 1421 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a 1422 * explicit entry for "." when the name is "*". 1423 */ 1424 if (addroot) { 1425 result = dns_order_add(order, dns_rootname, rdtype, rdclass, 1426 mode); 1427 if (result != ISC_R_SUCCESS) { 1428 return (result); 1429 } 1430 } 1431 1432 return (dns_order_add(order, dns_fixedname_name(&fixed), rdtype, 1433 rdclass, mode)); 1434 } 1435 1436 static isc_result_t 1437 configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { 1438 isc_netaddr_t na; 1439 dns_peer_t *peer; 1440 const cfg_obj_t *obj; 1441 const char *str; 1442 isc_result_t result; 1443 unsigned int prefixlen; 1444 1445 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); 1446 1447 peer = NULL; 1448 result = dns_peer_newprefix(mctx, &na, prefixlen, &peer); 1449 if (result != ISC_R_SUCCESS) { 1450 return (result); 1451 } 1452 1453 obj = NULL; 1454 (void)cfg_map_get(cpeer, "bogus", &obj); 1455 if (obj != NULL) { 1456 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); 1457 } 1458 1459 obj = NULL; 1460 (void)cfg_map_get(cpeer, "provide-ixfr", &obj); 1461 if (obj != NULL) { 1462 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); 1463 } 1464 1465 obj = NULL; 1466 (void)cfg_map_get(cpeer, "request-expire", &obj); 1467 if (obj != NULL) { 1468 CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj))); 1469 } 1470 1471 obj = NULL; 1472 (void)cfg_map_get(cpeer, "request-ixfr", &obj); 1473 if (obj != NULL) { 1474 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); 1475 } 1476 1477 obj = NULL; 1478 (void)cfg_map_get(cpeer, "request-nsid", &obj); 1479 if (obj != NULL) { 1480 CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); 1481 } 1482 1483 obj = NULL; 1484 (void)cfg_map_get(cpeer, "send-cookie", &obj); 1485 if (obj != NULL) { 1486 CHECK(dns_peer_setsendcookie(peer, cfg_obj_asboolean(obj))); 1487 } 1488 1489 obj = NULL; 1490 (void)cfg_map_get(cpeer, "edns", &obj); 1491 if (obj != NULL) { 1492 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); 1493 } 1494 1495 obj = NULL; 1496 (void)cfg_map_get(cpeer, "edns-udp-size", &obj); 1497 if (obj != NULL) { 1498 uint32_t udpsize = cfg_obj_asuint32(obj); 1499 if (udpsize < 512U) { 1500 udpsize = 512U; 1501 } 1502 if (udpsize > 4096U) { 1503 udpsize = 4096U; 1504 } 1505 CHECK(dns_peer_setudpsize(peer, (uint16_t)udpsize)); 1506 } 1507 1508 obj = NULL; 1509 (void)cfg_map_get(cpeer, "edns-version", &obj); 1510 if (obj != NULL) { 1511 uint32_t ednsversion = cfg_obj_asuint32(obj); 1512 if (ednsversion > 255U) { 1513 ednsversion = 255U; 1514 } 1515 CHECK(dns_peer_setednsversion(peer, (uint8_t)ednsversion)); 1516 } 1517 1518 obj = NULL; 1519 (void)cfg_map_get(cpeer, "max-udp-size", &obj); 1520 if (obj != NULL) { 1521 uint32_t udpsize = cfg_obj_asuint32(obj); 1522 if (udpsize < 512U) { 1523 udpsize = 512U; 1524 } 1525 if (udpsize > 4096U) { 1526 udpsize = 4096U; 1527 } 1528 CHECK(dns_peer_setmaxudp(peer, (uint16_t)udpsize)); 1529 } 1530 1531 obj = NULL; 1532 (void)cfg_map_get(cpeer, "padding", &obj); 1533 if (obj != NULL) { 1534 uint32_t padding = cfg_obj_asuint32(obj); 1535 if (padding > 512U) { 1536 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 1537 "server padding value cannot " 1538 "exceed 512: lowering"); 1539 padding = 512U; 1540 } 1541 CHECK(dns_peer_setpadding(peer, (uint16_t)padding)); 1542 } 1543 1544 obj = NULL; 1545 (void)cfg_map_get(cpeer, "tcp-only", &obj); 1546 if (obj != NULL) { 1547 CHECK(dns_peer_setforcetcp(peer, cfg_obj_asboolean(obj))); 1548 } 1549 1550 obj = NULL; 1551 (void)cfg_map_get(cpeer, "tcp-keepalive", &obj); 1552 if (obj != NULL) { 1553 CHECK(dns_peer_settcpkeepalive(peer, cfg_obj_asboolean(obj))); 1554 } 1555 1556 obj = NULL; 1557 (void)cfg_map_get(cpeer, "transfers", &obj); 1558 if (obj != NULL) { 1559 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); 1560 } 1561 1562 obj = NULL; 1563 (void)cfg_map_get(cpeer, "transfer-format", &obj); 1564 if (obj != NULL) { 1565 str = cfg_obj_asstring(obj); 1566 if (strcasecmp(str, "many-answers") == 0) { 1567 CHECK(dns_peer_settransferformat(peer, 1568 dns_many_answers)); 1569 } else if (strcasecmp(str, "one-answer") == 0) { 1570 CHECK(dns_peer_settransferformat(peer, dns_one_answer)); 1571 } else { 1572 UNREACHABLE(); 1573 } 1574 } 1575 1576 obj = NULL; 1577 (void)cfg_map_get(cpeer, "keys", &obj); 1578 if (obj != NULL) { 1579 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); 1580 if (result != ISC_R_SUCCESS) { 1581 goto cleanup; 1582 } 1583 } 1584 1585 obj = NULL; 1586 if (na.family == AF_INET) { 1587 (void)cfg_map_get(cpeer, "transfer-source", &obj); 1588 } else { 1589 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); 1590 } 1591 if (obj != NULL) { 1592 result = dns_peer_settransfersource(peer, 1593 cfg_obj_assockaddr(obj)); 1594 if (result != ISC_R_SUCCESS) { 1595 goto cleanup; 1596 } 1597 named_add_reserved_dispatch(named_g_server, 1598 cfg_obj_assockaddr(obj)); 1599 } 1600 1601 obj = NULL; 1602 if (na.family == AF_INET) { 1603 (void)cfg_map_get(cpeer, "notify-source", &obj); 1604 } else { 1605 (void)cfg_map_get(cpeer, "notify-source-v6", &obj); 1606 } 1607 if (obj != NULL) { 1608 result = dns_peer_setnotifysource(peer, 1609 cfg_obj_assockaddr(obj)); 1610 if (result != ISC_R_SUCCESS) { 1611 goto cleanup; 1612 } 1613 named_add_reserved_dispatch(named_g_server, 1614 cfg_obj_assockaddr(obj)); 1615 } 1616 1617 obj = NULL; 1618 if (na.family == AF_INET) { 1619 (void)cfg_map_get(cpeer, "query-source", &obj); 1620 } else { 1621 (void)cfg_map_get(cpeer, "query-source-v6", &obj); 1622 } 1623 if (obj != NULL) { 1624 result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj)); 1625 if (result != ISC_R_SUCCESS) { 1626 goto cleanup; 1627 } 1628 named_add_reserved_dispatch(named_g_server, 1629 cfg_obj_assockaddr(obj)); 1630 } 1631 1632 *peerp = peer; 1633 return (ISC_R_SUCCESS); 1634 1635 cleanup: 1636 dns_peer_detach(&peer); 1637 return (result); 1638 } 1639 1640 static isc_result_t 1641 configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, 1642 const dns_dyndbctx_t *dctx) { 1643 isc_result_t result = ISC_R_SUCCESS; 1644 const cfg_obj_t *obj; 1645 const char *name, *library; 1646 1647 /* Get the name of the dyndb instance and the library path . */ 1648 name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name")); 1649 library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library")); 1650 1651 obj = cfg_tuple_get(dyndb, "parameters"); 1652 if (obj != NULL) { 1653 result = dns_dyndb_load(library, name, cfg_obj_asstring(obj), 1654 cfg_obj_file(obj), cfg_obj_line(obj), 1655 mctx, dctx); 1656 } 1657 1658 if (result != ISC_R_SUCCESS) { 1659 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1660 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 1661 "dynamic database '%s' configuration failed: %s", 1662 name, isc_result_totext(result)); 1663 } 1664 return (result); 1665 } 1666 1667 static isc_result_t 1668 disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1669 isc_result_t result; 1670 const cfg_obj_t *algorithms; 1671 const cfg_listelt_t *element; 1672 const char *str; 1673 dns_fixedname_t fixed; 1674 dns_name_t *name; 1675 isc_buffer_t b; 1676 1677 name = dns_fixedname_initname(&fixed); 1678 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1679 isc_buffer_constinit(&b, str, strlen(str)); 1680 isc_buffer_add(&b, strlen(str)); 1681 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1682 1683 algorithms = cfg_tuple_get(disabled, "algorithms"); 1684 for (element = cfg_list_first(algorithms); element != NULL; 1685 element = cfg_list_next(element)) 1686 { 1687 isc_textregion_t r; 1688 dns_secalg_t alg; 1689 1690 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base); 1691 r.length = strlen(r.base); 1692 1693 result = dns_secalg_fromtext(&alg, &r); 1694 if (result != ISC_R_SUCCESS) { 1695 uint8_t ui; 1696 result = isc_parse_uint8(&ui, r.base, 10); 1697 alg = ui; 1698 } 1699 if (result != ISC_R_SUCCESS) { 1700 cfg_obj_log(cfg_listelt_value(element), named_g_lctx, 1701 ISC_LOG_ERROR, "invalid algorithm"); 1702 CHECK(result); 1703 } 1704 CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); 1705 } 1706 cleanup: 1707 return (result); 1708 } 1709 1710 static isc_result_t 1711 disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 1712 isc_result_t result; 1713 const cfg_obj_t *digests; 1714 const cfg_listelt_t *element; 1715 const char *str; 1716 dns_fixedname_t fixed; 1717 dns_name_t *name; 1718 isc_buffer_t b; 1719 1720 name = dns_fixedname_initname(&fixed); 1721 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 1722 isc_buffer_constinit(&b, str, strlen(str)); 1723 isc_buffer_add(&b, strlen(str)); 1724 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1725 1726 digests = cfg_tuple_get(disabled, "digests"); 1727 for (element = cfg_list_first(digests); element != NULL; 1728 element = cfg_list_next(element)) 1729 { 1730 isc_textregion_t r; 1731 dns_dsdigest_t digest; 1732 1733 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base); 1734 r.length = strlen(r.base); 1735 1736 /* disable_ds_digests handles numeric values. */ 1737 result = dns_dsdigest_fromtext(&digest, &r); 1738 if (result != ISC_R_SUCCESS) { 1739 cfg_obj_log(cfg_listelt_value(element), named_g_lctx, 1740 ISC_LOG_ERROR, "invalid algorithm"); 1741 CHECK(result); 1742 } 1743 CHECK(dns_resolver_disable_ds_digest(resolver, name, digest)); 1744 } 1745 cleanup: 1746 return (result); 1747 } 1748 1749 static bool 1750 on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { 1751 const cfg_listelt_t *element; 1752 dns_fixedname_t fixed; 1753 dns_name_t *name; 1754 isc_result_t result; 1755 const cfg_obj_t *value; 1756 const char *str; 1757 isc_buffer_t b; 1758 1759 name = dns_fixedname_initname(&fixed); 1760 1761 for (element = cfg_list_first(disablelist); element != NULL; 1762 element = cfg_list_next(element)) 1763 { 1764 value = cfg_listelt_value(element); 1765 str = cfg_obj_asstring(value); 1766 isc_buffer_constinit(&b, str, strlen(str)); 1767 isc_buffer_add(&b, strlen(str)); 1768 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 1769 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1770 if (dns_name_equal(name, zonename)) { 1771 return (true); 1772 } 1773 } 1774 return (false); 1775 } 1776 1777 static isc_result_t 1778 check_dbtype(dns_zone_t *zone, unsigned int dbtypec, const char **dbargv, 1779 isc_mem_t *mctx) { 1780 char **argv = NULL; 1781 unsigned int i; 1782 isc_result_t result = ISC_R_SUCCESS; 1783 1784 CHECK(dns_zone_getdbtype(zone, &argv, mctx)); 1785 1786 /* 1787 * Check that all the arguments match. 1788 */ 1789 for (i = 0; i < dbtypec; i++) { 1790 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) { 1791 CHECK(ISC_R_FAILURE); 1792 1793 /* 1794 * Check that there are not extra arguments. 1795 */ 1796 } 1797 } 1798 1799 /* 1800 * Check that there are not extra arguments. 1801 */ 1802 if (i == dbtypec && argv[i] != NULL) { 1803 result = ISC_R_FAILURE; 1804 } 1805 1806 cleanup: 1807 isc_mem_free(mctx, argv); 1808 return (result); 1809 } 1810 1811 static isc_result_t 1812 setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) { 1813 isc_result_t result; 1814 isc_stats_t *zoneqrystats; 1815 1816 dns_zone_setstatlevel(zone, level); 1817 1818 zoneqrystats = NULL; 1819 if (level == dns_zonestat_full) { 1820 result = isc_stats_create(mctx, &zoneqrystats, 1821 ns_statscounter_max); 1822 if (result != ISC_R_SUCCESS) { 1823 return (result); 1824 } 1825 } 1826 dns_zone_setrequeststats(zone, zoneqrystats); 1827 if (zoneqrystats != NULL) { 1828 isc_stats_detach(&zoneqrystats); 1829 } 1830 1831 return (ISC_R_SUCCESS); 1832 } 1833 1834 static named_cache_t * 1835 cachelist_find(named_cachelist_t *cachelist, const char *cachename, 1836 dns_rdataclass_t rdclass) { 1837 named_cache_t *nsc; 1838 1839 for (nsc = ISC_LIST_HEAD(*cachelist); nsc != NULL; 1840 nsc = ISC_LIST_NEXT(nsc, link)) 1841 { 1842 if (nsc->rdclass == rdclass && 1843 strcmp(dns_cache_getname(nsc->cache), cachename) == 0) 1844 { 1845 return (nsc); 1846 } 1847 } 1848 1849 return (NULL); 1850 } 1851 1852 static bool 1853 cache_reusable(dns_view_t *originview, dns_view_t *view, 1854 bool new_zero_no_soattl) { 1855 if (originview->rdclass != view->rdclass || 1856 originview->checknames != view->checknames || 1857 dns_resolver_getzeronosoattl(originview->resolver) != 1858 new_zero_no_soattl || 1859 originview->acceptexpired != view->acceptexpired || 1860 originview->enablevalidation != view->enablevalidation || 1861 originview->maxcachettl != view->maxcachettl || 1862 originview->maxncachettl != view->maxncachettl) 1863 { 1864 return (false); 1865 } 1866 1867 return (true); 1868 } 1869 1870 static bool 1871 cache_sharable(dns_view_t *originview, dns_view_t *view, 1872 bool new_zero_no_soattl, uint64_t new_max_cache_size, 1873 uint32_t new_stale_ttl, uint32_t new_stale_refresh_time) { 1874 /* 1875 * If the cache cannot even reused for the same view, it cannot be 1876 * shared with other views. 1877 */ 1878 if (!cache_reusable(originview, view, new_zero_no_soattl)) { 1879 return (false); 1880 } 1881 1882 /* 1883 * Check other cache related parameters that must be consistent among 1884 * the sharing views. 1885 */ 1886 if (dns_cache_getservestalettl(originview->cache) != new_stale_ttl || 1887 dns_cache_getservestalerefresh(originview->cache) != 1888 new_stale_refresh_time || 1889 dns_cache_getcachesize(originview->cache) != new_max_cache_size) 1890 { 1891 return (false); 1892 } 1893 1894 return (true); 1895 } 1896 1897 /* 1898 * Callback from DLZ configure when the driver sets up a writeable zone 1899 */ 1900 static isc_result_t 1901 dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) { 1902 dns_name_t *origin = dns_zone_getorigin(zone); 1903 dns_rdataclass_t zclass = view->rdclass; 1904 isc_result_t result; 1905 1906 result = dns_zonemgr_managezone(named_g_server->zonemgr, zone); 1907 if (result != ISC_R_SUCCESS) { 1908 return (result); 1909 } 1910 dns_zone_setstats(zone, named_g_server->zonestats); 1911 1912 return (named_zone_configure_writeable_dlz(dlzdb, zone, zclass, 1913 origin)); 1914 } 1915 1916 static isc_result_t 1917 dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, 1918 unsigned int prefixlen, const char *server, const char *contact) { 1919 char reverse[48 + sizeof("ip6.arpa.")] = { 0 }; 1920 char buf[sizeof("x.x.")]; 1921 const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." }; 1922 const char *sep = ": view "; 1923 const char *viewname = view->name; 1924 const unsigned char *s6; 1925 dns_fixedname_t fixed; 1926 dns_name_t *name; 1927 dns_zone_t *zone = NULL; 1928 int dns64_dbtypec = 4; 1929 isc_buffer_t b; 1930 isc_result_t result; 1931 1932 REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || 1933 prefixlen == 56 || prefixlen == 64 || prefixlen == 96); 1934 1935 if (!strcmp(viewname, "_default")) { 1936 sep = ""; 1937 viewname = ""; 1938 } 1939 1940 /* 1941 * Construct the reverse name of the zone. 1942 */ 1943 s6 = na->type.in6.s6_addr; 1944 while (prefixlen > 0) { 1945 prefixlen -= 8; 1946 snprintf(buf, sizeof(buf), "%x.%x.", s6[prefixlen / 8] & 0xf, 1947 (s6[prefixlen / 8] >> 4) & 0xf); 1948 strlcat(reverse, buf, sizeof(reverse)); 1949 } 1950 strlcat(reverse, "ip6.arpa.", sizeof(reverse)); 1951 1952 /* 1953 * Create the actual zone. 1954 */ 1955 if (server != NULL) { 1956 dns64_dbtype[2] = server; 1957 } 1958 if (contact != NULL) { 1959 dns64_dbtype[3] = contact; 1960 } 1961 name = dns_fixedname_initname(&fixed); 1962 isc_buffer_constinit(&b, reverse, strlen(reverse)); 1963 isc_buffer_add(&b, strlen(reverse)); 1964 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); 1965 CHECK(dns_zone_create(&zone, mctx)); 1966 CHECK(dns_zone_setorigin(zone, name)); 1967 dns_zone_setview(zone, view); 1968 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 1969 dns_zone_setclass(zone, view->rdclass); 1970 dns_zone_settype(zone, dns_zone_primary); 1971 dns_zone_setstats(zone, named_g_server->zonestats); 1972 dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype); 1973 if (view->queryacl != NULL) { 1974 dns_zone_setqueryacl(zone, view->queryacl); 1975 } 1976 if (view->queryonacl != NULL) { 1977 dns_zone_setqueryonacl(zone, view->queryonacl); 1978 } 1979 dns_zone_setdialup(zone, dns_dialuptype_no); 1980 dns_zone_setnotifytype(zone, dns_notifytype_no); 1981 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 1982 CHECK(setquerystats(zone, mctx, dns_zonestat_none)); /* XXXMPA */ 1983 CHECK(dns_view_addzone(view, zone)); 1984 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 1985 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 1986 "dns64 reverse zone%s%s: %s", sep, viewname, reverse); 1987 1988 cleanup: 1989 if (zone != NULL) { 1990 dns_zone_detach(&zone); 1991 } 1992 return (result); 1993 } 1994 1995 #ifdef USE_DNSRPS 1996 typedef struct conf_dnsrps_ctx conf_dnsrps_ctx_t; 1997 struct conf_dnsrps_ctx { 1998 isc_result_t result; 1999 char *cstr; 2000 size_t cstr_size; 2001 isc_mem_t *mctx; 2002 }; 2003 2004 /* 2005 * Add to the DNSRPS configuration string. 2006 */ 2007 static bool 2008 conf_dnsrps_sadd(conf_dnsrps_ctx_t *ctx, const char *p, ...) { 2009 size_t new_len, cur_len, new_cstr_size; 2010 char *new_cstr; 2011 va_list args; 2012 2013 if (ctx->cstr == NULL) { 2014 ctx->cstr = isc_mem_get(ctx->mctx, 256); 2015 ctx->cstr[0] = '\0'; 2016 ctx->cstr_size = 256; 2017 } 2018 2019 cur_len = strlen(ctx->cstr); 2020 va_start(args, p); 2021 new_len = vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, 2022 args) + 2023 1; 2024 va_end(args); 2025 2026 if (cur_len + new_len <= ctx->cstr_size) { 2027 return (true); 2028 } 2029 2030 new_cstr_size = ((cur_len + new_len) / 256 + 1) * 256; 2031 new_cstr = isc_mem_get(ctx->mctx, new_cstr_size); 2032 2033 memmove(new_cstr, ctx->cstr, cur_len); 2034 isc_mem_put(ctx->mctx, ctx->cstr, ctx->cstr_size); 2035 ctx->cstr_size = new_cstr_size; 2036 ctx->cstr = new_cstr; 2037 2038 /* cannot use args twice after a single va_start()on some systems */ 2039 va_start(args, p); 2040 vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, args); 2041 va_end(args); 2042 return (true); 2043 } 2044 2045 /* 2046 * Get an DNSRPS configuration value using the global and view options 2047 * for the default. Return false upon failure. 2048 */ 2049 static bool 2050 conf_dnsrps_get(const cfg_obj_t **sub_obj, const cfg_obj_t **maps, 2051 const cfg_obj_t *obj, const char *name, 2052 conf_dnsrps_ctx_t *ctx) { 2053 if (ctx != NULL && ctx->result != ISC_R_SUCCESS) { 2054 *sub_obj = NULL; 2055 return (false); 2056 } 2057 2058 *sub_obj = cfg_tuple_get(obj, name); 2059 if (cfg_obj_isvoid(*sub_obj)) { 2060 *sub_obj = NULL; 2061 if (maps != NULL && 2062 ISC_R_SUCCESS != named_config_get(maps, name, sub_obj)) 2063 { 2064 *sub_obj = NULL; 2065 } 2066 } 2067 return (true); 2068 } 2069 2070 /* 2071 * Handle a DNSRPS boolean configuration value with the global and view 2072 * options providing the default. 2073 */ 2074 static void 2075 conf_dnsrps_yes_no(const cfg_obj_t *obj, const char *name, 2076 conf_dnsrps_ctx_t *ctx) { 2077 const cfg_obj_t *sub_obj; 2078 2079 if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { 2080 return; 2081 } 2082 if (sub_obj == NULL) { 2083 return; 2084 } 2085 if (ctx == NULL) { 2086 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 2087 "\"%s\" without \"dnsrps-enable yes\"", name); 2088 return; 2089 } 2090 2091 conf_dnsrps_sadd(ctx, " %s %s", name, 2092 cfg_obj_asboolean(sub_obj) ? "yes" : "no"); 2093 } 2094 2095 static void 2096 conf_dnsrps_num(const cfg_obj_t *obj, const char *name, 2097 conf_dnsrps_ctx_t *ctx) { 2098 const cfg_obj_t *sub_obj; 2099 2100 if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { 2101 return; 2102 } 2103 if (sub_obj == NULL) { 2104 return; 2105 } 2106 if (ctx == NULL) { 2107 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 2108 "\"%s\" without \"dnsrps-enable yes\"", name); 2109 return; 2110 } 2111 2112 if (cfg_obj_isduration(sub_obj)) { 2113 conf_dnsrps_sadd(ctx, " %s %d", name, 2114 cfg_obj_asduration(sub_obj)); 2115 } else { 2116 conf_dnsrps_sadd(ctx, " %s %d", name, 2117 cfg_obj_asuint32(sub_obj)); 2118 } 2119 } 2120 2121 /* 2122 * Convert the parsed RPZ configuration statement to a string for 2123 * dns_rpz_new_zones(). 2124 */ 2125 static isc_result_t 2126 conf_dnsrps(dns_view_t *view, const cfg_obj_t **maps, bool nsip_enabled, 2127 bool nsdname_enabled, dns_rpz_zbits_t *nsip_on, 2128 dns_rpz_zbits_t *nsdname_on, char **rps_cstr, size_t *rps_cstr_size, 2129 const cfg_obj_t *rpz_obj, const cfg_listelt_t *zone_element) { 2130 conf_dnsrps_ctx_t ctx; 2131 const cfg_obj_t *zone_obj, *obj; 2132 dns_rpz_num_t rpz_num; 2133 bool on; 2134 const char *s; 2135 2136 memset(&ctx, 0, sizeof(ctx)); 2137 ctx.result = ISC_R_SUCCESS; 2138 ctx.mctx = view->mctx; 2139 2140 for (rpz_num = 0; zone_element != NULL && ctx.result == ISC_R_SUCCESS; 2141 ++rpz_num) 2142 { 2143 zone_obj = cfg_listelt_value(zone_element); 2144 2145 s = cfg_obj_asstring(cfg_tuple_get(zone_obj, "zone name")); 2146 conf_dnsrps_sadd(&ctx, "zone \"%s\"", s); 2147 2148 obj = cfg_tuple_get(zone_obj, "policy"); 2149 if (!cfg_obj_isvoid(obj)) { 2150 s = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 2151 conf_dnsrps_sadd(&ctx, " policy %s", s); 2152 if (strcasecmp(s, "cname") == 0) { 2153 s = cfg_obj_asstring( 2154 cfg_tuple_get(obj, "cname")); 2155 conf_dnsrps_sadd(&ctx, " %s", s); 2156 } 2157 } 2158 2159 conf_dnsrps_yes_no(zone_obj, "recursive-only", &ctx); 2160 conf_dnsrps_yes_no(zone_obj, "log", &ctx); 2161 conf_dnsrps_num(zone_obj, "max-policy-ttl", &ctx); 2162 obj = cfg_tuple_get(rpz_obj, "nsip-enable"); 2163 if (!cfg_obj_isvoid(obj)) { 2164 if (cfg_obj_asboolean(obj)) { 2165 *nsip_on |= DNS_RPZ_ZBIT(rpz_num); 2166 } else { 2167 *nsip_on &= ~DNS_RPZ_ZBIT(rpz_num); 2168 } 2169 } 2170 on = ((*nsip_on & DNS_RPZ_ZBIT(rpz_num)) != 0); 2171 if (nsip_enabled != on) { 2172 conf_dnsrps_sadd(&ctx, on ? " nsip-enable yes " 2173 : " nsip-enable no "); 2174 } 2175 obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); 2176 if (!cfg_obj_isvoid(obj)) { 2177 if (cfg_obj_asboolean(obj)) { 2178 *nsdname_on |= DNS_RPZ_ZBIT(rpz_num); 2179 } else { 2180 *nsdname_on &= ~DNS_RPZ_ZBIT(rpz_num); 2181 } 2182 } 2183 on = ((*nsdname_on & DNS_RPZ_ZBIT(rpz_num)) != 0); 2184 if (nsdname_enabled != on) { 2185 conf_dnsrps_sadd(&ctx, on ? " nsdname-enable yes " 2186 : " nsdname-enable no "); 2187 } 2188 conf_dnsrps_sadd(&ctx, ";\n"); 2189 zone_element = cfg_list_next(zone_element); 2190 } 2191 2192 conf_dnsrps_yes_no(rpz_obj, "recursive-only", &ctx); 2193 conf_dnsrps_num(rpz_obj, "max-policy-ttl", &ctx); 2194 conf_dnsrps_num(rpz_obj, "min-ns-dots", &ctx); 2195 conf_dnsrps_yes_no(rpz_obj, "qname-wait-recurse", &ctx); 2196 conf_dnsrps_yes_no(rpz_obj, "break-dnssec", &ctx); 2197 if (!nsip_enabled) { 2198 conf_dnsrps_sadd(&ctx, " nsip-enable no "); 2199 } 2200 if (!nsdname_enabled) { 2201 conf_dnsrps_sadd(&ctx, " nsdname-enable no "); 2202 } 2203 2204 /* 2205 * Get the general dnsrpzd parameters from the response-policy 2206 * statement in the view and the general options. 2207 */ 2208 if (conf_dnsrps_get(&obj, maps, rpz_obj, "dnsrps-options", &ctx) && 2209 obj != NULL) 2210 { 2211 conf_dnsrps_sadd(&ctx, " %s\n", cfg_obj_asstring(obj)); 2212 } 2213 2214 if (ctx.result == ISC_R_SUCCESS) { 2215 *rps_cstr = ctx.cstr; 2216 *rps_cstr_size = ctx.cstr_size; 2217 } else { 2218 if (ctx.cstr != NULL) { 2219 isc_mem_put(ctx.mctx, ctx.cstr, ctx.cstr_size); 2220 } 2221 *rps_cstr = NULL; 2222 *rps_cstr_size = 0; 2223 } 2224 return (ctx.result); 2225 } 2226 #endif /* ifdef USE_DNSRPS */ 2227 2228 static isc_result_t 2229 configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 2230 const char *str, const char *msg) { 2231 isc_result_t result; 2232 2233 result = dns_name_fromstring(name, str, DNS_NAME_DOWNCASE, view->mctx); 2234 if (result != ISC_R_SUCCESS) { 2235 cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2236 "invalid %s '%s'", msg, str); 2237 } 2238 return (result); 2239 } 2240 2241 static isc_result_t 2242 configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, 2243 const char *str, const dns_name_t *origin) { 2244 isc_result_t result; 2245 2246 result = dns_name_fromstring2(name, str, origin, DNS_NAME_DOWNCASE, 2247 view->mctx); 2248 if (result != ISC_R_SUCCESS) { 2249 cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2250 "invalid zone '%s'", str); 2251 } 2252 return (result); 2253 } 2254 2255 static isc_result_t 2256 configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, 2257 bool recursive_only_default, bool add_soa_default, 2258 dns_ttl_t ttl_default, uint32_t minupdateinterval_default, 2259 const dns_rpz_zone_t *old, bool *old_rpz_okp) { 2260 const cfg_obj_t *rpz_obj, *obj; 2261 const char *str; 2262 dns_rpz_zone_t *zone = NULL; 2263 isc_result_t result; 2264 dns_rpz_num_t rpz_num; 2265 2266 REQUIRE(old != NULL || !*old_rpz_okp); 2267 2268 rpz_obj = cfg_listelt_value(element); 2269 2270 if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) { 2271 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2272 "limit of %d response policy zones exceeded", 2273 DNS_RPZ_MAX_ZONES); 2274 return (ISC_R_FAILURE); 2275 } 2276 2277 result = dns_rpz_new_zone(view->rpzs, &zone); 2278 if (result != ISC_R_SUCCESS) { 2279 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2280 "Error creating new RPZ zone : %s", 2281 isc_result_totext(result)); 2282 return (result); 2283 } 2284 2285 obj = cfg_tuple_get(rpz_obj, "recursive-only"); 2286 if (cfg_obj_isvoid(obj) ? recursive_only_default 2287 : cfg_obj_asboolean(obj)) 2288 { 2289 view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(zone->num); 2290 } else { 2291 view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(zone->num); 2292 } 2293 2294 obj = cfg_tuple_get(rpz_obj, "log"); 2295 if (!cfg_obj_isvoid(obj) && !cfg_obj_asboolean(obj)) { 2296 view->rpzs->p.no_log |= DNS_RPZ_ZBIT(zone->num); 2297 } else { 2298 view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(zone->num); 2299 } 2300 2301 obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 2302 if (cfg_obj_isduration(obj)) { 2303 zone->max_policy_ttl = cfg_obj_asduration(obj); 2304 } else { 2305 zone->max_policy_ttl = ttl_default; 2306 } 2307 if (*old_rpz_okp && zone->max_policy_ttl != old->max_policy_ttl) { 2308 *old_rpz_okp = false; 2309 } 2310 2311 obj = cfg_tuple_get(rpz_obj, "min-update-interval"); 2312 if (cfg_obj_isduration(obj)) { 2313 zone->min_update_interval = cfg_obj_asduration(obj); 2314 } else { 2315 zone->min_update_interval = minupdateinterval_default; 2316 } 2317 if (*old_rpz_okp && 2318 zone->min_update_interval != old->min_update_interval) 2319 { 2320 *old_rpz_okp = false; 2321 } 2322 2323 str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); 2324 result = configure_rpz_name(view, rpz_obj, &zone->origin, str, "zone"); 2325 if (result != ISC_R_SUCCESS) { 2326 return (result); 2327 } 2328 if (dns_name_equal(&zone->origin, dns_rootname)) { 2329 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2330 "invalid zone name '%s'", str); 2331 return (DNS_R_EMPTYLABEL); 2332 } 2333 if (!view->rpzs->p.dnsrps_enabled) { 2334 for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones - 1; 2335 ++rpz_num) 2336 { 2337 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, 2338 &zone->origin)) 2339 { 2340 cfg_obj_log(rpz_obj, named_g_lctx, 2341 DNS_RPZ_ERROR_LEVEL, 2342 "duplicate '%s'", str); 2343 result = DNS_R_DUPLICATE; 2344 return (result); 2345 } 2346 } 2347 } 2348 if (*old_rpz_okp && !dns_name_equal(&old->origin, &zone->origin)) { 2349 *old_rpz_okp = false; 2350 } 2351 2352 result = configure_rpz_name2(view, rpz_obj, &zone->client_ip, 2353 DNS_RPZ_CLIENT_IP_ZONE, &zone->origin); 2354 if (result != ISC_R_SUCCESS) { 2355 return (result); 2356 } 2357 2358 result = configure_rpz_name2(view, rpz_obj, &zone->ip, DNS_RPZ_IP_ZONE, 2359 &zone->origin); 2360 if (result != ISC_R_SUCCESS) { 2361 return (result); 2362 } 2363 2364 result = configure_rpz_name2(view, rpz_obj, &zone->nsdname, 2365 DNS_RPZ_NSDNAME_ZONE, &zone->origin); 2366 if (result != ISC_R_SUCCESS) { 2367 return (result); 2368 } 2369 2370 result = configure_rpz_name2(view, rpz_obj, &zone->nsip, 2371 DNS_RPZ_NSIP_ZONE, &zone->origin); 2372 if (result != ISC_R_SUCCESS) { 2373 return (result); 2374 } 2375 2376 result = configure_rpz_name(view, rpz_obj, &zone->passthru, 2377 DNS_RPZ_PASSTHRU_NAME, "name"); 2378 if (result != ISC_R_SUCCESS) { 2379 return (result); 2380 } 2381 2382 result = configure_rpz_name(view, rpz_obj, &zone->drop, 2383 DNS_RPZ_DROP_NAME, "name"); 2384 if (result != ISC_R_SUCCESS) { 2385 return (result); 2386 } 2387 2388 result = configure_rpz_name(view, rpz_obj, &zone->tcp_only, 2389 DNS_RPZ_TCP_ONLY_NAME, "name"); 2390 if (result != ISC_R_SUCCESS) { 2391 return (result); 2392 } 2393 2394 obj = cfg_tuple_get(rpz_obj, "policy"); 2395 if (cfg_obj_isvoid(obj)) { 2396 zone->policy = DNS_RPZ_POLICY_GIVEN; 2397 } else { 2398 str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); 2399 zone->policy = dns_rpz_str2policy(str); 2400 INSIST(zone->policy != DNS_RPZ_POLICY_ERROR); 2401 if (zone->policy == DNS_RPZ_POLICY_CNAME) { 2402 str = cfg_obj_asstring(cfg_tuple_get(obj, "cname")); 2403 result = configure_rpz_name(view, rpz_obj, &zone->cname, 2404 str, "cname"); 2405 if (result != ISC_R_SUCCESS) { 2406 return (result); 2407 } 2408 } 2409 } 2410 if (*old_rpz_okp && (zone->policy != old->policy || 2411 !dns_name_equal(&old->cname, &zone->cname))) 2412 { 2413 *old_rpz_okp = false; 2414 } 2415 2416 obj = cfg_tuple_get(rpz_obj, "add-soa"); 2417 if (cfg_obj_isvoid(obj)) { 2418 zone->addsoa = add_soa_default; 2419 } else { 2420 zone->addsoa = cfg_obj_asboolean(obj); 2421 } 2422 if (*old_rpz_okp && zone->addsoa != old->addsoa) { 2423 *old_rpz_okp = false; 2424 } 2425 2426 return (ISC_R_SUCCESS); 2427 } 2428 2429 static isc_result_t 2430 configure_rpz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t **maps, 2431 const cfg_obj_t *rpz_obj, bool *old_rpz_okp) { 2432 bool dnsrps_enabled; 2433 const cfg_listelt_t *zone_element; 2434 char *rps_cstr; 2435 size_t rps_cstr_size; 2436 const cfg_obj_t *sub_obj; 2437 bool recursive_only_default, add_soa_default; 2438 bool nsip_enabled, nsdname_enabled; 2439 dns_rpz_zbits_t nsip_on, nsdname_on; 2440 dns_ttl_t ttl_default; 2441 uint32_t minupdateinterval_default; 2442 dns_rpz_zones_t *zones; 2443 const dns_rpz_zones_t *old; 2444 bool pview_must_detach = false; 2445 const dns_rpz_zone_t *old_zone; 2446 isc_result_t result; 2447 int i; 2448 2449 *old_rpz_okp = false; 2450 2451 zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list")); 2452 if (zone_element == NULL) { 2453 return (ISC_R_SUCCESS); 2454 } 2455 2456 nsip_enabled = true; 2457 sub_obj = cfg_tuple_get(rpz_obj, "nsip-enable"); 2458 if (!cfg_obj_isvoid(sub_obj)) { 2459 nsip_enabled = cfg_obj_asboolean(sub_obj); 2460 } 2461 nsip_on = nsip_enabled ? DNS_RPZ_ALL_ZBITS : 0; 2462 2463 nsdname_enabled = true; 2464 sub_obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); 2465 if (!cfg_obj_isvoid(sub_obj)) { 2466 nsdname_enabled = cfg_obj_asboolean(sub_obj); 2467 } 2468 nsdname_on = nsdname_enabled ? DNS_RPZ_ALL_ZBITS : 0; 2469 2470 /* 2471 * "dnsrps-enable yes|no" can be either a global or response-policy 2472 * clause. 2473 */ 2474 dnsrps_enabled = false; 2475 rps_cstr = NULL; 2476 rps_cstr_size = 0; 2477 sub_obj = NULL; 2478 (void)named_config_get(maps, "dnsrps-enable", &sub_obj); 2479 if (sub_obj != NULL) { 2480 dnsrps_enabled = cfg_obj_asboolean(sub_obj); 2481 } 2482 sub_obj = cfg_tuple_get(rpz_obj, "dnsrps-enable"); 2483 if (!cfg_obj_isvoid(sub_obj)) { 2484 dnsrps_enabled = cfg_obj_asboolean(sub_obj); 2485 } 2486 #ifndef USE_DNSRPS 2487 if (dnsrps_enabled) { 2488 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2489 "\"dnsrps-enable yes\" but" 2490 " without `./configure --enable-dnsrps`"); 2491 return (ISC_R_FAILURE); 2492 } 2493 #else /* ifndef USE_DNSRPS */ 2494 if (dnsrps_enabled) { 2495 if (librpz == NULL) { 2496 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, 2497 "\"dnsrps-enable yes\" but %s", 2498 librpz_lib_open_emsg.c); 2499 return (ISC_R_FAILURE); 2500 } 2501 2502 /* 2503 * Generate the DNS Response Policy Service 2504 * configuration string. 2505 */ 2506 result = conf_dnsrps(view, maps, nsip_enabled, nsdname_enabled, 2507 &nsip_on, &nsdname_on, &rps_cstr, 2508 &rps_cstr_size, rpz_obj, zone_element); 2509 if (result != ISC_R_SUCCESS) { 2510 return (result); 2511 } 2512 } 2513 #endif /* ifndef USE_DNSRPS */ 2514 2515 result = dns_rpz_new_zones(view->mctx, named_g_taskmgr, 2516 named_g_timermgr, rps_cstr, rps_cstr_size, 2517 &view->rpzs); 2518 if (result != ISC_R_SUCCESS) { 2519 return (result); 2520 } 2521 2522 zones = view->rpzs; 2523 2524 zones->p.nsip_on = nsip_on; 2525 zones->p.nsdname_on = nsdname_on; 2526 2527 sub_obj = cfg_tuple_get(rpz_obj, "recursive-only"); 2528 if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { 2529 recursive_only_default = false; 2530 } else { 2531 recursive_only_default = true; 2532 } 2533 2534 sub_obj = cfg_tuple_get(rpz_obj, "add-soa"); 2535 if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { 2536 add_soa_default = false; 2537 } else { 2538 add_soa_default = true; 2539 } 2540 2541 sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec"); 2542 if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) { 2543 zones->p.break_dnssec = true; 2544 } else { 2545 zones->p.break_dnssec = false; 2546 } 2547 2548 sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); 2549 if (cfg_obj_isduration(sub_obj)) { 2550 ttl_default = cfg_obj_asduration(sub_obj); 2551 } else { 2552 ttl_default = DNS_RPZ_MAX_TTL_DEFAULT; 2553 } 2554 2555 sub_obj = cfg_tuple_get(rpz_obj, "min-update-interval"); 2556 if (cfg_obj_isduration(sub_obj)) { 2557 minupdateinterval_default = cfg_obj_asduration(sub_obj); 2558 } else { 2559 minupdateinterval_default = DNS_RPZ_MINUPDATEINTERVAL_DEFAULT; 2560 } 2561 2562 sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots"); 2563 if (cfg_obj_isuint32(sub_obj)) { 2564 zones->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1; 2565 } else { 2566 zones->p.min_ns_labels = 2; 2567 } 2568 2569 sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse"); 2570 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2571 zones->p.qname_wait_recurse = true; 2572 } else { 2573 zones->p.qname_wait_recurse = false; 2574 } 2575 2576 sub_obj = cfg_tuple_get(rpz_obj, "nsdname-wait-recurse"); 2577 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2578 zones->p.nsdname_wait_recurse = true; 2579 } else { 2580 zones->p.nsdname_wait_recurse = false; 2581 } 2582 2583 sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse"); 2584 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { 2585 zones->p.nsip_wait_recurse = true; 2586 } else { 2587 zones->p.nsip_wait_recurse = false; 2588 } 2589 2590 if (pview != NULL) { 2591 old = pview->rpzs; 2592 } else { 2593 result = dns_viewlist_find(&named_g_server->viewlist, 2594 view->name, view->rdclass, &pview); 2595 if (result == ISC_R_SUCCESS) { 2596 pview_must_detach = true; 2597 old = pview->rpzs; 2598 } else { 2599 old = NULL; 2600 } 2601 } 2602 2603 if (old == NULL) { 2604 *old_rpz_okp = false; 2605 } else { 2606 *old_rpz_okp = true; 2607 } 2608 2609 for (i = 0; zone_element != NULL; 2610 ++i, zone_element = cfg_list_next(zone_element)) 2611 { 2612 INSIST(!*old_rpz_okp || old != NULL); 2613 if (*old_rpz_okp && i < old->p.num_zones) { 2614 old_zone = old->zones[i]; 2615 } else { 2616 *old_rpz_okp = false; 2617 old_zone = NULL; 2618 } 2619 result = configure_rpz_zone( 2620 view, zone_element, recursive_only_default, 2621 add_soa_default, ttl_default, minupdateinterval_default, 2622 old_zone, old_rpz_okp); 2623 if (result != ISC_R_SUCCESS) { 2624 if (pview_must_detach) { 2625 dns_view_detach(&pview); 2626 } 2627 return (result); 2628 } 2629 } 2630 2631 /* 2632 * If this is a reloading and the parameters and list of policy 2633 * zones are unchanged, then use the same policy data. 2634 * Data for individual zones that must be reloaded will be merged. 2635 */ 2636 if (*old_rpz_okp) { 2637 if (old != NULL && 2638 memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0) 2639 { 2640 *old_rpz_okp = false; 2641 } else if ((old == NULL || old->rps_cstr == NULL) != 2642 (zones->rps_cstr == NULL)) 2643 { 2644 *old_rpz_okp = false; 2645 } else if (old != NULL && zones->rps_cstr != NULL && 2646 strcmp(old->rps_cstr, zones->rps_cstr) != 0) 2647 { 2648 *old_rpz_okp = false; 2649 } 2650 } 2651 2652 if (*old_rpz_okp) { 2653 dns_rpz_shutdown_rpzs(view->rpzs); 2654 dns_rpz_detach_rpzs(&view->rpzs); 2655 dns_rpz_attach_rpzs(pview->rpzs, &view->rpzs); 2656 dns_rpz_detach_rpzs(&pview->rpzs); 2657 } else if (old != NULL && pview != NULL) { 2658 ++pview->rpzs->rpz_ver; 2659 view->rpzs->rpz_ver = pview->rpzs->rpz_ver; 2660 cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_DEBUG_LEVEL1, 2661 "updated RPZ policy: version %d", 2662 view->rpzs->rpz_ver); 2663 } 2664 2665 if (pview_must_detach) { 2666 dns_view_detach(&pview); 2667 } 2668 2669 return (ISC_R_SUCCESS); 2670 } 2671 2672 static void 2673 catz_addmodzone_taskaction(isc_task_t *task, isc_event_t *event0) { 2674 catz_chgzone_event_t *ev = (catz_chgzone_event_t *)event0; 2675 isc_result_t result; 2676 dns_forwarders_t *dnsforwarders = NULL; 2677 dns_name_t *name = NULL; 2678 isc_buffer_t namebuf; 2679 isc_buffer_t *confbuf; 2680 char nameb[DNS_NAME_FORMATSIZE]; 2681 const cfg_obj_t *zlist = NULL; 2682 cfg_obj_t *zoneconf = NULL; 2683 cfg_obj_t *zoneobj = NULL; 2684 ns_cfgctx_t *cfg; 2685 dns_zone_t *zone = NULL; 2686 2687 /* 2688 * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' 2689 * is true, so this is expected to be non-NULL. 2690 */ 2691 cfg = (ns_cfgctx_t *)ev->view->new_zone_config; 2692 if (cfg == NULL) { 2693 CHECK(ISC_R_FAILURE); 2694 } 2695 2696 name = dns_catz_entry_getname(ev->entry); 2697 2698 isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); 2699 dns_name_totext(name, true, &namebuf); 2700 isc_buffer_putuint8(&namebuf, 0); 2701 2702 result = dns_fwdtable_find(ev->view->fwdtable, name, NULL, 2703 &dnsforwarders); 2704 if (result == ISC_R_SUCCESS && 2705 dnsforwarders->fwdpolicy == dns_fwdpolicy_only) 2706 { 2707 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2708 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2709 "catz: catz_addmodzone_taskaction: " 2710 "zone '%s' will not be processed because of the " 2711 "explicitly configured forwarding for that zone", 2712 nameb); 2713 goto cleanup; 2714 } 2715 2716 result = dns_view_findzone(ev->view, name, &zone); 2717 2718 if (ev->mod) { 2719 dns_catz_zone_t *parentcatz; 2720 2721 if (result != ISC_R_SUCCESS) { 2722 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2723 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2724 "catz: error \"%s\" while trying to " 2725 "modify zone '%s'", 2726 isc_result_totext(result), nameb); 2727 goto cleanup; 2728 } 2729 2730 if (!dns_zone_getadded(zone)) { 2731 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2732 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2733 "catz: catz_addmodzone_taskaction: " 2734 "zone '%s' is not a dynamically " 2735 "added zone", 2736 nameb); 2737 goto cleanup; 2738 } 2739 2740 parentcatz = dns_zone_get_parentcatz(zone); 2741 2742 if (parentcatz == NULL) { 2743 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2744 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2745 "catz: catz_addmodzone_taskaction: " 2746 "zone '%s' exists and is not added by " 2747 "a catalog zone, so won't be modified", 2748 nameb); 2749 goto cleanup; 2750 } 2751 if (parentcatz != ev->origin) { 2752 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2753 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2754 "catz: catz_addmodzone_taskaction: " 2755 "zone '%s' exists in multiple " 2756 "catalog zones", 2757 nameb); 2758 goto cleanup; 2759 } 2760 2761 dns_zone_detach(&zone); 2762 } else { 2763 /* Zone shouldn't already exist when adding */ 2764 if (result == ISC_R_SUCCESS) { 2765 if (dns_zone_get_parentcatz(zone) == NULL) { 2766 isc_log_write( 2767 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2768 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2769 "catz: " 2770 "catz_addmodzone_taskaction: " 2771 "zone '%s' will not be added " 2772 "because it is an explicitly " 2773 "configured zone", 2774 nameb); 2775 } else { 2776 isc_log_write( 2777 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2778 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2779 "catz: " 2780 "catz_addmodzone_taskaction: " 2781 "zone '%s' will not be added " 2782 "because another catalog zone " 2783 "already contains an entry with " 2784 "that zone", 2785 nameb); 2786 } 2787 goto cleanup; 2788 } else if (result != ISC_R_NOTFOUND && 2789 result != DNS_R_PARTIALMATCH) 2790 { 2791 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2792 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2793 "catz: error \"%s\" while trying to " 2794 "add zone '%s'", 2795 isc_result_totext(result), nameb); 2796 goto cleanup; 2797 } else { /* this can happen in case of DNS_R_PARTIALMATCH */ 2798 if (zone != NULL) { 2799 dns_zone_detach(&zone); 2800 } 2801 } 2802 } 2803 RUNTIME_CHECK(zone == NULL); 2804 /* Create a config for new zone */ 2805 confbuf = NULL; 2806 result = dns_catz_generate_zonecfg(ev->origin, ev->entry, &confbuf); 2807 if (result == ISC_R_SUCCESS) { 2808 cfg_parser_reset(cfg->add_parser); 2809 result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, 2810 &cfg_type_addzoneconf, 0, &zoneconf); 2811 isc_buffer_free(&confbuf); 2812 } 2813 /* 2814 * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() 2815 * failed. 2816 */ 2817 if (result != ISC_R_SUCCESS) { 2818 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2819 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 2820 "catz: error \"%s\" while trying to generate " 2821 "config for zone '%s'", 2822 isc_result_totext(result), nameb); 2823 goto cleanup; 2824 } 2825 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 2826 if (!cfg_obj_islist(zlist)) { 2827 CHECK(ISC_R_FAILURE); 2828 } 2829 2830 /* For now we only support adding one zone at a time */ 2831 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 2832 2833 /* Mark view unfrozen so that zone can be added */ 2834 2835 result = isc_task_beginexclusive(task); 2836 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2837 dns_view_thaw(ev->view); 2838 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, 2839 ev->cbd->server->mctx, ev->view, 2840 &ev->cbd->server->viewlist, 2841 &ev->cbd->server->kasplist, cfg->actx, true, 2842 false, true, ev->mod); 2843 dns_view_freeze(ev->view); 2844 isc_task_endexclusive(task); 2845 2846 if (result != ISC_R_SUCCESS) { 2847 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2848 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2849 "catz: failed to configure zone '%s' - %d", nameb, 2850 result); 2851 goto cleanup; 2852 } 2853 2854 /* Is it there yet? */ 2855 CHECK(dns_zt_find(ev->view->zonetable, name, 0, NULL, &zone)); 2856 2857 /* 2858 * Load the zone from the master file. If this fails, we'll 2859 * need to undo the configuration we've done already. 2860 */ 2861 result = dns_zone_load(zone, true); 2862 if (result != ISC_R_SUCCESS) { 2863 dns_db_t *dbp = NULL; 2864 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2865 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 2866 "catz: dns_zone_load() failed " 2867 "with %s; reverting.", 2868 isc_result_totext(result)); 2869 2870 /* If the zone loaded partially, unload it */ 2871 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 2872 dns_db_detach(&dbp); 2873 dns_zone_unload(zone); 2874 } 2875 2876 /* Remove the zone from the zone table */ 2877 dns_zt_unmount(ev->view->zonetable, zone); 2878 goto cleanup; 2879 } 2880 2881 /* Flag the zone as having been added at runtime */ 2882 dns_zone_setadded(zone, true); 2883 dns_zone_set_parentcatz(zone, ev->origin); 2884 2885 cleanup: 2886 if (zone != NULL) { 2887 dns_zone_detach(&zone); 2888 } 2889 if (zoneconf != NULL) { 2890 cfg_obj_destroy(cfg->add_parser, &zoneconf); 2891 } 2892 dns_catz_entry_detach(ev->origin, &ev->entry); 2893 dns_catz_detach_catz(&ev->origin); 2894 dns_view_weakdetach(&ev->view); 2895 isc_event_free(ISC_EVENT_PTR(&ev)); 2896 } 2897 2898 static void 2899 catz_delzone_taskaction(isc_task_t *task, isc_event_t *event0) { 2900 catz_chgzone_event_t *ev = (catz_chgzone_event_t *)event0; 2901 isc_result_t result; 2902 dns_zone_t *zone = NULL; 2903 dns_db_t *dbp = NULL; 2904 char cname[DNS_NAME_FORMATSIZE]; 2905 const char *file; 2906 2907 result = isc_task_beginexclusive(task); 2908 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2909 2910 dns_name_format(dns_catz_entry_getname(ev->entry), cname, 2911 DNS_NAME_FORMATSIZE); 2912 result = dns_view_findzone(ev->view, dns_catz_entry_getname(ev->entry), 2913 &zone); 2914 if (result != ISC_R_SUCCESS) { 2915 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2916 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2917 "catz: catz_delzone_taskaction: " 2918 "zone '%s' not found", 2919 cname); 2920 goto cleanup; 2921 } 2922 2923 if (!dns_zone_getadded(zone)) { 2924 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2925 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2926 "catz: catz_delzone_taskaction: " 2927 "zone '%s' is not a dynamically added zone", 2928 cname); 2929 goto cleanup; 2930 } 2931 2932 if (dns_zone_get_parentcatz(zone) != ev->origin) { 2933 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2934 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2935 "catz: catz_delzone_taskaction: zone " 2936 "'%s' exists in multiple catalog zones", 2937 cname); 2938 goto cleanup; 2939 } 2940 2941 /* Stop answering for this zone */ 2942 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 2943 dns_db_detach(&dbp); 2944 dns_zone_unload(zone); 2945 } 2946 2947 CHECK(dns_zt_unmount(ev->view->zonetable, zone)); 2948 file = dns_zone_getfile(zone); 2949 if (file != NULL) { 2950 isc_file_remove(file); 2951 file = dns_zone_getjournal(zone); 2952 if (file != NULL) { 2953 isc_file_remove(file); 2954 } 2955 } 2956 2957 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 2958 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 2959 "catz: catz_delzone_taskaction: " 2960 "zone '%s' deleted", 2961 cname); 2962 cleanup: 2963 isc_task_endexclusive(task); 2964 if (zone != NULL) { 2965 dns_zone_detach(&zone); 2966 } 2967 dns_catz_entry_detach(ev->origin, &ev->entry); 2968 dns_catz_detach_catz(&ev->origin); 2969 dns_view_weakdetach(&ev->view); 2970 isc_event_free(ISC_EVENT_PTR(&ev)); 2971 } 2972 2973 static isc_result_t 2974 catz_create_chg_task(dns_catz_entry_t *entry, dns_catz_zone_t *origin, 2975 dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata, 2976 isc_eventtype_t type) { 2977 catz_chgzone_event_t *event = NULL; 2978 isc_task_t *task = NULL; 2979 isc_result_t result; 2980 isc_taskaction_t action = NULL; 2981 2982 result = isc_taskmgr_excltask(taskmgr, &task); 2983 if (result != ISC_R_SUCCESS) { 2984 return (result); 2985 } 2986 2987 switch (type) { 2988 case DNS_EVENT_CATZADDZONE: 2989 case DNS_EVENT_CATZMODZONE: 2990 action = catz_addmodzone_taskaction; 2991 break; 2992 case DNS_EVENT_CATZDELZONE: 2993 action = catz_delzone_taskaction; 2994 break; 2995 default: 2996 REQUIRE(0); 2997 UNREACHABLE(); 2998 } 2999 3000 event = (catz_chgzone_event_t *)isc_event_allocate( 3001 view->mctx, origin, type, action, NULL, sizeof(*event)); 3002 3003 event->cbd = (catz_cb_data_t *)udata; 3004 event->entry = NULL; 3005 event->origin = NULL; 3006 event->view = NULL; 3007 event->mod = (type == DNS_EVENT_CATZMODZONE); 3008 3009 dns_catz_entry_attach(entry, &event->entry); 3010 dns_catz_attach_catz(origin, &event->origin); 3011 dns_view_weakattach(view, &event->view); 3012 3013 isc_task_send(task, ISC_EVENT_PTR(&event)); 3014 isc_task_detach(&task); 3015 3016 return (ISC_R_SUCCESS); 3017 } 3018 3019 static isc_result_t 3020 catz_addzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3021 isc_taskmgr_t *taskmgr, void *udata) { 3022 return (catz_create_chg_task(entry, origin, view, taskmgr, udata, 3023 DNS_EVENT_CATZADDZONE)); 3024 } 3025 3026 static isc_result_t 3027 catz_delzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3028 isc_taskmgr_t *taskmgr, void *udata) { 3029 return (catz_create_chg_task(entry, origin, view, taskmgr, udata, 3030 DNS_EVENT_CATZDELZONE)); 3031 } 3032 3033 static isc_result_t 3034 catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, 3035 isc_taskmgr_t *taskmgr, void *udata) { 3036 return (catz_create_chg_task(entry, origin, view, taskmgr, udata, 3037 DNS_EVENT_CATZMODZONE)); 3038 } 3039 3040 static void 3041 catz_reconfigure(dns_catz_entry_t *entry, dns_view_t *view, 3042 catz_reconfig_data_t *data) { 3043 isc_buffer_t namebuf; 3044 isc_buffer_t *confbuf = NULL; 3045 const cfg_obj_t *zlist = NULL; 3046 char nameb[DNS_NAME_FORMATSIZE]; 3047 cfg_obj_t *zoneconf = NULL; 3048 cfg_obj_t *zoneobj = NULL; 3049 ns_cfgctx_t *cfg = NULL; 3050 dns_zone_t *zone = NULL; 3051 isc_result_t result; 3052 3053 isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); 3054 dns_name_totext(dns_catz_entry_getname(entry), DNS_NAME_OMITFINALDOT, 3055 &namebuf); 3056 isc_buffer_putuint8(&namebuf, 0); 3057 3058 result = dns_view_findzone(view, dns_catz_entry_getname(entry), &zone); 3059 if (result != ISC_R_SUCCESS) { 3060 return; 3061 } 3062 3063 /* 3064 * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' 3065 * is true, so this is expected to be non-NULL. 3066 */ 3067 cfg = (ns_cfgctx_t *)view->new_zone_config; 3068 if (cfg == NULL) { 3069 CHECK(ISC_R_FAILURE); 3070 } 3071 3072 result = dns_catz_generate_zonecfg(data->catz, entry, &confbuf); 3073 if (result == ISC_R_SUCCESS) { 3074 cfg_parser_reset(cfg->add_parser); 3075 result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, 3076 &cfg_type_addzoneconf, 0, &zoneconf); 3077 isc_buffer_free(&confbuf); 3078 } 3079 /* 3080 * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() 3081 * failed. 3082 */ 3083 if (result != ISC_R_SUCCESS) { 3084 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3085 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 3086 "catz_reconfigure: error \"%s\" while trying to " 3087 "generate config for member zone '%s'", 3088 isc_result_totext(result), nameb); 3089 goto cleanup; 3090 } 3091 3092 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 3093 if (!cfg_obj_islist(zlist)) { 3094 CHECK(ISC_R_FAILURE); 3095 } 3096 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 3097 3098 result = configure_zone(data->config, zoneobj, cfg->vconfig, 3099 data->cbd->server->mctx, view, 3100 &data->cbd->server->viewlist, 3101 &data->cbd->server->kasplist, cfg->actx, true, 3102 false, true, true); 3103 if (result != ISC_R_SUCCESS) { 3104 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3105 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 3106 "catz_reconfigure : error \"%s\" while trying to " 3107 "reconfigure member zone '%s'", 3108 isc_result_totext(result), nameb); 3109 goto cleanup; 3110 } 3111 3112 cleanup: 3113 if (zoneconf != NULL) { 3114 cfg_obj_destroy(cfg->add_parser, &zoneconf); 3115 } 3116 3117 dns_zone_detach(&zone); 3118 } 3119 3120 static isc_result_t 3121 configure_catz_zone(dns_view_t *view, dns_view_t *pview, 3122 const cfg_obj_t *config, const cfg_listelt_t *element) { 3123 const cfg_obj_t *catz_obj, *obj; 3124 dns_catz_zone_t *zone = NULL; 3125 const char *str; 3126 isc_result_t result; 3127 dns_name_t origin; 3128 dns_catz_options_t *opts; 3129 3130 dns_name_init(&origin, NULL); 3131 catz_obj = cfg_listelt_value(element); 3132 3133 str = cfg_obj_asstring(cfg_tuple_get(catz_obj, "zone name")); 3134 3135 result = dns_name_fromstring(&origin, str, DNS_NAME_DOWNCASE, 3136 view->mctx); 3137 if (result == ISC_R_SUCCESS && dns_name_equal(&origin, dns_rootname)) { 3138 result = DNS_R_EMPTYLABEL; 3139 } 3140 3141 if (result != ISC_R_SUCCESS) { 3142 cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3143 "catz: invalid zone name '%s'", str); 3144 goto cleanup; 3145 } 3146 3147 result = dns_catz_add_zone(view->catzs, &origin, &zone); 3148 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) { 3149 cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3150 "catz: unable to create catalog zone '%s', " 3151 "error %s", 3152 str, isc_result_totext(result)); 3153 goto cleanup; 3154 } 3155 3156 if (result == ISC_R_EXISTS) { 3157 isc_ht_iter_t *it = NULL; 3158 catz_reconfig_data_t data = { 3159 .catz = zone, 3160 .config = config, 3161 .cbd = (catz_cb_data_t *)dns_catz_zones_get_udata( 3162 view->catzs), 3163 }; 3164 3165 RUNTIME_CHECK(pview != NULL); 3166 3167 /* 3168 * We have to walk through all the member zones, attach 3169 * them to the current view and reconfigure 3170 */ 3171 dns_catz_get_iterator(zone, &it); 3172 3173 for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS; 3174 result = isc_ht_iter_next(it)) 3175 { 3176 dns_name_t *name = NULL; 3177 dns_zone_t *dnszone = NULL; 3178 dns_catz_entry_t *entry = NULL; 3179 isc_result_t tresult; 3180 3181 isc_ht_iter_current(it, (void **)&entry); 3182 name = dns_catz_entry_getname(entry); 3183 3184 tresult = dns_view_findzone(pview, name, &dnszone); 3185 if (tresult != ISC_R_SUCCESS) { 3186 continue; 3187 } 3188 3189 dns_zone_setview(dnszone, view); 3190 dns_view_addzone(view, dnszone); 3191 3192 catz_reconfigure(entry, view, &data); 3193 3194 /* 3195 * The dns_view_findzone() call above increments the 3196 * zone's reference count, which we need to decrement 3197 * back. However, as dns_zone_detach() sets the 3198 * supplied pointer to NULL, calling it is deferred 3199 * until the dnszone variable is no longer used. 3200 */ 3201 dns_zone_detach(&dnszone); 3202 } 3203 3204 isc_ht_iter_destroy(&it); 3205 3206 result = ISC_R_SUCCESS; 3207 } 3208 3209 dns_catz_zone_resetdefoptions(zone); 3210 opts = dns_catz_zone_getdefoptions(zone); 3211 3212 obj = cfg_tuple_get(catz_obj, "default-masters"); 3213 if (obj == NULL || !cfg_obj_istuple(obj)) { 3214 obj = cfg_tuple_get(catz_obj, "default-primaries"); 3215 } 3216 if (obj != NULL && cfg_obj_istuple(obj)) { 3217 result = named_config_getipandkeylist( 3218 config, "primaries", obj, view->mctx, &opts->masters); 3219 } 3220 3221 obj = cfg_tuple_get(catz_obj, "in-memory"); 3222 if (obj != NULL && cfg_obj_isboolean(obj)) { 3223 opts->in_memory = cfg_obj_asboolean(obj); 3224 } 3225 3226 obj = cfg_tuple_get(catz_obj, "zone-directory"); 3227 if (!opts->in_memory && obj != NULL && cfg_obj_isstring(obj)) { 3228 opts->zonedir = isc_mem_strdup(view->mctx, 3229 cfg_obj_asstring(obj)); 3230 if (isc_file_isdirectory(opts->zonedir) != ISC_R_SUCCESS) { 3231 cfg_obj_log(obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, 3232 "catz: zone-directory '%s' " 3233 "not found; zone files will not be " 3234 "saved", 3235 opts->zonedir); 3236 opts->in_memory = true; 3237 } 3238 } 3239 3240 obj = cfg_tuple_get(catz_obj, "min-update-interval"); 3241 if (obj != NULL && cfg_obj_isduration(obj)) { 3242 opts->min_update_interval = cfg_obj_asduration(obj); 3243 } 3244 3245 cleanup: 3246 dns_name_free(&origin, view->mctx); 3247 3248 return (result); 3249 } 3250 3251 static catz_cb_data_t ns_catz_cbdata; 3252 static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = { 3253 catz_addzone, catz_modzone, catz_delzone, &ns_catz_cbdata 3254 }; 3255 3256 static isc_result_t 3257 configure_catz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t *config, 3258 const cfg_obj_t *catz_obj) { 3259 const cfg_listelt_t *zone_element = NULL; 3260 const dns_catz_zones_t *old = NULL; 3261 bool pview_must_detach = false; 3262 isc_result_t result; 3263 3264 /* xxxwpk TODO do it cleaner, once, somewhere */ 3265 ns_catz_cbdata.server = named_g_server; 3266 3267 zone_element = cfg_list_first(cfg_tuple_get(catz_obj, "zone list")); 3268 if (zone_element == NULL) { 3269 return (ISC_R_SUCCESS); 3270 } 3271 3272 CHECK(dns_catz_new_zones(view->mctx, named_g_taskmgr, named_g_timermgr, 3273 &view->catzs, &ns_catz_zonemodmethods)); 3274 3275 if (pview != NULL) { 3276 old = pview->catzs; 3277 } else { 3278 result = dns_viewlist_find(&named_g_server->viewlist, 3279 view->name, view->rdclass, &pview); 3280 if (result == ISC_R_SUCCESS) { 3281 pview_must_detach = true; 3282 old = pview->catzs; 3283 } 3284 } 3285 3286 if (old != NULL) { 3287 dns_catz_shutdown_catzs(view->catzs); 3288 dns_catz_detach_catzs(&view->catzs); 3289 dns_catz_attach_catzs(pview->catzs, &view->catzs); 3290 dns_catz_detach_catzs(&pview->catzs); 3291 dns_catz_prereconfig(view->catzs); 3292 } 3293 3294 while (zone_element != NULL) { 3295 CHECK(configure_catz_zone(view, pview, config, zone_element)); 3296 zone_element = cfg_list_next(zone_element); 3297 } 3298 3299 if (old != NULL) { 3300 dns_catz_postreconfig(view->catzs); 3301 } 3302 3303 result = ISC_R_SUCCESS; 3304 3305 cleanup: 3306 if (pview_must_detach) { 3307 dns_view_detach(&pview); 3308 } 3309 3310 return (result); 3311 } 3312 3313 #define CHECK_RRL(cond, pat, val1, val2) \ 3314 do { \ 3315 if (!(cond)) { \ 3316 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, pat, \ 3317 val1, val2); \ 3318 result = ISC_R_RANGE; \ 3319 goto cleanup; \ 3320 } \ 3321 } while (0) 3322 3323 #define CHECK_RRL_RATE(rate, def, max_rate, name) \ 3324 do { \ 3325 obj = NULL; \ 3326 rrl->rate.str = name; \ 3327 result = cfg_map_get(map, name, &obj); \ 3328 if (result == ISC_R_SUCCESS) { \ 3329 rrl->rate.r = cfg_obj_asuint32(obj); \ 3330 CHECK_RRL(rrl->rate.r <= max_rate, name " %d > %d", \ 3331 rrl->rate.r, max_rate); \ 3332 } else { \ 3333 rrl->rate.r = def; \ 3334 } \ 3335 rrl->rate.scaled = rrl->rate.r; \ 3336 } while (0) 3337 3338 static isc_result_t 3339 configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) { 3340 const cfg_obj_t *obj; 3341 dns_rrl_t *rrl; 3342 isc_result_t result; 3343 int min_entries, i, j; 3344 3345 /* 3346 * Most DNS servers have few clients, but intentinally open 3347 * recursive and authoritative servers often have many. 3348 * So start with a small number of entries unless told otherwise 3349 * to reduce cold-start costs. 3350 */ 3351 min_entries = 500; 3352 obj = NULL; 3353 result = cfg_map_get(map, "min-table-size", &obj); 3354 if (result == ISC_R_SUCCESS) { 3355 min_entries = cfg_obj_asuint32(obj); 3356 if (min_entries < 1) { 3357 min_entries = 1; 3358 } 3359 } 3360 result = dns_rrl_init(&rrl, view, min_entries); 3361 if (result != ISC_R_SUCCESS) { 3362 return (result); 3363 } 3364 3365 i = ISC_MAX(20000, min_entries); 3366 obj = NULL; 3367 result = cfg_map_get(map, "max-table-size", &obj); 3368 if (result == ISC_R_SUCCESS) { 3369 i = cfg_obj_asuint32(obj); 3370 CHECK_RRL(i >= min_entries, 3371 "max-table-size %d < min-table-size %d", i, 3372 min_entries); 3373 } 3374 rrl->max_entries = i; 3375 3376 CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE, 3377 "responses-per-second"); 3378 CHECK_RRL_RATE(referrals_per_second, rrl->responses_per_second.r, 3379 DNS_RRL_MAX_RATE, "referrals-per-second"); 3380 CHECK_RRL_RATE(nodata_per_second, rrl->responses_per_second.r, 3381 DNS_RRL_MAX_RATE, "nodata-per-second"); 3382 CHECK_RRL_RATE(nxdomains_per_second, rrl->responses_per_second.r, 3383 DNS_RRL_MAX_RATE, "nxdomains-per-second"); 3384 CHECK_RRL_RATE(errors_per_second, rrl->responses_per_second.r, 3385 DNS_RRL_MAX_RATE, "errors-per-second"); 3386 3387 CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, "all-per-second"); 3388 3389 CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, "slip"); 3390 3391 i = 15; 3392 obj = NULL; 3393 result = cfg_map_get(map, "window", &obj); 3394 if (result == ISC_R_SUCCESS) { 3395 i = cfg_obj_asuint32(obj); 3396 CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW, 3397 "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW); 3398 } 3399 rrl->window = i; 3400 3401 i = 0; 3402 obj = NULL; 3403 result = cfg_map_get(map, "qps-scale", &obj); 3404 if (result == ISC_R_SUCCESS) { 3405 i = cfg_obj_asuint32(obj); 3406 CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, ""); 3407 } 3408 rrl->qps_scale = i; 3409 rrl->qps = 1.0; 3410 3411 i = 24; 3412 obj = NULL; 3413 result = cfg_map_get(map, "ipv4-prefix-length", &obj); 3414 if (result == ISC_R_SUCCESS) { 3415 i = cfg_obj_asuint32(obj); 3416 CHECK_RRL(i >= 8 && i <= 32, 3417 "invalid 'ipv4-prefix-length %d'%s", i, ""); 3418 } 3419 rrl->ipv4_prefixlen = i; 3420 if (i == 32) { 3421 rrl->ipv4_mask = 0xffffffff; 3422 } else { 3423 rrl->ipv4_mask = htonl(0xffffffff << (32 - i)); 3424 } 3425 3426 i = 56; 3427 obj = NULL; 3428 result = cfg_map_get(map, "ipv6-prefix-length", &obj); 3429 if (result == ISC_R_SUCCESS) { 3430 i = cfg_obj_asuint32(obj); 3431 CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX, 3432 "ipv6-prefix-length %d < 16 or > %d", i, 3433 DNS_RRL_MAX_PREFIX); 3434 } 3435 rrl->ipv6_prefixlen = i; 3436 for (j = 0; j < 4; ++j) { 3437 if (i <= 0) { 3438 rrl->ipv6_mask[j] = 0; 3439 } else if (i < 32) { 3440 rrl->ipv6_mask[j] = htonl(0xffffffff << (32 - i)); 3441 } else { 3442 rrl->ipv6_mask[j] = 0xffffffff; 3443 } 3444 i -= 32; 3445 } 3446 3447 obj = NULL; 3448 result = cfg_map_get(map, "exempt-clients", &obj); 3449 if (result == ISC_R_SUCCESS) { 3450 result = cfg_acl_fromconfig(obj, config, named_g_lctx, 3451 named_g_aclconfctx, named_g_mctx, 0, 3452 &rrl->exempt); 3453 CHECK_RRL(result == ISC_R_SUCCESS, "invalid %s%s", 3454 "address match list", ""); 3455 } 3456 3457 obj = NULL; 3458 result = cfg_map_get(map, "log-only", &obj); 3459 if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj)) { 3460 rrl->log_only = true; 3461 } else { 3462 rrl->log_only = false; 3463 } 3464 3465 return (ISC_R_SUCCESS); 3466 3467 cleanup: 3468 dns_rrl_view_destroy(view); 3469 return (result); 3470 } 3471 3472 static isc_result_t 3473 add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 3474 const dns_name_t *origin, const dns_name_t *contact) { 3475 dns_dbnode_t *node = NULL; 3476 dns_rdata_t rdata = DNS_RDATA_INIT; 3477 dns_rdatalist_t rdatalist; 3478 dns_rdataset_t rdataset; 3479 isc_result_t result; 3480 unsigned char buf[DNS_SOA_BUFFERSIZE]; 3481 3482 CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800, 3483 7200, 604800, 86400, buf, &rdata)); 3484 3485 dns_rdatalist_init(&rdatalist); 3486 rdatalist.type = rdata.type; 3487 rdatalist.rdclass = rdata.rdclass; 3488 rdatalist.ttl = 86400; 3489 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 3490 3491 dns_rdataset_init(&rdataset); 3492 CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); 3493 CHECK(dns_db_findnode(db, name, true, &node)); 3494 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 3495 3496 cleanup: 3497 if (node != NULL) { 3498 dns_db_detachnode(db, &node); 3499 } 3500 return (result); 3501 } 3502 3503 static isc_result_t 3504 add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 3505 const dns_name_t *nsname) { 3506 dns_dbnode_t *node = NULL; 3507 dns_rdata_ns_t ns; 3508 dns_rdata_t rdata = DNS_RDATA_INIT; 3509 dns_rdatalist_t rdatalist; 3510 dns_rdataset_t rdataset; 3511 isc_result_t result; 3512 isc_buffer_t b; 3513 unsigned char buf[DNS_NAME_MAXWIRE]; 3514 3515 isc_buffer_init(&b, buf, sizeof(buf)); 3516 3517 ns.common.rdtype = dns_rdatatype_ns; 3518 ns.common.rdclass = dns_db_class(db); 3519 ns.mctx = NULL; 3520 dns_name_init(&ns.name, NULL); 3521 dns_name_clone(nsname, &ns.name); 3522 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, 3523 &ns, &b)); 3524 3525 dns_rdatalist_init(&rdatalist); 3526 rdatalist.type = rdata.type; 3527 rdatalist.rdclass = rdata.rdclass; 3528 rdatalist.ttl = 86400; 3529 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 3530 3531 dns_rdataset_init(&rdataset); 3532 CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); 3533 CHECK(dns_db_findnode(db, name, true, &node)); 3534 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 3535 3536 cleanup: 3537 if (node != NULL) { 3538 dns_db_detachnode(db, &node); 3539 } 3540 return (result); 3541 } 3542 3543 static isc_result_t 3544 create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view, 3545 const cfg_obj_t *zonelist, const char **empty_dbtype, 3546 int empty_dbtypec, dns_zonestat_level_t statlevel) { 3547 char namebuf[DNS_NAME_FORMATSIZE]; 3548 const cfg_listelt_t *element; 3549 const cfg_obj_t *obj; 3550 const cfg_obj_t *zconfig; 3551 const cfg_obj_t *zoptions; 3552 const char *rbt_dbtype[4] = { "rbt" }; 3553 const char *sep = ": view "; 3554 const char *str; 3555 const char *viewname = view->name; 3556 dns_db_t *db = NULL; 3557 dns_dbversion_t *version = NULL; 3558 dns_fixedname_t cfixed; 3559 dns_fixedname_t fixed; 3560 dns_fixedname_t nsfixed; 3561 dns_name_t *contact; 3562 dns_name_t *ns; 3563 dns_name_t *zname; 3564 dns_zone_t *zone = NULL; 3565 int rbt_dbtypec = 1; 3566 isc_result_t result; 3567 dns_namereln_t namereln; 3568 int order; 3569 unsigned int nlabels; 3570 3571 zname = dns_fixedname_initname(&fixed); 3572 ns = dns_fixedname_initname(&nsfixed); 3573 contact = dns_fixedname_initname(&cfixed); 3574 3575 /* 3576 * Look for forward "zones" beneath this empty zone and if so 3577 * create a custom db for the empty zone. 3578 */ 3579 for (element = cfg_list_first(zonelist); element != NULL; 3580 element = cfg_list_next(element)) 3581 { 3582 zconfig = cfg_listelt_value(element); 3583 str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 3584 CHECK(dns_name_fromstring(zname, str, 0, NULL)); 3585 namereln = dns_name_fullcompare(zname, name, &order, &nlabels); 3586 if (namereln != dns_namereln_subdomain) { 3587 continue; 3588 } 3589 3590 zoptions = cfg_tuple_get(zconfig, "options"); 3591 3592 obj = NULL; 3593 (void)cfg_map_get(zoptions, "type", &obj); 3594 if (obj != NULL && 3595 strcasecmp(cfg_obj_asstring(obj), "forward") == 0) 3596 { 3597 obj = NULL; 3598 (void)cfg_map_get(zoptions, "forward", &obj); 3599 if (obj == NULL) { 3600 continue; 3601 } 3602 if (strcasecmp(cfg_obj_asstring(obj), "only") != 0) { 3603 continue; 3604 } 3605 } 3606 if (db == NULL) { 3607 CHECK(dns_db_create(view->mctx, "rbt", name, 3608 dns_dbtype_zone, view->rdclass, 0, 3609 NULL, &db)); 3610 CHECK(dns_db_newversion(db, &version)); 3611 if (strcmp(empty_dbtype[2], "@") == 0) { 3612 dns_name_clone(name, ns); 3613 } else { 3614 CHECK(dns_name_fromstring(ns, empty_dbtype[2], 3615 0, NULL)); 3616 } 3617 CHECK(dns_name_fromstring(contact, empty_dbtype[3], 0, 3618 NULL)); 3619 CHECK(add_soa(db, version, name, ns, contact)); 3620 CHECK(add_ns(db, version, name, ns)); 3621 } 3622 CHECK(add_ns(db, version, zname, dns_rootname)); 3623 } 3624 3625 /* 3626 * Is the existing zone the ok to use? 3627 */ 3628 if (pzone != NULL) { 3629 unsigned int typec; 3630 const char **dbargv; 3631 3632 if (db != NULL) { 3633 typec = rbt_dbtypec; 3634 dbargv = rbt_dbtype; 3635 } else { 3636 typec = empty_dbtypec; 3637 dbargv = empty_dbtype; 3638 } 3639 3640 result = check_dbtype(pzone, typec, dbargv, view->mctx); 3641 if (result != ISC_R_SUCCESS) { 3642 pzone = NULL; 3643 } 3644 3645 if (pzone != NULL && 3646 dns_zone_gettype(pzone) != dns_zone_primary) 3647 { 3648 pzone = NULL; 3649 } 3650 if (pzone != NULL && dns_zone_getfile(pzone) != NULL) { 3651 pzone = NULL; 3652 } 3653 if (pzone != NULL) { 3654 dns_zone_getraw(pzone, &zone); 3655 if (zone != NULL) { 3656 dns_zone_detach(&zone); 3657 pzone = NULL; 3658 } 3659 } 3660 } 3661 3662 if (pzone == NULL) { 3663 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 3664 CHECK(dns_zone_setorigin(zone, name)); 3665 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 3666 if (db == NULL) { 3667 dns_zone_setdbtype(zone, empty_dbtypec, empty_dbtype); 3668 } 3669 dns_zone_setclass(zone, view->rdclass); 3670 dns_zone_settype(zone, dns_zone_primary); 3671 dns_zone_setstats(zone, named_g_server->zonestats); 3672 } else { 3673 dns_zone_attach(pzone, &zone); 3674 } 3675 3676 dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, false); 3677 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 3678 dns_zone_setnotifytype(zone, dns_notifytype_no); 3679 dns_zone_setdialup(zone, dns_dialuptype_no); 3680 dns_zone_setautomatic(zone, true); 3681 if (view->queryacl != NULL) { 3682 dns_zone_setqueryacl(zone, view->queryacl); 3683 } else { 3684 dns_zone_clearqueryacl(zone); 3685 } 3686 if (view->queryonacl != NULL) { 3687 dns_zone_setqueryonacl(zone, view->queryonacl); 3688 } else { 3689 dns_zone_clearqueryonacl(zone); 3690 } 3691 dns_zone_clearupdateacl(zone); 3692 if (view->transferacl != NULL) { 3693 dns_zone_setxfracl(zone, view->transferacl); 3694 } else { 3695 dns_zone_clearxfracl(zone); 3696 } 3697 3698 CHECK(setquerystats(zone, view->mctx, statlevel)); 3699 if (db != NULL) { 3700 dns_db_closeversion(db, &version, true); 3701 CHECK(dns_zone_replacedb(zone, db, false)); 3702 } 3703 dns_zone_setoption(zone, DNS_ZONEOPT_AUTOEMPTY, true); 3704 dns_zone_setview(zone, view); 3705 CHECK(dns_view_addzone(view, zone)); 3706 3707 if (!strcmp(viewname, "_default")) { 3708 sep = ""; 3709 viewname = ""; 3710 } 3711 dns_name_format(name, namebuf, sizeof(namebuf)); 3712 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_ZONELOAD, 3713 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 3714 "automatic empty zone%s%s: %s", sep, viewname, namebuf); 3715 3716 cleanup: 3717 if (zone != NULL) { 3718 dns_zone_detach(&zone); 3719 } 3720 if (version != NULL) { 3721 dns_db_closeversion(db, &version, false); 3722 } 3723 if (db != NULL) { 3724 dns_db_detach(&db); 3725 } 3726 3727 INSIST(version == NULL); 3728 3729 return (result); 3730 } 3731 3732 static isc_result_t 3733 create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view, 3734 const dns_name_t *name, const char *type, isc_mem_t *mctx, 3735 const char *server, const char *contact) { 3736 char namebuf[DNS_NAME_FORMATSIZE]; 3737 const char *dbtype[4] = { "_builtin", NULL, "@", "." }; 3738 const char *sep = ": view "; 3739 const char *viewname = view->name; 3740 dns_zone_t *zone = NULL; 3741 int dbtypec = 4; 3742 isc_result_t result; 3743 3744 REQUIRE(type != NULL); 3745 3746 if (!strcmp(viewname, "_default")) { 3747 sep = ""; 3748 viewname = ""; 3749 } 3750 3751 dbtype[1] = type; 3752 if (server != NULL) { 3753 dbtype[2] = server; 3754 } 3755 if (contact != NULL) { 3756 dbtype[3] = contact; 3757 } 3758 3759 if (pzone != NULL) { 3760 result = check_dbtype(pzone, dbtypec, dbtype, view->mctx); 3761 if (result != ISC_R_SUCCESS) { 3762 pzone = NULL; 3763 } 3764 } 3765 3766 if (pzone == NULL) { 3767 /* 3768 * Create the actual zone. 3769 */ 3770 CHECK(dns_zone_create(&zone, mctx)); 3771 CHECK(dns_zone_setorigin(zone, name)); 3772 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 3773 dns_zone_setclass(zone, view->rdclass); 3774 dns_zone_settype(zone, dns_zone_primary); 3775 dns_zone_setstats(zone, named_g_server->zonestats); 3776 dns_zone_setdbtype(zone, dbtypec, dbtype); 3777 dns_zone_setdialup(zone, dns_dialuptype_no); 3778 dns_zone_setnotifytype(zone, dns_notifytype_no); 3779 dns_zone_setautomatic(zone, true); 3780 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 3781 } else { 3782 dns_zone_attach(pzone, &zone); 3783 } 3784 if (view->queryacl != NULL) { 3785 dns_zone_setqueryacl(zone, view->queryacl); 3786 } else { 3787 dns_zone_clearqueryacl(zone); 3788 } 3789 if (view->queryonacl != NULL) { 3790 dns_zone_setqueryonacl(zone, view->queryonacl); 3791 } else { 3792 dns_zone_clearqueryonacl(zone); 3793 } 3794 dns_zone_setview(zone, view); 3795 CHECK(dns_view_addzone(view, zone)); 3796 3797 dns_name_format(name, namebuf, sizeof(namebuf)); 3798 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 3799 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 3800 "automatic ipv4only zone%s%s: %s", sep, viewname, 3801 namebuf); 3802 3803 cleanup: 3804 if (zone != NULL) { 3805 dns_zone_detach(&zone); 3806 } 3807 return (result); 3808 } 3809 3810 #ifdef HAVE_DNSTAP 3811 static isc_result_t 3812 configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) { 3813 isc_result_t result; 3814 const cfg_obj_t *obj, *obj2; 3815 const cfg_listelt_t *element; 3816 const char *dpath; 3817 const cfg_obj_t *dlist = NULL; 3818 dns_dtmsgtype_t dttypes = 0; 3819 unsigned int i; 3820 struct fstrm_iothr_options *fopt = NULL; 3821 3822 result = named_config_get(maps, "dnstap", &dlist); 3823 if (result != ISC_R_SUCCESS) { 3824 return (ISC_R_SUCCESS); 3825 } 3826 3827 for (element = cfg_list_first(dlist); element != NULL; 3828 element = cfg_list_next(element)) 3829 { 3830 const char *str; 3831 dns_dtmsgtype_t dt = 0; 3832 3833 obj = cfg_listelt_value(element); 3834 obj2 = cfg_tuple_get(obj, "type"); 3835 str = cfg_obj_asstring(obj2); 3836 if (strcasecmp(str, "client") == 0) { 3837 dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR; 3838 } else if (strcasecmp(str, "auth") == 0) { 3839 dt |= DNS_DTTYPE_AQ | DNS_DTTYPE_AR; 3840 } else if (strcasecmp(str, "resolver") == 0) { 3841 dt |= DNS_DTTYPE_RQ | DNS_DTTYPE_RR; 3842 } else if (strcasecmp(str, "forwarder") == 0) { 3843 dt |= DNS_DTTYPE_FQ | DNS_DTTYPE_FR; 3844 } else if (strcasecmp(str, "update") == 0) { 3845 dt |= DNS_DTTYPE_UQ | DNS_DTTYPE_UR; 3846 } else if (strcasecmp(str, "all") == 0) { 3847 dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR | DNS_DTTYPE_AQ | 3848 DNS_DTTYPE_AR | DNS_DTTYPE_RQ | DNS_DTTYPE_RR | 3849 DNS_DTTYPE_FQ | DNS_DTTYPE_FR | DNS_DTTYPE_UQ | 3850 DNS_DTTYPE_UR; 3851 } 3852 3853 obj2 = cfg_tuple_get(obj, "mode"); 3854 if (obj2 == NULL || cfg_obj_isvoid(obj2)) { 3855 dttypes |= dt; 3856 continue; 3857 } 3858 3859 str = cfg_obj_asstring(obj2); 3860 if (strcasecmp(str, "query") == 0) { 3861 dt &= ~DNS_DTTYPE_RESPONSE; 3862 } else if (strcasecmp(str, "response") == 0) { 3863 dt &= ~DNS_DTTYPE_QUERY; 3864 } 3865 3866 dttypes |= dt; 3867 } 3868 3869 if (named_g_server->dtenv == NULL && dttypes != 0) { 3870 dns_dtmode_t dmode; 3871 uint64_t max_size = 0; 3872 uint32_t rolls = 0; 3873 isc_log_rollsuffix_t suffix = isc_log_rollsuffix_increment; 3874 3875 obj = NULL; 3876 CHECKM(named_config_get(maps, "dnstap-output", &obj), 3877 "'dnstap-output' must be set if 'dnstap' is set"); 3878 3879 obj2 = cfg_tuple_get(obj, "mode"); 3880 if (obj2 == NULL) { 3881 CHECKM(ISC_R_FAILURE, "dnstap-output mode not found"); 3882 } 3883 if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0) { 3884 dmode = dns_dtmode_file; 3885 } else { 3886 dmode = dns_dtmode_unix; 3887 } 3888 3889 obj2 = cfg_tuple_get(obj, "path"); 3890 if (obj2 == NULL) { 3891 CHECKM(ISC_R_FAILURE, "dnstap-output path not found"); 3892 } 3893 3894 dpath = cfg_obj_asstring(obj2); 3895 3896 obj2 = cfg_tuple_get(obj, "size"); 3897 if (obj2 != NULL && cfg_obj_isuint64(obj2)) { 3898 max_size = cfg_obj_asuint64(obj2); 3899 if (max_size > SIZE_MAX) { 3900 cfg_obj_log(obj2, named_g_lctx, ISC_LOG_WARNING, 3901 "'dnstap-output size " 3902 "%" PRIu64 "' " 3903 "is too large for this " 3904 "system; reducing to %lu", 3905 max_size, (unsigned long)SIZE_MAX); 3906 max_size = SIZE_MAX; 3907 } 3908 } 3909 3910 obj2 = cfg_tuple_get(obj, "versions"); 3911 if (obj2 != NULL && cfg_obj_isuint32(obj2)) { 3912 rolls = cfg_obj_asuint32(obj2); 3913 } else { 3914 rolls = ISC_LOG_ROLLINFINITE; 3915 } 3916 3917 obj2 = cfg_tuple_get(obj, "suffix"); 3918 if (obj2 != NULL && cfg_obj_isstring(obj2) && 3919 strcasecmp(cfg_obj_asstring(obj2), "timestamp") == 0) 3920 { 3921 suffix = isc_log_rollsuffix_timestamp; 3922 } 3923 3924 fopt = fstrm_iothr_options_init(); 3925 /* 3926 * Both network threads and worker threads may log dnstap data. 3927 */ 3928 fstrm_iothr_options_set_num_input_queues(fopt, 3929 2 * named_g_cpus); 3930 fstrm_iothr_options_set_queue_model( 3931 fopt, FSTRM_IOTHR_QUEUE_MODEL_MPSC); 3932 3933 obj = NULL; 3934 result = named_config_get(maps, "fstrm-set-buffer-hint", &obj); 3935 if (result == ISC_R_SUCCESS) { 3936 i = cfg_obj_asuint32(obj); 3937 fstrm_iothr_options_set_buffer_hint(fopt, i); 3938 } 3939 3940 obj = NULL; 3941 result = named_config_get(maps, "fstrm-set-flush-timeout", 3942 &obj); 3943 if (result == ISC_R_SUCCESS) { 3944 i = cfg_obj_asuint32(obj); 3945 fstrm_iothr_options_set_flush_timeout(fopt, i); 3946 } 3947 3948 obj = NULL; 3949 result = named_config_get(maps, "fstrm-set-input-queue-size", 3950 &obj); 3951 if (result == ISC_R_SUCCESS) { 3952 i = cfg_obj_asuint32(obj); 3953 fstrm_iothr_options_set_input_queue_size(fopt, i); 3954 } 3955 3956 obj = NULL; 3957 result = named_config_get( 3958 maps, "fstrm-set-output-notify-threshold", &obj); 3959 if (result == ISC_R_SUCCESS) { 3960 i = cfg_obj_asuint32(obj); 3961 fstrm_iothr_options_set_queue_notify_threshold(fopt, i); 3962 } 3963 3964 obj = NULL; 3965 result = named_config_get(maps, "fstrm-set-output-queue-model", 3966 &obj); 3967 if (result == ISC_R_SUCCESS) { 3968 if (strcasecmp(cfg_obj_asstring(obj), "spsc") == 0) { 3969 i = FSTRM_IOTHR_QUEUE_MODEL_SPSC; 3970 } else { 3971 i = FSTRM_IOTHR_QUEUE_MODEL_MPSC; 3972 } 3973 fstrm_iothr_options_set_queue_model(fopt, i); 3974 } 3975 3976 obj = NULL; 3977 result = named_config_get(maps, "fstrm-set-output-queue-size", 3978 &obj); 3979 if (result == ISC_R_SUCCESS) { 3980 i = cfg_obj_asuint32(obj); 3981 fstrm_iothr_options_set_output_queue_size(fopt, i); 3982 } 3983 3984 obj = NULL; 3985 result = named_config_get(maps, "fstrm-set-reopen-interval", 3986 &obj); 3987 if (result == ISC_R_SUCCESS) { 3988 i = cfg_obj_asduration(obj); 3989 fstrm_iothr_options_set_reopen_interval(fopt, i); 3990 } 3991 3992 CHECKM(dns_dt_create(named_g_mctx, dmode, dpath, &fopt, 3993 named_g_server->task, 3994 &named_g_server->dtenv), 3995 "unable to create dnstap environment"); 3996 3997 CHECKM(dns_dt_setupfile(named_g_server->dtenv, max_size, rolls, 3998 suffix), 3999 "unable to set up dnstap logfile"); 4000 } 4001 4002 if (named_g_server->dtenv == NULL) { 4003 return (ISC_R_SUCCESS); 4004 } 4005 4006 obj = NULL; 4007 result = named_config_get(maps, "dnstap-version", &obj); 4008 if (result != ISC_R_SUCCESS) { 4009 /* not specified; use the product and version */ 4010 dns_dt_setversion(named_g_server->dtenv, PACKAGE_STRING); 4011 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 4012 /* Quoted string */ 4013 dns_dt_setversion(named_g_server->dtenv, cfg_obj_asstring(obj)); 4014 } 4015 4016 obj = NULL; 4017 result = named_config_get(maps, "dnstap-identity", &obj); 4018 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 4019 /* "hostname" is interpreted as boolean true */ 4020 char buf[256]; 4021 if (gethostname(buf, sizeof(buf)) == 0) { 4022 dns_dt_setidentity(named_g_server->dtenv, buf); 4023 } 4024 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 4025 /* Quoted string */ 4026 dns_dt_setidentity(named_g_server->dtenv, 4027 cfg_obj_asstring(obj)); 4028 } 4029 4030 dns_dt_attach(named_g_server->dtenv, &view->dtenv); 4031 view->dttypes = dttypes; 4032 4033 result = ISC_R_SUCCESS; 4034 4035 cleanup: 4036 if (fopt != NULL) { 4037 fstrm_iothr_options_destroy(&fopt); 4038 } 4039 4040 return (result); 4041 } 4042 #endif /* HAVE_DNSTAP */ 4043 4044 static isc_result_t 4045 create_mapped_acl(void) { 4046 isc_result_t result; 4047 dns_acl_t *acl = NULL; 4048 struct in6_addr in6 = IN6ADDR_V4MAPPED_INIT; 4049 isc_netaddr_t addr; 4050 4051 isc_netaddr_fromin6(&addr, &in6); 4052 4053 result = dns_acl_create(named_g_mctx, 1, &acl); 4054 if (result != ISC_R_SUCCESS) { 4055 return (result); 4056 } 4057 4058 result = dns_iptable_addprefix(acl->iptable, &addr, 96, true); 4059 if (result == ISC_R_SUCCESS) { 4060 dns_acl_attach(acl, &named_g_mapped); 4061 } 4062 dns_acl_detach(&acl); 4063 return (result); 4064 } 4065 4066 /*% 4067 * A callback for the cfg_pluginlist_foreach() call in configure_view() below. 4068 * If registering any plugin fails, registering subsequent ones is not 4069 * attempted. 4070 */ 4071 static isc_result_t 4072 register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj, 4073 const char *plugin_path, const char *parameters, 4074 void *callback_data) { 4075 dns_view_t *view = callback_data; 4076 char full_path[PATH_MAX]; 4077 isc_result_t result; 4078 4079 result = ns_plugin_expandpath(plugin_path, full_path, 4080 sizeof(full_path)); 4081 if (result != ISC_R_SUCCESS) { 4082 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4083 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4084 "%s: plugin configuration failed: " 4085 "unable to get full plugin path: %s", 4086 plugin_path, isc_result_totext(result)); 4087 return (result); 4088 } 4089 4090 result = ns_plugin_register(full_path, parameters, config, 4091 cfg_obj_file(obj), cfg_obj_line(obj), 4092 named_g_mctx, named_g_lctx, 4093 named_g_aclconfctx, view); 4094 if (result != ISC_R_SUCCESS) { 4095 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4096 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4097 "%s: plugin configuration failed: %s", full_path, 4098 isc_result_totext(result)); 4099 } 4100 4101 return (result); 4102 } 4103 4104 /* 4105 * Determine if a minimal-sized cache can be used for a given view, according 4106 * to 'maps' (implicit defaults, global options, view options) and 'optionmaps' 4107 * (global options, view options). This is only allowed for views which have 4108 * recursion disabled and do not have "max-cache-size" set explicitly. Using 4109 * minimal-sized caches prevents a situation in which all explicitly configured 4110 * and built-in views inherit the default "max-cache-size 90%;" setting, which 4111 * could lead to memory exhaustion with multiple views configured. 4112 */ 4113 static bool 4114 minimal_cache_allowed(const cfg_obj_t *maps[4], 4115 const cfg_obj_t *optionmaps[3]) { 4116 const cfg_obj_t *obj; 4117 4118 /* 4119 * Do not use a minimal-sized cache for a view with recursion enabled. 4120 */ 4121 obj = NULL; 4122 (void)named_config_get(maps, "recursion", &obj); 4123 INSIST(obj != NULL); 4124 if (cfg_obj_asboolean(obj)) { 4125 return (false); 4126 } 4127 4128 /* 4129 * Do not use a minimal-sized cache if a specific size was requested. 4130 */ 4131 obj = NULL; 4132 (void)named_config_get(optionmaps, "max-cache-size", &obj); 4133 if (obj != NULL) { 4134 return (false); 4135 } 4136 4137 return (true); 4138 } 4139 4140 static const char *const response_synonyms[] = { "response", NULL }; 4141 4142 static const dns_name_t * 4143 algorithm_name(unsigned int alg) { 4144 switch (alg) { 4145 case DST_ALG_HMACMD5: 4146 return (dns_tsig_hmacmd5_name); 4147 case DST_ALG_HMACSHA1: 4148 return (dns_tsig_hmacsha1_name); 4149 case DST_ALG_HMACSHA224: 4150 return (dns_tsig_hmacsha224_name); 4151 case DST_ALG_HMACSHA256: 4152 return (dns_tsig_hmacsha256_name); 4153 case DST_ALG_HMACSHA384: 4154 return (dns_tsig_hmacsha384_name); 4155 case DST_ALG_HMACSHA512: 4156 return (dns_tsig_hmacsha512_name); 4157 case DST_ALG_GSSAPI: 4158 return (dns_tsig_gssapi_name); 4159 default: 4160 UNREACHABLE(); 4161 } 4162 } 4163 4164 /* 4165 * Configure 'view' according to 'vconfig', taking defaults from 4166 * 'config' where values are missing in 'vconfig'. 4167 * 4168 * When configuring the default view, 'vconfig' will be NULL and the 4169 * global defaults in 'config' used exclusively. 4170 */ 4171 static isc_result_t 4172 configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, 4173 cfg_obj_t *vconfig, named_cachelist_t *cachelist, 4174 dns_kasplist_t *kasplist, const cfg_obj_t *bindkeys, 4175 isc_mem_t *mctx, cfg_aclconfctx_t *actx, bool need_hints) { 4176 const cfg_obj_t *maps[4]; 4177 const cfg_obj_t *cfgmaps[3]; 4178 const cfg_obj_t *optionmaps[3]; 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_tsig_keyring_t *ring = NULL; 4206 dns_transport_list_t *transports = NULL; 4207 dns_view_t *pview = NULL; /* Production view */ 4208 isc_mem_t *cmctx = NULL, *hmctx = NULL; 4209 dns_dispatch_t *dispatch4 = NULL; 4210 dns_dispatch_t *dispatch6 = NULL; 4211 bool rpz_configured = false; 4212 bool catz_configured = false; 4213 bool shared_cache = false; 4214 int i = 0, j = 0, k = 0; 4215 const char *str; 4216 const char *cachename = NULL; 4217 dns_order_t *order = NULL; 4218 uint32_t udpsize; 4219 uint32_t maxbits; 4220 unsigned int resopts = 0; 4221 dns_zone_t *zone = NULL; 4222 uint32_t max_clients_per_query; 4223 bool empty_zones_enable; 4224 const cfg_obj_t *disablelist = NULL; 4225 isc_stats_t *resstats = NULL; 4226 dns_stats_t *resquerystats = NULL; 4227 bool auto_root = false; 4228 named_cache_t *nsc; 4229 bool zero_no_soattl; 4230 dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; 4231 unsigned int query_timeout, ndisp; 4232 bool old_rpz_ok = false; 4233 dns_dyndbctx_t *dctx = NULL; 4234 unsigned int resolver_param; 4235 dns_ntatable_t *ntatable = NULL; 4236 const char *qminmode = NULL; 4237 4238 REQUIRE(DNS_VIEW_VALID(view)); 4239 4240 if (config != NULL) { 4241 (void)cfg_map_get(config, "options", &options); 4242 } 4243 4244 /* 4245 * maps: view options, options, defaults 4246 * cfgmaps: view options, config 4247 * optionmaps: view options, options 4248 */ 4249 if (vconfig != NULL) { 4250 voptions = cfg_tuple_get(vconfig, "options"); 4251 maps[i++] = voptions; 4252 optionmaps[j++] = voptions; 4253 cfgmaps[k++] = voptions; 4254 } 4255 if (options != NULL) { 4256 maps[i++] = options; 4257 optionmaps[j++] = options; 4258 } 4259 4260 maps[i++] = named_g_defaults; 4261 maps[i] = NULL; 4262 optionmaps[j] = NULL; 4263 if (config != NULL) { 4264 cfgmaps[k++] = config; 4265 } 4266 cfgmaps[k] = NULL; 4267 4268 /* 4269 * Set the view's port number for outgoing queries. 4270 */ 4271 CHECKM(named_config_getport(config, "port", &port), "port"); 4272 dns_view_setdstport(view, port); 4273 4274 /* 4275 * Make the list of response policy zone names for a view that 4276 * is used for real lookups and so cares about hints. 4277 */ 4278 obj = NULL; 4279 if (view->rdclass == dns_rdataclass_in && need_hints && 4280 named_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) 4281 { 4282 CHECK(configure_rpz(view, NULL, maps, obj, &old_rpz_ok)); 4283 rpz_configured = true; 4284 } 4285 4286 obj = NULL; 4287 if (view->rdclass != dns_rdataclass_in && need_hints && 4288 named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) 4289 { 4290 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4291 "'catalog-zones' option is only supported " 4292 "for views with class IN"); 4293 } 4294 4295 obj = NULL; 4296 if (view->rdclass == dns_rdataclass_in && need_hints && 4297 named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) 4298 { 4299 CHECK(configure_catz(view, NULL, config, obj)); 4300 catz_configured = true; 4301 } 4302 4303 /* 4304 * Configure the zones. 4305 */ 4306 zonelist = NULL; 4307 if (voptions != NULL) { 4308 (void)cfg_map_get(voptions, "zone", &zonelist); 4309 } else { 4310 (void)cfg_map_get(config, "zone", &zonelist); 4311 } 4312 4313 /* 4314 * Load zone configuration 4315 */ 4316 for (element = cfg_list_first(zonelist); element != NULL; 4317 element = cfg_list_next(element)) 4318 { 4319 const cfg_obj_t *zconfig = cfg_listelt_value(element); 4320 CHECK(configure_zone(config, zconfig, vconfig, mctx, view, 4321 viewlist, kasplist, actx, false, 4322 old_rpz_ok, false, false)); 4323 zone_element_latest = element; 4324 } 4325 4326 /* 4327 * Check that a primary or secondary zone was found for each 4328 * zone named in the response policy statement, unless we are 4329 * using RPZ service interface. 4330 */ 4331 if (view->rpzs != NULL && !view->rpzs->p.dnsrps_enabled) { 4332 dns_rpz_num_t n; 4333 4334 for (n = 0; n < view->rpzs->p.num_zones; ++n) { 4335 if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) { 4336 char namebuf[DNS_NAME_FORMATSIZE]; 4337 4338 dns_name_format(&view->rpzs->zones[n]->origin, 4339 namebuf, sizeof(namebuf)); 4340 isc_log_write(named_g_lctx, 4341 NAMED_LOGCATEGORY_GENERAL, 4342 NAMED_LOGMODULE_SERVER, 4343 DNS_RPZ_ERROR_LEVEL, 4344 "rpz '%s' is not a primary or a " 4345 "secondary zone", 4346 namebuf); 4347 result = ISC_R_NOTFOUND; 4348 goto cleanup; 4349 } 4350 } 4351 } 4352 4353 /* 4354 * If we're allowing added zones, then load zone configuration 4355 * from the newzone file for zones that were added during previous 4356 * runs. 4357 */ 4358 CHECK(configure_newzones(view, config, vconfig, mctx, actx)); 4359 4360 /* 4361 * Create Dynamically Loadable Zone driver. 4362 */ 4363 dlzlist = NULL; 4364 if (voptions != NULL) { 4365 (void)cfg_map_get(voptions, "dlz", &dlzlist); 4366 } else { 4367 (void)cfg_map_get(config, "dlz", &dlzlist); 4368 } 4369 4370 for (element = cfg_list_first(dlzlist); element != NULL; 4371 element = cfg_list_next(element)) 4372 { 4373 dlz = cfg_listelt_value(element); 4374 4375 obj = NULL; 4376 (void)cfg_map_get(dlz, "database", &obj); 4377 if (obj != NULL) { 4378 dns_dlzdb_t *dlzdb = NULL; 4379 const cfg_obj_t *name, *search = NULL; 4380 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 4381 4382 if (s == NULL) { 4383 result = ISC_R_NOMEMORY; 4384 goto cleanup; 4385 } 4386 4387 result = isc_commandline_strtoargv(mctx, s, &dlzargc, 4388 &dlzargv, 0); 4389 if (result != ISC_R_SUCCESS) { 4390 isc_mem_free(mctx, s); 4391 goto cleanup; 4392 } 4393 4394 name = cfg_map_getname(dlz); 4395 result = dns_dlzcreate(mctx, cfg_obj_asstring(name), 4396 dlzargv[0], dlzargc, dlzargv, 4397 &dlzdb); 4398 isc_mem_free(mctx, s); 4399 isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv)); 4400 if (result != ISC_R_SUCCESS) { 4401 goto cleanup; 4402 } 4403 4404 /* 4405 * If the DLZ backend supports configuration, 4406 * and is searchable, then call its configure 4407 * method now. If not searchable, we'll take 4408 * care of it when we process the zone statement. 4409 */ 4410 (void)cfg_map_get(dlz, "search", &search); 4411 if (search == NULL || cfg_obj_asboolean(search)) { 4412 dlzdb->search = true; 4413 result = dns_dlzconfigure( 4414 view, dlzdb, dlzconfigure_callback); 4415 if (result != ISC_R_SUCCESS) { 4416 goto cleanup; 4417 } 4418 ISC_LIST_APPEND(view->dlz_searched, dlzdb, 4419 link); 4420 } else { 4421 dlzdb->search = false; 4422 ISC_LIST_APPEND(view->dlz_unsearched, dlzdb, 4423 link); 4424 } 4425 } 4426 } 4427 4428 /* 4429 * Obtain configuration parameters that affect the decision of whether 4430 * we can reuse/share an existing cache. 4431 */ 4432 obj = NULL; 4433 result = named_config_get(maps, "max-cache-size", &obj); 4434 INSIST(result == ISC_R_SUCCESS); 4435 /* 4436 * If "-T maxcachesize=..." is in effect, it overrides any other 4437 * "max-cache-size" setting found in configuration, either implicit or 4438 * explicit. For simplicity, the value passed to that command line 4439 * option is always treated as the number of bytes to set 4440 * "max-cache-size" to. 4441 */ 4442 if (named_g_maxcachesize != 0) { 4443 max_cache_size = named_g_maxcachesize; 4444 } else if (minimal_cache_allowed(maps, optionmaps)) { 4445 /* 4446 * dns_cache_setcachesize() will adjust this to the smallest 4447 * allowed value. 4448 */ 4449 max_cache_size = 1; 4450 } else if (cfg_obj_isstring(obj)) { 4451 str = cfg_obj_asstring(obj); 4452 INSIST(strcasecmp(str, "unlimited") == 0); 4453 max_cache_size = 0; 4454 } else if (cfg_obj_ispercentage(obj)) { 4455 max_cache_size = SIZE_AS_PERCENT; 4456 max_cache_size_percent = cfg_obj_aspercentage(obj); 4457 } else { 4458 isc_resourcevalue_t value; 4459 value = cfg_obj_asuint64(obj); 4460 if (value > SIZE_MAX) { 4461 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4462 "'max-cache-size " 4463 "%" PRIu64 "' " 4464 "is too large for this " 4465 "system; reducing to %lu", 4466 value, (unsigned long)SIZE_MAX); 4467 value = SIZE_MAX; 4468 } 4469 max_cache_size = (size_t)value; 4470 } 4471 4472 if (max_cache_size == SIZE_AS_PERCENT) { 4473 uint64_t totalphys = isc_meminfo_totalphys(); 4474 4475 max_cache_size = 4476 (size_t)(totalphys * max_cache_size_percent / 100); 4477 if (totalphys == 0) { 4478 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4479 "Unable to determine amount of physical " 4480 "memory, setting 'max-cache-size' to " 4481 "unlimited"); 4482 } else { 4483 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, 4484 "'max-cache-size %d%%' " 4485 "- setting to %" PRIu64 "MB " 4486 "(out of %" PRIu64 "MB)", 4487 max_cache_size_percent, 4488 (uint64_t)(max_cache_size / (1024 * 1024)), 4489 totalphys / (1024 * 1024)); 4490 } 4491 } 4492 4493 /* Check-names. */ 4494 obj = NULL; 4495 result = named_checknames_get(maps, response_synonyms, &obj); 4496 INSIST(result == ISC_R_SUCCESS); 4497 4498 str = cfg_obj_asstring(obj); 4499 if (strcasecmp(str, "fail") == 0) { 4500 resopts |= DNS_RESOLVER_CHECKNAMES | 4501 DNS_RESOLVER_CHECKNAMESFAIL; 4502 view->checknames = true; 4503 } else if (strcasecmp(str, "warn") == 0) { 4504 resopts |= DNS_RESOLVER_CHECKNAMES; 4505 view->checknames = false; 4506 } else if (strcasecmp(str, "ignore") == 0) { 4507 view->checknames = false; 4508 } else { 4509 UNREACHABLE(); 4510 } 4511 4512 obj = NULL; 4513 result = named_config_get(maps, "zero-no-soa-ttl-cache", &obj); 4514 INSIST(result == ISC_R_SUCCESS); 4515 zero_no_soattl = cfg_obj_asboolean(obj); 4516 4517 obj = NULL; 4518 result = named_config_get(maps, "dns64", &obj); 4519 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && 4520 strcmp(view->name, "_meta")) 4521 { 4522 isc_netaddr_t na, suffix, *sp; 4523 unsigned int prefixlen; 4524 const char *server, *contact; 4525 const cfg_obj_t *myobj; 4526 4527 myobj = NULL; 4528 result = named_config_get(maps, "dns64-server", &myobj); 4529 if (result == ISC_R_SUCCESS) { 4530 server = cfg_obj_asstring(myobj); 4531 } else { 4532 server = NULL; 4533 } 4534 4535 myobj = NULL; 4536 result = named_config_get(maps, "dns64-contact", &myobj); 4537 if (result == ISC_R_SUCCESS) { 4538 contact = cfg_obj_asstring(myobj); 4539 } else { 4540 contact = NULL; 4541 } 4542 4543 for (element = cfg_list_first(obj); element != NULL; 4544 element = cfg_list_next(element)) 4545 { 4546 const cfg_obj_t *map = cfg_listelt_value(element); 4547 dns_dns64_t *dns64 = NULL; 4548 unsigned int dns64options = 0; 4549 4550 cfg_obj_asnetprefix(cfg_map_getname(map), &na, 4551 &prefixlen); 4552 4553 obj = NULL; 4554 (void)cfg_map_get(map, "suffix", &obj); 4555 if (obj != NULL) { 4556 sp = &suffix; 4557 isc_netaddr_fromsockaddr( 4558 sp, cfg_obj_assockaddr(obj)); 4559 } else { 4560 sp = NULL; 4561 } 4562 4563 clients = mapped = excluded = NULL; 4564 obj = NULL; 4565 (void)cfg_map_get(map, "clients", &obj); 4566 if (obj != NULL) { 4567 result = cfg_acl_fromconfig(obj, config, 4568 named_g_lctx, actx, 4569 mctx, 0, &clients); 4570 if (result != ISC_R_SUCCESS) { 4571 goto cleanup; 4572 } 4573 } 4574 obj = NULL; 4575 (void)cfg_map_get(map, "mapped", &obj); 4576 if (obj != NULL) { 4577 result = cfg_acl_fromconfig(obj, config, 4578 named_g_lctx, actx, 4579 mctx, 0, &mapped); 4580 if (result != ISC_R_SUCCESS) { 4581 goto cleanup; 4582 } 4583 } 4584 obj = NULL; 4585 (void)cfg_map_get(map, "exclude", &obj); 4586 if (obj != NULL) { 4587 result = cfg_acl_fromconfig(obj, config, 4588 named_g_lctx, actx, 4589 mctx, 0, &excluded); 4590 if (result != ISC_R_SUCCESS) { 4591 goto cleanup; 4592 } 4593 } else { 4594 if (named_g_mapped == NULL) { 4595 result = create_mapped_acl(); 4596 if (result != ISC_R_SUCCESS) { 4597 goto cleanup; 4598 } 4599 } 4600 dns_acl_attach(named_g_mapped, &excluded); 4601 } 4602 4603 obj = NULL; 4604 (void)cfg_map_get(map, "recursive-only", &obj); 4605 if (obj != NULL && cfg_obj_asboolean(obj)) { 4606 dns64options |= DNS_DNS64_RECURSIVE_ONLY; 4607 } 4608 4609 obj = NULL; 4610 (void)cfg_map_get(map, "break-dnssec", &obj); 4611 if (obj != NULL && cfg_obj_asboolean(obj)) { 4612 dns64options |= DNS_DNS64_BREAK_DNSSEC; 4613 } 4614 4615 result = dns_dns64_create(mctx, &na, prefixlen, sp, 4616 clients, mapped, excluded, 4617 dns64options, &dns64); 4618 if (result != ISC_R_SUCCESS) { 4619 goto cleanup; 4620 } 4621 dns_dns64_append(&view->dns64, dns64); 4622 view->dns64cnt++; 4623 result = dns64_reverse(view, mctx, &na, prefixlen, 4624 server, contact); 4625 if (result != ISC_R_SUCCESS) { 4626 goto cleanup; 4627 } 4628 if (clients != NULL) { 4629 dns_acl_detach(&clients); 4630 } 4631 if (mapped != NULL) { 4632 dns_acl_detach(&mapped); 4633 } 4634 if (excluded != NULL) { 4635 dns_acl_detach(&excluded); 4636 } 4637 } 4638 } 4639 4640 obj = NULL; 4641 result = named_config_get(maps, "dnssec-accept-expired", &obj); 4642 INSIST(result == ISC_R_SUCCESS); 4643 view->acceptexpired = cfg_obj_asboolean(obj); 4644 4645 obj = NULL; 4646 /* 'optionmaps', not 'maps': don't check named_g_defaults yet */ 4647 (void)named_config_get(optionmaps, "dnssec-validation", &obj); 4648 if (obj == NULL) { 4649 /* 4650 * Default to VALIDATION_DEFAULT as set in config.c. 4651 */ 4652 (void)cfg_map_get(named_g_defaults, "dnssec-validation", &obj); 4653 INSIST(obj != NULL); 4654 } 4655 if (obj != NULL) { 4656 if (cfg_obj_isboolean(obj)) { 4657 view->enablevalidation = cfg_obj_asboolean(obj); 4658 } else { 4659 /* 4660 * If dnssec-validation is set but not boolean, 4661 * then it must be "auto" 4662 */ 4663 view->enablevalidation = true; 4664 auto_root = true; 4665 } 4666 } 4667 4668 obj = NULL; 4669 result = named_config_get(maps, "max-cache-ttl", &obj); 4670 INSIST(result == ISC_R_SUCCESS); 4671 view->maxcachettl = cfg_obj_asduration(obj); 4672 4673 obj = NULL; 4674 result = named_config_get(maps, "max-ncache-ttl", &obj); 4675 INSIST(result == ISC_R_SUCCESS); 4676 view->maxncachettl = cfg_obj_asduration(obj); 4677 4678 obj = NULL; 4679 result = named_config_get(maps, "min-cache-ttl", &obj); 4680 INSIST(result == ISC_R_SUCCESS); 4681 view->mincachettl = cfg_obj_asduration(obj); 4682 4683 obj = NULL; 4684 result = named_config_get(maps, "min-ncache-ttl", &obj); 4685 INSIST(result == ISC_R_SUCCESS); 4686 view->minncachettl = cfg_obj_asduration(obj); 4687 4688 obj = NULL; 4689 result = named_config_get(maps, "synth-from-dnssec", &obj); 4690 INSIST(result == ISC_R_SUCCESS); 4691 view->synthfromdnssec = cfg_obj_asboolean(obj); 4692 4693 obj = NULL; 4694 result = named_config_get(maps, "stale-cache-enable", &obj); 4695 INSIST(result == ISC_R_SUCCESS); 4696 if (cfg_obj_asboolean(obj)) { 4697 obj = NULL; 4698 result = named_config_get(maps, "max-stale-ttl", &obj); 4699 INSIST(result == ISC_R_SUCCESS); 4700 max_stale_ttl = ISC_MAX(cfg_obj_asduration(obj), 1); 4701 } 4702 /* 4703 * If 'stale-cache-enable' is false, max_stale_ttl is set to 0, 4704 * meaning keeping stale RRsets in cache is disabled. 4705 */ 4706 4707 obj = NULL; 4708 result = named_config_get(maps, "stale-answer-enable", &obj); 4709 INSIST(result == ISC_R_SUCCESS); 4710 view->staleanswersenable = cfg_obj_asboolean(obj); 4711 4712 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 4713 view->rdclass, &pview); 4714 if (result == ISC_R_SUCCESS) { 4715 view->staleanswersok = pview->staleanswersok; 4716 dns_view_detach(&pview); 4717 } else { 4718 view->staleanswersok = dns_stale_answer_conf; 4719 } 4720 4721 obj = NULL; 4722 result = named_config_get(maps, "stale-answer-client-timeout", &obj); 4723 INSIST(result == ISC_R_SUCCESS); 4724 if (cfg_obj_isstring(obj)) { 4725 /* 4726 * The only string values available for this option 4727 * are "disabled" and "off". 4728 * We use (uint32_t) -1 to represent disabled since 4729 * a value of zero means that stale data can be used 4730 * to promptly answer the query, while an attempt to 4731 * refresh the RRset will still be made in background. 4732 */ 4733 view->staleanswerclienttimeout = (uint32_t)-1; 4734 } else { 4735 view->staleanswerclienttimeout = cfg_obj_asuint32(obj); 4736 } 4737 4738 obj = NULL; 4739 result = named_config_get(maps, "stale-refresh-time", &obj); 4740 INSIST(result == ISC_R_SUCCESS); 4741 stale_refresh_time = cfg_obj_asduration(obj); 4742 4743 /* 4744 * Configure the view's cache. 4745 * 4746 * First, check to see if there are any attach-cache options. If yes, 4747 * attempt to lookup an existing cache at attach it to the view. If 4748 * there is not one, then try to reuse an existing cache if possible; 4749 * otherwise create a new cache. 4750 * 4751 * Note that the ADB is not preserved or shared in either case. 4752 * 4753 * When a matching view is found, the associated statistics are also 4754 * retrieved and reused. 4755 * 4756 * XXX Determining when it is safe to reuse or share a cache is tricky. 4757 * When the view's configuration changes, the cached data may become 4758 * invalid because it reflects our old view of the world. We check 4759 * some of the configuration parameters that could invalidate the cache 4760 * or otherwise make it unshareable, but there are other configuration 4761 * options that should be checked. For example, if a view uses a 4762 * forwarder, changes in the forwarder configuration may invalidate 4763 * the cache. At the moment, it's the administrator's responsibility to 4764 * ensure these configuration options don't invalidate reusing/sharing. 4765 */ 4766 obj = NULL; 4767 result = named_config_get(maps, "attach-cache", &obj); 4768 if (result == ISC_R_SUCCESS) { 4769 cachename = cfg_obj_asstring(obj); 4770 } else { 4771 cachename = view->name; 4772 } 4773 cache = NULL; 4774 nsc = cachelist_find(cachelist, cachename, view->rdclass); 4775 if (nsc != NULL) { 4776 if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, 4777 max_cache_size, max_stale_ttl, 4778 stale_refresh_time)) 4779 { 4780 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 4781 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 4782 "views %s and %s can't share the cache " 4783 "due to configuration parameter mismatch", 4784 nsc->primaryview->name, view->name); 4785 result = ISC_R_FAILURE; 4786 goto cleanup; 4787 } 4788 dns_cache_attach(nsc->cache, &cache); 4789 shared_cache = true; 4790 } else { 4791 if (strcmp(cachename, view->name) == 0) { 4792 result = dns_viewlist_find(&named_g_server->viewlist, 4793 cachename, view->rdclass, 4794 &pview); 4795 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 4796 { 4797 goto cleanup; 4798 } 4799 if (pview != NULL) { 4800 if (!cache_reusable(pview, view, 4801 zero_no_soattl)) 4802 { 4803 isc_log_write(named_g_lctx, 4804 NAMED_LOGCATEGORY_GENERAL, 4805 NAMED_LOGMODULE_SERVER, 4806 ISC_LOG_DEBUG(1), 4807 "cache cannot be reused " 4808 "for view %s due to " 4809 "configuration parameter " 4810 "mismatch", 4811 view->name); 4812 } else { 4813 INSIST(pview->cache != NULL); 4814 isc_log_write(named_g_lctx, 4815 NAMED_LOGCATEGORY_GENERAL, 4816 NAMED_LOGMODULE_SERVER, 4817 ISC_LOG_DEBUG(3), 4818 "reusing existing cache"); 4819 dns_cache_attach(pview->cache, &cache); 4820 } 4821 dns_view_getresstats(pview, &resstats); 4822 dns_view_getresquerystats(pview, 4823 &resquerystats); 4824 dns_view_detach(&pview); 4825 } 4826 } 4827 if (cache == NULL) { 4828 /* 4829 * Create a cache with the desired name. This normally 4830 * equals the view name, but may also be a forward 4831 * reference to a view that share the cache with this 4832 * view but is not yet configured. If it is not the 4833 * view name but not a forward reference either, then it 4834 * is simply a named cache that is not shared. 4835 */ 4836 CHECK(dns_cache_create(mctx, named_g_taskmgr, 4837 named_g_timermgr, view->rdclass, 4838 cachename, "rbt", 0, NULL, 4839 &cache)); 4840 } 4841 nsc = isc_mem_get(mctx, sizeof(*nsc)); 4842 nsc->cache = NULL; 4843 dns_cache_attach(cache, &nsc->cache); 4844 nsc->primaryview = view; 4845 nsc->needflush = false; 4846 nsc->adbsizeadjusted = false; 4847 nsc->rdclass = view->rdclass; 4848 ISC_LINK_INIT(nsc, link); 4849 ISC_LIST_APPEND(*cachelist, nsc, link); 4850 } 4851 dns_view_setcache(view, cache, shared_cache); 4852 4853 dns_cache_setcachesize(cache, max_cache_size); 4854 dns_cache_setservestalettl(cache, max_stale_ttl); 4855 dns_cache_setservestalerefresh(cache, stale_refresh_time); 4856 4857 dns_cache_detach(&cache); 4858 4859 obj = NULL; 4860 result = named_config_get(maps, "stale-answer-ttl", &obj); 4861 INSIST(result == ISC_R_SUCCESS); 4862 view->staleanswerttl = ISC_MAX(cfg_obj_asduration(obj), 1); 4863 4864 /* 4865 * Resolver. 4866 */ 4867 CHECK(get_view_querysource_dispatch( 4868 maps, AF_INET, &dispatch4, 4869 (ISC_LIST_PREV(view, link) == NULL))); 4870 CHECK(get_view_querysource_dispatch( 4871 maps, AF_INET6, &dispatch6, 4872 (ISC_LIST_PREV(view, link) == NULL))); 4873 if (dispatch4 == NULL && dispatch6 == NULL) { 4874 UNEXPECTED_ERROR("unable to obtain either an IPv4 or" 4875 " an IPv6 dispatch"); 4876 result = ISC_R_UNEXPECTED; 4877 goto cleanup; 4878 } 4879 4880 if (resstats == NULL) { 4881 CHECK(isc_stats_create(mctx, &resstats, 4882 dns_resstatscounter_max)); 4883 } 4884 dns_view_setresstats(view, resstats); 4885 if (resquerystats == NULL) { 4886 CHECK(dns_rdatatypestats_create(mctx, &resquerystats)); 4887 } 4888 dns_view_setresquerystats(view, resquerystats); 4889 4890 ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH); 4891 CHECK(dns_view_createresolver( 4892 view, named_g_taskmgr, RESOLVER_NTASKS_PERCPU * named_g_cpus, 4893 ndisp, named_g_netmgr, named_g_timermgr, resopts, 4894 named_g_dispatchmgr, dispatch4, dispatch6)); 4895 4896 /* 4897 * Set the ADB cache size to 1/8th of the max-cache-size or 4898 * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. 4899 */ 4900 max_adb_size = 0; 4901 if (max_cache_size != 0U) { 4902 max_adb_size = max_cache_size / 8; 4903 if (max_adb_size == 0U) { 4904 max_adb_size = 1; /* Force minimum. */ 4905 } 4906 if (view != nsc->primaryview && 4907 max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) 4908 { 4909 max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; 4910 if (!nsc->adbsizeadjusted) { 4911 dns_adb_setadbsize(nsc->primaryview->adb, 4912 MAX_ADB_SIZE_FOR_CACHESHARE); 4913 nsc->adbsizeadjusted = true; 4914 } 4915 } 4916 } 4917 dns_adb_setadbsize(view->adb, max_adb_size); 4918 4919 /* 4920 * Set up ADB quotas 4921 */ 4922 { 4923 uint32_t fps, freq; 4924 double low, high, discount; 4925 4926 obj = NULL; 4927 result = named_config_get(maps, "fetches-per-server", &obj); 4928 INSIST(result == ISC_R_SUCCESS); 4929 obj2 = cfg_tuple_get(obj, "fetches"); 4930 fps = cfg_obj_asuint32(obj2); 4931 obj2 = cfg_tuple_get(obj, "response"); 4932 if (!cfg_obj_isvoid(obj2)) { 4933 const char *resp = cfg_obj_asstring(obj2); 4934 isc_result_t r = DNS_R_SERVFAIL; 4935 4936 if (strcasecmp(resp, "drop") == 0) { 4937 r = DNS_R_DROP; 4938 } else if (strcasecmp(resp, "fail") == 0) { 4939 r = DNS_R_SERVFAIL; 4940 } else { 4941 UNREACHABLE(); 4942 } 4943 4944 dns_resolver_setquotaresponse(view->resolver, 4945 dns_quotatype_server, r); 4946 } 4947 4948 obj = NULL; 4949 result = named_config_get(maps, "fetch-quota-params", &obj); 4950 INSIST(result == ISC_R_SUCCESS); 4951 4952 obj2 = cfg_tuple_get(obj, "frequency"); 4953 freq = cfg_obj_asuint32(obj2); 4954 4955 obj2 = cfg_tuple_get(obj, "low"); 4956 low = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 4957 4958 obj2 = cfg_tuple_get(obj, "high"); 4959 high = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 4960 4961 obj2 = cfg_tuple_get(obj, "discount"); 4962 discount = (double)cfg_obj_asfixedpoint(obj2) / 100.0; 4963 4964 dns_adb_setquota(view->adb, fps, freq, low, high, discount); 4965 } 4966 4967 /* 4968 * Set resolver's lame-ttl. 4969 */ 4970 obj = NULL; 4971 result = named_config_get(maps, "lame-ttl", &obj); 4972 INSIST(result == ISC_R_SUCCESS); 4973 lame_ttl = cfg_obj_asduration(obj); 4974 if (lame_ttl > 0) { 4975 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 4976 "disabling lame cache despite lame-ttl > 0 as it " 4977 "may cause performance issues"); 4978 lame_ttl = 0; 4979 } 4980 dns_resolver_setlamettl(view->resolver, lame_ttl); 4981 4982 /* 4983 * Set the resolver's query timeout. 4984 */ 4985 obj = NULL; 4986 result = named_config_get(maps, "resolver-query-timeout", &obj); 4987 INSIST(result == ISC_R_SUCCESS); 4988 query_timeout = cfg_obj_asuint32(obj); 4989 dns_resolver_settimeout(view->resolver, query_timeout); 4990 4991 /* 4992 * Adjust stale-answer-client-timeout upper bound 4993 * to be resolver-query-timeout - 1s. 4994 * This assignment is safe as dns_resolver_settimeout() 4995 * ensures that resolver->querytimeout value will be in the 4996 * [MINIMUM_QUERY_TIMEOUT, MAXIMUM_QUERY_TIMEOUT] range and 4997 * MINIMUM_QUERY_TIMEOUT is > 1000 (in ms). 4998 */ 4999 if (view->staleanswerclienttimeout != (uint32_t)-1 && 5000 view->staleanswerclienttimeout > 5001 (dns_resolver_gettimeout(view->resolver) - 1000)) 5002 { 5003 view->staleanswerclienttimeout = 5004 dns_resolver_gettimeout(view->resolver) - 1000; 5005 isc_log_write( 5006 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 5007 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 5008 "stale-answer-client-timeout adjusted to %" PRIu32, 5009 view->staleanswerclienttimeout); 5010 } 5011 5012 /* Specify whether to use 0-TTL for negative response for SOA query */ 5013 dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); 5014 5015 /* 5016 * Set the resolver's EDNS UDP size. 5017 */ 5018 obj = NULL; 5019 result = named_config_get(maps, "edns-udp-size", &obj); 5020 INSIST(result == ISC_R_SUCCESS); 5021 udpsize = cfg_obj_asuint32(obj); 5022 if (udpsize < 512) { 5023 udpsize = 512; 5024 } 5025 if (udpsize > 4096) { 5026 udpsize = 4096; 5027 } 5028 dns_resolver_setudpsize(view->resolver, (uint16_t)udpsize); 5029 5030 /* 5031 * Set the maximum UDP response size. 5032 */ 5033 obj = NULL; 5034 result = named_config_get(maps, "max-udp-size", &obj); 5035 INSIST(result == ISC_R_SUCCESS); 5036 udpsize = cfg_obj_asuint32(obj); 5037 if (udpsize < 512) { 5038 udpsize = 512; 5039 } 5040 if (udpsize > 4096) { 5041 udpsize = 4096; 5042 } 5043 view->maxudp = udpsize; 5044 5045 /* 5046 * Set the maximum UDP when a COOKIE is not provided. 5047 */ 5048 obj = NULL; 5049 result = named_config_get(maps, "nocookie-udp-size", &obj); 5050 INSIST(result == ISC_R_SUCCESS); 5051 udpsize = cfg_obj_asuint32(obj); 5052 if (udpsize < 128) { 5053 udpsize = 128; 5054 } 5055 if (udpsize > view->maxudp) { 5056 udpsize = view->maxudp; 5057 } 5058 view->nocookieudp = udpsize; 5059 5060 /* 5061 * Set the maximum rsa exponent bits. 5062 */ 5063 obj = NULL; 5064 result = named_config_get(maps, "max-rsa-exponent-size", &obj); 5065 INSIST(result == ISC_R_SUCCESS); 5066 maxbits = cfg_obj_asuint32(obj); 5067 if (maxbits != 0 && maxbits < 35) { 5068 maxbits = 35; 5069 } 5070 if (maxbits > 4096) { 5071 maxbits = 4096; 5072 } 5073 view->maxbits = maxbits; 5074 5075 /* 5076 * Set resolver retry parameters. 5077 */ 5078 obj = NULL; 5079 CHECK(named_config_get(maps, "resolver-retry-interval", &obj)); 5080 resolver_param = cfg_obj_asuint32(obj); 5081 if (resolver_param > 0) { 5082 dns_resolver_setretryinterval(view->resolver, resolver_param); 5083 } 5084 5085 obj = NULL; 5086 CHECK(named_config_get(maps, "resolver-nonbackoff-tries", &obj)); 5087 resolver_param = cfg_obj_asuint32(obj); 5088 if (resolver_param > 0) { 5089 dns_resolver_setnonbackofftries(view->resolver, resolver_param); 5090 } 5091 5092 /* 5093 * Set supported DNSSEC algorithms. 5094 */ 5095 dns_resolver_reset_algorithms(view->resolver); 5096 disabled = NULL; 5097 (void)named_config_get(maps, "disable-algorithms", &disabled); 5098 if (disabled != NULL) { 5099 for (element = cfg_list_first(disabled); element != NULL; 5100 element = cfg_list_next(element)) 5101 { 5102 CHECK(disable_algorithms(cfg_listelt_value(element), 5103 view->resolver)); 5104 } 5105 } 5106 5107 /* 5108 * Set supported DS digest types. 5109 */ 5110 dns_resolver_reset_ds_digests(view->resolver); 5111 disabled = NULL; 5112 (void)named_config_get(maps, "disable-ds-digests", &disabled); 5113 if (disabled != NULL) { 5114 for (element = cfg_list_first(disabled); element != NULL; 5115 element = cfg_list_next(element)) 5116 { 5117 CHECK(disable_ds_digests(cfg_listelt_value(element), 5118 view->resolver)); 5119 } 5120 } 5121 5122 /* 5123 * A global or view "forwarders" option, if present, 5124 * creates an entry for "." in the forwarding table. 5125 */ 5126 forwardtype = NULL; 5127 forwarders = NULL; 5128 (void)named_config_get(maps, "forward", &forwardtype); 5129 (void)named_config_get(maps, "forwarders", &forwarders); 5130 if (forwarders != NULL) { 5131 CHECK(configure_forward(config, view, dns_rootname, forwarders, 5132 forwardtype)); 5133 } 5134 5135 /* 5136 * Dual Stack Servers. 5137 */ 5138 alternates = NULL; 5139 (void)named_config_get(maps, "dual-stack-servers", &alternates); 5140 if (alternates != NULL) { 5141 CHECK(configure_alternates(config, view, alternates)); 5142 } 5143 5144 /* 5145 * We have default hints for class IN if we need them. 5146 */ 5147 if (view->rdclass == dns_rdataclass_in && view->hints == NULL) { 5148 dns_view_sethints(view, named_g_server->in_roothints); 5149 } 5150 5151 /* 5152 * If we still have no hints, this is a non-IN view with no 5153 * "hints zone" configured. Issue a warning, except if this 5154 * is a root server. Root servers never need to consult 5155 * their hints, so it's no point requiring users to configure 5156 * them. 5157 */ 5158 if (view->hints == NULL) { 5159 dns_zone_t *rootzone = NULL; 5160 (void)dns_view_findzone(view, dns_rootname, &rootzone); 5161 if (rootzone != NULL) { 5162 dns_zone_detach(&rootzone); 5163 need_hints = false; 5164 } 5165 if (need_hints) { 5166 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 5167 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 5168 "no root hints for view '%s'", 5169 view->name); 5170 } 5171 } 5172 5173 /* 5174 * Configure the view's transports (DoT/DoH) 5175 */ 5176 CHECK(named_transports_fromconfig(config, vconfig, view->mctx, 5177 &transports)); 5178 dns_view_settransports(view, transports); 5179 dns_transport_list_detach(&transports); 5180 5181 /* 5182 * Configure the view's TSIG keys. 5183 */ 5184 CHECK(named_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); 5185 if (named_g_server->sessionkey != NULL) { 5186 dns_tsigkey_t *tsigkey = NULL; 5187 result = dns_tsigkey_createfromkey( 5188 named_g_server->session_keyname, 5189 algorithm_name(named_g_server->session_keyalg), 5190 named_g_server->sessionkey, false, NULL, 0, 0, mctx, 5191 NULL, &tsigkey); 5192 if (result == ISC_R_SUCCESS) { 5193 result = dns_tsigkeyring_add( 5194 ring, named_g_server->session_keyname, tsigkey); 5195 dns_tsigkey_detach(&tsigkey); 5196 } 5197 CHECK(result); 5198 } 5199 dns_view_setkeyring(view, ring); 5200 dns_tsigkeyring_detach(&ring); 5201 5202 /* 5203 * See if we can re-use a dynamic key ring. 5204 */ 5205 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 5206 view->rdclass, &pview); 5207 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 5208 goto cleanup; 5209 } 5210 if (pview != NULL) { 5211 dns_view_getdynamickeyring(pview, &ring); 5212 if (ring != NULL) { 5213 dns_view_setdynamickeyring(view, ring); 5214 } 5215 dns_tsigkeyring_detach(&ring); 5216 dns_view_detach(&pview); 5217 } else { 5218 dns_view_restorekeyring(view); 5219 } 5220 5221 /* 5222 * Configure the view's peer list. 5223 */ 5224 { 5225 const cfg_obj_t *peers = NULL; 5226 dns_peerlist_t *newpeers = NULL; 5227 5228 (void)named_config_get(cfgmaps, "server", &peers); 5229 CHECK(dns_peerlist_new(mctx, &newpeers)); 5230 for (element = cfg_list_first(peers); element != NULL; 5231 element = cfg_list_next(element)) 5232 { 5233 const cfg_obj_t *cpeer = cfg_listelt_value(element); 5234 dns_peer_t *peer; 5235 5236 CHECK(configure_peer(cpeer, mctx, &peer)); 5237 dns_peerlist_addpeer(newpeers, peer); 5238 dns_peer_detach(&peer); 5239 } 5240 dns_peerlist_detach(&view->peers); 5241 view->peers = newpeers; /* Transfer ownership. */ 5242 } 5243 5244 /* 5245 * Configure the views rrset-order. 5246 */ 5247 { 5248 const cfg_obj_t *rrsetorder = NULL; 5249 5250 (void)named_config_get(maps, "rrset-order", &rrsetorder); 5251 CHECK(dns_order_create(mctx, &order)); 5252 for (element = cfg_list_first(rrsetorder); element != NULL; 5253 element = cfg_list_next(element)) 5254 { 5255 const cfg_obj_t *ent = cfg_listelt_value(element); 5256 5257 CHECK(configure_order(order, ent)); 5258 } 5259 if (view->order != NULL) { 5260 dns_order_detach(&view->order); 5261 } 5262 dns_order_attach(order, &view->order); 5263 dns_order_detach(&order); 5264 } 5265 /* 5266 * Copy the aclenv object. 5267 */ 5268 dns_aclenv_copy(view->aclenv, ns_interfacemgr_getaclenv( 5269 named_g_server->interfacemgr)); 5270 5271 /* 5272 * Configure the "match-clients" and "match-destinations" ACL. 5273 * (These are only meaningful at the view level, but 'config' 5274 * must be passed so that named ACLs defined at the global level 5275 * can be retrieved.) 5276 */ 5277 CHECK(configure_view_acl(vconfig, config, NULL, "match-clients", NULL, 5278 actx, named_g_mctx, &view->matchclients)); 5279 CHECK(configure_view_acl(vconfig, config, NULL, "match-destinations", 5280 NULL, actx, named_g_mctx, 5281 &view->matchdestinations)); 5282 5283 /* 5284 * Configure the "match-recursive-only" option. 5285 */ 5286 obj = NULL; 5287 (void)named_config_get(maps, "match-recursive-only", &obj); 5288 if (obj != NULL && cfg_obj_asboolean(obj)) { 5289 view->matchrecursiveonly = true; 5290 } else { 5291 view->matchrecursiveonly = false; 5292 } 5293 5294 /* 5295 * Configure other configurable data. 5296 */ 5297 obj = NULL; 5298 result = named_config_get(maps, "recursion", &obj); 5299 INSIST(result == ISC_R_SUCCESS); 5300 view->recursion = cfg_obj_asboolean(obj); 5301 5302 obj = NULL; 5303 result = named_config_get(maps, "qname-minimization", &obj); 5304 INSIST(result == ISC_R_SUCCESS); 5305 qminmode = cfg_obj_asstring(obj); 5306 INSIST(qminmode != NULL); 5307 if (!strcmp(qminmode, "strict")) { 5308 view->qminimization = true; 5309 view->qmin_strict = true; 5310 } else if (!strcmp(qminmode, "relaxed")) { 5311 view->qminimization = true; 5312 view->qmin_strict = false; 5313 } else { /* "disabled" or "off" */ 5314 view->qminimization = false; 5315 view->qmin_strict = false; 5316 } 5317 5318 obj = NULL; 5319 result = named_config_get(maps, "auth-nxdomain", &obj); 5320 INSIST(result == ISC_R_SUCCESS); 5321 view->auth_nxdomain = cfg_obj_asboolean(obj); 5322 5323 /* deprecated */ 5324 obj = NULL; 5325 result = named_config_get(maps, "glue-cache", &obj); 5326 INSIST(result == ISC_R_SUCCESS); 5327 view->use_glue_cache = cfg_obj_asboolean(obj); 5328 5329 obj = NULL; 5330 result = named_config_get(maps, "minimal-any", &obj); 5331 INSIST(result == ISC_R_SUCCESS); 5332 view->minimal_any = cfg_obj_asboolean(obj); 5333 5334 obj = NULL; 5335 result = named_config_get(maps, "minimal-responses", &obj); 5336 INSIST(result == ISC_R_SUCCESS); 5337 if (cfg_obj_isboolean(obj)) { 5338 if (cfg_obj_asboolean(obj)) { 5339 view->minimalresponses = dns_minimal_yes; 5340 } else { 5341 view->minimalresponses = dns_minimal_no; 5342 } 5343 } else { 5344 str = cfg_obj_asstring(obj); 5345 if (strcasecmp(str, "no-auth") == 0) { 5346 view->minimalresponses = dns_minimal_noauth; 5347 } else if (strcasecmp(str, "no-auth-recursive") == 0) { 5348 view->minimalresponses = dns_minimal_noauthrec; 5349 } else { 5350 UNREACHABLE(); 5351 } 5352 } 5353 5354 obj = NULL; 5355 result = named_config_get(maps, "transfer-format", &obj); 5356 INSIST(result == ISC_R_SUCCESS); 5357 str = cfg_obj_asstring(obj); 5358 if (strcasecmp(str, "many-answers") == 0) { 5359 view->transfer_format = dns_many_answers; 5360 } else if (strcasecmp(str, "one-answer") == 0) { 5361 view->transfer_format = dns_one_answer; 5362 } else { 5363 UNREACHABLE(); 5364 } 5365 5366 obj = NULL; 5367 result = named_config_get(maps, "trust-anchor-telemetry", &obj); 5368 INSIST(result == ISC_R_SUCCESS); 5369 view->trust_anchor_telemetry = cfg_obj_asboolean(obj); 5370 5371 obj = NULL; 5372 result = named_config_get(maps, "root-key-sentinel", &obj); 5373 INSIST(result == ISC_R_SUCCESS); 5374 view->root_key_sentinel = cfg_obj_asboolean(obj); 5375 5376 /* 5377 * Set the "allow-query", "allow-query-cache", "allow-recursion", 5378 * "allow-recursion-on" and "allow-query-cache-on" ACLs if 5379 * configured in named.conf, but NOT from the global defaults. 5380 * This is done by leaving the third argument to configure_view_acl() 5381 * NULL. 5382 * 5383 * We ignore the global defaults here because these ACLs 5384 * can inherit from each other. If any are still unset after 5385 * applying the inheritance rules, we'll look up the defaults at 5386 * that time. 5387 */ 5388 5389 /* named.conf only */ 5390 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query", NULL, 5391 actx, named_g_mctx, &view->queryacl)); 5392 5393 /* named.conf only */ 5394 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache", 5395 NULL, actx, named_g_mctx, &view->cacheacl)); 5396 /* named.conf only */ 5397 CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on", 5398 NULL, actx, named_g_mctx, &view->cacheonacl)); 5399 5400 if (strcmp(view->name, "_bind") != 0 && 5401 view->rdclass != dns_rdataclass_chaos) 5402 { 5403 /* named.conf only */ 5404 CHECK(configure_view_acl(vconfig, config, NULL, 5405 "allow-recursion", NULL, actx, 5406 named_g_mctx, &view->recursionacl)); 5407 /* named.conf only */ 5408 CHECK(configure_view_acl(vconfig, config, NULL, 5409 "allow-recursion-on", NULL, actx, 5410 named_g_mctx, &view->recursiononacl)); 5411 } 5412 5413 if (view->recursion) { 5414 /* 5415 * "allow-query-cache" inherits from "allow-recursion" if set, 5416 * otherwise from "allow-query" if set. 5417 */ 5418 if (view->cacheacl == NULL) { 5419 if (view->recursionacl != NULL) { 5420 dns_acl_attach(view->recursionacl, 5421 &view->cacheacl); 5422 } else if (view->queryacl != NULL) { 5423 dns_acl_attach(view->queryacl, &view->cacheacl); 5424 } 5425 } 5426 5427 /* 5428 * "allow-recursion" inherits from "allow-query-cache" if set, 5429 * otherwise from "allow-query" if set. 5430 */ 5431 if (view->recursionacl == NULL) { 5432 if (view->cacheacl != NULL) { 5433 dns_acl_attach(view->cacheacl, 5434 &view->recursionacl); 5435 } else if (view->queryacl != NULL) { 5436 dns_acl_attach(view->queryacl, 5437 &view->recursionacl); 5438 } 5439 } 5440 5441 /* 5442 * "allow-query-cache-on" inherits from "allow-recursion-on" 5443 * if set. 5444 */ 5445 if (view->cacheonacl == NULL) { 5446 if (view->recursiononacl != NULL) { 5447 dns_acl_attach(view->recursiononacl, 5448 &view->cacheonacl); 5449 } 5450 } 5451 5452 /* 5453 * "allow-recursion-on" inherits from "allow-query-cache-on" 5454 * if set. 5455 */ 5456 if (view->recursiononacl == NULL) { 5457 if (view->cacheonacl != NULL) { 5458 dns_acl_attach(view->cacheonacl, 5459 &view->recursiononacl); 5460 } 5461 } 5462 5463 /* 5464 * If any are still unset at this point, we now get default 5465 * values for from the global config. 5466 */ 5467 5468 if (view->recursionacl == NULL) { 5469 /* global default only */ 5470 CHECK(configure_view_acl( 5471 NULL, NULL, named_g_config, "allow-recursion", 5472 NULL, actx, named_g_mctx, &view->recursionacl)); 5473 } 5474 if (view->recursiononacl == NULL) { 5475 /* global default only */ 5476 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5477 "allow-recursion-on", NULL, 5478 actx, named_g_mctx, 5479 &view->recursiononacl)); 5480 } 5481 if (view->cacheacl == NULL) { 5482 /* global default only */ 5483 CHECK(configure_view_acl( 5484 NULL, NULL, named_g_config, "allow-query-cache", 5485 NULL, actx, named_g_mctx, &view->cacheacl)); 5486 } 5487 if (view->cacheonacl == NULL) { 5488 /* global default only */ 5489 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5490 "allow-query-cache-on", NULL, 5491 actx, named_g_mctx, 5492 &view->cacheonacl)); 5493 } 5494 } else { 5495 /* 5496 * We're not recursive; if the query-cache ACLs haven't 5497 * been set at the options/view level, set them to none. 5498 */ 5499 if (view->cacheacl == NULL) { 5500 CHECK(dns_acl_none(mctx, &view->cacheacl)); 5501 } 5502 if (view->cacheonacl == NULL) { 5503 CHECK(dns_acl_none(mctx, &view->cacheonacl)); 5504 } 5505 } 5506 5507 /* 5508 * Finished setting recursion and query-cache ACLs, so now we 5509 * can get the allow-query default if it wasn't set in named.conf 5510 */ 5511 if (view->queryacl == NULL) { 5512 /* global default only */ 5513 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5514 "allow-query", NULL, actx, 5515 named_g_mctx, &view->queryacl)); 5516 } 5517 5518 /* 5519 * Ignore case when compressing responses to the specified 5520 * clients. This causes case not always to be preserved, 5521 * and is needed by some broken clients. 5522 */ 5523 CHECK(configure_view_acl(vconfig, config, named_g_config, 5524 "no-case-compress", NULL, actx, named_g_mctx, 5525 &view->nocasecompress)); 5526 5527 /* 5528 * Disable name compression completely, this is a tradeoff 5529 * between CPU and network usage. 5530 */ 5531 obj = NULL; 5532 result = named_config_get(maps, "message-compression", &obj); 5533 INSIST(result == ISC_R_SUCCESS); 5534 view->msgcompression = cfg_obj_asboolean(obj); 5535 5536 /* 5537 * Filter setting on addresses in the answer section. 5538 */ 5539 CHECK(configure_view_acl(vconfig, config, named_g_config, 5540 "deny-answer-addresses", "acl", actx, 5541 named_g_mctx, &view->denyansweracl)); 5542 CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", 5543 "except-from", named_g_mctx, 5544 &view->answeracl_exclude)); 5545 5546 /* 5547 * Filter setting on names (CNAME/DNAME targets) in the answer section. 5548 */ 5549 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 5550 "name", named_g_mctx, 5551 &view->denyanswernames)); 5552 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", 5553 "except-from", named_g_mctx, 5554 &view->answernames_exclude)); 5555 5556 /* 5557 * Configure sortlist, if set 5558 */ 5559 CHECK(configure_view_sortlist(vconfig, config, actx, named_g_mctx, 5560 &view->sortlist)); 5561 5562 /* 5563 * Configure default allow-update and allow-update-forwarding ACLs, 5564 * so they can be inherited by zones. (XXX: These are not 5565 * read from the options/view level here. However, they may be 5566 * read from there in zoneconf.c:configure_zone_acl() later.) 5567 */ 5568 if (view->updateacl == NULL) { 5569 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5570 "allow-update", NULL, actx, 5571 named_g_mctx, &view->updateacl)); 5572 } 5573 if (view->upfwdacl == NULL) { 5574 CHECK(configure_view_acl(NULL, NULL, named_g_config, 5575 "allow-update-forwarding", NULL, actx, 5576 named_g_mctx, &view->upfwdacl)); 5577 } 5578 5579 /* 5580 * Configure default allow-transfer and allow-notify ACLs so they 5581 * can be inherited by zones. 5582 */ 5583 if (view->transferacl == NULL) { 5584 CHECK(configure_view_acl(vconfig, config, named_g_config, 5585 "allow-transfer", NULL, actx, 5586 named_g_mctx, &view->transferacl)); 5587 } 5588 if (view->notifyacl == NULL) { 5589 CHECK(configure_view_acl(vconfig, config, named_g_config, 5590 "allow-notify", NULL, actx, 5591 named_g_mctx, &view->notifyacl)); 5592 } 5593 5594 obj = NULL; 5595 result = named_config_get(maps, "provide-ixfr", &obj); 5596 INSIST(result == ISC_R_SUCCESS); 5597 view->provideixfr = cfg_obj_asboolean(obj); 5598 5599 obj = NULL; 5600 result = named_config_get(maps, "request-nsid", &obj); 5601 INSIST(result == ISC_R_SUCCESS); 5602 view->requestnsid = cfg_obj_asboolean(obj); 5603 5604 obj = NULL; 5605 result = named_config_get(maps, "send-cookie", &obj); 5606 INSIST(result == ISC_R_SUCCESS); 5607 view->sendcookie = cfg_obj_asboolean(obj); 5608 5609 obj = NULL; 5610 if (view->pad_acl != NULL) { 5611 dns_acl_detach(&view->pad_acl); 5612 } 5613 result = named_config_get(optionmaps, "response-padding", &obj); 5614 if (result == ISC_R_SUCCESS) { 5615 const cfg_obj_t *padobj = cfg_tuple_get(obj, "block-size"); 5616 const cfg_obj_t *aclobj = cfg_tuple_get(obj, "acl"); 5617 uint32_t padding = cfg_obj_asuint32(padobj); 5618 5619 if (padding > 512U) { 5620 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 5621 "response-padding block-size cannot " 5622 "exceed 512: lowering"); 5623 padding = 512U; 5624 } 5625 view->padding = (uint16_t)padding; 5626 CHECK(cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, 5627 named_g_mctx, 0, &view->pad_acl)); 5628 } 5629 5630 obj = NULL; 5631 result = named_config_get(maps, "require-server-cookie", &obj); 5632 INSIST(result == ISC_R_SUCCESS); 5633 view->requireservercookie = cfg_obj_asboolean(obj); 5634 5635 obj = NULL; 5636 result = named_config_get(maps, "v6-bias", &obj); 5637 INSIST(result == ISC_R_SUCCESS); 5638 view->v6bias = cfg_obj_asuint32(obj) * 1000; 5639 5640 obj = NULL; 5641 result = named_config_get(maps, "max-clients-per-query", &obj); 5642 INSIST(result == ISC_R_SUCCESS); 5643 max_clients_per_query = cfg_obj_asuint32(obj); 5644 5645 obj = NULL; 5646 result = named_config_get(maps, "clients-per-query", &obj); 5647 INSIST(result == ISC_R_SUCCESS); 5648 dns_resolver_setclientsperquery(view->resolver, cfg_obj_asuint32(obj), 5649 max_clients_per_query); 5650 5651 /* 5652 * This is used for the cache and also as a default value 5653 * for zone databases. 5654 */ 5655 obj = NULL; 5656 result = named_config_get(maps, "max-records-per-type", &obj); 5657 INSIST(result == ISC_R_SUCCESS); 5658 dns_view_setmaxrrperset(view, cfg_obj_asuint32(obj)); 5659 5660 /* 5661 * This is used for the cache and also as a default value 5662 * for zone databases. 5663 */ 5664 obj = NULL; 5665 result = named_config_get(maps, "max-types-per-name", &obj); 5666 INSIST(result == ISC_R_SUCCESS); 5667 dns_view_setmaxtypepername(view, cfg_obj_asuint32(obj)); 5668 5669 obj = NULL; 5670 result = named_config_get(maps, "max-recursion-depth", &obj); 5671 INSIST(result == ISC_R_SUCCESS); 5672 dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); 5673 5674 obj = NULL; 5675 result = named_config_get(maps, "max-recursion-queries", &obj); 5676 INSIST(result == ISC_R_SUCCESS); 5677 dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); 5678 5679 obj = NULL; 5680 result = named_config_get(maps, "max-query-restarts", &obj); 5681 INSIST(result == ISC_R_SUCCESS); 5682 dns_view_setmaxrestarts(view, cfg_obj_asuint32(obj)); 5683 5684 obj = NULL; 5685 result = named_config_get(maps, "fetches-per-zone", &obj); 5686 INSIST(result == ISC_R_SUCCESS); 5687 obj2 = cfg_tuple_get(obj, "fetches"); 5688 dns_resolver_setfetchesperzone(view->resolver, cfg_obj_asuint32(obj2)); 5689 obj2 = cfg_tuple_get(obj, "response"); 5690 if (!cfg_obj_isvoid(obj2)) { 5691 const char *resp = cfg_obj_asstring(obj2); 5692 isc_result_t r = DNS_R_SERVFAIL; 5693 5694 if (strcasecmp(resp, "drop") == 0) { 5695 r = DNS_R_DROP; 5696 } else if (strcasecmp(resp, "fail") == 0) { 5697 r = DNS_R_SERVFAIL; 5698 } else { 5699 UNREACHABLE(); 5700 } 5701 5702 dns_resolver_setquotaresponse(view->resolver, 5703 dns_quotatype_zone, r); 5704 } 5705 5706 obj = NULL; 5707 result = named_config_get(maps, "prefetch", &obj); 5708 INSIST(result == ISC_R_SUCCESS); 5709 prefetch_trigger = cfg_tuple_get(obj, "trigger"); 5710 view->prefetch_trigger = cfg_obj_asuint32(prefetch_trigger); 5711 if (view->prefetch_trigger > 10) { 5712 view->prefetch_trigger = 10; 5713 } 5714 prefetch_eligible = cfg_tuple_get(obj, "eligible"); 5715 if (cfg_obj_isvoid(prefetch_eligible)) { 5716 int m; 5717 for (m = 1; maps[m] != NULL; m++) { 5718 obj = NULL; 5719 result = named_config_get(&maps[m], "prefetch", &obj); 5720 INSIST(result == ISC_R_SUCCESS); 5721 prefetch_eligible = cfg_tuple_get(obj, "eligible"); 5722 if (cfg_obj_isuint32(prefetch_eligible)) { 5723 break; 5724 } 5725 } 5726 INSIST(cfg_obj_isuint32(prefetch_eligible)); 5727 } 5728 view->prefetch_eligible = cfg_obj_asuint32(prefetch_eligible); 5729 if (view->prefetch_eligible < view->prefetch_trigger + 6) { 5730 view->prefetch_eligible = view->prefetch_trigger + 6; 5731 } 5732 5733 /* 5734 * For now, there is only one kind of trusted keys, the 5735 * "security roots". 5736 */ 5737 CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, 5738 auto_root, mctx)); 5739 dns_resolver_resetmustbesecure(view->resolver); 5740 obj = NULL; 5741 result = named_config_get(maps, "dnssec-must-be-secure", &obj); 5742 if (result == ISC_R_SUCCESS) { 5743 CHECK(mustbesecure(obj, view->resolver)); 5744 } 5745 5746 obj = NULL; 5747 result = named_config_get(maps, "nta-recheck", &obj); 5748 INSIST(result == ISC_R_SUCCESS); 5749 view->nta_recheck = cfg_obj_asduration(obj); 5750 5751 obj = NULL; 5752 result = named_config_get(maps, "nta-lifetime", &obj); 5753 INSIST(result == ISC_R_SUCCESS); 5754 view->nta_lifetime = cfg_obj_asduration(obj); 5755 5756 obj = NULL; 5757 result = named_config_get(maps, "preferred-glue", &obj); 5758 if (result == ISC_R_SUCCESS) { 5759 str = cfg_obj_asstring(obj); 5760 if (strcasecmp(str, "a") == 0) { 5761 view->preferred_glue = dns_rdatatype_a; 5762 } else if (strcasecmp(str, "aaaa") == 0) { 5763 view->preferred_glue = dns_rdatatype_aaaa; 5764 } else { 5765 view->preferred_glue = 0; 5766 } 5767 } else { 5768 view->preferred_glue = 0; 5769 } 5770 5771 obj = NULL; 5772 result = named_config_get(maps, "root-delegation-only", &obj); 5773 if (result == ISC_R_SUCCESS) { 5774 dns_view_setrootdelonly(view, true); 5775 } 5776 if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 5777 const cfg_obj_t *exclude; 5778 dns_fixedname_t fixed; 5779 dns_name_t *name; 5780 5781 name = dns_fixedname_initname(&fixed); 5782 for (element = cfg_list_first(obj); element != NULL; 5783 element = cfg_list_next(element)) 5784 { 5785 exclude = cfg_listelt_value(element); 5786 CHECK(dns_name_fromstring( 5787 name, cfg_obj_asstring(exclude), 0, NULL)); 5788 dns_view_excludedelegationonly(view, name); 5789 } 5790 } else { 5791 dns_view_setrootdelonly(view, false); 5792 } 5793 5794 /* 5795 * Load DynDB modules. 5796 */ 5797 dyndb_list = NULL; 5798 if (voptions != NULL) { 5799 (void)cfg_map_get(voptions, "dyndb", &dyndb_list); 5800 } else { 5801 (void)cfg_map_get(config, "dyndb", &dyndb_list); 5802 } 5803 5804 for (element = cfg_list_first(dyndb_list); element != NULL; 5805 element = cfg_list_next(element)) 5806 { 5807 const cfg_obj_t *dyndb = cfg_listelt_value(element); 5808 5809 if (dctx == NULL) { 5810 const void *hashinit = isc_hash_get_initializer(); 5811 CHECK(dns_dyndb_createctx(mctx, hashinit, named_g_lctx, 5812 view, named_g_server->zonemgr, 5813 named_g_server->task, 5814 named_g_timermgr, &dctx)); 5815 } 5816 5817 CHECK(configure_dyndb(dyndb, mctx, dctx)); 5818 } 5819 5820 /* 5821 * Load plugins. 5822 */ 5823 plugin_list = NULL; 5824 if (voptions != NULL) { 5825 (void)cfg_map_get(voptions, "plugin", &plugin_list); 5826 } else { 5827 (void)cfg_map_get(config, "plugin", &plugin_list); 5828 } 5829 5830 if (plugin_list != NULL) { 5831 INSIST(view->hooktable == NULL); 5832 CHECK(ns_hooktable_create(view->mctx, 5833 (ns_hooktable_t **)&view->hooktable)); 5834 view->hooktable_free = ns_hooktable_free; 5835 5836 ns_plugins_create(view->mctx, (ns_plugins_t **)&view->plugins); 5837 view->plugins_free = ns_plugins_free; 5838 5839 CHECK(cfg_pluginlist_foreach(config, plugin_list, named_g_lctx, 5840 register_one_plugin, view)); 5841 } 5842 5843 /* 5844 * Setup automatic empty zones. If recursion is off then 5845 * they are disabled by default. 5846 */ 5847 obj = NULL; 5848 (void)named_config_get(maps, "empty-zones-enable", &obj); 5849 (void)named_config_get(maps, "disable-empty-zone", &disablelist); 5850 if (obj == NULL && disablelist == NULL && 5851 view->rdclass == dns_rdataclass_in) 5852 { 5853 empty_zones_enable = view->recursion; 5854 } else if (view->rdclass == dns_rdataclass_in) { 5855 if (obj != NULL) { 5856 empty_zones_enable = cfg_obj_asboolean(obj); 5857 } else { 5858 empty_zones_enable = view->recursion; 5859 } 5860 } else { 5861 empty_zones_enable = false; 5862 } 5863 5864 if (empty_zones_enable) { 5865 const char *empty; 5866 int empty_zone = 0; 5867 dns_fixedname_t fixed; 5868 dns_name_t *name; 5869 isc_buffer_t buffer; 5870 char server[DNS_NAME_FORMATSIZE + 1]; 5871 char contact[DNS_NAME_FORMATSIZE + 1]; 5872 const char *empty_dbtype[4] = { "_builtin", "empty", NULL, 5873 NULL }; 5874 int empty_dbtypec = 4; 5875 dns_zonestat_level_t statlevel = dns_zonestat_none; 5876 5877 name = dns_fixedname_initname(&fixed); 5878 5879 obj = NULL; 5880 result = named_config_get(maps, "empty-server", &obj); 5881 if (result == ISC_R_SUCCESS) { 5882 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 5883 0, NULL)); 5884 isc_buffer_init(&buffer, server, sizeof(server) - 1); 5885 CHECK(dns_name_totext(name, false, &buffer)); 5886 server[isc_buffer_usedlength(&buffer)] = 0; 5887 empty_dbtype[2] = server; 5888 } else { 5889 empty_dbtype[2] = "@"; 5890 } 5891 5892 obj = NULL; 5893 result = named_config_get(maps, "empty-contact", &obj); 5894 if (result == ISC_R_SUCCESS) { 5895 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 5896 0, NULL)); 5897 isc_buffer_init(&buffer, contact, sizeof(contact) - 1); 5898 CHECK(dns_name_totext(name, false, &buffer)); 5899 contact[isc_buffer_usedlength(&buffer)] = 0; 5900 empty_dbtype[3] = contact; 5901 } else { 5902 empty_dbtype[3] = "."; 5903 } 5904 5905 obj = NULL; 5906 result = named_config_get(maps, "zone-statistics", &obj); 5907 INSIST(result == ISC_R_SUCCESS); 5908 if (cfg_obj_isboolean(obj)) { 5909 if (cfg_obj_asboolean(obj)) { 5910 statlevel = dns_zonestat_full; 5911 } else { 5912 statlevel = dns_zonestat_none; 5913 } 5914 } else { 5915 const char *levelstr = cfg_obj_asstring(obj); 5916 if (strcasecmp(levelstr, "full") == 0) { 5917 statlevel = dns_zonestat_full; 5918 } else if (strcasecmp(levelstr, "terse") == 0) { 5919 statlevel = dns_zonestat_terse; 5920 } else if (strcasecmp(levelstr, "none") == 0) { 5921 statlevel = dns_zonestat_none; 5922 } else { 5923 UNREACHABLE(); 5924 } 5925 } 5926 5927 for (empty = empty_zones[empty_zone]; empty != NULL; 5928 empty = empty_zones[++empty_zone]) 5929 { 5930 dns_forwarders_t *dnsforwarders = NULL; 5931 5932 /* 5933 * Look for zone on drop list. 5934 */ 5935 CHECK(dns_name_fromstring(name, empty, 0, NULL)); 5936 if (disablelist != NULL && 5937 on_disable_list(disablelist, name)) 5938 { 5939 continue; 5940 } 5941 5942 /* 5943 * This zone already exists. 5944 */ 5945 (void)dns_view_findzone(view, name, &zone); 5946 if (zone != NULL) { 5947 dns_zone_detach(&zone); 5948 continue; 5949 } 5950 5951 /* 5952 * If we would forward this name don't add a 5953 * empty zone for it. 5954 */ 5955 result = dns_fwdtable_find(view->fwdtable, name, NULL, 5956 &dnsforwarders); 5957 if ((result == ISC_R_SUCCESS || 5958 result == DNS_R_PARTIALMATCH) && 5959 dnsforwarders->fwdpolicy == dns_fwdpolicy_only) 5960 { 5961 continue; 5962 } 5963 5964 /* 5965 * See if we can re-use a existing zone. 5966 */ 5967 result = dns_viewlist_find(&named_g_server->viewlist, 5968 view->name, view->rdclass, 5969 &pview); 5970 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 5971 { 5972 goto cleanup; 5973 } 5974 5975 if (pview != NULL) { 5976 (void)dns_view_findzone(pview, name, &zone); 5977 dns_view_detach(&pview); 5978 } 5979 5980 CHECK(create_empty_zone(zone, name, view, zonelist, 5981 empty_dbtype, empty_dbtypec, 5982 statlevel)); 5983 if (zone != NULL) { 5984 dns_zone_detach(&zone); 5985 } 5986 } 5987 } 5988 5989 obj = NULL; 5990 if (view->rdclass == dns_rdataclass_in) { 5991 (void)named_config_get(maps, "ipv4only-enable", &obj); 5992 } 5993 if (view->rdclass == dns_rdataclass_in && (obj != NULL) 5994 ? cfg_obj_asboolean(obj) 5995 : !ISC_LIST_EMPTY(view->dns64)) 5996 { 5997 const char *server, *contact; 5998 dns_fixedname_t fixed; 5999 dns_name_t *name; 6000 struct { 6001 const char *name; 6002 const char *type; 6003 } zones[] = { 6004 { "ipv4only.arpa", "ipv4only" }, 6005 { "170.0.0.192.in-addr.arpa", "ipv4reverse" }, 6006 { "171.0.0.192.in-addr.arpa", "ipv4reverse" }, 6007 }; 6008 size_t ipv4only_zone; 6009 6010 obj = NULL; 6011 result = named_config_get(maps, "ipv4only-server", &obj); 6012 if (result == ISC_R_SUCCESS) { 6013 server = cfg_obj_asstring(obj); 6014 } else { 6015 server = NULL; 6016 } 6017 6018 obj = NULL; 6019 result = named_config_get(maps, "ipv4only-contact", &obj); 6020 if (result == ISC_R_SUCCESS) { 6021 contact = cfg_obj_asstring(obj); 6022 } else { 6023 contact = NULL; 6024 } 6025 6026 name = dns_fixedname_initname(&fixed); 6027 for (ipv4only_zone = 0; ipv4only_zone < ARRAY_SIZE(zones); 6028 ipv4only_zone++) 6029 { 6030 dns_forwarders_t *dnsforwarders = NULL; 6031 6032 CHECK(dns_name_fromstring( 6033 name, zones[ipv4only_zone].name, 0, NULL)); 6034 6035 (void)dns_view_findzone(view, name, &zone); 6036 if (zone != NULL) { 6037 dns_zone_detach(&zone); 6038 continue; 6039 } 6040 6041 /* 6042 * If we would forward this name don't add it. 6043 */ 6044 result = dns_fwdtable_find(view->fwdtable, name, NULL, 6045 &dnsforwarders); 6046 if ((result == ISC_R_SUCCESS || 6047 result == DNS_R_PARTIALMATCH) && 6048 dnsforwarders->fwdpolicy == dns_fwdpolicy_only) 6049 { 6050 continue; 6051 } 6052 6053 /* 6054 * See if we can re-use a existing zone. 6055 */ 6056 result = dns_viewlist_find(&named_g_server->viewlist, 6057 view->name, view->rdclass, 6058 &pview); 6059 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 6060 { 6061 goto cleanup; 6062 } 6063 6064 if (pview != NULL) { 6065 (void)dns_view_findzone(pview, name, &zone); 6066 dns_view_detach(&pview); 6067 } 6068 6069 CHECK(create_ipv4only_zone(zone, view, name, 6070 zones[ipv4only_zone].type, 6071 mctx, server, contact)); 6072 if (zone != NULL) { 6073 dns_zone_detach(&zone); 6074 } 6075 } 6076 } 6077 6078 obj = NULL; 6079 result = named_config_get(maps, "rate-limit", &obj); 6080 if (result == ISC_R_SUCCESS) { 6081 result = configure_rrl(view, config, obj); 6082 if (result != ISC_R_SUCCESS) { 6083 goto cleanup; 6084 } 6085 } 6086 6087 /* 6088 * Set the servfail-ttl. 6089 */ 6090 obj = NULL; 6091 result = named_config_get(maps, "servfail-ttl", &obj); 6092 INSIST(result == ISC_R_SUCCESS); 6093 fail_ttl = cfg_obj_asduration(obj); 6094 if (fail_ttl > 30) { 6095 fail_ttl = 30; 6096 } 6097 dns_view_setfailttl(view, fail_ttl); 6098 6099 /* 6100 * Name space to look up redirect information in. 6101 */ 6102 obj = NULL; 6103 result = named_config_get(maps, "nxdomain-redirect", &obj); 6104 if (result == ISC_R_SUCCESS) { 6105 dns_name_t *name = dns_fixedname_name(&view->redirectfixed); 6106 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 0, 6107 NULL)); 6108 view->redirectzone = name; 6109 } else { 6110 view->redirectzone = NULL; 6111 } 6112 6113 /* 6114 * Exceptions to DNSSEC validation. 6115 */ 6116 obj = NULL; 6117 result = named_config_get(maps, "validate-except", &obj); 6118 if (result == ISC_R_SUCCESS) { 6119 result = dns_view_getntatable(view, &ntatable); 6120 } 6121 if (result == ISC_R_SUCCESS) { 6122 for (element = cfg_list_first(obj); element != NULL; 6123 element = cfg_list_next(element)) 6124 { 6125 dns_fixedname_t fntaname; 6126 dns_name_t *ntaname; 6127 6128 ntaname = dns_fixedname_initname(&fntaname); 6129 obj = cfg_listelt_value(element); 6130 CHECK(dns_name_fromstring( 6131 ntaname, cfg_obj_asstring(obj), 0, NULL)); 6132 CHECK(dns_ntatable_add(ntatable, ntaname, true, 0, 6133 0xffffffffU)); 6134 } 6135 } 6136 6137 #ifdef HAVE_DNSTAP 6138 /* 6139 * Set up the dnstap environment and configure message 6140 * types to log. 6141 */ 6142 CHECK(configure_dnstap(maps, view)); 6143 #endif /* HAVE_DNSTAP */ 6144 6145 result = ISC_R_SUCCESS; 6146 6147 cleanup: 6148 /* 6149 * Revert to the old view if there was an error. 6150 */ 6151 if (result != ISC_R_SUCCESS) { 6152 isc_result_t result2; 6153 6154 result2 = dns_viewlist_find(&named_g_server->viewlist, 6155 view->name, view->rdclass, &pview); 6156 if (result2 == ISC_R_SUCCESS) { 6157 dns_view_thaw(pview); 6158 6159 obj = NULL; 6160 if (rpz_configured && 6161 pview->rdclass == dns_rdataclass_in && need_hints && 6162 named_config_get(maps, "response-policy", &obj) == 6163 ISC_R_SUCCESS) 6164 { 6165 /* 6166 * We are swapping the places of the `view` and 6167 * `pview` in the function's parameters list 6168 * because we are reverting the same operation 6169 * done previously in the "correct" order. 6170 */ 6171 result2 = configure_rpz(pview, view, maps, obj, 6172 &old_rpz_ok); 6173 if (result2 != ISC_R_SUCCESS) { 6174 isc_log_write(named_g_lctx, 6175 NAMED_LOGCATEGORY_GENERAL, 6176 NAMED_LOGMODULE_SERVER, 6177 ISC_LOG_ERROR, 6178 "rpz configuration " 6179 "revert failed for view " 6180 "'%s'", 6181 pview->name); 6182 } 6183 } 6184 6185 obj = NULL; 6186 if (catz_configured && 6187 pview->rdclass == dns_rdataclass_in && need_hints && 6188 named_config_get(maps, "catalog-zones", &obj) == 6189 ISC_R_SUCCESS) 6190 { 6191 /* 6192 * We are swapping the places of the `view` and 6193 * `pview` in the function's parameters list 6194 * because we are reverting the same operation 6195 * done previously in the "correct" order. 6196 */ 6197 result2 = configure_catz(pview, view, config, 6198 obj); 6199 if (result2 != ISC_R_SUCCESS) { 6200 isc_log_write(named_g_lctx, 6201 NAMED_LOGCATEGORY_GENERAL, 6202 NAMED_LOGMODULE_SERVER, 6203 ISC_LOG_ERROR, 6204 "catz configuration " 6205 "revert failed for view " 6206 "'%s'", 6207 pview->name); 6208 } 6209 } 6210 6211 dns_view_freeze(pview); 6212 } 6213 6214 if (pview != NULL) { 6215 dns_view_detach(&pview); 6216 } 6217 6218 if (zone_element_latest != NULL) { 6219 for (element = cfg_list_first(zonelist); 6220 element != NULL; element = cfg_list_next(element)) 6221 { 6222 const cfg_obj_t *zconfig = 6223 cfg_listelt_value(element); 6224 configure_zone_setviewcommit(result, zconfig, 6225 view); 6226 if (element == zone_element_latest) { 6227 /* 6228 * This was the latest element that was 6229 * successfully configured earlier. 6230 */ 6231 break; 6232 } 6233 } 6234 } 6235 } 6236 6237 if (ntatable != NULL) { 6238 dns_ntatable_detach(&ntatable); 6239 } 6240 if (clients != NULL) { 6241 dns_acl_detach(&clients); 6242 } 6243 if (mapped != NULL) { 6244 dns_acl_detach(&mapped); 6245 } 6246 if (excluded != NULL) { 6247 dns_acl_detach(&excluded); 6248 } 6249 if (ring != NULL) { 6250 dns_tsigkeyring_detach(&ring); 6251 } 6252 if (zone != NULL) { 6253 dns_zone_detach(&zone); 6254 } 6255 if (dispatch4 != NULL) { 6256 dns_dispatch_detach(&dispatch4); 6257 } 6258 if (dispatch6 != NULL) { 6259 dns_dispatch_detach(&dispatch6); 6260 } 6261 if (resstats != NULL) { 6262 isc_stats_detach(&resstats); 6263 } 6264 if (resquerystats != NULL) { 6265 dns_stats_detach(&resquerystats); 6266 } 6267 if (order != NULL) { 6268 dns_order_detach(&order); 6269 } 6270 if (cmctx != NULL) { 6271 isc_mem_detach(&cmctx); 6272 } 6273 if (hmctx != NULL) { 6274 isc_mem_detach(&hmctx); 6275 } 6276 if (cache != NULL) { 6277 dns_cache_detach(&cache); 6278 } 6279 if (dctx != NULL) { 6280 dns_dyndb_destroyctx(&dctx); 6281 } 6282 6283 return (result); 6284 } 6285 6286 static isc_result_t 6287 configure_hints(dns_view_t *view, const char *filename) { 6288 isc_result_t result; 6289 dns_db_t *db; 6290 6291 db = NULL; 6292 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); 6293 if (result == ISC_R_SUCCESS) { 6294 dns_view_sethints(view, db); 6295 dns_db_detach(&db); 6296 } 6297 6298 return (result); 6299 } 6300 6301 static isc_result_t 6302 configure_alternates(const cfg_obj_t *config, dns_view_t *view, 6303 const cfg_obj_t *alternates) { 6304 const cfg_obj_t *portobj; 6305 const cfg_obj_t *addresses; 6306 const cfg_listelt_t *element; 6307 isc_result_t result = ISC_R_SUCCESS; 6308 in_port_t port; 6309 6310 /* 6311 * Determine which port to send requests to. 6312 */ 6313 CHECKM(named_config_getport(config, "port", &port), "port"); 6314 6315 if (alternates != NULL) { 6316 portobj = cfg_tuple_get(alternates, "port"); 6317 if (cfg_obj_isuint32(portobj)) { 6318 uint32_t val = cfg_obj_asuint32(portobj); 6319 if (val > UINT16_MAX) { 6320 cfg_obj_log(portobj, named_g_lctx, 6321 ISC_LOG_ERROR, 6322 "port '%u' out of range", val); 6323 return (ISC_R_RANGE); 6324 } 6325 port = (in_port_t)val; 6326 } 6327 } 6328 6329 addresses = NULL; 6330 if (alternates != NULL) { 6331 addresses = cfg_tuple_get(alternates, "addresses"); 6332 } 6333 6334 for (element = cfg_list_first(addresses); element != NULL; 6335 element = cfg_list_next(element)) 6336 { 6337 const cfg_obj_t *alternate = cfg_listelt_value(element); 6338 isc_sockaddr_t sa; 6339 6340 if (!cfg_obj_issockaddr(alternate)) { 6341 dns_fixedname_t fixed; 6342 dns_name_t *name; 6343 const char *str = cfg_obj_asstring( 6344 cfg_tuple_get(alternate, "name")); 6345 isc_buffer_t buffer; 6346 in_port_t myport = port; 6347 6348 isc_buffer_constinit(&buffer, str, strlen(str)); 6349 isc_buffer_add(&buffer, strlen(str)); 6350 name = dns_fixedname_initname(&fixed); 6351 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, 6352 NULL)); 6353 6354 portobj = cfg_tuple_get(alternate, "port"); 6355 if (cfg_obj_isuint32(portobj)) { 6356 uint32_t val = cfg_obj_asuint32(portobj); 6357 if (val > UINT16_MAX) { 6358 cfg_obj_log(portobj, named_g_lctx, 6359 ISC_LOG_ERROR, 6360 "port '%u' out of range", 6361 val); 6362 return (ISC_R_RANGE); 6363 } 6364 myport = (in_port_t)val; 6365 } 6366 dns_resolver_addalternate(view->resolver, NULL, name, 6367 myport); 6368 continue; 6369 } 6370 6371 sa = *cfg_obj_assockaddr(alternate); 6372 if (isc_sockaddr_getport(&sa) == 0) { 6373 isc_sockaddr_setport(&sa, port); 6374 } 6375 dns_resolver_addalternate(view->resolver, &sa, NULL, 0); 6376 } 6377 6378 cleanup: 6379 return (result); 6380 } 6381 6382 static isc_result_t 6383 configure_forward(const cfg_obj_t *config, dns_view_t *view, 6384 const dns_name_t *origin, const cfg_obj_t *forwarders, 6385 const cfg_obj_t *forwardtype) { 6386 const cfg_obj_t *portobj = NULL; 6387 const cfg_obj_t *faddresses = NULL; 6388 const cfg_listelt_t *element = NULL; 6389 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 6390 dns_forwarderlist_t fwdlist; 6391 dns_forwarder_t *fwd = NULL; 6392 isc_result_t result; 6393 in_port_t port; 6394 6395 ISC_LIST_INIT(fwdlist); 6396 6397 /* 6398 * Determine which port to send forwarded requests to. 6399 */ 6400 CHECKM(named_config_getport(config, "port", &port), "port"); 6401 6402 if (forwarders != NULL) { 6403 portobj = cfg_tuple_get(forwarders, "port"); 6404 if (cfg_obj_isuint32(portobj)) { 6405 uint32_t val = cfg_obj_asuint32(portobj); 6406 if (val > UINT16_MAX) { 6407 cfg_obj_log(portobj, named_g_lctx, 6408 ISC_LOG_ERROR, 6409 "port '%u' out of range", val); 6410 return (ISC_R_RANGE); 6411 } 6412 port = (in_port_t)val; 6413 } 6414 } 6415 6416 faddresses = NULL; 6417 if (forwarders != NULL) { 6418 faddresses = cfg_tuple_get(forwarders, "addresses"); 6419 } 6420 6421 for (element = cfg_list_first(faddresses); element != NULL; 6422 element = cfg_list_next(element)) 6423 { 6424 const cfg_obj_t *forwarder = cfg_listelt_value(element); 6425 fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t)); 6426 fwd->addr = *cfg_obj_assockaddr(forwarder); 6427 if (isc_sockaddr_getport(&fwd->addr) == 0) { 6428 isc_sockaddr_setport(&fwd->addr, port); 6429 } 6430 ISC_LINK_INIT(fwd, link); 6431 ISC_LIST_APPEND(fwdlist, fwd, link); 6432 } 6433 6434 if (ISC_LIST_EMPTY(fwdlist)) { 6435 if (forwardtype != NULL) { 6436 cfg_obj_log(forwardtype, named_g_lctx, ISC_LOG_WARNING, 6437 "no forwarders seen; disabling " 6438 "forwarding"); 6439 } 6440 fwdpolicy = dns_fwdpolicy_none; 6441 } else { 6442 if (forwardtype == NULL) { 6443 fwdpolicy = dns_fwdpolicy_first; 6444 } else { 6445 const char *forwardstr = cfg_obj_asstring(forwardtype); 6446 if (strcasecmp(forwardstr, "first") == 0) { 6447 fwdpolicy = dns_fwdpolicy_first; 6448 } else if (strcasecmp(forwardstr, "only") == 0) { 6449 fwdpolicy = dns_fwdpolicy_only; 6450 } else { 6451 UNREACHABLE(); 6452 } 6453 } 6454 } 6455 6456 result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist, 6457 fwdpolicy); 6458 if (result != ISC_R_SUCCESS) { 6459 char namebuf[DNS_NAME_FORMATSIZE]; 6460 dns_name_format(origin, namebuf, sizeof(namebuf)); 6461 cfg_obj_log(forwarders, named_g_lctx, ISC_LOG_WARNING, 6462 "could not set up forwarding for domain '%s': %s", 6463 namebuf, isc_result_totext(result)); 6464 goto cleanup; 6465 } 6466 6467 if (fwdpolicy == dns_fwdpolicy_only) { 6468 dns_view_sfd_add(view, origin); 6469 } 6470 6471 result = ISC_R_SUCCESS; 6472 6473 cleanup: 6474 6475 while (!ISC_LIST_EMPTY(fwdlist)) { 6476 fwd = ISC_LIST_HEAD(fwdlist); 6477 ISC_LIST_UNLINK(fwdlist, fwd, link); 6478 isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t)); 6479 } 6480 6481 return (result); 6482 } 6483 6484 static isc_result_t 6485 get_viewinfo(const cfg_obj_t *vconfig, const char **namep, 6486 dns_rdataclass_t *classp) { 6487 isc_result_t result = ISC_R_SUCCESS; 6488 const char *viewname; 6489 dns_rdataclass_t viewclass; 6490 6491 REQUIRE(namep != NULL && *namep == NULL); 6492 REQUIRE(classp != NULL); 6493 6494 if (vconfig != NULL) { 6495 const cfg_obj_t *classobj = NULL; 6496 6497 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 6498 classobj = cfg_tuple_get(vconfig, "class"); 6499 CHECK(named_config_getclass(classobj, dns_rdataclass_in, 6500 &viewclass)); 6501 if (dns_rdataclass_ismeta(viewclass)) { 6502 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6503 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6504 "view '%s': class must not be meta", 6505 viewname); 6506 CHECK(ISC_R_FAILURE); 6507 } 6508 } else { 6509 viewname = "_default"; 6510 viewclass = dns_rdataclass_in; 6511 } 6512 6513 *namep = viewname; 6514 *classp = viewclass; 6515 6516 cleanup: 6517 return (result); 6518 } 6519 6520 /* 6521 * Find a view based on its configuration info and attach to it. 6522 * 6523 * If 'vconfig' is NULL, attach to the default view. 6524 */ 6525 static isc_result_t 6526 find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 6527 dns_view_t **viewp) { 6528 isc_result_t result; 6529 const char *viewname = NULL; 6530 dns_rdataclass_t viewclass; 6531 dns_view_t *view = NULL; 6532 6533 result = get_viewinfo(vconfig, &viewname, &viewclass); 6534 if (result != ISC_R_SUCCESS) { 6535 return (result); 6536 } 6537 6538 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 6539 if (result != ISC_R_SUCCESS) { 6540 return (result); 6541 } 6542 6543 *viewp = view; 6544 return (ISC_R_SUCCESS); 6545 } 6546 6547 /* 6548 * Create a new view and add it to the list. 6549 * 6550 * If 'vconfig' is NULL, create the default view. 6551 * 6552 * The view created is attached to '*viewp'. 6553 */ 6554 static isc_result_t 6555 create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 6556 dns_view_t **viewp) { 6557 isc_result_t result; 6558 const char *viewname = NULL; 6559 dns_rdataclass_t viewclass; 6560 dns_view_t *view = NULL; 6561 6562 result = get_viewinfo(vconfig, &viewname, &viewclass); 6563 if (result != ISC_R_SUCCESS) { 6564 return (result); 6565 } 6566 6567 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 6568 if (result == ISC_R_SUCCESS) { 6569 return (ISC_R_EXISTS); 6570 } 6571 if (result != ISC_R_NOTFOUND) { 6572 return (result); 6573 } 6574 INSIST(view == NULL); 6575 6576 result = dns_view_create(named_g_mctx, viewclass, viewname, &view); 6577 if (result != ISC_R_SUCCESS) { 6578 return (result); 6579 } 6580 6581 isc_nonce_buf(view->secret, sizeof(view->secret)); 6582 6583 ISC_LIST_APPEND(*viewlist, view, link); 6584 dns_view_attach(view, viewp); 6585 return (ISC_R_SUCCESS); 6586 } 6587 6588 /* 6589 * Configure or reconfigure a zone. 6590 */ 6591 static isc_result_t 6592 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 6593 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 6594 dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, 6595 cfg_aclconfctx_t *aclconf, bool added, bool old_rpz_ok, 6596 bool is_catz_member, bool modify) { 6597 dns_view_t *pview = NULL; /* Production view */ 6598 dns_zone_t *zone = NULL; /* New or reused zone */ 6599 dns_zone_t *raw = NULL; /* New or reused raw zone */ 6600 dns_zone_t *dupzone = NULL; 6601 const cfg_obj_t *options = NULL; 6602 const cfg_obj_t *zoptions = NULL; 6603 const cfg_obj_t *typeobj = NULL; 6604 const cfg_obj_t *forwarders = NULL; 6605 const cfg_obj_t *forwardtype = NULL; 6606 const cfg_obj_t *ixfrfromdiffs = NULL; 6607 const cfg_obj_t *only = NULL; 6608 const cfg_obj_t *viewobj = NULL; 6609 isc_result_t result = ISC_R_SUCCESS; 6610 isc_result_t tresult; 6611 isc_buffer_t buffer; 6612 dns_fixedname_t fixorigin; 6613 dns_name_t *origin; 6614 const char *zname; 6615 dns_rdataclass_t zclass; 6616 const char *ztypestr; 6617 dns_rpz_num_t rpz_num; 6618 bool zone_is_catz = false; 6619 bool zone_maybe_inline = false; 6620 bool inline_signing = false; 6621 bool fullsign = false; 6622 6623 options = NULL; 6624 (void)cfg_map_get(config, "options", &options); 6625 6626 zoptions = cfg_tuple_get(zconfig, "options"); 6627 6628 /* 6629 * Get the zone origin as a dns_name_t. 6630 */ 6631 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 6632 isc_buffer_constinit(&buffer, zname, strlen(zname)); 6633 isc_buffer_add(&buffer, strlen(zname)); 6634 dns_fixedname_init(&fixorigin); 6635 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, 6636 dns_rootname, 0, NULL)); 6637 origin = dns_fixedname_name(&fixorigin); 6638 6639 CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"), 6640 view->rdclass, &zclass)); 6641 if (zclass != view->rdclass) { 6642 const char *vname = NULL; 6643 if (vconfig != NULL) { 6644 vname = cfg_obj_asstring( 6645 cfg_tuple_get(vconfig, "name")); 6646 } else { 6647 vname = "<default view>"; 6648 } 6649 6650 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6651 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6652 "zone '%s': wrong class for view '%s'", zname, 6653 vname); 6654 result = ISC_R_FAILURE; 6655 goto cleanup; 6656 } 6657 6658 (void)cfg_map_get(zoptions, "in-view", &viewobj); 6659 if (viewobj != NULL) { 6660 const char *inview = cfg_obj_asstring(viewobj); 6661 dns_view_t *otherview = NULL; 6662 6663 if (viewlist == NULL) { 6664 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6665 "'in-view' option is not permitted in " 6666 "dynamically added zones"); 6667 result = ISC_R_FAILURE; 6668 goto cleanup; 6669 } 6670 6671 result = dns_viewlist_find(viewlist, inview, view->rdclass, 6672 &otherview); 6673 if (result != ISC_R_SUCCESS) { 6674 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6675 "view '%s' is not yet defined.", inview); 6676 result = ISC_R_FAILURE; 6677 goto cleanup; 6678 } 6679 6680 result = dns_view_findzone(otherview, origin, &zone); 6681 dns_view_detach(&otherview); 6682 if (result != ISC_R_SUCCESS) { 6683 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6684 "zone '%s' not defined in view '%s'", zname, 6685 inview); 6686 result = ISC_R_FAILURE; 6687 goto cleanup; 6688 } 6689 6690 CHECK(dns_view_addzone(view, zone)); 6691 dns_zone_detach(&zone); 6692 6693 /* 6694 * If the zone contains a 'forwarders' statement, configure 6695 * selective forwarding. Note: this is not inherited from the 6696 * other view. 6697 */ 6698 forwarders = NULL; 6699 result = cfg_map_get(zoptions, "forwarders", &forwarders); 6700 if (result == ISC_R_SUCCESS) { 6701 forwardtype = NULL; 6702 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6703 CHECK(configure_forward(config, view, origin, 6704 forwarders, forwardtype)); 6705 } 6706 result = ISC_R_SUCCESS; 6707 goto cleanup; 6708 } 6709 6710 (void)cfg_map_get(zoptions, "type", &typeobj); 6711 if (typeobj == NULL) { 6712 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6713 "zone '%s' 'type' not specified", zname); 6714 result = ISC_R_FAILURE; 6715 goto cleanup; 6716 } 6717 ztypestr = cfg_obj_asstring(typeobj); 6718 6719 /* 6720 * "hints zones" aren't zones. If we've got one, 6721 * configure it and return. 6722 */ 6723 if (strcasecmp(ztypestr, "hint") == 0) { 6724 const cfg_obj_t *fileobj = NULL; 6725 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { 6726 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6727 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6728 "zone '%s': 'file' not specified", zname); 6729 result = ISC_R_FAILURE; 6730 goto cleanup; 6731 } 6732 if (dns_name_equal(origin, dns_rootname)) { 6733 const char *hintsfile = cfg_obj_asstring(fileobj); 6734 6735 CHECK(configure_hints(view, hintsfile)); 6736 6737 /* 6738 * Hint zones may also refer to delegation only points. 6739 */ 6740 only = NULL; 6741 tresult = cfg_map_get(zoptions, "delegation-only", 6742 &only); 6743 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) 6744 { 6745 dns_view_adddelegationonly(view, origin); 6746 } 6747 } else { 6748 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6749 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 6750 "ignoring non-root hint zone '%s'", 6751 zname); 6752 result = ISC_R_SUCCESS; 6753 } 6754 /* Skip ordinary zone processing. */ 6755 goto cleanup; 6756 } 6757 6758 /* 6759 * "forward zones" aren't zones either. Translate this syntax into 6760 * the appropriate selective forwarding configuration and return. 6761 */ 6762 if (strcasecmp(ztypestr, "forward") == 0) { 6763 forwardtype = NULL; 6764 forwarders = NULL; 6765 6766 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6767 (void)cfg_map_get(zoptions, "forwarders", &forwarders); 6768 CHECK(configure_forward(config, view, origin, forwarders, 6769 forwardtype)); 6770 6771 /* 6772 * Forward zones may also set delegation only. 6773 */ 6774 only = NULL; 6775 tresult = cfg_map_get(zoptions, "delegation-only", &only); 6776 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) { 6777 dns_view_adddelegationonly(view, origin); 6778 } 6779 goto cleanup; 6780 } 6781 6782 /* 6783 * "delegation-only zones" aren't zones either. 6784 */ 6785 if (strcasecmp(ztypestr, "delegation-only") == 0) { 6786 dns_view_adddelegationonly(view, origin); 6787 goto cleanup; 6788 } 6789 6790 /* 6791 * Redirect zones only require minimal configuration. 6792 */ 6793 if (strcasecmp(ztypestr, "redirect") == 0) { 6794 if (view->redirect != NULL) { 6795 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6796 "redirect zone already exists"); 6797 result = ISC_R_EXISTS; 6798 goto cleanup; 6799 } 6800 result = dns_viewlist_find(viewlist, view->name, view->rdclass, 6801 &pview); 6802 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6803 goto cleanup; 6804 } 6805 if (pview != NULL && pview->redirect != NULL) { 6806 dns_zone_attach(pview->redirect, &zone); 6807 dns_zone_setview(zone, view); 6808 } else { 6809 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, 6810 &zone)); 6811 CHECK(dns_zone_setorigin(zone, origin)); 6812 dns_zone_setview(zone, view); 6813 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, 6814 zone)); 6815 dns_zone_setstats(zone, named_g_server->zonestats); 6816 } 6817 CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, 6818 kasplist, zone, NULL)); 6819 dns_zone_attach(zone, &view->redirect); 6820 goto cleanup; 6821 } 6822 6823 if (!modify) { 6824 /* 6825 * Check for duplicates in the new zone table. 6826 */ 6827 result = dns_view_findzone(view, origin, &dupzone); 6828 if (result == ISC_R_SUCCESS) { 6829 /* 6830 * We already have this zone! 6831 */ 6832 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, 6833 "zone '%s' already exists", zname); 6834 dns_zone_detach(&dupzone); 6835 result = ISC_R_EXISTS; 6836 goto cleanup; 6837 } 6838 INSIST(dupzone == NULL); 6839 } 6840 6841 /* 6842 * Note whether this is a response policy zone and which one if so, 6843 * unless we are using RPZ service interface. In that case, the 6844 * BIND zone database has nothing to do with rpz and so we don't care. 6845 */ 6846 for (rpz_num = 0;; ++rpz_num) { 6847 if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones || 6848 view->rpzs->p.dnsrps_enabled) 6849 { 6850 rpz_num = DNS_RPZ_INVALID_NUM; 6851 break; 6852 } 6853 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin)) 6854 { 6855 break; 6856 } 6857 } 6858 6859 if (!is_catz_member && view->catzs != NULL && 6860 dns_catz_get_zone(view->catzs, origin) != NULL) 6861 { 6862 zone_is_catz = true; 6863 } 6864 6865 /* 6866 * See if we can reuse an existing zone. This is 6867 * only possible if all of these are true: 6868 * - The zone's view exists 6869 * - A zone with the right name exists in the view 6870 * - The zone is compatible with the config 6871 * options (e.g., an existing primary zone cannot 6872 * be reused if the options specify a secondary zone) 6873 * - The zone was not and is still not a response policy zone 6874 * or the zone is a policy zone with an unchanged number 6875 * and we are using the old policy zone summary data. 6876 */ 6877 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 6878 view->rdclass, &pview); 6879 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6880 goto cleanup; 6881 } 6882 if (pview != NULL) { 6883 result = dns_view_findzone(pview, origin, &zone); 6884 } 6885 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 6886 goto cleanup; 6887 } 6888 6889 if (zone != NULL && !named_zone_reusable(zone, zconfig)) { 6890 dns_zone_detach(&zone); 6891 fullsign = true; 6892 } 6893 6894 if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) || 6895 (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok))) 6896 { 6897 dns_zone_detach(&zone); 6898 } 6899 6900 if (zone != NULL) { 6901 /* 6902 * We found a reusable zone. Make it use the 6903 * new view. 6904 */ 6905 dns_zone_setview(zone, view); 6906 } else { 6907 /* 6908 * We cannot reuse an existing zone, we have 6909 * to create a new one. 6910 */ 6911 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 6912 CHECK(dns_zone_setorigin(zone, origin)); 6913 dns_zone_setview(zone, view); 6914 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 6915 dns_zone_setstats(zone, named_g_server->zonestats); 6916 } 6917 if (rpz_num != DNS_RPZ_INVALID_NUM) { 6918 result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num); 6919 if (result != ISC_R_SUCCESS) { 6920 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6921 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 6922 "zone '%s': incompatible" 6923 " masterfile-format or database" 6924 " for a response policy zone", 6925 zname); 6926 goto cleanup; 6927 } 6928 } 6929 6930 if (zone_is_catz) { 6931 dns_zone_catz_enable(zone, view->catzs); 6932 } else if (dns_zone_catz_is_enabled(zone)) { 6933 dns_zone_catz_disable(zone); 6934 } 6935 6936 /* 6937 * If the zone contains a 'forwarders' statement, configure 6938 * selective forwarding. 6939 */ 6940 forwarders = NULL; 6941 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) { 6942 forwardtype = NULL; 6943 (void)cfg_map_get(zoptions, "forward", &forwardtype); 6944 CHECK(configure_forward(config, view, origin, forwarders, 6945 forwardtype)); 6946 } 6947 6948 /* 6949 * Stub and forward zones may also refer to delegation only points. 6950 */ 6951 only = NULL; 6952 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) { 6953 if (cfg_obj_asboolean(only)) { 6954 dns_view_adddelegationonly(view, origin); 6955 } 6956 } 6957 6958 /* 6959 * Mark whether the zone was originally added at runtime or not 6960 */ 6961 dns_zone_setadded(zone, added); 6962 6963 /* 6964 * Determine if we need to set up inline signing. 6965 */ 6966 zone_maybe_inline = ((strcasecmp(ztypestr, "primary") == 0 || 6967 strcasecmp(ztypestr, "master") == 0 || 6968 strcasecmp(ztypestr, "secondary") == 0 || 6969 strcasecmp(ztypestr, "slave") == 0)); 6970 6971 if (zone_maybe_inline) { 6972 inline_signing = named_zone_inlinesigning(zconfig); 6973 } 6974 if (inline_signing) { 6975 dns_zone_getraw(zone, &raw); 6976 if (raw == NULL) { 6977 CHECK(dns_zone_create(&raw, mctx)); 6978 CHECK(dns_zone_setorigin(raw, origin)); 6979 dns_zone_setview(raw, view); 6980 dns_zone_setstats(raw, named_g_server->zonestats); 6981 CHECK(dns_zone_link(zone, raw)); 6982 } 6983 if (cfg_map_get(zoptions, "ixfr-from-differences", 6984 &ixfrfromdiffs) == ISC_R_SUCCESS) 6985 { 6986 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 6987 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 6988 "zone '%s': 'ixfr-from-differences' is " 6989 "ignored for inline-signed zones", 6990 zname); 6991 } 6992 } 6993 6994 /* 6995 * Configure the zone. 6996 */ 6997 CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, kasplist, 6998 zone, raw)); 6999 7000 /* 7001 * Add the zone to its view in the new view list. 7002 */ 7003 if (!modify) { 7004 CHECK(dns_view_addzone(view, zone)); 7005 } 7006 7007 if (zone_is_catz) { 7008 /* 7009 * force catz reload if the zone is loaded; 7010 * if it's not it'll get reloaded on zone load 7011 */ 7012 dns_db_t *db = NULL; 7013 7014 tresult = dns_zone_getdb(zone, &db); 7015 if (tresult == ISC_R_SUCCESS) { 7016 dns_catz_dbupdate_callback(db, view->catzs); 7017 dns_db_detach(&db); 7018 } 7019 } 7020 7021 /* 7022 * Ensure that zone keys are reloaded on reconfig 7023 */ 7024 if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0) { 7025 dns_zone_rekey(zone, fullsign); 7026 } 7027 7028 cleanup: 7029 if (zone != NULL) { 7030 dns_zone_detach(&zone); 7031 } 7032 if (raw != NULL) { 7033 dns_zone_detach(&raw); 7034 } 7035 if (pview != NULL) { 7036 dns_view_detach(&pview); 7037 } 7038 7039 return (result); 7040 } 7041 7042 /* 7043 * Configure built-in zone for storing managed-key data. 7044 */ 7045 static isc_result_t 7046 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { 7047 isc_result_t result; 7048 dns_view_t *pview = NULL; 7049 dns_zone_t *zone = NULL; 7050 dns_acl_t *none = NULL; 7051 char filename[PATH_MAX]; 7052 bool defaultview; 7053 7054 REQUIRE(view != NULL); 7055 7056 /* See if we can re-use an existing keydata zone. */ 7057 result = dns_viewlist_find(&named_g_server->viewlist, view->name, 7058 view->rdclass, &pview); 7059 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { 7060 return (result); 7061 } 7062 7063 if (pview != NULL) { 7064 if (pview->managed_keys != NULL) { 7065 dns_zone_attach(pview->managed_keys, 7066 &view->managed_keys); 7067 dns_zone_setview(pview->managed_keys, view); 7068 dns_zone_setviewcommit(pview->managed_keys); 7069 dns_view_detach(&pview); 7070 dns_zone_synckeyzone(view->managed_keys); 7071 return (ISC_R_SUCCESS); 7072 } 7073 7074 dns_view_detach(&pview); 7075 } 7076 7077 /* No existing keydata zone was found; create one */ 7078 CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); 7079 CHECK(dns_zone_setorigin(zone, dns_rootname)); 7080 7081 defaultview = (strcmp(view->name, "_default") == 0); 7082 CHECK(isc_file_sanitize( 7083 directory, defaultview ? "managed-keys" : view->name, 7084 defaultview ? "bind" : "mkeys", filename, sizeof(filename))); 7085 CHECK(dns_zone_setfile(zone, filename, dns_masterformat_text, 7086 &dns_master_style_default)); 7087 7088 dns_zone_setview(zone, view); 7089 dns_zone_settype(zone, dns_zone_key); 7090 dns_zone_setclass(zone, view->rdclass); 7091 7092 CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); 7093 7094 CHECK(dns_acl_none(mctx, &none)); 7095 dns_zone_setqueryacl(zone, none); 7096 dns_zone_setqueryonacl(zone, none); 7097 dns_acl_detach(&none); 7098 7099 dns_zone_setdialup(zone, dns_dialuptype_no); 7100 dns_zone_setnotifytype(zone, dns_notifytype_no); 7101 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); 7102 dns_zone_setjournalsize(zone, 0); 7103 7104 dns_zone_setstats(zone, named_g_server->zonestats); 7105 CHECK(setquerystats(zone, mctx, dns_zonestat_none)); 7106 7107 if (view->managed_keys != NULL) { 7108 dns_zone_detach(&view->managed_keys); 7109 } 7110 dns_zone_attach(zone, &view->managed_keys); 7111 7112 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7113 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7114 "set up managed keys zone for view %s, file '%s'", 7115 view->name, filename); 7116 7117 cleanup: 7118 if (zone != NULL) { 7119 dns_zone_detach(&zone); 7120 } 7121 if (none != NULL) { 7122 dns_acl_detach(&none); 7123 } 7124 7125 return (result); 7126 } 7127 7128 /* 7129 * Configure a single server quota. 7130 */ 7131 static void 7132 configure_server_quota(const cfg_obj_t **maps, const char *name, 7133 isc_quota_t *quota) { 7134 const cfg_obj_t *obj = NULL; 7135 isc_result_t result; 7136 7137 result = named_config_get(maps, name, &obj); 7138 INSIST(result == ISC_R_SUCCESS); 7139 isc_quota_max(quota, cfg_obj_asuint32(obj)); 7140 } 7141 7142 /* 7143 * This function is called as soon as the 'directory' statement has been 7144 * parsed. This can be extended to support other options if necessary. 7145 */ 7146 static isc_result_t 7147 directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { 7148 isc_result_t result; 7149 const char *directory; 7150 7151 REQUIRE(strcasecmp("directory", clausename) == 0); 7152 7153 UNUSED(arg); 7154 UNUSED(clausename); 7155 7156 /* 7157 * Change directory. 7158 */ 7159 directory = cfg_obj_asstring(obj); 7160 7161 if (!isc_file_ischdiridempotent(directory)) { 7162 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 7163 "option 'directory' contains relative path '%s'", 7164 directory); 7165 } 7166 7167 #if 0 7168 if (!isc_file_isdirwritable(directory)) { 7169 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7170 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7171 "directory '%s' is not writable", directory); 7172 return (ISC_R_NOPERM); 7173 } 7174 #endif 7175 7176 result = isc_dir_chdir(directory); 7177 if (result != ISC_R_SUCCESS) { 7178 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7179 "change directory to '%s' failed: %s", directory, 7180 isc_result_totext(result)); 7181 return (result); 7182 } 7183 7184 char cwd[PATH_MAX]; 7185 if (getcwd(cwd, sizeof(cwd)) == cwd) { 7186 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7187 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7188 "the working directory is now '%s'", cwd); 7189 } 7190 7191 return (ISC_R_SUCCESS); 7192 } 7193 7194 /* 7195 * This event callback is invoked to do periodic network interface 7196 * scanning. 7197 */ 7198 7199 static void 7200 interface_timer_tick(isc_task_t *task, isc_event_t *event) { 7201 named_server_t *server = (named_server_t *)event->ev_arg; 7202 INSIST(task == server->task); 7203 UNUSED(task); 7204 7205 isc_event_free(&event); 7206 ns_interfacemgr_scan(server->interfacemgr, false, false); 7207 } 7208 7209 static void 7210 heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) { 7211 named_server_t *server = (named_server_t *)event->ev_arg; 7212 dns_view_t *view; 7213 7214 UNUSED(task); 7215 isc_event_free(&event); 7216 view = ISC_LIST_HEAD(server->viewlist); 7217 while (view != NULL) { 7218 dns_view_dialup(view); 7219 view = ISC_LIST_NEXT(view, link); 7220 } 7221 } 7222 7223 typedef struct { 7224 isc_mem_t *mctx; 7225 isc_task_t *task; 7226 dns_fetch_t *fetch; 7227 dns_view_t *view; 7228 dns_fixedname_t tatname; 7229 dns_fixedname_t keyname; 7230 dns_rdataset_t rdataset; 7231 dns_rdataset_t sigrdataset; 7232 } ns_tat_t; 7233 7234 static int 7235 cid(const void *a, const void *b) { 7236 const uint16_t ida = *(const uint16_t *)a; 7237 const uint16_t idb = *(const uint16_t *)b; 7238 if (ida < idb) { 7239 return (-1); 7240 } else if (ida > idb) { 7241 return (1); 7242 } else { 7243 return (0); 7244 } 7245 } 7246 7247 static void 7248 tat_done(isc_task_t *task, isc_event_t *event) { 7249 dns_fetchevent_t *devent; 7250 ns_tat_t *tat; 7251 7252 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE); 7253 INSIST(event->ev_arg != NULL); 7254 7255 UNUSED(task); 7256 7257 tat = event->ev_arg; 7258 devent = (dns_fetchevent_t *)event; 7259 7260 /* Free resources which are not of interest */ 7261 if (devent->node != NULL) { 7262 dns_db_detachnode(devent->db, &devent->node); 7263 } 7264 if (devent->db != NULL) { 7265 dns_db_detach(&devent->db); 7266 } 7267 isc_event_free(&event); 7268 dns_resolver_destroyfetch(&tat->fetch); 7269 if (dns_rdataset_isassociated(&tat->rdataset)) { 7270 dns_rdataset_disassociate(&tat->rdataset); 7271 } 7272 if (dns_rdataset_isassociated(&tat->sigrdataset)) { 7273 dns_rdataset_disassociate(&tat->sigrdataset); 7274 } 7275 dns_view_detach(&tat->view); 7276 isc_task_detach(&tat->task); 7277 isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); 7278 } 7279 7280 struct dotat_arg { 7281 dns_view_t *view; 7282 isc_task_t *task; 7283 }; 7284 7285 /*% 7286 * Prepare the QNAME for the TAT query to be sent by processing the trust 7287 * anchors present at 'keynode' of 'keytable'. Store the result in 'dst' and 7288 * the domain name which 'keynode' is associated with in 'origin'. 7289 * 7290 * A maximum of 12 key IDs can be reported in a single TAT query due to the 7291 * 63-octet length limit for any single label in a domain name. If there are 7292 * more than 12 keys configured at 'keynode', only the first 12 will be 7293 * reported in the TAT query. 7294 */ 7295 static isc_result_t 7296 get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) { 7297 dns_rdataset_t dsset; 7298 unsigned int i, n = 0; 7299 uint16_t ids[12]; 7300 isc_textregion_t r; 7301 char label[64]; 7302 int m; 7303 7304 dns_rdataset_init(&dsset); 7305 if (dns_keynode_dsset(keynode, &dsset)) { 7306 isc_result_t result; 7307 7308 for (result = dns_rdataset_first(&dsset); 7309 result == ISC_R_SUCCESS; 7310 result = dns_rdataset_next(&dsset)) 7311 { 7312 dns_rdata_t rdata = DNS_RDATA_INIT; 7313 dns_rdata_ds_t ds; 7314 7315 dns_rdata_reset(&rdata); 7316 dns_rdataset_current(&dsset, &rdata); 7317 result = dns_rdata_tostruct(&rdata, &ds, NULL); 7318 RUNTIME_CHECK(result == ISC_R_SUCCESS); 7319 if (n < (sizeof(ids) / sizeof(ids[0]))) { 7320 ids[n] = ds.key_tag; 7321 n++; 7322 } 7323 } 7324 dns_rdataset_disassociate(&dsset); 7325 } 7326 7327 if (n == 0) { 7328 return (DNS_R_EMPTYNAME); 7329 } 7330 7331 if (n > 1) { 7332 qsort(ids, n, sizeof(ids[0]), cid); 7333 } 7334 7335 /* 7336 * Encoded as "_ta-xxxx\(-xxxx\)*" where xxxx is the hex version of 7337 * of the keyid. 7338 */ 7339 label[0] = 0; 7340 r.base = label; 7341 r.length = sizeof(label); 7342 m = snprintf(r.base, r.length, "_ta"); 7343 if (m < 0 || (unsigned)m > r.length) { 7344 return (ISC_R_FAILURE); 7345 } 7346 isc_textregion_consume(&r, m); 7347 for (i = 0; i < n; i++) { 7348 m = snprintf(r.base, r.length, "-%04x", ids[i]); 7349 if (m < 0 || (unsigned)m > r.length) { 7350 return (ISC_R_FAILURE); 7351 } 7352 isc_textregion_consume(&r, m); 7353 } 7354 7355 return (dns_name_fromstring2(target, label, keyname, 0, NULL)); 7356 } 7357 7358 static void 7359 tat_send(isc_task_t *task, isc_event_t *event) { 7360 ns_tat_t *tat; 7361 char namebuf[DNS_NAME_FORMATSIZE]; 7362 dns_fixedname_t fdomain; 7363 dns_name_t *domain; 7364 dns_rdataset_t nameservers; 7365 isc_result_t result; 7366 dns_name_t *keyname; 7367 dns_name_t *tatname; 7368 7369 INSIST(event != NULL && event->ev_type == NAMED_EVENT_TATSEND); 7370 INSIST(event->ev_arg != NULL); 7371 7372 UNUSED(task); 7373 7374 tat = event->ev_arg; 7375 7376 keyname = dns_fixedname_name(&tat->keyname); 7377 tatname = dns_fixedname_name(&tat->tatname); 7378 7379 dns_name_format(tatname, namebuf, sizeof(namebuf)); 7380 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7381 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7382 "%s: sending trust-anchor-telemetry query '%s/NULL'", 7383 tat->view->name, namebuf); 7384 7385 /* 7386 * TAT queries should be sent to the authoritative servers for a given 7387 * zone. If this function is called for a keytable node corresponding 7388 * to a locally served zone, calling dns_resolver_createfetch() with 7389 * NULL 'domain' and 'nameservers' arguments will cause 'tatname' to be 7390 * resolved locally, without sending any TAT queries upstream. 7391 * 7392 * Work around this issue by calling dns_view_findzonecut() first. If 7393 * the zone is served locally, the NS RRset for the given domain name 7394 * will be retrieved from local data; if it is not, the deepest zone 7395 * cut we have for it will be retrieved from cache. In either case, 7396 * passing the results to dns_resolver_createfetch() will prevent it 7397 * from returning NXDOMAIN for 'tatname' while still allowing it to 7398 * chase down any potential delegations returned by upstream servers in 7399 * order to eventually find the destination host to send the TAT query 7400 * to. 7401 * 7402 * After the dns_view_findzonecut() call, 'domain' will hold the 7403 * deepest zone cut we can find for 'keyname' while 'nameservers' will 7404 * hold the NS RRset at that zone cut. 7405 */ 7406 domain = dns_fixedname_initname(&fdomain); 7407 dns_rdataset_init(&nameservers); 7408 result = dns_view_findzonecut(tat->view, keyname, domain, NULL, 0, 0, 7409 true, true, &nameservers, NULL); 7410 if (result == ISC_R_SUCCESS) { 7411 result = dns_resolver_createfetch( 7412 tat->view->resolver, tatname, dns_rdatatype_null, 7413 domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, 7414 tat->task, tat_done, tat, &tat->rdataset, 7415 &tat->sigrdataset, &tat->fetch); 7416 } 7417 7418 /* 7419 * 'domain' holds the dns_name_t pointer inside a dst_key_t structure. 7420 * dns_resolver_createfetch() creates its own copy of 'domain' if it 7421 * succeeds. Thus, 'domain' is not freed here. 7422 * 7423 * Even if dns_view_findzonecut() returned something else than 7424 * ISC_R_SUCCESS, it still could have associated 'nameservers'. 7425 * dns_resolver_createfetch() creates its own copy of 'nameservers' if 7426 * it succeeds. Thus, we need to check whether 'nameservers' is 7427 * associated and release it if it is. 7428 */ 7429 if (dns_rdataset_isassociated(&nameservers)) { 7430 dns_rdataset_disassociate(&nameservers); 7431 } 7432 7433 if (result != ISC_R_SUCCESS) { 7434 dns_view_detach(&tat->view); 7435 isc_task_detach(&tat->task); 7436 isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); 7437 } 7438 isc_event_free(&event); 7439 } 7440 7441 static void 7442 dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, dns_name_t *keyname, 7443 void *arg) { 7444 struct dotat_arg *dotat_arg = arg; 7445 isc_result_t result; 7446 dns_view_t *view; 7447 isc_task_t *task; 7448 ns_tat_t *tat; 7449 isc_event_t *event; 7450 7451 REQUIRE(keytable != NULL); 7452 REQUIRE(keynode != NULL); 7453 REQUIRE(dotat_arg != NULL); 7454 7455 view = dotat_arg->view; 7456 task = dotat_arg->task; 7457 7458 tat = isc_mem_get(dotat_arg->view->mctx, sizeof(*tat)); 7459 7460 tat->fetch = NULL; 7461 tat->mctx = NULL; 7462 tat->task = NULL; 7463 tat->view = NULL; 7464 dns_rdataset_init(&tat->rdataset); 7465 dns_rdataset_init(&tat->sigrdataset); 7466 dns_name_copy(keyname, dns_fixedname_initname(&tat->keyname)); 7467 result = get_tat_qname(dns_fixedname_initname(&tat->tatname), keyname, 7468 keynode); 7469 if (result != ISC_R_SUCCESS) { 7470 isc_mem_put(dotat_arg->view->mctx, tat, sizeof(*tat)); 7471 return; 7472 } 7473 isc_mem_attach(dotat_arg->view->mctx, &tat->mctx); 7474 isc_task_attach(task, &tat->task); 7475 dns_view_attach(view, &tat->view); 7476 7477 /* 7478 * We don't want to be holding the keytable lock when calling 7479 * dns_view_findzonecut() as it creates a lock order loop so 7480 * call dns_view_findzonecut() in a event handler. 7481 * 7482 * zone->lock (dns_zone_setviewcommit) while holding view->lock 7483 * (dns_view_setviewcommit) 7484 * 7485 * keytable->lock (dns_keytable_find) while holding zone->lock 7486 * (zone_asyncload) 7487 * 7488 * view->lock (dns_view_findzonecut) while holding keytable->lock 7489 * (dns_keytable_forall) 7490 */ 7491 event = isc_event_allocate(tat->mctx, keytable, NAMED_EVENT_TATSEND, 7492 tat_send, tat, sizeof(isc_event_t)); 7493 isc_task_send(task, &event); 7494 } 7495 7496 static void 7497 tat_timer_tick(isc_task_t *task, isc_event_t *event) { 7498 isc_result_t result; 7499 named_server_t *server = (named_server_t *)event->ev_arg; 7500 struct dotat_arg arg; 7501 dns_view_t *view; 7502 dns_keytable_t *secroots = NULL; 7503 7504 isc_event_free(&event); 7505 7506 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 7507 view = ISC_LIST_NEXT(view, link)) 7508 { 7509 if (!view->trust_anchor_telemetry || !view->enablevalidation) { 7510 continue; 7511 } 7512 7513 result = dns_view_getsecroots(view, &secroots); 7514 if (result != ISC_R_SUCCESS) { 7515 continue; 7516 } 7517 7518 arg.view = view; 7519 arg.task = task; 7520 (void)dns_keytable_forall(secroots, dotat, &arg); 7521 dns_keytable_detach(&secroots); 7522 } 7523 } 7524 7525 static void 7526 pps_timer_tick(isc_task_t *task, isc_event_t *event) { 7527 static unsigned int oldrequests = 0; 7528 unsigned int requests = atomic_load_relaxed(&ns_client_requests); 7529 7530 UNUSED(task); 7531 isc_event_free(&event); 7532 7533 /* 7534 * Don't worry about wrapping as the overflow result will be right. 7535 */ 7536 dns_pps = (requests - oldrequests) / 1200; 7537 oldrequests = requests; 7538 } 7539 7540 /* 7541 * Replace the current value of '*field', a dynamically allocated 7542 * string or NULL, with a dynamically allocated copy of the 7543 * null-terminated string pointed to by 'value', or NULL. 7544 */ 7545 static isc_result_t 7546 setstring(named_server_t *server, char **field, const char *value) { 7547 char *copy; 7548 7549 if (value != NULL) { 7550 copy = isc_mem_strdup(server->mctx, value); 7551 } else { 7552 copy = NULL; 7553 } 7554 7555 if (*field != NULL) { 7556 isc_mem_free(server->mctx, *field); 7557 } 7558 7559 *field = copy; 7560 return (ISC_R_SUCCESS); 7561 } 7562 7563 /* 7564 * Replace the current value of '*field', a dynamically allocated 7565 * string or NULL, with another dynamically allocated string 7566 * or NULL if whether 'obj' is a string or void value, respectively. 7567 */ 7568 static isc_result_t 7569 setoptstring(named_server_t *server, char **field, const cfg_obj_t *obj) { 7570 if (cfg_obj_isvoid(obj)) { 7571 return (setstring(server, field, NULL)); 7572 } else { 7573 return (setstring(server, field, cfg_obj_asstring(obj))); 7574 } 7575 } 7576 7577 static void 7578 set_limit(const cfg_obj_t **maps, const char *configname, 7579 const char *description, isc_resource_t resourceid, 7580 isc_resourcevalue_t defaultvalue) { 7581 const cfg_obj_t *obj = NULL; 7582 const char *resource; 7583 isc_resourcevalue_t value; 7584 isc_result_t result; 7585 7586 if (named_config_get(maps, configname, &obj) != ISC_R_SUCCESS) { 7587 return; 7588 } 7589 7590 if (cfg_obj_isstring(obj)) { 7591 resource = cfg_obj_asstring(obj); 7592 if (strcasecmp(resource, "unlimited") == 0) { 7593 value = ISC_RESOURCE_UNLIMITED; 7594 } else { 7595 INSIST(strcasecmp(resource, "default") == 0); 7596 value = defaultvalue; 7597 } 7598 } else { 7599 value = cfg_obj_asuint64(obj); 7600 } 7601 7602 result = isc_resource_setlimit(resourceid, value); 7603 isc_log_write( 7604 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, 7605 result == ISC_R_SUCCESS ? ISC_LOG_DEBUG(3) : ISC_LOG_WARNING, 7606 "set maximum %s to %" PRIu64 ": %s", description, value, 7607 isc_result_totext(result)); 7608 } 7609 7610 #define SETLIMIT(cfgvar, resource, description) \ 7611 set_limit(maps, cfgvar, description, isc_resource_##resource, \ 7612 named_g_init##resource) 7613 7614 static void 7615 set_limits(const cfg_obj_t **maps) { 7616 SETLIMIT("stacksize", stacksize, "stack size"); 7617 SETLIMIT("datasize", datasize, "data size"); 7618 SETLIMIT("coresize", coresize, "core size"); 7619 SETLIMIT("files", openfiles, "open files"); 7620 } 7621 7622 static void 7623 portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports, 7624 bool positive) { 7625 const cfg_listelt_t *element; 7626 7627 for (element = cfg_list_first(ports); element != NULL; 7628 element = cfg_list_next(element)) 7629 { 7630 const cfg_obj_t *obj = cfg_listelt_value(element); 7631 7632 if (cfg_obj_isuint32(obj)) { 7633 in_port_t port = (in_port_t)cfg_obj_asuint32(obj); 7634 7635 if (positive) { 7636 isc_portset_add(portset, port); 7637 } else { 7638 isc_portset_remove(portset, port); 7639 } 7640 } else { 7641 const cfg_obj_t *obj_loport, *obj_hiport; 7642 in_port_t loport, hiport; 7643 7644 obj_loport = cfg_tuple_get(obj, "loport"); 7645 loport = (in_port_t)cfg_obj_asuint32(obj_loport); 7646 obj_hiport = cfg_tuple_get(obj, "hiport"); 7647 hiport = (in_port_t)cfg_obj_asuint32(obj_hiport); 7648 7649 if (positive) { 7650 isc_portset_addrange(portset, loport, hiport); 7651 } else { 7652 isc_portset_removerange(portset, loport, 7653 hiport); 7654 } 7655 } 7656 } 7657 } 7658 7659 static isc_result_t 7660 removed(dns_zone_t *zone, void *uap) { 7661 if (dns_zone_getview(zone) != uap) { 7662 return (ISC_R_SUCCESS); 7663 } 7664 7665 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", 7666 dns_zonetype_name(dns_zone_gettype(zone))); 7667 return (ISC_R_SUCCESS); 7668 } 7669 7670 static void 7671 cleanup_session_key(named_server_t *server, isc_mem_t *mctx) { 7672 if (server->session_keyfile != NULL) { 7673 isc_file_remove(server->session_keyfile); 7674 isc_mem_free(mctx, server->session_keyfile); 7675 server->session_keyfile = NULL; 7676 } 7677 7678 if (server->session_keyname != NULL) { 7679 if (dns_name_dynamic(server->session_keyname)) { 7680 dns_name_free(server->session_keyname, mctx); 7681 } 7682 isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); 7683 server->session_keyname = NULL; 7684 } 7685 7686 if (server->sessionkey != NULL) { 7687 dst_key_free(&server->sessionkey); 7688 } 7689 7690 server->session_keyalg = DST_ALG_UNKNOWN; 7691 server->session_keybits = 0; 7692 } 7693 7694 static isc_result_t 7695 generate_session_key(const char *filename, const char *keynamestr, 7696 const dns_name_t *keyname, const char *algstr, 7697 unsigned int algtype, uint16_t bits, isc_mem_t *mctx, 7698 bool first_time, dst_key_t **keyp) { 7699 isc_result_t result = ISC_R_SUCCESS; 7700 dst_key_t *key = NULL; 7701 isc_buffer_t key_txtbuffer; 7702 isc_buffer_t key_rawbuffer; 7703 char key_txtsecret[256]; 7704 char key_rawsecret[64]; 7705 isc_region_t key_rawregion; 7706 FILE *fp = NULL; 7707 7708 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7709 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7710 "generating session key for dynamic DNS"); 7711 7712 /* generate key */ 7713 result = dst_key_generate(keyname, algtype, bits, 1, 0, 7714 DNS_KEYPROTO_ANY, dns_rdataclass_in, mctx, 7715 &key, NULL); 7716 if (result != ISC_R_SUCCESS) { 7717 return (result); 7718 } 7719 7720 /* 7721 * Dump the key to the buffer for later use. 7722 */ 7723 isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); 7724 CHECK(dst_key_tobuffer(key, &key_rawbuffer)); 7725 7726 isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); 7727 isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); 7728 CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); 7729 7730 /* Dump the key to the key file. */ 7731 fp = named_os_openfile(filename, S_IRUSR | S_IWUSR, first_time); 7732 if (fp == NULL) { 7733 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7734 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7735 "could not create %s", filename); 7736 result = ISC_R_NOPERM; 7737 goto cleanup; 7738 } 7739 7740 fprintf(fp, 7741 "key \"%s\" {\n" 7742 "\talgorithm %s;\n" 7743 "\tsecret \"%.*s\";\n};\n", 7744 keynamestr, algstr, (int)isc_buffer_usedlength(&key_txtbuffer), 7745 (char *)isc_buffer_base(&key_txtbuffer)); 7746 7747 CHECK(isc_stdio_flush(fp)); 7748 result = isc_stdio_close(fp); 7749 fp = NULL; 7750 if (result != ISC_R_SUCCESS) { 7751 goto cleanup; 7752 } 7753 7754 *keyp = key; 7755 return (ISC_R_SUCCESS); 7756 7757 cleanup: 7758 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7759 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7760 "failed to generate session key " 7761 "for dynamic DNS: %s", 7762 isc_result_totext(result)); 7763 if (fp != NULL) { 7764 (void)isc_stdio_close(fp); 7765 (void)isc_file_remove(filename); 7766 } 7767 if (key != NULL) { 7768 dst_key_free(&key); 7769 } 7770 7771 return (result); 7772 } 7773 7774 static isc_result_t 7775 configure_session_key(const cfg_obj_t **maps, named_server_t *server, 7776 isc_mem_t *mctx, bool first_time) { 7777 const char *keyfile, *keynamestr, *algstr; 7778 unsigned int algtype; 7779 dns_fixedname_t fname; 7780 dns_name_t *keyname; 7781 const dns_name_t *algname; 7782 isc_buffer_t buffer; 7783 uint16_t bits; 7784 const cfg_obj_t *obj; 7785 bool need_deleteold = false; 7786 bool need_createnew = false; 7787 isc_result_t result; 7788 7789 obj = NULL; 7790 result = named_config_get(maps, "session-keyfile", &obj); 7791 if (result == ISC_R_SUCCESS) { 7792 if (cfg_obj_isvoid(obj)) { 7793 keyfile = NULL; /* disable it */ 7794 } else { 7795 keyfile = cfg_obj_asstring(obj); 7796 } 7797 } else { 7798 keyfile = named_g_defaultsessionkeyfile; 7799 } 7800 7801 obj = NULL; 7802 result = named_config_get(maps, "session-keyname", &obj); 7803 INSIST(result == ISC_R_SUCCESS); 7804 keynamestr = cfg_obj_asstring(obj); 7805 isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr)); 7806 isc_buffer_add(&buffer, strlen(keynamestr)); 7807 keyname = dns_fixedname_initname(&fname); 7808 result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); 7809 if (result != ISC_R_SUCCESS) { 7810 return (result); 7811 } 7812 7813 obj = NULL; 7814 result = named_config_get(maps, "session-keyalg", &obj); 7815 INSIST(result == ISC_R_SUCCESS); 7816 algstr = cfg_obj_asstring(obj); 7817 algname = NULL; 7818 result = named_config_getkeyalgorithm2(algstr, &algname, &algtype, 7819 &bits); 7820 if (result != ISC_R_SUCCESS) { 7821 const char *s = " (keeping current key)"; 7822 7823 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 7824 "session-keyalg: " 7825 "unsupported or unknown algorithm '%s'%s", 7826 algstr, server->session_keyfile != NULL ? s : ""); 7827 return (result); 7828 } 7829 7830 /* See if we need to (re)generate a new key. */ 7831 if (keyfile == NULL) { 7832 if (server->session_keyfile != NULL) { 7833 need_deleteold = true; 7834 } 7835 } else if (server->session_keyfile == NULL) { 7836 need_createnew = true; 7837 } else if (strcmp(keyfile, server->session_keyfile) != 0 || 7838 !dns_name_equal(server->session_keyname, keyname) || 7839 server->session_keyalg != algtype || 7840 server->session_keybits != bits) 7841 { 7842 need_deleteold = true; 7843 need_createnew = true; 7844 } 7845 7846 if (need_deleteold) { 7847 INSIST(server->session_keyfile != NULL); 7848 INSIST(server->session_keyname != NULL); 7849 INSIST(server->sessionkey != NULL); 7850 7851 cleanup_session_key(server, mctx); 7852 } 7853 7854 if (need_createnew) { 7855 INSIST(server->sessionkey == NULL); 7856 INSIST(server->session_keyfile == NULL); 7857 INSIST(server->session_keyname == NULL); 7858 INSIST(server->session_keyalg == DST_ALG_UNKNOWN); 7859 INSIST(server->session_keybits == 0); 7860 7861 server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); 7862 dns_name_init(server->session_keyname, NULL); 7863 dns_name_dup(keyname, mctx, server->session_keyname); 7864 7865 server->session_keyfile = isc_mem_strdup(mctx, keyfile); 7866 7867 server->session_keyalg = algtype; 7868 server->session_keybits = bits; 7869 7870 CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr, 7871 algtype, bits, mctx, first_time, 7872 &server->sessionkey)); 7873 } 7874 7875 return (result); 7876 7877 cleanup: 7878 cleanup_session_key(server, mctx); 7879 return (result); 7880 } 7881 7882 #ifndef HAVE_LMDB 7883 static isc_result_t 7884 count_newzones(dns_view_t *view, ns_cfgctx_t *nzcfg, int *num_zonesp) { 7885 isc_result_t result; 7886 7887 /* The new zone file may not exist. That is OK. */ 7888 if (!isc_file_exists(view->new_zone_file)) { 7889 *num_zonesp = 0; 7890 return (ISC_R_SUCCESS); 7891 } 7892 7893 /* 7894 * In the case of NZF files, we also parse the configuration in 7895 * the file at this stage. 7896 * 7897 * This may be called in multiple views, so we reset 7898 * the parser each time. 7899 */ 7900 cfg_parser_reset(named_g_addparser); 7901 result = cfg_parse_file(named_g_addparser, view->new_zone_file, 7902 &cfg_type_addzoneconf, &nzcfg->nzf_config); 7903 if (result == ISC_R_SUCCESS) { 7904 int num_zones; 7905 7906 num_zones = count_zones(nzcfg->nzf_config); 7907 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7908 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7909 "NZF file '%s' contains %d zones", 7910 view->new_zone_file, num_zones); 7911 if (num_zonesp != NULL) { 7912 *num_zonesp = num_zones; 7913 } 7914 } else { 7915 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7916 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 7917 "Error parsing NZF file '%s': %s", 7918 view->new_zone_file, isc_result_totext(result)); 7919 } 7920 7921 return (result); 7922 } 7923 7924 #else /* HAVE_LMDB */ 7925 7926 static isc_result_t 7927 count_newzones(dns_view_t *view, ns_cfgctx_t *nzcfg, int *num_zonesp) { 7928 isc_result_t result; 7929 int n; 7930 7931 UNUSED(nzcfg); 7932 7933 REQUIRE(num_zonesp != NULL); 7934 7935 LOCK(&view->new_zone_lock); 7936 7937 CHECK(migrate_nzf(view)); 7938 7939 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7940 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7941 "loading NZD zone count from '%s' " 7942 "for view '%s'", 7943 view->new_zone_db, view->name); 7944 7945 CHECK(nzd_count(view, &n)); 7946 7947 *num_zonesp = n; 7948 7949 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 7950 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 7951 "NZD database '%s' contains %d zones", view->new_zone_db, 7952 n); 7953 7954 cleanup: 7955 if (result != ISC_R_SUCCESS) { 7956 *num_zonesp = 0; 7957 } 7958 7959 UNLOCK(&view->new_zone_lock); 7960 7961 return (ISC_R_SUCCESS); 7962 } 7963 7964 #endif /* HAVE_LMDB */ 7965 7966 static isc_result_t 7967 setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 7968 cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx, 7969 int *num_zones) { 7970 isc_result_t result = ISC_R_SUCCESS; 7971 bool allow = false; 7972 ns_cfgctx_t *nzcfg = NULL; 7973 const cfg_obj_t *maps[4]; 7974 const cfg_obj_t *options = NULL, *voptions = NULL; 7975 const cfg_obj_t *nz = NULL; 7976 const cfg_obj_t *nzdir = NULL; 7977 const char *dir = NULL; 7978 const cfg_obj_t *obj = NULL; 7979 int i = 0; 7980 uint64_t mapsize = 0ULL; 7981 7982 REQUIRE(config != NULL); 7983 7984 if (vconfig != NULL) { 7985 voptions = cfg_tuple_get(vconfig, "options"); 7986 } 7987 if (voptions != NULL) { 7988 maps[i++] = voptions; 7989 } 7990 result = cfg_map_get(config, "options", &options); 7991 if (result == ISC_R_SUCCESS) { 7992 maps[i++] = options; 7993 } 7994 maps[i++] = named_g_defaults; 7995 maps[i] = NULL; 7996 7997 result = named_config_get(maps, "allow-new-zones", &nz); 7998 if (result == ISC_R_SUCCESS) { 7999 allow = cfg_obj_asboolean(nz); 8000 } 8001 result = named_config_get(maps, "new-zones-directory", &nzdir); 8002 if (result == ISC_R_SUCCESS) { 8003 dir = cfg_obj_asstring(nzdir); 8004 result = isc_file_isdirectory(dir); 8005 if (result != ISC_R_SUCCESS) { 8006 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, 8007 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8008 "invalid new-zones-directory %s: %s", dir, 8009 isc_result_totext(result)); 8010 return (result); 8011 } 8012 if (!isc_file_isdirwritable(dir)) { 8013 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8014 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8015 "new-zones-directory '%s' " 8016 "is not writable", 8017 dir); 8018 return (ISC_R_NOPERM); 8019 } 8020 8021 dns_view_setnewzonedir(view, dir); 8022 } 8023 8024 #ifdef HAVE_LMDB 8025 result = named_config_get(maps, "lmdb-mapsize", &obj); 8026 if (result == ISC_R_SUCCESS && obj != NULL) { 8027 mapsize = cfg_obj_asuint64(obj); 8028 if (mapsize < (1ULL << 20)) { /* 1 megabyte */ 8029 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 8030 "'lmdb-mapsize " 8031 "%" PRId64 "' " 8032 "is too small", 8033 mapsize); 8034 return (ISC_R_FAILURE); 8035 } else if (mapsize > (1ULL << 40)) { /* 1 terabyte */ 8036 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, 8037 "'lmdb-mapsize " 8038 "%" PRId64 "' " 8039 "is too large", 8040 mapsize); 8041 return (ISC_R_FAILURE); 8042 } 8043 } 8044 #else /* ifdef HAVE_LMDB */ 8045 UNUSED(obj); 8046 #endif /* HAVE_LMDB */ 8047 8048 /* 8049 * A non-empty catalog-zones statement implies allow-new-zones 8050 */ 8051 if (!allow) { 8052 const cfg_obj_t *cz = NULL; 8053 result = named_config_get(maps, "catalog-zones", &cz); 8054 if (result == ISC_R_SUCCESS) { 8055 const cfg_listelt_t *e = 8056 cfg_list_first(cfg_tuple_get(cz, "zone list")); 8057 if (e != NULL) { 8058 allow = true; 8059 } 8060 } 8061 } 8062 8063 if (!allow) { 8064 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 8065 if (num_zones != NULL) { 8066 *num_zones = 0; 8067 } 8068 return (ISC_R_SUCCESS); 8069 } 8070 8071 nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg)); 8072 8073 /* 8074 * We attach the parser that was used for config as well 8075 * as the one that will be used for added zones, to avoid 8076 * a shutdown race later. 8077 */ 8078 memset(nzcfg, 0, sizeof(*nzcfg)); 8079 cfg_parser_attach(conf_parser, &nzcfg->conf_parser); 8080 cfg_parser_attach(named_g_addparser, &nzcfg->add_parser); 8081 isc_mem_attach(view->mctx, &nzcfg->mctx); 8082 cfg_aclconfctx_attach(actx, &nzcfg->actx); 8083 8084 result = dns_view_setnewzones(view, true, nzcfg, newzone_cfgctx_destroy, 8085 mapsize); 8086 if (result != ISC_R_SUCCESS) { 8087 dns_view_setnewzones(view, false, NULL, NULL, 0ULL); 8088 return (result); 8089 } 8090 8091 cfg_obj_attach(config, &nzcfg->config); 8092 if (vconfig != NULL) { 8093 cfg_obj_attach(vconfig, &nzcfg->vconfig); 8094 } 8095 8096 result = count_newzones(view, nzcfg, num_zones); 8097 return (result); 8098 } 8099 8100 static void 8101 configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, 8102 dns_view_t *view) { 8103 const char *zname; 8104 dns_fixedname_t fixorigin; 8105 dns_name_t *origin; 8106 isc_result_t result2; 8107 dns_view_t *pview = NULL; 8108 dns_zone_t *zone = NULL; 8109 8110 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 8111 origin = dns_fixedname_initname(&fixorigin); 8112 8113 result2 = dns_name_fromstring(origin, zname, 0, NULL); 8114 if (result2 != ISC_R_SUCCESS) { 8115 return; 8116 } 8117 8118 result2 = dns_viewlist_find(&named_g_server->viewlist, view->name, 8119 view->rdclass, &pview); 8120 if (result2 != ISC_R_SUCCESS) { 8121 return; 8122 } 8123 8124 result2 = dns_view_findzone(pview, origin, &zone); 8125 if (result2 != ISC_R_SUCCESS) { 8126 dns_view_detach(&pview); 8127 return; 8128 } 8129 8130 if (result == ISC_R_SUCCESS) { 8131 dns_zone_setviewcommit(zone); 8132 } else { 8133 dns_zone_setviewrevert(zone); 8134 } 8135 8136 dns_zone_detach(&zone); 8137 dns_view_detach(&pview); 8138 } 8139 8140 #ifndef HAVE_LMDB 8141 8142 static isc_result_t 8143 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 8144 isc_mem_t *mctx, cfg_aclconfctx_t *actx) { 8145 isc_result_t result; 8146 ns_cfgctx_t *nzctx; 8147 const cfg_obj_t *zonelist; 8148 const cfg_listelt_t *element; 8149 8150 nzctx = view->new_zone_config; 8151 if (nzctx == NULL || nzctx->nzf_config == NULL) { 8152 return (ISC_R_SUCCESS); 8153 } 8154 8155 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8156 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8157 "loading additional zones for view '%s'", view->name); 8158 8159 zonelist = NULL; 8160 cfg_map_get(nzctx->nzf_config, "zone", &zonelist); 8161 8162 for (element = cfg_list_first(zonelist); element != NULL; 8163 element = cfg_list_next(element)) 8164 { 8165 const cfg_obj_t *zconfig = cfg_listelt_value(element); 8166 CHECK(configure_zone(config, zconfig, vconfig, mctx, view, 8167 &named_g_server->viewlist, 8168 &named_g_server->kasplist, actx, true, 8169 false, false, false)); 8170 } 8171 8172 result = ISC_R_SUCCESS; 8173 8174 cleanup: 8175 for (element = cfg_list_first(zonelist); element != NULL; 8176 element = cfg_list_next(element)) 8177 { 8178 const cfg_obj_t *zconfig = cfg_listelt_value(element); 8179 configure_zone_setviewcommit(result, zconfig, view); 8180 } 8181 8182 return (result); 8183 } 8184 8185 #else /* HAVE_LMDB */ 8186 8187 static isc_result_t 8188 data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, 8189 cfg_obj_t **zoneconfig) { 8190 isc_result_t result; 8191 const char *zone_name; 8192 size_t zone_name_len; 8193 const char *zone_config; 8194 size_t zone_config_len; 8195 cfg_obj_t *zoneconf = NULL; 8196 char bufname[DNS_NAME_FORMATSIZE]; 8197 8198 REQUIRE(view != NULL); 8199 REQUIRE(key != NULL); 8200 REQUIRE(data != NULL); 8201 REQUIRE(text != NULL); 8202 REQUIRE(zoneconfig != NULL && *zoneconfig == NULL); 8203 8204 if (*text == NULL) { 8205 isc_buffer_allocate(view->mctx, text, 256); 8206 } else { 8207 isc_buffer_clear(*text); 8208 } 8209 8210 zone_name = (const char *)key->mv_data; 8211 zone_name_len = key->mv_size; 8212 INSIST(zone_name != NULL && zone_name_len > 0); 8213 8214 zone_config = (const char *)data->mv_data; 8215 zone_config_len = data->mv_size; 8216 INSIST(zone_config != NULL && zone_config_len > 0); 8217 8218 /* zone zonename { config; }; */ 8219 result = isc_buffer_reserve(text, 6 + zone_name_len + 2 + 8220 zone_config_len + 2); 8221 if (result != ISC_R_SUCCESS) { 8222 goto cleanup; 8223 } 8224 8225 CHECK(putstr(text, "zone \"")); 8226 CHECK(putmem(text, (const void *)zone_name, zone_name_len)); 8227 CHECK(putstr(text, "\" ")); 8228 CHECK(putmem(text, (const void *)zone_config, zone_config_len)); 8229 CHECK(putstr(text, ";\n")); 8230 8231 snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len, 8232 zone_name); 8233 8234 cfg_parser_reset(named_g_addparser); 8235 result = cfg_parse_buffer(named_g_addparser, *text, bufname, 0, 8236 &cfg_type_addzoneconf, 0, &zoneconf); 8237 if (result != ISC_R_SUCCESS) { 8238 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8239 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8240 "parsing config for zone '%.*s' in " 8241 "NZD database '%s' failed", 8242 (int)zone_name_len, zone_name, view->new_zone_db); 8243 goto cleanup; 8244 } 8245 8246 *zoneconfig = zoneconf; 8247 zoneconf = NULL; 8248 result = ISC_R_SUCCESS; 8249 8250 cleanup: 8251 if (zoneconf != NULL) { 8252 cfg_obj_destroy(named_g_addparser, &zoneconf); 8253 } 8254 8255 return (result); 8256 } 8257 8258 /*% 8259 * Prototype for a callback which can be used with for_all_newzone_cfgs(). 8260 */ 8261 typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig, 8262 cfg_obj_t *config, cfg_obj_t *vconfig, 8263 isc_mem_t *mctx, dns_view_t *view, 8264 cfg_aclconfctx_t *actx); 8265 8266 /*% 8267 * For each zone found in a NZD opened by the caller, create an object 8268 * representing its configuration and invoke "callback" with the created 8269 * object, "config", "vconfig", "mctx", "view" and "actx" as arguments (all 8270 * these are non-global variables required to invoke configure_zone()). 8271 * Immediately interrupt processing if an error is encountered while 8272 * transforming NZD data into a zone configuration object or if "callback" 8273 * returns an error. 8274 * 8275 * Caller must hold 'view->new_zone_lock'. 8276 */ 8277 static isc_result_t 8278 for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config, 8279 cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 8280 cfg_aclconfctx_t *actx, MDB_txn *txn, MDB_dbi dbi) { 8281 const cfg_obj_t *zconfig, *zlist; 8282 isc_result_t result = ISC_R_SUCCESS; 8283 cfg_obj_t *zconfigobj = NULL; 8284 isc_buffer_t *text = NULL; 8285 MDB_cursor *cursor = NULL; 8286 MDB_val data, key; 8287 int status; 8288 8289 status = mdb_cursor_open(txn, dbi, &cursor); 8290 if (status != MDB_SUCCESS) { 8291 return (ISC_R_FAILURE); 8292 } 8293 8294 for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); 8295 status == MDB_SUCCESS; 8296 status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) 8297 { 8298 /* 8299 * Create a configuration object from data fetched from NZD. 8300 */ 8301 result = data_to_cfg(view, &key, &data, &text, &zconfigobj); 8302 if (result != ISC_R_SUCCESS) { 8303 break; 8304 } 8305 8306 /* 8307 * Extract zone configuration from configuration object. 8308 */ 8309 zlist = NULL; 8310 result = cfg_map_get(zconfigobj, "zone", &zlist); 8311 if (result != ISC_R_SUCCESS) { 8312 break; 8313 } else if (!cfg_obj_islist(zlist)) { 8314 result = ISC_R_FAILURE; 8315 break; 8316 } 8317 zconfig = cfg_listelt_value(cfg_list_first(zlist)); 8318 8319 /* 8320 * Invoke callback. 8321 */ 8322 result = callback(zconfig, config, vconfig, mctx, view, actx); 8323 if (result != ISC_R_SUCCESS) { 8324 break; 8325 } 8326 8327 /* 8328 * Destroy the configuration object created in this iteration. 8329 */ 8330 cfg_obj_destroy(named_g_addparser, &zconfigobj); 8331 } 8332 8333 if (text != NULL) { 8334 isc_buffer_free(&text); 8335 } 8336 if (zconfigobj != NULL) { 8337 cfg_obj_destroy(named_g_addparser, &zconfigobj); 8338 } 8339 mdb_cursor_close(cursor); 8340 8341 return (result); 8342 } 8343 8344 /*% 8345 * Attempt to configure a zone found in NZD and return the result. 8346 */ 8347 static isc_result_t 8348 configure_newzone(const cfg_obj_t *zconfig, cfg_obj_t *config, 8349 cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 8350 cfg_aclconfctx_t *actx) { 8351 return (configure_zone( 8352 config, zconfig, vconfig, mctx, view, &named_g_server->viewlist, 8353 &named_g_server->kasplist, actx, true, false, false, false)); 8354 } 8355 8356 /*% 8357 * Revert new view assignment for a zone found in NZD. 8358 */ 8359 static isc_result_t 8360 configure_newzone_revert(const cfg_obj_t *zconfig, cfg_obj_t *config, 8361 cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 8362 cfg_aclconfctx_t *actx) { 8363 UNUSED(config); 8364 UNUSED(vconfig); 8365 UNUSED(mctx); 8366 UNUSED(actx); 8367 8368 configure_zone_setviewcommit(ISC_R_FAILURE, zconfig, view); 8369 8370 return (ISC_R_SUCCESS); 8371 } 8372 8373 static isc_result_t 8374 configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, 8375 isc_mem_t *mctx, cfg_aclconfctx_t *actx) { 8376 isc_result_t result; 8377 MDB_txn *txn = NULL; 8378 MDB_dbi dbi; 8379 8380 if (view->new_zone_config == NULL) { 8381 return (ISC_R_SUCCESS); 8382 } 8383 8384 LOCK(&view->new_zone_lock); 8385 8386 result = nzd_open(view, MDB_RDONLY, &txn, &dbi); 8387 if (result != ISC_R_SUCCESS) { 8388 UNLOCK(&view->new_zone_lock); 8389 return (ISC_R_SUCCESS); 8390 } 8391 8392 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8393 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8394 "loading NZD configs from '%s' " 8395 "for view '%s'", 8396 view->new_zone_db, view->name); 8397 8398 result = for_all_newzone_cfgs(configure_newzone, config, vconfig, mctx, 8399 view, actx, txn, dbi); 8400 if (result != ISC_R_SUCCESS) { 8401 /* 8402 * An error was encountered while attempting to configure zones 8403 * found in NZD. As this error may have been caused by a 8404 * configure_zone() failure, try restoring a sane configuration 8405 * by reattaching all zones found in NZD to the old view. If 8406 * this also fails, too bad, there is nothing more we can do in 8407 * terms of trying to make things right. 8408 */ 8409 (void)for_all_newzone_cfgs(configure_newzone_revert, config, 8410 vconfig, mctx, view, actx, txn, dbi); 8411 } 8412 8413 (void)nzd_close(&txn, false); 8414 8415 UNLOCK(&view->new_zone_lock); 8416 8417 return (result); 8418 } 8419 8420 static isc_result_t 8421 get_newzone_config(dns_view_t *view, const char *zonename, 8422 cfg_obj_t **zoneconfig) { 8423 isc_result_t result; 8424 int status; 8425 cfg_obj_t *zoneconf = NULL; 8426 isc_buffer_t *text = NULL; 8427 MDB_txn *txn = NULL; 8428 MDB_dbi dbi; 8429 MDB_val key, data; 8430 char zname[DNS_NAME_FORMATSIZE]; 8431 dns_fixedname_t fname; 8432 dns_name_t *name; 8433 isc_buffer_t b; 8434 8435 INSIST(zoneconfig != NULL && *zoneconfig == NULL); 8436 8437 LOCK(&view->new_zone_lock); 8438 8439 CHECK(nzd_open(view, MDB_RDONLY, &txn, &dbi)); 8440 8441 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8442 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8443 "loading NZD config from '%s' " 8444 "for zone '%s'", 8445 view->new_zone_db, zonename); 8446 8447 /* Normalize zone name */ 8448 isc_buffer_constinit(&b, zonename, strlen(zonename)); 8449 isc_buffer_add(&b, strlen(zonename)); 8450 name = dns_fixedname_initname(&fname); 8451 CHECK(dns_name_fromtext(name, &b, dns_rootname, DNS_NAME_DOWNCASE, 8452 NULL)); 8453 dns_name_format(name, zname, sizeof(zname)); 8454 8455 key.mv_data = zname; 8456 key.mv_size = strlen(zname); 8457 8458 status = mdb_get(txn, dbi, &key, &data); 8459 if (status != MDB_SUCCESS) { 8460 CHECK(ISC_R_FAILURE); 8461 } 8462 8463 CHECK(data_to_cfg(view, &key, &data, &text, &zoneconf)); 8464 8465 *zoneconfig = zoneconf; 8466 zoneconf = NULL; 8467 result = ISC_R_SUCCESS; 8468 8469 cleanup: 8470 (void)nzd_close(&txn, false); 8471 8472 UNLOCK(&view->new_zone_lock); 8473 8474 if (zoneconf != NULL) { 8475 cfg_obj_destroy(named_g_addparser, &zoneconf); 8476 } 8477 if (text != NULL) { 8478 isc_buffer_free(&text); 8479 } 8480 8481 return (result); 8482 } 8483 8484 #endif /* HAVE_LMDB */ 8485 8486 static int 8487 count_zones(const cfg_obj_t *conf) { 8488 const cfg_obj_t *zonelist = NULL; 8489 const cfg_listelt_t *element; 8490 int n = 0; 8491 8492 REQUIRE(conf != NULL); 8493 8494 cfg_map_get(conf, "zone", &zonelist); 8495 for (element = cfg_list_first(zonelist); element != NULL; 8496 element = cfg_list_next(element)) 8497 { 8498 n++; 8499 } 8500 8501 return (n); 8502 } 8503 8504 static isc_result_t 8505 check_lockfile(named_server_t *server, const cfg_obj_t *config, 8506 bool first_time) { 8507 isc_result_t result; 8508 const char *filename = NULL; 8509 const cfg_obj_t *maps[3]; 8510 const cfg_obj_t *options; 8511 const cfg_obj_t *obj; 8512 int i; 8513 8514 i = 0; 8515 options = NULL; 8516 result = cfg_map_get(config, "options", &options); 8517 if (result == ISC_R_SUCCESS) { 8518 maps[i++] = options; 8519 } 8520 maps[i++] = named_g_defaults; 8521 maps[i] = NULL; 8522 8523 obj = NULL; 8524 (void)named_config_get(maps, "lock-file", &obj); 8525 8526 if (!first_time) { 8527 if (obj != NULL && cfg_obj_isstring(obj) && 8528 server->lockfile != NULL && !named_g_forcelock && 8529 strcmp(cfg_obj_asstring(obj), server->lockfile) != 0) 8530 { 8531 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8532 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 8533 "changing 'lock-file' " 8534 "has no effect until the " 8535 "server is restarted"); 8536 } 8537 8538 return (ISC_R_SUCCESS); 8539 } 8540 8541 if (obj != NULL) { 8542 if (named_g_forcelock) { 8543 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8544 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 8545 "'lock-file' has no effect " 8546 "because the server was run with -X"); 8547 if (named_g_defaultlockfile != NULL) { 8548 server->lockfile = isc_mem_strdup( 8549 server->mctx, named_g_defaultlockfile); 8550 } 8551 } else if (cfg_obj_isvoid(obj)) { 8552 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8553 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 8554 "skipping lock-file check"); 8555 } else if (cfg_obj_isstring(obj)) { 8556 filename = cfg_obj_asstring(obj); 8557 server->lockfile = isc_mem_strdup(server->mctx, 8558 filename); 8559 } 8560 } else if (named_g_forcelock && named_g_defaultlockfile != NULL) { 8561 server->lockfile = isc_mem_strdup(server->mctx, 8562 named_g_defaultlockfile); 8563 } 8564 8565 if (server->lockfile == NULL) { 8566 return (ISC_R_SUCCESS); 8567 } 8568 8569 if (named_os_issingleton(server->lockfile)) { 8570 return (ISC_R_SUCCESS); 8571 } 8572 8573 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8574 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8575 "could not lock %s; another named " 8576 "process may be running", 8577 server->lockfile); 8578 return (ISC_R_FAILURE); 8579 } 8580 8581 static isc_result_t 8582 load_configuration(const char *filename, named_server_t *server, 8583 bool first_time) { 8584 cfg_obj_t *config = NULL, *bindkeys = NULL; 8585 cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; 8586 const cfg_listelt_t *element; 8587 const cfg_obj_t *builtin_views; 8588 const cfg_obj_t *maps[3]; 8589 const cfg_obj_t *obj; 8590 const cfg_obj_t *options; 8591 const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; 8592 const cfg_obj_t *kasps; 8593 dns_kasp_t *kasp = NULL; 8594 dns_kasp_t *kasp_next = NULL; 8595 dns_kasp_t *default_kasp = NULL; 8596 dns_kasplist_t tmpkasplist, kasplist; 8597 const cfg_obj_t *views; 8598 dns_view_t *view = NULL; 8599 dns_view_t *view_next = NULL; 8600 dns_viewlist_t tmpviewlist; 8601 dns_viewlist_t viewlist, builtin_viewlist; 8602 in_port_t listen_port, udpport_low, udpport_high; 8603 int i, backlog; 8604 int num_zones = 0; 8605 bool exclusive = false; 8606 isc_interval_t interval; 8607 isc_logconfig_t *logc = NULL; 8608 isc_portset_t *v4portset = NULL; 8609 isc_portset_t *v6portset = NULL; 8610 isc_result_t result, tresult; 8611 uint32_t heartbeat_interval; 8612 uint32_t interface_interval; 8613 uint32_t udpsize; 8614 uint32_t transfer_message_size; 8615 uint32_t recv_tcp_buffer_size; 8616 uint32_t send_tcp_buffer_size; 8617 uint32_t recv_udp_buffer_size; 8618 uint32_t send_udp_buffer_size; 8619 named_cache_t *nsc; 8620 named_cachelist_t cachelist, tmpcachelist; 8621 ns_altsecret_t *altsecret; 8622 ns_altsecretlist_t altsecrets, tmpaltsecrets; 8623 uint32_t softquota = 0; 8624 uint32_t max; 8625 uint64_t initial, idle, keepalive, advertised; 8626 bool loadbalancesockets; 8627 dns_aclenv_t *env = 8628 ns_interfacemgr_getaclenv(named_g_server->interfacemgr); 8629 8630 ISC_LIST_INIT(kasplist); 8631 ISC_LIST_INIT(viewlist); 8632 ISC_LIST_INIT(builtin_viewlist); 8633 ISC_LIST_INIT(cachelist); 8634 ISC_LIST_INIT(altsecrets); 8635 8636 /* Create the ACL configuration context */ 8637 if (named_g_aclconfctx != NULL) { 8638 cfg_aclconfctx_detach(&named_g_aclconfctx); 8639 } 8640 CHECK(cfg_aclconfctx_create(named_g_mctx, &named_g_aclconfctx)); 8641 8642 /* 8643 * Shut down all dyndb instances. 8644 */ 8645 dns_dyndb_cleanup(false); 8646 8647 /* 8648 * Parse the global default pseudo-config file. 8649 */ 8650 if (first_time) { 8651 result = named_config_parsedefaults(named_g_parser, 8652 &named_g_config); 8653 if (result != ISC_R_SUCCESS) { 8654 named_main_earlyfatal("unable to load " 8655 "internal defaults: %s", 8656 isc_result_totext(result)); 8657 } 8658 RUNTIME_CHECK(cfg_map_get(named_g_config, "options", 8659 &named_g_defaults) == ISC_R_SUCCESS); 8660 } 8661 8662 /* 8663 * Log the current working directory. 8664 */ 8665 if (first_time) { 8666 char cwd[PATH_MAX]; 8667 if (getcwd(cwd, sizeof(cwd)) == cwd) { 8668 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8669 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8670 "the initial working directory is '%s'", 8671 cwd); 8672 } 8673 } 8674 8675 /* 8676 * Parse the configuration file using the new config code. 8677 */ 8678 config = NULL; 8679 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8680 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8681 "loading configuration from '%s'", filename); 8682 CHECK(cfg_parser_create(named_g_mctx, named_g_lctx, &conf_parser)); 8683 cfg_parser_setcallback(conf_parser, directory_callback, NULL); 8684 result = cfg_parse_file(conf_parser, filename, &cfg_type_namedconf, 8685 &config); 8686 8687 CHECK(result); 8688 8689 /* 8690 * Check the validity of the configuration. 8691 * 8692 * (Ignore plugin parameters for now; they will be 8693 * checked later when the modules are actually loaded and 8694 * registered.) 8695 */ 8696 CHECK(bind9_check_namedconf(config, false, false, named_g_lctx, 8697 named_g_mctx)); 8698 8699 /* Let's recreate the TLS context cache */ 8700 if (server->tlsctx_server_cache != NULL) { 8701 isc_tlsctx_cache_detach(&server->tlsctx_server_cache); 8702 } 8703 8704 isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_server_cache); 8705 8706 if (server->tlsctx_client_cache != NULL) { 8707 isc_tlsctx_cache_detach(&server->tlsctx_client_cache); 8708 } 8709 8710 isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_client_cache); 8711 8712 dns_zonemgr_set_tlsctx_cache(server->zonemgr, 8713 server->tlsctx_client_cache); 8714 8715 /* 8716 * Fill in the maps array, used for resolving defaults. 8717 */ 8718 i = 0; 8719 options = NULL; 8720 result = cfg_map_get(config, "options", &options); 8721 if (result == ISC_R_SUCCESS) { 8722 maps[i++] = options; 8723 } 8724 maps[i++] = named_g_defaults; 8725 maps[i] = NULL; 8726 8727 #if HAVE_LIBNGHTTP2 8728 obj = NULL; 8729 result = named_config_get(maps, "http-port", &obj); 8730 INSIST(result == ISC_R_SUCCESS); 8731 named_g_httpport = (in_port_t)cfg_obj_asuint32(obj); 8732 8733 obj = NULL; 8734 result = named_config_get(maps, "https-port", &obj); 8735 INSIST(result == ISC_R_SUCCESS); 8736 named_g_httpsport = (in_port_t)cfg_obj_asuint32(obj); 8737 8738 obj = NULL; 8739 result = named_config_get(maps, "http-listener-clients", &obj); 8740 INSIST(result == ISC_R_SUCCESS); 8741 named_g_http_listener_clients = cfg_obj_asuint32(obj); 8742 8743 obj = NULL; 8744 result = named_config_get(maps, "http-streams-per-connection", &obj); 8745 INSIST(result == ISC_R_SUCCESS); 8746 named_g_http_streams_per_conn = cfg_obj_asuint32(obj); 8747 #endif 8748 8749 /* 8750 * If bind.keys exists, load it. If "dnssec-validation auto" 8751 * is turned on, the root key found there will be used as a 8752 * default trust anchor. 8753 */ 8754 obj = NULL; 8755 result = named_config_get(maps, "bindkeys-file", &obj); 8756 INSIST(result == ISC_R_SUCCESS); 8757 CHECKM(setstring(server, &server->bindkeysfile, cfg_obj_asstring(obj)), 8758 "strdup"); 8759 INSIST(server->bindkeysfile != NULL); 8760 8761 if (access(server->bindkeysfile, R_OK) == 0) { 8762 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8763 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8764 "reading built-in trust anchors " 8765 "from file '%s'", 8766 server->bindkeysfile); 8767 8768 CHECK(cfg_parser_create(named_g_mctx, named_g_lctx, 8769 &bindkeys_parser)); 8770 8771 result = cfg_parse_file(bindkeys_parser, server->bindkeysfile, 8772 &cfg_type_bindkeys, &bindkeys); 8773 if (result != ISC_R_SUCCESS) { 8774 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8775 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8776 "unable to parse '%s' error '%s'; using " 8777 "built-in keys instead", 8778 server->bindkeysfile, 8779 isc_result_totext(result)); 8780 } 8781 } else { 8782 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8783 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 8784 "unable to open '%s'; using built-in keys " 8785 "instead", 8786 server->bindkeysfile); 8787 } 8788 8789 /* Ensure exclusive access to configuration data. */ 8790 if (!exclusive) { 8791 result = isc_task_beginexclusive(server->task); 8792 RUNTIME_CHECK(result == ISC_R_SUCCESS); 8793 exclusive = true; 8794 } 8795 8796 /* 8797 * Set process limits, which (usually) needs to be done as root. 8798 */ 8799 set_limits(maps); 8800 8801 /* 8802 * Check the process lockfile. 8803 */ 8804 CHECK(check_lockfile(server, config, first_time)); 8805 8806 #if defined(HAVE_GEOIP2) 8807 /* 8808 * Release any previously opened GeoIP2 databases. 8809 */ 8810 named_geoip_unload(); 8811 8812 /* 8813 * Initialize GeoIP databases from the configured location. 8814 * This should happen before configuring any ACLs, so that we 8815 * know what databases are available and can reject any GeoIP 8816 * ACLs that can't work. 8817 */ 8818 obj = NULL; 8819 result = named_config_get(maps, "geoip-directory", &obj); 8820 INSIST(result == ISC_R_SUCCESS); 8821 if (cfg_obj_isstring(obj)) { 8822 char *dir; 8823 DE_CONST(cfg_obj_asstring(obj), dir); 8824 named_geoip_load(dir); 8825 } 8826 named_g_aclconfctx->geoip = named_g_geoip; 8827 #endif /* HAVE_GEOIP2 */ 8828 8829 /* 8830 * Configure various server options. 8831 */ 8832 configure_server_quota(maps, "transfers-out", 8833 &server->sctx->xfroutquota); 8834 configure_server_quota(maps, "tcp-clients", &server->sctx->tcpquota); 8835 configure_server_quota(maps, "recursive-clients", 8836 &server->sctx->recursionquota); 8837 configure_server_quota(maps, "update-quota", &server->sctx->updquota); 8838 8839 max = isc_quota_getmax(&server->sctx->recursionquota); 8840 if (max > 1000) { 8841 unsigned margin = ISC_MAX(100, named_g_cpus + 1); 8842 if (margin + 100 > max) { 8843 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 8844 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 8845 "'recursive-clients %d' too low when " 8846 "running with %d worker threads", 8847 max, named_g_cpus); 8848 CHECK(ISC_R_RANGE); 8849 } 8850 softquota = max - margin; 8851 } else { 8852 softquota = (max * 90) / 100; 8853 } 8854 8855 isc_quota_soft(&server->sctx->recursionquota, softquota); 8856 8857 /* 8858 * Set "blackhole". Only legal at options level; there is 8859 * no default. 8860 */ 8861 CHECK(configure_view_acl(NULL, config, NULL, "blackhole", NULL, 8862 named_g_aclconfctx, named_g_mctx, 8863 &server->sctx->blackholeacl)); 8864 if (server->sctx->blackholeacl != NULL) { 8865 dns_dispatchmgr_setblackhole(named_g_dispatchmgr, 8866 server->sctx->blackholeacl); 8867 } 8868 8869 /* 8870 * Set "keep-response-order". Only legal at options or 8871 * global defaults level. 8872 */ 8873 CHECK(configure_view_acl(NULL, config, named_g_config, 8874 "keep-response-order", NULL, 8875 named_g_aclconfctx, named_g_mctx, 8876 &server->sctx->keepresporder)); 8877 8878 obj = NULL; 8879 result = named_config_get(maps, "match-mapped-addresses", &obj); 8880 INSIST(result == ISC_R_SUCCESS); 8881 env->match_mapped = cfg_obj_asboolean(obj); 8882 8883 CHECKM(named_statschannels_configure(named_g_server, config, 8884 named_g_aclconfctx), 8885 "configuring statistics server(s)"); 8886 8887 /* 8888 * Configure the network manager 8889 */ 8890 obj = NULL; 8891 result = named_config_get(maps, "tcp-initial-timeout", &obj); 8892 INSIST(result == ISC_R_SUCCESS); 8893 initial = cfg_obj_asuint32(obj) * 100; 8894 if (initial > MAX_INITIAL_TIMEOUT) { 8895 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8896 "tcp-initial-timeout value is out of range: " 8897 "lowering to %" PRIu32, 8898 MAX_INITIAL_TIMEOUT / 100); 8899 initial = MAX_INITIAL_TIMEOUT; 8900 } else if (initial < MIN_INITIAL_TIMEOUT) { 8901 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8902 "tcp-initial-timeout value is out of range: " 8903 "raising to %" PRIu32, 8904 MIN_INITIAL_TIMEOUT / 100); 8905 initial = MIN_INITIAL_TIMEOUT; 8906 } 8907 8908 obj = NULL; 8909 result = named_config_get(maps, "tcp-idle-timeout", &obj); 8910 INSIST(result == ISC_R_SUCCESS); 8911 idle = cfg_obj_asuint32(obj) * 100; 8912 if (idle > MAX_IDLE_TIMEOUT) { 8913 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8914 "tcp-idle-timeout value is out of range: " 8915 "lowering to %" PRIu32, 8916 MAX_IDLE_TIMEOUT / 100); 8917 idle = MAX_IDLE_TIMEOUT; 8918 } else if (idle < MIN_IDLE_TIMEOUT) { 8919 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8920 "tcp-idle-timeout value is out of range: " 8921 "raising to %" PRIu32, 8922 MIN_IDLE_TIMEOUT / 100); 8923 idle = MIN_IDLE_TIMEOUT; 8924 } 8925 8926 obj = NULL; 8927 result = named_config_get(maps, "tcp-keepalive-timeout", &obj); 8928 INSIST(result == ISC_R_SUCCESS); 8929 keepalive = cfg_obj_asuint32(obj) * 100; 8930 if (keepalive > MAX_KEEPALIVE_TIMEOUT) { 8931 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8932 "tcp-keepalive-timeout value is out of range: " 8933 "lowering to %" PRIu32, 8934 MAX_KEEPALIVE_TIMEOUT / 100); 8935 keepalive = MAX_KEEPALIVE_TIMEOUT; 8936 } else if (keepalive < MIN_KEEPALIVE_TIMEOUT) { 8937 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8938 "tcp-keepalive-timeout value is out of range: " 8939 "raising to %" PRIu32, 8940 MIN_KEEPALIVE_TIMEOUT / 100); 8941 keepalive = MIN_KEEPALIVE_TIMEOUT; 8942 } 8943 8944 obj = NULL; 8945 result = named_config_get(maps, "tcp-advertised-timeout", &obj); 8946 INSIST(result == ISC_R_SUCCESS); 8947 advertised = cfg_obj_asuint32(obj) * 100; 8948 if (advertised > MAX_ADVERTISED_TIMEOUT) { 8949 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 8950 "tcp-advertized-timeout value is out of range: " 8951 "lowering to %" PRIu32, 8952 MAX_ADVERTISED_TIMEOUT / 100); 8953 advertised = MAX_ADVERTISED_TIMEOUT; 8954 } 8955 8956 isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, 8957 advertised); 8958 8959 #define CAP_IF_NOT_ZERO(v, min, max) \ 8960 if (v > 0 && v < min) { \ 8961 v = min; \ 8962 } else if (v > max) { \ 8963 v = max; \ 8964 } 8965 8966 /* Set the kernel send and receive buffer sizes */ 8967 obj = NULL; 8968 result = named_config_get(maps, "tcp-receive-buffer", &obj); 8969 INSIST(result == ISC_R_SUCCESS); 8970 recv_tcp_buffer_size = cfg_obj_asuint32(obj); 8971 CAP_IF_NOT_ZERO(recv_tcp_buffer_size, 4096, INT32_MAX); 8972 8973 obj = NULL; 8974 result = named_config_get(maps, "tcp-send-buffer", &obj); 8975 INSIST(result == ISC_R_SUCCESS); 8976 send_tcp_buffer_size = cfg_obj_asuint32(obj); 8977 CAP_IF_NOT_ZERO(send_tcp_buffer_size, 4096, INT32_MAX); 8978 8979 obj = NULL; 8980 result = named_config_get(maps, "udp-receive-buffer", &obj); 8981 INSIST(result == ISC_R_SUCCESS); 8982 recv_udp_buffer_size = cfg_obj_asuint32(obj); 8983 CAP_IF_NOT_ZERO(recv_udp_buffer_size, 4096, INT32_MAX); 8984 8985 obj = NULL; 8986 result = named_config_get(maps, "udp-send-buffer", &obj); 8987 INSIST(result == ISC_R_SUCCESS); 8988 send_udp_buffer_size = cfg_obj_asuint32(obj); 8989 CAP_IF_NOT_ZERO(send_udp_buffer_size, 4096, INT32_MAX); 8990 8991 isc_nm_setnetbuffers(named_g_netmgr, recv_tcp_buffer_size, 8992 send_tcp_buffer_size, recv_udp_buffer_size, 8993 send_udp_buffer_size); 8994 8995 #undef CAP_IF_NOT_ZERO 8996 8997 /* 8998 * Configure sets of UDP query source ports. 8999 */ 9000 CHECKM(isc_portset_create(named_g_mctx, &v4portset), "creating UDP " 9001 "port set"); 9002 CHECKM(isc_portset_create(named_g_mctx, &v6portset), "creating UDP " 9003 "port set"); 9004 9005 usev4ports = NULL; 9006 usev6ports = NULL; 9007 avoidv4ports = NULL; 9008 avoidv6ports = NULL; 9009 9010 (void)named_config_get(maps, "use-v4-udp-ports", &usev4ports); 9011 if (usev4ports != NULL) { 9012 portset_fromconf(v4portset, usev4ports, true); 9013 } else { 9014 CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low, 9015 &udpport_high), 9016 "get the default UDP/IPv4 port range"); 9017 if (udpport_low == udpport_high) { 9018 isc_portset_add(v4portset, udpport_low); 9019 } else { 9020 isc_portset_addrange(v4portset, udpport_low, 9021 udpport_high); 9022 } 9023 if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE4)) { 9024 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9025 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9026 "using default UDP/IPv4 port range: " 9027 "[%d, %d]", 9028 udpport_low, udpport_high); 9029 } 9030 } 9031 (void)named_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports); 9032 if (avoidv4ports != NULL) { 9033 portset_fromconf(v4portset, avoidv4ports, false); 9034 } 9035 9036 (void)named_config_get(maps, "use-v6-udp-ports", &usev6ports); 9037 if (usev6ports != NULL) { 9038 portset_fromconf(v6portset, usev6ports, true); 9039 } else { 9040 CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low, 9041 &udpport_high), 9042 "get the default UDP/IPv6 port range"); 9043 if (udpport_low == udpport_high) { 9044 isc_portset_add(v6portset, udpport_low); 9045 } else { 9046 isc_portset_addrange(v6portset, udpport_low, 9047 udpport_high); 9048 } 9049 if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE6)) { 9050 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9051 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9052 "using default UDP/IPv6 port range: " 9053 "[%d, %d]", 9054 udpport_low, udpport_high); 9055 } 9056 } 9057 (void)named_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports); 9058 if (avoidv6ports != NULL) { 9059 portset_fromconf(v6portset, avoidv6ports, false); 9060 } 9061 9062 dns_dispatchmgr_setavailports(named_g_dispatchmgr, v4portset, 9063 v6portset); 9064 9065 /* 9066 * Set the EDNS UDP size when we don't match a view. 9067 */ 9068 obj = NULL; 9069 result = named_config_get(maps, "edns-udp-size", &obj); 9070 INSIST(result == ISC_R_SUCCESS); 9071 udpsize = cfg_obj_asuint32(obj); 9072 if (udpsize < 512) { 9073 udpsize = 512; 9074 } 9075 if (udpsize > 4096) { 9076 udpsize = 4096; 9077 } 9078 server->sctx->udpsize = (uint16_t)udpsize; 9079 9080 /* Set the transfer message size for TCP */ 9081 obj = NULL; 9082 result = named_config_get(maps, "transfer-message-size", &obj); 9083 INSIST(result == ISC_R_SUCCESS); 9084 transfer_message_size = cfg_obj_asuint32(obj); 9085 if (transfer_message_size < 512) { 9086 transfer_message_size = 512; 9087 } else if (transfer_message_size > 65535) { 9088 transfer_message_size = 65535; 9089 } 9090 server->sctx->transfer_tcp_message_size = 9091 (uint16_t)transfer_message_size; 9092 9093 /* 9094 * Configure the zone manager. 9095 */ 9096 obj = NULL; 9097 result = named_config_get(maps, "transfers-in", &obj); 9098 INSIST(result == ISC_R_SUCCESS); 9099 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); 9100 9101 obj = NULL; 9102 result = named_config_get(maps, "transfers-per-ns", &obj); 9103 INSIST(result == ISC_R_SUCCESS); 9104 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); 9105 9106 obj = NULL; 9107 result = named_config_get(maps, "notify-rate", &obj); 9108 INSIST(result == ISC_R_SUCCESS); 9109 dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj)); 9110 9111 obj = NULL; 9112 result = named_config_get(maps, "startup-notify-rate", &obj); 9113 INSIST(result == ISC_R_SUCCESS); 9114 dns_zonemgr_setstartupnotifyrate(server->zonemgr, 9115 cfg_obj_asuint32(obj)); 9116 9117 obj = NULL; 9118 result = named_config_get(maps, "serial-query-rate", &obj); 9119 INSIST(result == ISC_R_SUCCESS); 9120 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); 9121 9122 /* 9123 * Determine which port to use for listening for incoming connections. 9124 */ 9125 if (named_g_port != 0) { 9126 listen_port = named_g_port; 9127 } else { 9128 CHECKM(named_config_getport(config, "port", &listen_port), 9129 "port"); 9130 } 9131 9132 /* 9133 * Find the listen queue depth. 9134 */ 9135 obj = NULL; 9136 result = named_config_get(maps, "tcp-listen-queue", &obj); 9137 INSIST(result == ISC_R_SUCCESS); 9138 backlog = cfg_obj_asuint32(obj); 9139 if ((backlog > 0) && (backlog < 10)) { 9140 backlog = 10; 9141 } 9142 ns_interfacemgr_setbacklog(server->interfacemgr, backlog); 9143 9144 obj = NULL; 9145 result = named_config_get(maps, "reuseport", &obj); 9146 INSIST(result == ISC_R_SUCCESS); 9147 loadbalancesockets = cfg_obj_asboolean(obj); 9148 #if HAVE_SO_REUSEPORT_LB 9149 if (first_time) { 9150 isc_nm_setloadbalancesockets(named_g_netmgr, 9151 cfg_obj_asboolean(obj)); 9152 } else if (loadbalancesockets != 9153 isc_nm_getloadbalancesockets(named_g_netmgr)) 9154 { 9155 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 9156 "changing reuseport value requires server restart"); 9157 } 9158 #else 9159 if (loadbalancesockets) { 9160 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, 9161 "reuseport has no effect on this system"); 9162 } 9163 #endif 9164 9165 /* 9166 * Configure the interface manager according to the "listen-on" 9167 * statement. 9168 */ 9169 { 9170 const cfg_obj_t *clistenon = NULL; 9171 ns_listenlist_t *listenon = NULL; 9172 9173 clistenon = NULL; 9174 /* 9175 * Even though listen-on is present in the default 9176 * configuration, this way is easier. 9177 */ 9178 if (options != NULL) { 9179 (void)cfg_map_get(options, "listen-on", &clistenon); 9180 } 9181 if (clistenon != NULL) { 9182 CHECK(listenlist_fromconfig( 9183 clistenon, config, named_g_aclconfctx, 9184 named_g_mctx, AF_INET, 9185 server->tlsctx_server_cache, &listenon)); 9186 } else { 9187 /* 9188 * Not specified, use default. 9189 */ 9190 CHECK(ns_listenlist_default(named_g_mctx, listen_port, 9191 true, AF_INET, &listenon)); 9192 } 9193 if (listenon != NULL) { 9194 ns_interfacemgr_setlistenon4(server->interfacemgr, 9195 listenon); 9196 ns_listenlist_detach(&listenon); 9197 } 9198 } 9199 /* 9200 * Ditto for IPv6. 9201 */ 9202 { 9203 const cfg_obj_t *clistenon = NULL; 9204 ns_listenlist_t *listenon = NULL; 9205 9206 if (options != NULL) { 9207 (void)cfg_map_get(options, "listen-on-v6", &clistenon); 9208 } 9209 if (clistenon != NULL) { 9210 CHECK(listenlist_fromconfig( 9211 clistenon, config, named_g_aclconfctx, 9212 named_g_mctx, AF_INET6, 9213 server->tlsctx_server_cache, &listenon)); 9214 } else { 9215 /* 9216 * Not specified, use default. 9217 */ 9218 CHECK(ns_listenlist_default(named_g_mctx, listen_port, 9219 true, AF_INET6, &listenon)); 9220 } 9221 if (listenon != NULL) { 9222 ns_interfacemgr_setlistenon6(server->interfacemgr, 9223 listenon); 9224 ns_listenlist_detach(&listenon); 9225 } 9226 } 9227 9228 /* 9229 * Rescan the interface list to pick up changes in the 9230 * listen-on option. It's important that we do this before we try 9231 * to configure the query source, since the dispatcher we use might 9232 * be shared with an interface. 9233 */ 9234 result = ns_interfacemgr_scan(server->interfacemgr, true, true); 9235 9236 /* 9237 * Check that named is able to TCP listen on at least one 9238 * interface. Otherwise, another named process could be running 9239 * and we should fail. 9240 */ 9241 if (first_time && (result == ISC_R_ADDRINUSE)) { 9242 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9243 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9244 "unable to listen on any configured interfaces"); 9245 result = ISC_R_FAILURE; 9246 goto cleanup; 9247 } 9248 9249 /* 9250 * Arrange for further interface scanning to occur periodically 9251 * as specified by the "interface-interval" option. 9252 */ 9253 obj = NULL; 9254 result = named_config_get(maps, "interface-interval", &obj); 9255 INSIST(result == ISC_R_SUCCESS); 9256 interface_interval = cfg_obj_asduration(obj); 9257 if (interface_interval == 0) { 9258 CHECK(isc_timer_reset(server->interface_timer, 9259 isc_timertype_inactive, NULL, NULL, 9260 true)); 9261 } else if (server->interface_interval != interface_interval) { 9262 isc_interval_set(&interval, interface_interval, 0); 9263 CHECK(isc_timer_reset(server->interface_timer, 9264 isc_timertype_ticker, NULL, &interval, 9265 false)); 9266 } 9267 server->interface_interval = interface_interval; 9268 9269 /* 9270 * Enable automatic interface scans. 9271 */ 9272 obj = NULL; 9273 result = named_config_get(maps, "automatic-interface-scan", &obj); 9274 INSIST(result == ISC_R_SUCCESS); 9275 server->sctx->interface_auto = cfg_obj_asboolean(obj); 9276 9277 /* 9278 * Configure the dialup heartbeat timer. 9279 */ 9280 obj = NULL; 9281 result = named_config_get(maps, "heartbeat-interval", &obj); 9282 INSIST(result == ISC_R_SUCCESS); 9283 heartbeat_interval = cfg_obj_asuint32(obj) * 60; 9284 if (heartbeat_interval == 0) { 9285 CHECK(isc_timer_reset(server->heartbeat_timer, 9286 isc_timertype_inactive, NULL, NULL, 9287 true)); 9288 } else if (server->heartbeat_interval != heartbeat_interval) { 9289 isc_interval_set(&interval, heartbeat_interval, 0); 9290 CHECK(isc_timer_reset(server->heartbeat_timer, 9291 isc_timertype_ticker, NULL, &interval, 9292 false)); 9293 } 9294 server->heartbeat_interval = heartbeat_interval; 9295 9296 isc_interval_set(&interval, 1200, 0); 9297 CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL, 9298 &interval, false)); 9299 9300 isc_interval_set(&interval, named_g_tat_interval, 0); 9301 CHECK(isc_timer_reset(server->tat_timer, isc_timertype_ticker, NULL, 9302 &interval, false)); 9303 9304 /* 9305 * Write the PID file. 9306 */ 9307 obj = NULL; 9308 if (named_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) { 9309 if (cfg_obj_isvoid(obj)) { 9310 named_os_writepidfile(NULL, first_time); 9311 } else { 9312 named_os_writepidfile(cfg_obj_asstring(obj), 9313 first_time); 9314 } 9315 } else { 9316 named_os_writepidfile(named_g_defaultpidfile, first_time); 9317 } 9318 9319 /* 9320 * Configure the server-wide session key. This must be done before 9321 * configure views because zone configuration may need to know 9322 * session-keyname. 9323 * 9324 * Failure of session key generation isn't fatal at this time; if it 9325 * turns out that a session key is really needed but doesn't exist, 9326 * we'll treat it as a fatal error then. 9327 */ 9328 (void)configure_session_key(maps, server, named_g_mctx, first_time); 9329 9330 /* 9331 * Create the built-in kasp policies ("default", "insecure"). 9332 */ 9333 kasps = NULL; 9334 (void)cfg_map_get(named_g_config, "dnssec-policy", &kasps); 9335 for (element = cfg_list_first(kasps); element != NULL; 9336 element = cfg_list_next(element)) 9337 { 9338 cfg_obj_t *kconfig = cfg_listelt_value(element); 9339 9340 kasp = NULL; 9341 CHECK(cfg_kasp_fromconfig(kconfig, default_kasp, named_g_mctx, 9342 named_g_lctx, &kasplist, &kasp)); 9343 INSIST(kasp != NULL); 9344 dns_kasp_freeze(kasp); 9345 9346 /* Insist that the first built-in policy is the default one. */ 9347 if (default_kasp == NULL) { 9348 INSIST(strcmp(dns_kasp_getname(kasp), "default") == 0); 9349 dns_kasp_attach(kasp, &default_kasp); 9350 } 9351 9352 dns_kasp_detach(&kasp); 9353 } 9354 INSIST(default_kasp != NULL); 9355 9356 /* 9357 * Create the DNSSEC key and signing policies (KASP). 9358 */ 9359 kasps = NULL; 9360 (void)cfg_map_get(config, "dnssec-policy", &kasps); 9361 for (element = cfg_list_first(kasps); element != NULL; 9362 element = cfg_list_next(element)) 9363 { 9364 cfg_obj_t *kconfig = cfg_listelt_value(element); 9365 kasp = NULL; 9366 CHECK(cfg_kasp_fromconfig(kconfig, default_kasp, named_g_mctx, 9367 named_g_lctx, &kasplist, &kasp)); 9368 INSIST(kasp != NULL); 9369 dns_kasp_freeze(kasp); 9370 dns_kasp_detach(&kasp); 9371 } 9372 9373 dns_kasp_detach(&default_kasp); 9374 tmpkasplist = server->kasplist; 9375 server->kasplist = kasplist; 9376 kasplist = tmpkasplist; 9377 9378 /* 9379 * Configure the views. 9380 */ 9381 views = NULL; 9382 (void)cfg_map_get(config, "view", &views); 9383 9384 /* 9385 * Create the views and count all the configured zones in 9386 * order to correctly size the zone manager's task table. 9387 * (We only count zones for configured views; the built-in 9388 * "bind" view can be ignored as it only adds a negligible 9389 * number of zones.) 9390 * 9391 * If we're allowing new zones, we need to be able to find the 9392 * new zone file and count those as well. So we setup the new 9393 * zone configuration context, but otherwise view configuration 9394 * waits until after the zone manager's task list has been sized. 9395 */ 9396 for (element = cfg_list_first(views); element != NULL; 9397 element = cfg_list_next(element)) 9398 { 9399 cfg_obj_t *vconfig = cfg_listelt_value(element); 9400 const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options"); 9401 int nzf_num_zones; 9402 9403 view = NULL; 9404 9405 CHECK(create_view(vconfig, &viewlist, &view)); 9406 INSIST(view != NULL); 9407 9408 num_zones += count_zones(voptions); 9409 9410 CHECK(setup_newzones(view, config, vconfig, conf_parser, 9411 named_g_aclconfctx, &nzf_num_zones)); 9412 num_zones += nzf_num_zones; 9413 9414 dns_view_detach(&view); 9415 } 9416 9417 /* 9418 * If there were no explicit views then we do the default 9419 * view here. 9420 */ 9421 if (views == NULL) { 9422 int nzf_num_zones; 9423 9424 CHECK(create_view(NULL, &viewlist, &view)); 9425 INSIST(view != NULL); 9426 9427 num_zones = count_zones(config); 9428 9429 CHECK(setup_newzones(view, config, NULL, conf_parser, 9430 named_g_aclconfctx, &nzf_num_zones)); 9431 num_zones += nzf_num_zones; 9432 9433 dns_view_detach(&view); 9434 } 9435 9436 /* 9437 * Zones have been counted; set the zone manager task pool size. 9438 */ 9439 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9440 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9441 "sizing zone task pool based on %d zones", num_zones); 9442 CHECK(dns_zonemgr_setsize(named_g_server->zonemgr, num_zones)); 9443 9444 /* 9445 * Configure and freeze all explicit views. Explicit 9446 * views that have zones were already created at parsing 9447 * time, but views with no zones must be created here. 9448 */ 9449 for (element = cfg_list_first(views); element != NULL; 9450 element = cfg_list_next(element)) 9451 { 9452 cfg_obj_t *vconfig = cfg_listelt_value(element); 9453 9454 view = NULL; 9455 CHECK(find_view(vconfig, &viewlist, &view)); 9456 CHECK(configure_view(view, &viewlist, config, vconfig, 9457 &cachelist, &server->kasplist, bindkeys, 9458 named_g_mctx, named_g_aclconfctx, true)); 9459 dns_view_freeze(view); 9460 dns_view_detach(&view); 9461 } 9462 9463 /* 9464 * Make sure we have a default view if and only if there 9465 * were no explicit views. 9466 */ 9467 if (views == NULL) { 9468 view = NULL; 9469 CHECK(find_view(NULL, &viewlist, &view)); 9470 CHECK(configure_view(view, &viewlist, config, NULL, &cachelist, 9471 &server->kasplist, bindkeys, named_g_mctx, 9472 named_g_aclconfctx, true)); 9473 dns_view_freeze(view); 9474 dns_view_detach(&view); 9475 } 9476 9477 /* 9478 * Create (or recreate) the built-in views. 9479 */ 9480 builtin_views = NULL; 9481 RUNTIME_CHECK(cfg_map_get(named_g_config, "view", &builtin_views) == 9482 ISC_R_SUCCESS); 9483 for (element = cfg_list_first(builtin_views); element != NULL; 9484 element = cfg_list_next(element)) 9485 { 9486 cfg_obj_t *vconfig = cfg_listelt_value(element); 9487 9488 CHECK(create_view(vconfig, &builtin_viewlist, &view)); 9489 CHECK(configure_view(view, &viewlist, config, vconfig, 9490 &cachelist, &server->kasplist, bindkeys, 9491 named_g_mctx, named_g_aclconfctx, false)); 9492 dns_view_freeze(view); 9493 dns_view_detach(&view); 9494 view = NULL; 9495 } 9496 9497 /* Now combine the two viewlists into one */ 9498 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 9499 9500 /* 9501 * Commit any dns_zone_setview() calls on all zones in the new 9502 * view. 9503 */ 9504 for (view = ISC_LIST_HEAD(viewlist); view != NULL; 9505 view = ISC_LIST_NEXT(view, link)) 9506 { 9507 dns_view_setviewcommit(view); 9508 } 9509 9510 /* Swap our new view list with the production one. */ 9511 tmpviewlist = server->viewlist; 9512 server->viewlist = viewlist; 9513 viewlist = tmpviewlist; 9514 9515 /* Make the view list available to each of the views */ 9516 view = ISC_LIST_HEAD(server->viewlist); 9517 while (view != NULL) { 9518 view->viewlist = &server->viewlist; 9519 view = ISC_LIST_NEXT(view, link); 9520 } 9521 9522 /* Swap our new cache list with the production one. */ 9523 tmpcachelist = server->cachelist; 9524 server->cachelist = cachelist; 9525 cachelist = tmpcachelist; 9526 9527 /* Load the TKEY information from the configuration. */ 9528 if (options != NULL) { 9529 dns_tkeyctx_t *t = NULL; 9530 CHECKM(named_tkeyctx_fromconfig(options, named_g_mctx, &t), 9531 "configuring TKEY"); 9532 if (server->sctx->tkeyctx != NULL) { 9533 dns_tkeyctx_destroy(&server->sctx->tkeyctx); 9534 } 9535 server->sctx->tkeyctx = t; 9536 } 9537 9538 /* 9539 * Bind the control port(s). 9540 */ 9541 CHECKM(named_controls_configure(named_g_server->controls, config, 9542 named_g_aclconfctx), 9543 "binding control channel(s)"); 9544 9545 #ifdef HAVE_LMDB 9546 /* 9547 * If we're using LMDB, we may have created newzones databases 9548 * as root, making it impossible to reopen them later after 9549 * switching to a new userid. We close them now, and reopen 9550 * after relinquishing privileges them. 9551 */ 9552 if (first_time) { 9553 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9554 view = ISC_LIST_NEXT(view, link)) 9555 { 9556 nzd_env_close(view); 9557 } 9558 } 9559 #endif /* HAVE_LMDB */ 9560 9561 /* 9562 * Relinquish root privileges. 9563 */ 9564 if (first_time) { 9565 named_os_changeuser(); 9566 } 9567 9568 #if 0 9569 /* 9570 * Check that the working directory is writable. 9571 */ 9572 if (!isc_file_isdirwritable(".")) { 9573 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9574 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9575 "the working directory is not writable"); 9576 result = ISC_R_NOPERM; 9577 goto cleanup; 9578 } 9579 #endif 9580 9581 #ifdef HAVE_LMDB 9582 /* 9583 * Reopen NZD databases. 9584 */ 9585 if (first_time) { 9586 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9587 view = ISC_LIST_NEXT(view, link)) 9588 { 9589 nzd_env_reopen(view); 9590 } 9591 } 9592 #endif /* HAVE_LMDB */ 9593 9594 /* 9595 * Configure the logging system. 9596 * 9597 * Do this after changing UID to make sure that any log 9598 * files specified in named.conf get created by the 9599 * unprivileged user, not root. 9600 */ 9601 if (named_g_logstderr) { 9602 const cfg_obj_t *logobj = NULL; 9603 9604 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9605 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 9606 "not using config file logging " 9607 "statement for logging due to " 9608 "-g option"); 9609 9610 (void)cfg_map_get(config, "logging", &logobj); 9611 if (logobj != NULL) { 9612 result = named_logconfig(NULL, logobj); 9613 if (result != ISC_R_SUCCESS) { 9614 isc_log_write( 9615 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9616 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 9617 "checking logging configuration " 9618 "failed: %s", 9619 isc_result_totext(result)); 9620 goto cleanup; 9621 } 9622 } 9623 } else { 9624 const cfg_obj_t *logobj = NULL; 9625 9626 isc_logconfig_create(named_g_lctx, &logc); 9627 9628 logobj = NULL; 9629 (void)cfg_map_get(config, "logging", &logobj); 9630 if (logobj != NULL) { 9631 CHECKM(named_logconfig(logc, logobj), 9632 "configuring logging"); 9633 } else { 9634 named_log_setdefaultchannels(logc); 9635 named_log_setdefaultsslkeylogfile(logc); 9636 CHECKM(named_log_setunmatchedcategory(logc), 9637 "setting up default 'category unmatched'"); 9638 CHECKM(named_log_setdefaultcategory(logc), 9639 "setting up default 'category default'"); 9640 } 9641 9642 isc_logconfig_use(named_g_lctx, logc); 9643 logc = NULL; 9644 9645 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9646 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9647 "now using logging configuration from " 9648 "config file"); 9649 } 9650 9651 /* 9652 * Set the default value of the query logging flag depending 9653 * whether a "queries" category has been defined. This is 9654 * a disgusting hack, but we need to do this for BIND 8 9655 * compatibility. 9656 */ 9657 if (first_time) { 9658 const cfg_obj_t *logobj = NULL; 9659 const cfg_obj_t *categories = NULL; 9660 9661 obj = NULL; 9662 if (named_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { 9663 ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES, 9664 cfg_obj_asboolean(obj)); 9665 } else { 9666 (void)cfg_map_get(config, "logging", &logobj); 9667 if (logobj != NULL) { 9668 (void)cfg_map_get(logobj, "category", 9669 &categories); 9670 } 9671 if (categories != NULL) { 9672 for (element = cfg_list_first(categories); 9673 element != NULL; 9674 element = cfg_list_next(element)) 9675 { 9676 const cfg_obj_t *catobj; 9677 const char *str; 9678 9679 obj = cfg_listelt_value(element); 9680 catobj = cfg_tuple_get(obj, "name"); 9681 str = cfg_obj_asstring(catobj); 9682 if (strcasecmp(str, "queries") == 0) { 9683 ns_server_setoption( 9684 server->sctx, 9685 NS_SERVER_LOGQUERIES, 9686 true); 9687 } 9688 } 9689 } 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 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)), 9717 "strdup"); 9718 9719 obj = NULL; 9720 result = named_config_get(maps, "dump-file", &obj); 9721 INSIST(result == ISC_R_SUCCESS); 9722 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)), 9723 "strdup"); 9724 9725 obj = NULL; 9726 result = named_config_get(maps, "secroots-file", &obj); 9727 INSIST(result == ISC_R_SUCCESS); 9728 CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)), 9729 "strdup"); 9730 9731 obj = NULL; 9732 result = named_config_get(maps, "recursing-file", &obj); 9733 INSIST(result == ISC_R_SUCCESS); 9734 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)), 9735 "strdup"); 9736 9737 obj = NULL; 9738 result = named_config_get(maps, "version", &obj); 9739 if (result == ISC_R_SUCCESS) { 9740 CHECKM(setoptstring(server, &server->version, obj), "strdup"); 9741 server->version_set = true; 9742 } else { 9743 server->version_set = false; 9744 } 9745 9746 obj = NULL; 9747 result = named_config_get(maps, "hostname", &obj); 9748 if (result == ISC_R_SUCCESS) { 9749 CHECKM(setoptstring(server, &server->hostname, obj), "strdup"); 9750 server->hostname_set = true; 9751 } else { 9752 server->hostname_set = false; 9753 } 9754 9755 obj = NULL; 9756 result = named_config_get(maps, "server-id", &obj); 9757 server->sctx->usehostname = false; 9758 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 9759 /* The parser translates "hostname" to true */ 9760 server->sctx->usehostname = true; 9761 result = ns_server_setserverid(server->sctx, NULL); 9762 } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { 9763 /* Found a quoted string */ 9764 result = ns_server_setserverid(server->sctx, 9765 cfg_obj_asstring(obj)); 9766 } else { 9767 result = ns_server_setserverid(server->sctx, NULL); 9768 } 9769 RUNTIME_CHECK(result == ISC_R_SUCCESS); 9770 9771 obj = NULL; 9772 result = named_config_get(maps, "flush-zones-on-shutdown", &obj); 9773 if (result == ISC_R_SUCCESS) { 9774 server->flushonshutdown = cfg_obj_asboolean(obj); 9775 } else { 9776 server->flushonshutdown = false; 9777 } 9778 9779 obj = NULL; 9780 result = named_config_get(maps, "answer-cookie", &obj); 9781 INSIST(result == ISC_R_SUCCESS); 9782 server->sctx->answercookie = cfg_obj_asboolean(obj); 9783 9784 obj = NULL; 9785 result = named_config_get(maps, "cookie-algorithm", &obj); 9786 INSIST(result == ISC_R_SUCCESS); 9787 if (strcasecmp(cfg_obj_asstring(obj), "siphash24") == 0) { 9788 server->sctx->cookiealg = ns_cookiealg_siphash24; 9789 } else if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) { 9790 server->sctx->cookiealg = ns_cookiealg_aes; 9791 } else { 9792 UNREACHABLE(); 9793 } 9794 9795 obj = NULL; 9796 result = named_config_get(maps, "cookie-secret", &obj); 9797 if (result == ISC_R_SUCCESS) { 9798 const char *str; 9799 bool first = true; 9800 isc_buffer_t b; 9801 unsigned int usedlength; 9802 unsigned int expectedlength; 9803 9804 for (element = cfg_list_first(obj); element != NULL; 9805 element = cfg_list_next(element)) 9806 { 9807 obj = cfg_listelt_value(element); 9808 str = cfg_obj_asstring(obj); 9809 9810 if (first) { 9811 memset(server->sctx->secret, 0, 9812 sizeof(server->sctx->secret)); 9813 isc_buffer_init(&b, server->sctx->secret, 9814 sizeof(server->sctx->secret)); 9815 result = isc_hex_decodestring(str, &b); 9816 if (result != ISC_R_SUCCESS && 9817 result != ISC_R_NOSPACE) 9818 { 9819 goto cleanup; 9820 } 9821 first = false; 9822 } else { 9823 altsecret = isc_mem_get(server->sctx->mctx, 9824 sizeof(*altsecret)); 9825 isc_buffer_init(&b, altsecret->secret, 9826 sizeof(altsecret->secret)); 9827 result = isc_hex_decodestring(str, &b); 9828 if (result != ISC_R_SUCCESS && 9829 result != ISC_R_NOSPACE) 9830 { 9831 isc_mem_put(server->sctx->mctx, 9832 altsecret, 9833 sizeof(*altsecret)); 9834 goto cleanup; 9835 } 9836 ISC_LIST_INITANDAPPEND(altsecrets, altsecret, 9837 link); 9838 } 9839 9840 usedlength = isc_buffer_usedlength(&b); 9841 switch (server->sctx->cookiealg) { 9842 case ns_cookiealg_siphash24: 9843 expectedlength = ISC_SIPHASH24_KEY_LENGTH; 9844 if (usedlength != expectedlength) { 9845 CHECKM(ISC_R_RANGE, "SipHash-2-4 " 9846 "cookie-secret " 9847 "must be 128 bits"); 9848 } 9849 break; 9850 case ns_cookiealg_aes: 9851 expectedlength = ISC_AES128_KEYLENGTH; 9852 if (usedlength != expectedlength) { 9853 CHECKM(ISC_R_RANGE, "AES cookie-secret " 9854 "must be 128 bits"); 9855 } 9856 break; 9857 } 9858 } 9859 } else { 9860 isc_nonce_buf(server->sctx->secret, 9861 sizeof(server->sctx->secret)); 9862 } 9863 9864 /* 9865 * Swap altsecrets lists. 9866 */ 9867 tmpaltsecrets = server->sctx->altsecrets; 9868 server->sctx->altsecrets = altsecrets; 9869 altsecrets = tmpaltsecrets; 9870 9871 (void)named_server_loadnta(server); 9872 9873 #ifdef USE_DNSRPS 9874 /* 9875 * Start and connect to the DNS Response Policy Service 9876 * daemon, dnsrpzd, for each view that uses DNSRPS. 9877 */ 9878 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 9879 view = ISC_LIST_NEXT(view, link)) 9880 { 9881 result = dns_dnsrps_connect(view->rpzs); 9882 if (result != ISC_R_SUCCESS) { 9883 view = NULL; 9884 goto cleanup; 9885 } 9886 } 9887 #endif /* ifdef USE_DNSRPS */ 9888 9889 result = ISC_R_SUCCESS; 9890 9891 cleanup: 9892 if (logc != NULL) { 9893 isc_logconfig_destroy(&logc); 9894 } 9895 9896 if (v4portset != NULL) { 9897 isc_portset_destroy(named_g_mctx, &v4portset); 9898 } 9899 9900 if (v6portset != NULL) { 9901 isc_portset_destroy(named_g_mctx, &v6portset); 9902 } 9903 9904 if (conf_parser != NULL) { 9905 if (config != NULL) { 9906 cfg_obj_destroy(conf_parser, &config); 9907 } 9908 cfg_parser_destroy(&conf_parser); 9909 } 9910 9911 if (bindkeys_parser != NULL) { 9912 if (bindkeys != NULL) { 9913 cfg_obj_destroy(bindkeys_parser, &bindkeys); 9914 } 9915 cfg_parser_destroy(&bindkeys_parser); 9916 } 9917 9918 if (view != NULL) { 9919 dns_view_detach(&view); 9920 } 9921 9922 if (kasp != NULL) { 9923 dns_kasp_detach(&kasp); 9924 } 9925 9926 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); 9927 9928 /* 9929 * This cleans up either the old production view list 9930 * or our temporary list depending on whether they 9931 * were swapped above or not. 9932 */ 9933 for (view = ISC_LIST_HEAD(viewlist); view != NULL; view = view_next) { 9934 view_next = ISC_LIST_NEXT(view, link); 9935 ISC_LIST_UNLINK(viewlist, view, link); 9936 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) 9937 { 9938 dns_view_setviewrevert(view); 9939 (void)dns_zt_apply(view->zonetable, isc_rwlocktype_read, 9940 false, NULL, removed, view); 9941 } 9942 dns_view_detach(&view); 9943 } 9944 9945 /* 9946 * Same cleanup for kasp list. 9947 */ 9948 for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) { 9949 kasp_next = ISC_LIST_NEXT(kasp, link); 9950 ISC_LIST_UNLINK(kasplist, kasp, link); 9951 dns_kasp_detach(&kasp); 9952 } 9953 9954 /* Same cleanup for cache list. */ 9955 while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { 9956 ISC_LIST_UNLINK(cachelist, nsc, link); 9957 dns_cache_detach(&nsc->cache); 9958 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 9959 } 9960 9961 /* Cleanup for altsecrets list. */ 9962 while ((altsecret = ISC_LIST_HEAD(altsecrets)) != NULL) { 9963 ISC_LIST_UNLINK(altsecrets, altsecret, link); 9964 isc_mem_put(server->sctx->mctx, altsecret, sizeof(*altsecret)); 9965 } 9966 9967 /* 9968 * Record the time of most recent configuration 9969 */ 9970 tresult = isc_time_now(&named_g_configtime); 9971 if (tresult != ISC_R_SUCCESS) { 9972 named_main_earlyfatal("isc_time_now() failed: %s", 9973 isc_result_totext(result)); 9974 } 9975 9976 /* Relinquish exclusive access to configuration data. */ 9977 if (exclusive) { 9978 isc_task_endexclusive(server->task); 9979 } 9980 9981 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 9982 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 9983 "load_configuration: %s", isc_result_totext(result)); 9984 9985 return (result); 9986 } 9987 9988 static isc_result_t 9989 view_loaded(void *arg) { 9990 isc_result_t result; 9991 ns_zoneload_t *zl = (ns_zoneload_t *)arg; 9992 9993 /* 9994 * Force zone maintenance. Do this after loading 9995 * so that we know when we need to force AXFR of 9996 * secondary zones whose master files are missing. 9997 * 9998 * We use the zoneload reference counter to let us 9999 * know when all views are finished. 10000 */ 10001 if (isc_refcount_decrement(&zl->refs) == 1) { 10002 named_server_t *server = zl->server; 10003 bool reconfig = zl->reconfig; 10004 dns_view_t *view = NULL; 10005 10006 isc_refcount_destroy(&zl->refs); 10007 isc_mem_put(server->mctx, zl, sizeof(*zl)); 10008 10009 /* 10010 * To maintain compatibility with log parsing tools that might 10011 * be looking for this string after "rndc reconfig", we keep it 10012 * as it is 10013 */ 10014 if (reconfig) { 10015 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10016 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10017 "any newly configured zones are now " 10018 "loaded"); 10019 } else { 10020 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10021 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10022 "all zones loaded"); 10023 } 10024 10025 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10026 view = ISC_LIST_NEXT(view, link)) 10027 { 10028 if (view->managed_keys != NULL) { 10029 result = dns_zone_synckeyzone( 10030 view->managed_keys); 10031 if (result != ISC_R_SUCCESS) { 10032 isc_log_write( 10033 named_g_lctx, 10034 DNS_LOGCATEGORY_DNSSEC, 10035 DNS_LOGMODULE_DNSSEC, 10036 ISC_LOG_ERROR, 10037 "failed to initialize " 10038 "managed-keys for view %s " 10039 "(%s): DNSSEC validation is " 10040 "at risk", 10041 view->name, 10042 isc_result_totext(result)); 10043 } 10044 } 10045 } 10046 10047 CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr), 10048 "forcing zone maintenance"); 10049 10050 named_os_started(); 10051 10052 #ifdef HAVE_FIPS_MODE 10053 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10054 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10055 "FIPS mode is %s", 10056 FIPS_mode() ? "enabled" : "disabled"); 10057 #endif /* ifdef HAVE_FIPS_MODE */ 10058 atomic_store(&server->reload_status, NAMED_RELOAD_DONE); 10059 10060 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10061 NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, 10062 "running"); 10063 } 10064 10065 return (ISC_R_SUCCESS); 10066 } 10067 10068 static isc_result_t 10069 load_zones(named_server_t *server, bool init, bool reconfig) { 10070 isc_result_t result; 10071 isc_taskmgr_t *taskmgr = dns_zonemgr_gettaskmgr(server->zonemgr); 10072 ns_zoneload_t *zl = NULL; 10073 dns_view_t *view = NULL; 10074 10075 zl = isc_mem_get(server->mctx, sizeof(*zl)); 10076 zl->server = server; 10077 zl->reconfig = reconfig; 10078 10079 result = isc_task_beginexclusive(server->task); 10080 RUNTIME_CHECK(result == ISC_R_SUCCESS); 10081 10082 isc_refcount_init(&zl->refs, 1); 10083 10084 /* 10085 * Schedule zones to be loaded from disk. 10086 */ 10087 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10088 view = ISC_LIST_NEXT(view, link)) 10089 { 10090 if (view->managed_keys != NULL) { 10091 result = dns_zone_load(view->managed_keys, false); 10092 if (result != ISC_R_SUCCESS && 10093 result != DNS_R_UPTODATE && 10094 result != DNS_R_CONTINUE) 10095 { 10096 goto cleanup; 10097 } 10098 } 10099 if (view->redirect != NULL) { 10100 result = dns_zone_load(view->redirect, false); 10101 if (result != ISC_R_SUCCESS && 10102 result != DNS_R_UPTODATE && 10103 result != DNS_R_CONTINUE) 10104 { 10105 goto cleanup; 10106 } 10107 } 10108 10109 /* 10110 * 'dns_view_asyncload' calls view_loaded if there are no 10111 * zones. 10112 */ 10113 isc_refcount_increment(&zl->refs); 10114 result = dns_view_asyncload(view, reconfig, view_loaded, zl); 10115 if (result != ISC_R_SUCCESS) { 10116 isc_refcount_decrement1(&zl->refs); 10117 goto cleanup; 10118 } 10119 } 10120 10121 cleanup: 10122 if (isc_refcount_decrement(&zl->refs) == 1) { 10123 isc_refcount_destroy(&zl->refs); 10124 isc_mem_put(server->mctx, zl, sizeof(*zl)); 10125 } 10126 10127 if (init) { 10128 /* 10129 * If we're setting up the server for the first time, set 10130 * the task manager into privileged mode; this ensures 10131 * that no other tasks will begin to run until after zone 10132 * loading is complete. We won't return from exclusive mode 10133 * until the loading is finished; we can then drop out of 10134 * privileged mode. 10135 * 10136 * We do *not* want to do this in the case of reload or 10137 * reconfig, as loading a large zone could cause the server 10138 * to be inactive for too long a time. 10139 */ 10140 isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged); 10141 isc_task_endexclusive(server->task); 10142 isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_normal); 10143 } else { 10144 isc_task_endexclusive(server->task); 10145 } 10146 10147 return (result); 10148 } 10149 10150 static void 10151 run_server(isc_task_t *task, isc_event_t *event) { 10152 isc_result_t result; 10153 named_server_t *server = (named_server_t *)event->ev_arg; 10154 dns_geoip_databases_t *geoip; 10155 10156 INSIST(task == server->task); 10157 10158 isc_event_free(&event); 10159 10160 CHECKFATAL(dns_dispatchmgr_create(named_g_mctx, named_g_netmgr, 10161 &named_g_dispatchmgr), 10162 "creating dispatch manager"); 10163 10164 dns_dispatchmgr_setstats(named_g_dispatchmgr, server->resolverstats); 10165 10166 #if defined(HAVE_GEOIP2) 10167 geoip = named_g_geoip; 10168 #else /* if defined(HAVE_GEOIP2) */ 10169 geoip = NULL; 10170 #endif /* if defined(HAVE_GEOIP2) */ 10171 10172 CHECKFATAL(ns_interfacemgr_create(named_g_mctx, server->sctx, 10173 named_g_taskmgr, named_g_timermgr, 10174 named_g_netmgr, named_g_dispatchmgr, 10175 server->task, geoip, named_g_cpus, 10176 true, &server->interfacemgr), 10177 "creating interface manager"); 10178 10179 CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive, 10180 NULL, NULL, server->task, 10181 interface_timer_tick, server, 10182 &server->interface_timer), 10183 "creating interface timer"); 10184 10185 CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive, 10186 NULL, NULL, server->task, 10187 heartbeat_timer_tick, server, 10188 &server->heartbeat_timer), 10189 "creating heartbeat timer"); 10190 10191 CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive, 10192 NULL, NULL, server->task, tat_timer_tick, 10193 server, &server->tat_timer), 10194 "creating trust anchor telemetry timer"); 10195 10196 CHECKFATAL(isc_timer_create(named_g_timermgr, isc_timertype_inactive, 10197 NULL, NULL, server->task, pps_timer_tick, 10198 server, &server->pps_timer), 10199 "creating 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, true, 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(isc_task_t *task, isc_event_t *event) { 10227 isc_result_t result; 10228 dns_view_t *view, *view_next = NULL; 10229 dns_kasp_t *kasp, *kasp_next = NULL; 10230 named_server_t *server = (named_server_t *)event->ev_arg; 10231 bool flush = server->flushonshutdown; 10232 named_cache_t *nsc; 10233 10234 UNUSED(task); 10235 INSIST(task == server->task); 10236 10237 /* 10238 * We need to shutdown the interface before going 10239 * exclusive (which would pause the netmgr). 10240 */ 10241 ns_interfacemgr_shutdown(server->interfacemgr); 10242 10243 result = isc_task_beginexclusive(server->task); 10244 RUNTIME_CHECK(result == ISC_R_SUCCESS); 10245 10246 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10247 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "shutting down%s", 10248 flush ? ": flushing changes" : ""); 10249 10250 named_statschannels_shutdown(server); 10251 named_controls_shutdown(server->controls); 10252 end_reserved_dispatches(server, true); 10253 cleanup_session_key(server, server->mctx); 10254 10255 if (named_g_aclconfctx != NULL) { 10256 cfg_aclconfctx_detach(&named_g_aclconfctx); 10257 } 10258 10259 cfg_obj_destroy(named_g_parser, &named_g_config); 10260 cfg_parser_destroy(&named_g_parser); 10261 cfg_parser_destroy(&named_g_addparser); 10262 10263 (void)named_server_saventa(server); 10264 10265 for (kasp = ISC_LIST_HEAD(server->kasplist); kasp != NULL; 10266 kasp = kasp_next) 10267 { 10268 kasp_next = ISC_LIST_NEXT(kasp, link); 10269 ISC_LIST_UNLINK(server->kasplist, kasp, link); 10270 dns_kasp_detach(&kasp); 10271 } 10272 10273 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 10274 view = view_next) 10275 { 10276 view_next = ISC_LIST_NEXT(view, link); 10277 ISC_LIST_UNLINK(server->viewlist, view, link); 10278 if (flush) { 10279 dns_view_flushanddetach(&view); 10280 } else { 10281 dns_view_detach(&view); 10282 } 10283 } 10284 10285 /* 10286 * Shut down all dyndb instances. 10287 */ 10288 dns_dyndb_cleanup(true); 10289 10290 while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { 10291 ISC_LIST_UNLINK(server->cachelist, nsc, link); 10292 dns_cache_detach(&nsc->cache); 10293 isc_mem_put(server->mctx, nsc, sizeof(*nsc)); 10294 } 10295 10296 isc_timer_destroy(&server->interface_timer); 10297 isc_timer_destroy(&server->heartbeat_timer); 10298 isc_timer_destroy(&server->pps_timer); 10299 isc_timer_destroy(&server->tat_timer); 10300 10301 ns_interfacemgr_detach(&server->interfacemgr); 10302 10303 dns_dispatchmgr_detach(&named_g_dispatchmgr); 10304 10305 dns_zonemgr_shutdown(server->zonemgr); 10306 10307 if (named_g_sessionkey != NULL) { 10308 dns_tsigkey_detach(&named_g_sessionkey); 10309 dns_name_free(&named_g_sessionkeyname, server->mctx); 10310 } 10311 #if defined(HAVE_GEOIP2) 10312 named_geoip_shutdown(); 10313 #endif /* HAVE_GEOIP2 */ 10314 10315 dns_db_detach(&server->in_roothints); 10316 10317 isc_task_endexclusive(server->task); 10318 10319 isc_task_detach(&server->task); 10320 10321 isc_event_free(&event); 10322 } 10323 10324 /*% 10325 * Find a view that matches the source and destination addresses of a query. 10326 */ 10327 static isc_result_t 10328 get_matching_view(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, 10329 dns_message_t *message, dns_aclenv_t *env, 10330 isc_result_t *sigresult, dns_view_t **viewp) { 10331 dns_view_t *view; 10332 10333 REQUIRE(message != NULL); 10334 REQUIRE(sigresult != NULL); 10335 REQUIRE(viewp != NULL && *viewp == NULL); 10336 10337 for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL; 10338 view = ISC_LIST_NEXT(view, link)) 10339 { 10340 if (message->rdclass == view->rdclass || 10341 message->rdclass == dns_rdataclass_any) 10342 { 10343 const dns_name_t *tsig = NULL; 10344 10345 *sigresult = dns_message_rechecksig(message, view); 10346 if (*sigresult == ISC_R_SUCCESS) { 10347 dns_tsigkey_t *tsigkey; 10348 10349 tsigkey = message->tsigkey; 10350 tsig = dns_tsigkey_identity(tsigkey); 10351 } 10352 10353 if (dns_acl_allowed(srcaddr, tsig, view->matchclients, 10354 env) && 10355 dns_acl_allowed(destaddr, tsig, 10356 view->matchdestinations, env) && 10357 !(view->matchrecursiveonly && 10358 (message->flags & DNS_MESSAGEFLAG_RD) == 0)) 10359 { 10360 dns_view_attach(view, viewp); 10361 return (ISC_R_SUCCESS); 10362 } 10363 } 10364 } 10365 10366 return (ISC_R_NOTFOUND); 10367 } 10368 10369 void 10370 named_server_create(isc_mem_t *mctx, named_server_t **serverp) { 10371 isc_result_t result; 10372 named_server_t *server = isc_mem_get(mctx, sizeof(*server)); 10373 10374 *server = (named_server_t){ 10375 .mctx = mctx, 10376 .statsfile = isc_mem_strdup(mctx, "named.stats"), 10377 .bindkeysfile = isc_mem_strdup(mctx, named_g_defaultbindkeys), 10378 .dumpfile = isc_mem_strdup(mctx, "named_dump.db"), 10379 .secrootsfile = isc_mem_strdup(mctx, "named.secroots"), 10380 .recfile = isc_mem_strdup(mctx, "named.recursing"), 10381 }; 10382 10383 #ifdef USE_DNSRPS 10384 CHECKFATAL(dns_dnsrps_server_create(), "initializing RPZ service " 10385 "interface"); 10386 #endif /* ifdef USE_DNSRPS */ 10387 10388 /* Initialize server data structures. */ 10389 ISC_LIST_INIT(server->kasplist); 10390 ISC_LIST_INIT(server->viewlist); 10391 10392 /* Must be first. */ 10393 CHECKFATAL(dst_lib_init(named_g_mctx, named_g_engine), "initializing " 10394 "DST"); 10395 10396 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, 10397 &server->in_roothints), 10398 "setting up root hints"); 10399 10400 atomic_init(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 10401 10402 /* 10403 * Setup the server task, which is responsible for coordinating 10404 * startup and shutdown of the server, as well as all exclusive 10405 * tasks. 10406 */ 10407 CHECKFATAL(isc_task_create_bound(named_g_taskmgr, 0, &server->task, 0), 10408 "creating server task"); 10409 isc_task_setname(server->task, "server", server); 10410 isc_taskmgr_setexcltask(named_g_taskmgr, server->task); 10411 10412 CHECKFATAL(ns_server_create(mctx, get_matching_view, &server->sctx), 10413 "creating server context"); 10414 10415 #if defined(HAVE_GEOIP2) 10416 /* 10417 * GeoIP must be initialized before the interface 10418 * manager (which includes the ACL environment) 10419 * is created. 10420 */ 10421 named_geoip_init(); 10422 #endif /* HAVE_GEOIP2 */ 10423 10424 #ifdef ENABLE_AFL 10425 server->sctx->fuzztype = named_g_fuzz_type; 10426 server->sctx->fuzznotify = named_fuzz_notify; 10427 #endif /* ifdef ENABLE_AFL */ 10428 10429 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server), 10430 "isc_task_onshutdown"); 10431 CHECKFATAL( 10432 isc_app_onrun(named_g_mctx, server->task, run_server, server), 10433 "isc_app_onrun"); 10434 10435 CHECKFATAL(dns_zonemgr_create(named_g_mctx, named_g_taskmgr, 10436 named_g_timermgr, named_g_netmgr, 10437 &server->zonemgr), 10438 "dns_zonemgr_create"); 10439 CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000), "dns_zonemgr_" 10440 "setsize"); 10441 10442 CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats, 10443 isc_sockstatscounter_max), 10444 "isc_stats_create"); 10445 isc_nm_setstats(named_g_netmgr, server->sockstats); 10446 10447 CHECKFATAL(isc_stats_create(named_g_mctx, &server->zonestats, 10448 dns_zonestatscounter_max), 10449 "dns_stats_create (zone)"); 10450 10451 CHECKFATAL(isc_stats_create(named_g_mctx, &server->resolverstats, 10452 dns_resstatscounter_max), 10453 "dns_stats_create (resolver)"); 10454 10455 CHECKFATAL(named_controls_create(server, &server->controls), 10456 "named_controls_create"); 10457 10458 ISC_LIST_INIT(server->dispatches); 10459 10460 ISC_LIST_INIT(server->statschannels); 10461 10462 ISC_LIST_INIT(server->cachelist); 10463 10464 server->magic = NAMED_SERVER_MAGIC; 10465 10466 *serverp = server; 10467 } 10468 10469 void 10470 named_server_destroy(named_server_t **serverp) { 10471 named_server_t *server = *serverp; 10472 REQUIRE(NAMED_SERVER_VALID(server)); 10473 10474 #ifdef HAVE_DNSTAP 10475 if (server->dtenv != NULL) { 10476 dns_dt_detach(&server->dtenv); 10477 } 10478 #endif /* HAVE_DNSTAP */ 10479 10480 #ifdef USE_DNSRPS 10481 dns_dnsrps_server_destroy(); 10482 #endif /* ifdef USE_DNSRPS */ 10483 10484 named_controls_destroy(&server->controls); 10485 10486 isc_stats_detach(&server->zonestats); 10487 isc_stats_detach(&server->sockstats); 10488 isc_stats_detach(&server->resolverstats); 10489 10490 if (server->sctx != NULL) { 10491 ns_server_detach(&server->sctx); 10492 } 10493 10494 isc_mem_free(server->mctx, server->statsfile); 10495 isc_mem_free(server->mctx, server->bindkeysfile); 10496 isc_mem_free(server->mctx, server->dumpfile); 10497 isc_mem_free(server->mctx, server->secrootsfile); 10498 isc_mem_free(server->mctx, server->recfile); 10499 10500 if (server->version != NULL) { 10501 isc_mem_free(server->mctx, server->version); 10502 } 10503 if (server->hostname != NULL) { 10504 isc_mem_free(server->mctx, server->hostname); 10505 } 10506 if (server->lockfile != NULL) { 10507 isc_mem_free(server->mctx, server->lockfile); 10508 } 10509 10510 if (server->zonemgr != NULL) { 10511 dns_zonemgr_detach(&server->zonemgr); 10512 } 10513 10514 dst_lib_destroy(); 10515 10516 INSIST(ISC_LIST_EMPTY(server->kasplist)); 10517 INSIST(ISC_LIST_EMPTY(server->viewlist)); 10518 INSIST(ISC_LIST_EMPTY(server->cachelist)); 10519 10520 if (server->tlsctx_server_cache != NULL) { 10521 isc_tlsctx_cache_detach(&server->tlsctx_server_cache); 10522 } 10523 10524 if (server->tlsctx_client_cache != NULL) { 10525 isc_tlsctx_cache_detach(&server->tlsctx_client_cache); 10526 } 10527 10528 server->magic = 0; 10529 isc_mem_put(server->mctx, server, sizeof(*server)); 10530 *serverp = NULL; 10531 } 10532 10533 static void 10534 fatal(named_server_t *server, const char *msg, isc_result_t result) { 10535 if (server != NULL && server->task != NULL) { 10536 /* 10537 * Prevent races between the OpenSSL on_exit registered 10538 * function and any other OpenSSL calls from other tasks 10539 * by requesting exclusive access to the task manager. 10540 */ 10541 (void)isc_task_beginexclusive(server->task); 10542 } 10543 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10544 NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "%s: %s", msg, 10545 isc_result_totext(result)); 10546 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10547 NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, 10548 "exiting (due to fatal error)"); 10549 named_os_shutdown(); 10550 _exit(EXIT_FAILURE); 10551 } 10552 10553 static void 10554 start_reserved_dispatches(named_server_t *server) { 10555 REQUIRE(NAMED_SERVER_VALID(server)); 10556 10557 server->dispatchgen++; 10558 } 10559 10560 static void 10561 end_reserved_dispatches(named_server_t *server, bool all) { 10562 named_dispatch_t *dispatch, *nextdispatch; 10563 10564 REQUIRE(NAMED_SERVER_VALID(server)); 10565 10566 for (dispatch = ISC_LIST_HEAD(server->dispatches); dispatch != NULL; 10567 dispatch = nextdispatch) 10568 { 10569 nextdispatch = ISC_LIST_NEXT(dispatch, link); 10570 if (!all && server->dispatchgen == dispatch->dispatchgen) { 10571 continue; 10572 } 10573 ISC_LIST_UNLINK(server->dispatches, dispatch, link); 10574 dns_dispatch_detach(&dispatch->dispatch); 10575 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 10576 } 10577 } 10578 10579 void 10580 named_add_reserved_dispatch(named_server_t *server, 10581 const isc_sockaddr_t *addr) { 10582 named_dispatch_t *dispatch; 10583 in_port_t port; 10584 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 10585 isc_result_t result; 10586 10587 REQUIRE(NAMED_SERVER_VALID(server)); 10588 10589 port = isc_sockaddr_getport(addr); 10590 if (port == 0 || port >= 1024) { 10591 return; 10592 } 10593 10594 for (dispatch = ISC_LIST_HEAD(server->dispatches); dispatch != NULL; 10595 dispatch = ISC_LIST_NEXT(dispatch, link)) 10596 { 10597 if (isc_sockaddr_equal(&dispatch->addr, addr)) { 10598 break; 10599 } 10600 } 10601 if (dispatch != NULL) { 10602 dispatch->dispatchgen = server->dispatchgen; 10603 return; 10604 } 10605 10606 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch)); 10607 10608 dispatch->addr = *addr; 10609 dispatch->dispatchgen = server->dispatchgen; 10610 dispatch->dispatch = NULL; 10611 10612 result = dns_dispatch_createudp(named_g_dispatchmgr, &dispatch->addr, 10613 &dispatch->dispatch); 10614 if (result != ISC_R_SUCCESS) { 10615 goto cleanup; 10616 } 10617 10618 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link); 10619 10620 return; 10621 10622 cleanup: 10623 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 10624 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 10625 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10626 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 10627 "unable to create dispatch for reserved port %s: %s", 10628 addrbuf, isc_result_totext(result)); 10629 } 10630 10631 static isc_result_t 10632 loadconfig(named_server_t *server) { 10633 isc_result_t result; 10634 start_reserved_dispatches(server); 10635 result = load_configuration(named_g_conffile, server, false); 10636 if (result == ISC_R_SUCCESS) { 10637 end_reserved_dispatches(server, false); 10638 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10639 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10640 "reloading configuration succeeded"); 10641 } else { 10642 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10643 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 10644 "reloading configuration failed: %s", 10645 isc_result_totext(result)); 10646 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 10647 } 10648 10649 return (result); 10650 } 10651 10652 static isc_result_t 10653 reload(named_server_t *server) { 10654 isc_result_t result; 10655 10656 atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 10657 10658 CHECK(loadconfig(server)); 10659 10660 result = load_zones(server, false, false); 10661 if (result == ISC_R_SUCCESS) { 10662 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10663 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10664 "reloading zones succeeded"); 10665 } else { 10666 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10667 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 10668 "reloading zones failed: %s", 10669 isc_result_totext(result)); 10670 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 10671 } 10672 cleanup: 10673 return (result); 10674 } 10675 10676 /* 10677 * Handle a reload event (from SIGHUP). 10678 */ 10679 static void 10680 named_server_reload(isc_task_t *task, isc_event_t *event) { 10681 named_server_t *server = (named_server_t *)event->ev_sender; 10682 10683 INSIST(task == server->task); 10684 UNUSED(task); 10685 10686 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10687 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 10688 "received SIGHUP signal to reload zones"); 10689 (void)reload(server); 10690 10691 isc_event_free(&event); 10692 } 10693 10694 void 10695 named_server_reloadwanted(named_server_t *server) { 10696 isc_event_t *event = isc_event_allocate( 10697 named_g_mctx, server, NAMED_EVENT_RELOAD, named_server_reload, 10698 NULL, sizeof(isc_event_t)); 10699 isc_task_send(server->task, &event); 10700 } 10701 10702 void 10703 named_server_scan_interfaces(named_server_t *server) { 10704 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 10705 NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 10706 "automatic interface rescan"); 10707 10708 ns_interfacemgr_scan(server->interfacemgr, true, false); 10709 } 10710 10711 /* 10712 * Get the next token from lexer 'lex'. 10713 * 10714 * NOTE: the token value for string tokens always uses the same pointer 10715 * value. Multiple calls to this function on the same lexer will always 10716 * return either that value (lex->data) or NULL. It is necessary to copy 10717 * the token into local storage if it needs to be referenced after the next 10718 * call to next_token(). 10719 */ 10720 static char * 10721 next_token(isc_lex_t *lex, isc_buffer_t **text) { 10722 isc_result_t result; 10723 isc_token_t token; 10724 10725 token.type = isc_tokentype_unknown; 10726 result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF | ISC_LEXOPT_QSTRING, 10727 &token); 10728 10729 switch (result) { 10730 case ISC_R_NOMORE: 10731 (void)isc_lex_close(lex); 10732 break; 10733 case ISC_R_SUCCESS: 10734 if (token.type == isc_tokentype_eof) { 10735 (void)isc_lex_close(lex); 10736 } 10737 break; 10738 case ISC_R_NOSPACE: 10739 if (text != NULL) { 10740 (void)putstr(text, "token too large"); 10741 (void)putnull(text); 10742 } 10743 return (NULL); 10744 default: 10745 if (text != NULL) { 10746 (void)putstr(text, isc_result_totext(result)); 10747 (void)putnull(text); 10748 } 10749 return (NULL); 10750 } 10751 10752 if (token.type == isc_tokentype_string || 10753 token.type == isc_tokentype_qstring) 10754 { 10755 return (token.value.as_textregion.base); 10756 } 10757 10758 return (NULL); 10759 } 10760 10761 /* 10762 * Find the zone specified in the control channel command, if any. 10763 * If a zone is specified, point '*zonep' at it, otherwise 10764 * set '*zonep' to NULL, and f 'zonename' is not NULL, copy 10765 * the zone name into it (N.B. 'zonename' must have space to hold 10766 * a full DNS name). 10767 * 10768 * If 'zonetxt' is set, the caller has already pulled a token 10769 * off the command line that is to be used as the zone name. (This 10770 * is sometimes done when it's necessary to check for an optional 10771 * argument before the zone name, as in "rndc sync [-clean] zone".) 10772 */ 10773 static isc_result_t 10774 zone_from_args(named_server_t *server, isc_lex_t *lex, const char *zonetxt, 10775 dns_zone_t **zonep, char *zonename, isc_buffer_t **text, 10776 bool skip) { 10777 char *ptr; 10778 char *classtxt; 10779 const char *viewtxt = NULL; 10780 dns_fixedname_t fname; 10781 dns_name_t *name; 10782 isc_result_t result; 10783 dns_view_t *view = NULL; 10784 dns_rdataclass_t rdclass; 10785 char problem[DNS_NAME_FORMATSIZE + 500] = ""; 10786 char zonebuf[DNS_NAME_FORMATSIZE]; 10787 bool redirect = false; 10788 10789 REQUIRE(zonep != NULL && *zonep == NULL); 10790 10791 if (skip) { 10792 /* Skip the command name. */ 10793 ptr = next_token(lex, text); 10794 if (ptr == NULL) { 10795 return (ISC_R_UNEXPECTEDEND); 10796 } 10797 } 10798 10799 /* Look for the zone name. */ 10800 if (zonetxt == NULL) { 10801 zonetxt = next_token(lex, text); 10802 } 10803 if (zonetxt == NULL) { 10804 return (ISC_R_SUCCESS); 10805 } 10806 10807 /* Copy zonetxt because it'll be overwritten by next_token() */ 10808 /* To locate a zone named "-redirect" use "-redirect." */ 10809 if (strcmp(zonetxt, "-redirect") == 0) { 10810 redirect = true; 10811 strlcpy(zonebuf, ".", DNS_NAME_FORMATSIZE); 10812 } else { 10813 strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE); 10814 } 10815 if (zonename != NULL) { 10816 strlcpy(zonename, redirect ? "." : zonetxt, 10817 DNS_NAME_FORMATSIZE); 10818 } 10819 10820 name = dns_fixedname_initname(&fname); 10821 CHECK(dns_name_fromstring(name, zonebuf, 0, NULL)); 10822 10823 /* Look for the optional class name. */ 10824 classtxt = next_token(lex, text); 10825 if (classtxt != NULL) { 10826 isc_textregion_t r; 10827 r.base = classtxt; 10828 r.length = strlen(classtxt); 10829 CHECK(dns_rdataclass_fromtext(&rdclass, &r)); 10830 10831 /* Look for the optional view name. */ 10832 viewtxt = next_token(lex, text); 10833 } else { 10834 rdclass = dns_rdataclass_in; 10835 } 10836 10837 if (viewtxt == NULL) { 10838 if (redirect) { 10839 result = dns_viewlist_find(&server->viewlist, 10840 "_default", 10841 dns_rdataclass_in, &view); 10842 if (result != ISC_R_SUCCESS || view->redirect == NULL) { 10843 result = ISC_R_NOTFOUND; 10844 snprintf(problem, sizeof(problem), 10845 "redirect zone not found in " 10846 "_default view"); 10847 } else { 10848 dns_zone_attach(view->redirect, zonep); 10849 result = ISC_R_SUCCESS; 10850 } 10851 } else { 10852 result = dns_viewlist_findzone(&server->viewlist, name, 10853 (classtxt == NULL), 10854 rdclass, zonep); 10855 if (result == ISC_R_NOTFOUND) { 10856 snprintf(problem, sizeof(problem), 10857 "no matching zone '%s' in any view", 10858 zonebuf); 10859 } else if (result == ISC_R_MULTIPLE) { 10860 snprintf(problem, sizeof(problem), 10861 "zone '%s' was found in multiple " 10862 "views", 10863 zonebuf); 10864 } 10865 } 10866 } else { 10867 result = dns_viewlist_find(&server->viewlist, viewtxt, rdclass, 10868 &view); 10869 if (result != ISC_R_SUCCESS) { 10870 snprintf(problem, sizeof(problem), 10871 "no matching view '%s'", viewtxt); 10872 goto report; 10873 } 10874 10875 if (redirect) { 10876 if (view->redirect != NULL) { 10877 dns_zone_attach(view->redirect, zonep); 10878 result = ISC_R_SUCCESS; 10879 } else { 10880 result = ISC_R_NOTFOUND; 10881 } 10882 } else { 10883 result = dns_zt_find(view->zonetable, name, 0, NULL, 10884 zonep); 10885 } 10886 if (result != ISC_R_SUCCESS) { 10887 snprintf(problem, sizeof(problem), 10888 "no matching zone '%s' in view '%s'", zonebuf, 10889 viewtxt); 10890 } 10891 } 10892 10893 /* Partial match? */ 10894 if (result != ISC_R_SUCCESS && *zonep != NULL) { 10895 dns_zone_detach(zonep); 10896 } 10897 if (result == DNS_R_PARTIALMATCH) { 10898 result = ISC_R_NOTFOUND; 10899 } 10900 report: 10901 if (result != ISC_R_SUCCESS) { 10902 isc_result_t tresult; 10903 10904 tresult = putstr(text, problem); 10905 if (tresult == ISC_R_SUCCESS) { 10906 (void)putnull(text); 10907 } 10908 } 10909 10910 cleanup: 10911 if (view != NULL) { 10912 dns_view_detach(&view); 10913 } 10914 10915 return (result); 10916 } 10917 10918 /* 10919 * Act on a "retransfer" command from the command channel. 10920 */ 10921 isc_result_t 10922 named_server_retransfercommand(named_server_t *server, isc_lex_t *lex, 10923 isc_buffer_t **text) { 10924 isc_result_t result; 10925 dns_zone_t *zone = NULL; 10926 dns_zone_t *raw = NULL; 10927 dns_zonetype_t type; 10928 10929 REQUIRE(text != NULL); 10930 10931 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 10932 if (result != ISC_R_SUCCESS) { 10933 return (result); 10934 } 10935 if (zone == NULL) { 10936 return (ISC_R_UNEXPECTEDEND); 10937 } 10938 dns_zone_getraw(zone, &raw); 10939 if (raw != NULL) { 10940 dns_zone_detach(&zone); 10941 dns_zone_attach(raw, &zone); 10942 dns_zone_detach(&raw); 10943 } 10944 type = dns_zone_gettype(zone); 10945 if (type == dns_zone_secondary || type == dns_zone_mirror || 10946 type == dns_zone_stub || 10947 (type == dns_zone_redirect && 10948 dns_zone_getredirecttype(zone) == dns_zone_secondary)) 10949 { 10950 dns_zone_forcereload(zone); 10951 } else { 10952 (void)putstr(text, "retransfer: inappropriate zone type: "); 10953 (void)putstr(text, dns_zonetype_name(type)); 10954 if (type == dns_zone_redirect) { 10955 type = dns_zone_getredirecttype(zone); 10956 (void)putstr(text, "("); 10957 (void)putstr(text, dns_zonetype_name(type)); 10958 (void)putstr(text, ")"); 10959 } 10960 (void)putnull(text); 10961 result = ISC_R_FAILURE; 10962 } 10963 dns_zone_detach(&zone); 10964 return (result); 10965 } 10966 10967 /* 10968 * Act on a "reload" command from the command channel. 10969 */ 10970 isc_result_t 10971 named_server_reloadcommand(named_server_t *server, isc_lex_t *lex, 10972 isc_buffer_t **text) { 10973 isc_result_t result; 10974 dns_zone_t *zone = NULL; 10975 dns_zonetype_t type; 10976 const char *msg = NULL; 10977 10978 REQUIRE(text != NULL); 10979 10980 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 10981 if (result != ISC_R_SUCCESS) { 10982 return (result); 10983 } 10984 if (zone == NULL) { 10985 result = reload(server); 10986 if (result == ISC_R_SUCCESS) { 10987 msg = "server reload successful"; 10988 } 10989 } else { 10990 type = dns_zone_gettype(zone); 10991 if (type == dns_zone_secondary || type == dns_zone_mirror || 10992 type == dns_zone_stub) 10993 { 10994 dns_zone_refresh(zone); 10995 dns_zone_detach(&zone); 10996 msg = "zone refresh queued"; 10997 } else { 10998 result = dns_zone_load(zone, false); 10999 dns_zone_detach(&zone); 11000 switch (result) { 11001 case ISC_R_SUCCESS: 11002 msg = "zone reload successful"; 11003 break; 11004 case DNS_R_CONTINUE: 11005 msg = "zone reload queued"; 11006 result = ISC_R_SUCCESS; 11007 break; 11008 case DNS_R_UPTODATE: 11009 msg = "zone reload up-to-date"; 11010 result = ISC_R_SUCCESS; 11011 break; 11012 default: 11013 /* failure message will be generated by rndc */ 11014 break; 11015 } 11016 } 11017 } 11018 if (msg != NULL) { 11019 (void)putstr(text, msg); 11020 (void)putnull(text); 11021 } 11022 return (result); 11023 } 11024 11025 /* 11026 * Act on a "reconfig" command from the command channel. 11027 */ 11028 isc_result_t 11029 named_server_reconfigcommand(named_server_t *server) { 11030 isc_result_t result; 11031 atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); 11032 11033 CHECK(loadconfig(server)); 11034 11035 result = load_zones(server, false, true); 11036 if (result == ISC_R_SUCCESS) { 11037 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11038 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11039 "scheduled loading new zones"); 11040 } else { 11041 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11042 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11043 "loading new zones failed: %s", 11044 isc_result_totext(result)); 11045 atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); 11046 } 11047 cleanup: 11048 return (result); 11049 } 11050 11051 /* 11052 * Act on a "notify" command from the command channel. 11053 */ 11054 isc_result_t 11055 named_server_notifycommand(named_server_t *server, isc_lex_t *lex, 11056 isc_buffer_t **text) { 11057 isc_result_t result; 11058 dns_zone_t *zone = NULL; 11059 const char msg[] = "zone notify queued"; 11060 11061 REQUIRE(text != NULL); 11062 11063 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11064 if (result != ISC_R_SUCCESS) { 11065 return (result); 11066 } 11067 if (zone == NULL) { 11068 return (ISC_R_UNEXPECTEDEND); 11069 } 11070 11071 dns_zone_notify(zone); 11072 dns_zone_detach(&zone); 11073 (void)putstr(text, msg); 11074 (void)putnull(text); 11075 11076 return (ISC_R_SUCCESS); 11077 } 11078 11079 /* 11080 * Act on a "refresh" command from the command channel. 11081 */ 11082 isc_result_t 11083 named_server_refreshcommand(named_server_t *server, isc_lex_t *lex, 11084 isc_buffer_t **text) { 11085 isc_result_t result; 11086 dns_zone_t *zone = NULL, *raw = NULL; 11087 const char msg1[] = "zone refresh queued"; 11088 const char msg2[] = "not a secondary, mirror, or stub zone"; 11089 dns_zonetype_t type; 11090 11091 REQUIRE(text != NULL); 11092 11093 result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); 11094 if (result != ISC_R_SUCCESS) { 11095 return (result); 11096 } 11097 if (zone == NULL) { 11098 return (ISC_R_UNEXPECTEDEND); 11099 } 11100 11101 dns_zone_getraw(zone, &raw); 11102 if (raw != NULL) { 11103 dns_zone_detach(&zone); 11104 dns_zone_attach(raw, &zone); 11105 dns_zone_detach(&raw); 11106 } 11107 11108 type = dns_zone_gettype(zone); 11109 if (type == dns_zone_secondary || type == dns_zone_mirror || 11110 type == dns_zone_stub) 11111 { 11112 dns_zone_refresh(zone); 11113 dns_zone_detach(&zone); 11114 (void)putstr(text, msg1); 11115 (void)putnull(text); 11116 return (ISC_R_SUCCESS); 11117 } 11118 11119 dns_zone_detach(&zone); 11120 (void)putstr(text, msg2); 11121 (void)putnull(text); 11122 return (ISC_R_FAILURE); 11123 } 11124 11125 isc_result_t 11126 named_server_togglequerylog(named_server_t *server, isc_lex_t *lex) { 11127 bool prev, value; 11128 char *ptr; 11129 11130 /* Skip the command name. */ 11131 ptr = next_token(lex, NULL); 11132 if (ptr == NULL) { 11133 return (ISC_R_UNEXPECTEDEND); 11134 } 11135 11136 prev = ns_server_getoption(server->sctx, NS_SERVER_LOGQUERIES); 11137 11138 ptr = next_token(lex, NULL); 11139 if (ptr == NULL) { 11140 value = !prev; 11141 } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 11142 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 11143 { 11144 value = true; 11145 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 11146 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 11147 { 11148 value = false; 11149 } else { 11150 return (DNS_R_SYNTAX); 11151 } 11152 11153 if (value == prev) { 11154 return (ISC_R_SUCCESS); 11155 } 11156 11157 ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES, value); 11158 11159 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11160 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11161 "query logging is now %s", value ? "on" : "off"); 11162 return (ISC_R_SUCCESS); 11163 } 11164 11165 static isc_result_t 11166 listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 11167 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 11168 isc_tlsctx_cache_t *tlsctx_cache, 11169 ns_listenlist_t **target) { 11170 isc_result_t result; 11171 const cfg_listelt_t *element; 11172 ns_listenlist_t *dlist = NULL; 11173 11174 REQUIRE(target != NULL && *target == NULL); 11175 11176 result = ns_listenlist_create(mctx, &dlist); 11177 if (result != ISC_R_SUCCESS) { 11178 return (result); 11179 } 11180 11181 for (element = cfg_list_first(listenlist); element != NULL; 11182 element = cfg_list_next(element)) 11183 { 11184 ns_listenelt_t *delt = NULL; 11185 const cfg_obj_t *listener = cfg_listelt_value(element); 11186 result = listenelt_fromconfig(listener, config, actx, mctx, 11187 family, tlsctx_cache, &delt); 11188 if (result != ISC_R_SUCCESS) { 11189 goto cleanup; 11190 } 11191 ISC_LIST_APPEND(dlist->elts, delt, link); 11192 } 11193 *target = dlist; 11194 return (ISC_R_SUCCESS); 11195 11196 cleanup: 11197 ns_listenlist_detach(&dlist); 11198 return (result); 11199 } 11200 11201 static const cfg_obj_t * 11202 find_maplist(const cfg_obj_t *config, const char *listname, const char *name) { 11203 isc_result_t result; 11204 const cfg_obj_t *maplist = NULL; 11205 const cfg_listelt_t *elt = NULL; 11206 11207 REQUIRE(config != NULL); 11208 REQUIRE(name != NULL); 11209 11210 result = cfg_map_get(config, listname, &maplist); 11211 if (result != ISC_R_SUCCESS) { 11212 return (NULL); 11213 } 11214 11215 for (elt = cfg_list_first(maplist); elt != NULL; 11216 elt = cfg_list_next(elt)) 11217 { 11218 const cfg_obj_t *map = cfg_listelt_value(elt); 11219 if (strcasecmp(cfg_obj_asstring(cfg_map_getname(map)), name) == 11220 0) 11221 { 11222 return (map); 11223 } 11224 } 11225 11226 return (NULL); 11227 } 11228 11229 /* 11230 * Create a listen list from the corresponding configuration 11231 * data structure. 11232 */ 11233 static isc_result_t 11234 listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 11235 cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, 11236 isc_tlsctx_cache_t *tlsctx_cache, 11237 ns_listenelt_t **target) { 11238 isc_result_t result; 11239 const cfg_obj_t *ltup = NULL; 11240 const cfg_obj_t *tlsobj = NULL, *httpobj = NULL; 11241 const cfg_obj_t *portobj = NULL; 11242 const cfg_obj_t *http_server = NULL; 11243 in_port_t port = 0; 11244 const char *key = NULL, *cert = NULL, *ca_file = NULL, 11245 *dhparam_file = NULL, *ciphers = NULL; 11246 bool tls_prefer_server_ciphers = false, 11247 tls_prefer_server_ciphers_set = false; 11248 bool tls_session_tickets = false, tls_session_tickets_set = false; 11249 bool do_tls = false, no_tls = false, http = false; 11250 ns_listenelt_t *delt = NULL; 11251 uint32_t tls_protos = 0; 11252 ns_listen_tls_params_t tls_params = { 0 }; 11253 const char *tlsname = NULL; 11254 11255 REQUIRE(target != NULL && *target == NULL); 11256 11257 ltup = cfg_tuple_get(listener, "tuple"); 11258 RUNTIME_CHECK(ltup != NULL); 11259 11260 tlsobj = cfg_tuple_get(ltup, "tls"); 11261 if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) { 11262 tlsname = cfg_obj_asstring(tlsobj); 11263 11264 if (strcasecmp(tlsname, "none") == 0) { 11265 no_tls = true; 11266 } else if (strcasecmp(tlsname, "ephemeral") == 0) { 11267 do_tls = true; 11268 } else { 11269 const cfg_obj_t *keyobj = NULL, *certobj = NULL, 11270 *ca_obj = NULL, *dhparam_obj = NULL; 11271 const cfg_obj_t *tlsmap = NULL; 11272 const cfg_obj_t *tls_proto_list = NULL; 11273 const cfg_obj_t *ciphers_obj = NULL; 11274 const cfg_obj_t *prefer_server_ciphers_obj = NULL; 11275 const cfg_obj_t *session_tickets_obj = NULL; 11276 11277 do_tls = true; 11278 11279 tlsmap = find_maplist(config, "tls", tlsname); 11280 if (tlsmap == NULL) { 11281 cfg_obj_log(tlsobj, named_g_lctx, ISC_LOG_ERROR, 11282 "tls '%s' is not defined", 11283 cfg_obj_asstring(tlsobj)); 11284 return (ISC_R_FAILURE); 11285 } 11286 11287 CHECK(cfg_map_get(tlsmap, "key-file", &keyobj)); 11288 key = cfg_obj_asstring(keyobj); 11289 11290 CHECK(cfg_map_get(tlsmap, "cert-file", &certobj)); 11291 cert = cfg_obj_asstring(certobj); 11292 11293 if (cfg_map_get(tlsmap, "ca-file", &ca_obj) == 11294 ISC_R_SUCCESS) 11295 { 11296 ca_file = cfg_obj_asstring(ca_obj); 11297 } 11298 11299 if (cfg_map_get(tlsmap, "protocols", &tls_proto_list) == 11300 ISC_R_SUCCESS) 11301 { 11302 const cfg_listelt_t *proto = NULL; 11303 INSIST(tls_proto_list != NULL); 11304 for (proto = cfg_list_first(tls_proto_list); 11305 proto != 0; proto = cfg_list_next(proto)) 11306 { 11307 const cfg_obj_t *tls_proto_obj = 11308 cfg_listelt_value(proto); 11309 const char *tls_sver = 11310 cfg_obj_asstring(tls_proto_obj); 11311 const isc_tls_protocol_version_t ver = 11312 isc_tls_protocol_name_to_version( 11313 tls_sver); 11314 11315 INSIST(ver != 11316 ISC_TLS_PROTO_VER_UNDEFINED); 11317 INSIST(isc_tls_protocol_supported(ver)); 11318 tls_protos |= ver; 11319 } 11320 } 11321 11322 if (cfg_map_get(tlsmap, "dhparam-file", &dhparam_obj) == 11323 ISC_R_SUCCESS) 11324 { 11325 dhparam_file = cfg_obj_asstring(dhparam_obj); 11326 } 11327 11328 if (cfg_map_get(tlsmap, "ciphers", &ciphers_obj) == 11329 ISC_R_SUCCESS) 11330 { 11331 ciphers = cfg_obj_asstring(ciphers_obj); 11332 } 11333 11334 if (cfg_map_get(tlsmap, "prefer-server-ciphers", 11335 &prefer_server_ciphers_obj) == 11336 ISC_R_SUCCESS) 11337 { 11338 tls_prefer_server_ciphers = cfg_obj_asboolean( 11339 prefer_server_ciphers_obj); 11340 tls_prefer_server_ciphers_set = true; 11341 } 11342 11343 if (cfg_map_get(tlsmap, "session-tickets", 11344 &session_tickets_obj) == ISC_R_SUCCESS) 11345 { 11346 tls_session_tickets = 11347 cfg_obj_asboolean(session_tickets_obj); 11348 tls_session_tickets_set = true; 11349 } 11350 } 11351 } 11352 11353 tls_params = (ns_listen_tls_params_t){ 11354 .name = tlsname, 11355 .key = key, 11356 .cert = cert, 11357 .ca_file = ca_file, 11358 .protocols = tls_protos, 11359 .dhparam_file = dhparam_file, 11360 .ciphers = ciphers, 11361 .prefer_server_ciphers = tls_prefer_server_ciphers, 11362 .prefer_server_ciphers_set = tls_prefer_server_ciphers_set, 11363 .session_tickets = tls_session_tickets, 11364 .session_tickets_set = tls_session_tickets_set 11365 }; 11366 11367 httpobj = cfg_tuple_get(ltup, "http"); 11368 if (httpobj != NULL && cfg_obj_isstring(httpobj)) { 11369 const char *httpname = cfg_obj_asstring(httpobj); 11370 11371 if (!do_tls && !no_tls) { 11372 return (ISC_R_FAILURE); 11373 } 11374 11375 http_server = find_maplist(config, "http", httpname); 11376 if (http_server == NULL && strcasecmp(httpname, "default") != 0) 11377 { 11378 cfg_obj_log(httpobj, named_g_lctx, ISC_LOG_ERROR, 11379 "http '%s' is not defined", 11380 cfg_obj_asstring(httpobj)); 11381 return (ISC_R_FAILURE); 11382 } 11383 11384 http = true; 11385 } 11386 11387 portobj = cfg_tuple_get(ltup, "port"); 11388 if (!cfg_obj_isuint32(portobj)) { 11389 if (http && do_tls) { 11390 if (named_g_httpsport != 0) { 11391 port = named_g_httpsport; 11392 } else { 11393 result = named_config_getport( 11394 config, "https-port", &port); 11395 if (result != ISC_R_SUCCESS) { 11396 return (result); 11397 } 11398 } 11399 } else if (http && !do_tls) { 11400 if (named_g_httpport != 0) { 11401 port = named_g_httpport; 11402 } else { 11403 result = named_config_getport( 11404 config, "http-port", &port); 11405 if (result != ISC_R_SUCCESS) { 11406 return (result); 11407 } 11408 } 11409 } else if (do_tls) { 11410 if (named_g_tlsport != 0) { 11411 port = named_g_tlsport; 11412 } else { 11413 result = named_config_getport( 11414 config, "tls-port", &port); 11415 if (result != ISC_R_SUCCESS) { 11416 return (result); 11417 } 11418 } 11419 } else { 11420 if (named_g_port != 0) { 11421 port = named_g_port; 11422 } else { 11423 result = named_config_getport(config, "port", 11424 &port); 11425 if (result != ISC_R_SUCCESS) { 11426 return (result); 11427 } 11428 } 11429 } 11430 } else { 11431 if (cfg_obj_asuint32(portobj) >= UINT16_MAX) { 11432 return (ISC_R_RANGE); 11433 } 11434 port = (in_port_t)cfg_obj_asuint32(portobj); 11435 } 11436 11437 #ifdef HAVE_LIBNGHTTP2 11438 if (http) { 11439 CHECK(listenelt_http(http_server, family, do_tls, &tls_params, 11440 tlsctx_cache, port, mctx, &delt)); 11441 } 11442 #endif /* HAVE_LIBNGHTTP2 */ 11443 11444 if (!http) { 11445 CHECK(ns_listenelt_create(mctx, port, NULL, family, do_tls, 11446 &tls_params, tlsctx_cache, &delt)); 11447 } 11448 11449 result = cfg_acl_fromconfig2(cfg_tuple_get(listener, "acl"), config, 11450 named_g_lctx, actx, mctx, 0, family, 11451 &delt->acl); 11452 if (result != ISC_R_SUCCESS) { 11453 ns_listenelt_destroy(delt); 11454 return (result); 11455 } 11456 *target = delt; 11457 11458 cleanup: 11459 return (result); 11460 } 11461 11462 #ifdef HAVE_LIBNGHTTP2 11463 static isc_result_t 11464 listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, 11465 const ns_listen_tls_params_t *tls_params, 11466 isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, 11467 isc_mem_t *mctx, ns_listenelt_t **target) { 11468 isc_result_t result = ISC_R_SUCCESS; 11469 ns_listenelt_t *delt = NULL; 11470 char **endpoints = NULL; 11471 const cfg_obj_t *eplist = NULL; 11472 const cfg_listelt_t *elt = NULL; 11473 size_t len = 1, i = 0; 11474 uint32_t max_clients = named_g_http_listener_clients; 11475 uint32_t max_streams = named_g_http_streams_per_conn; 11476 11477 REQUIRE(target != NULL && *target == NULL); 11478 11479 if (tls) { 11480 INSIST(tls_params != NULL); 11481 INSIST((tls_params->key == NULL) == (tls_params->cert == NULL)); 11482 } 11483 11484 if (port == 0) { 11485 port = tls ? named_g_httpsport : named_g_httpport; 11486 } 11487 11488 /* 11489 * If "default" was used, we set up the default endpoint 11490 * of "/dns-query". 11491 */ 11492 if (http != NULL) { 11493 const cfg_obj_t *cfg_max_clients = NULL; 11494 const cfg_obj_t *cfg_max_streams = NULL; 11495 11496 if (cfg_map_get(http, "endpoints", &eplist) == ISC_R_SUCCESS) { 11497 INSIST(eplist != NULL); 11498 len = cfg_list_length(eplist, false); 11499 } 11500 11501 if (cfg_map_get(http, "listener-clients", &cfg_max_clients) == 11502 ISC_R_SUCCESS) 11503 { 11504 INSIST(cfg_max_clients != NULL); 11505 max_clients = cfg_obj_asuint32(cfg_max_clients); 11506 } 11507 11508 if (cfg_map_get(http, "streams-per-connection", 11509 &cfg_max_streams) == ISC_R_SUCCESS) 11510 { 11511 INSIST(cfg_max_streams != NULL); 11512 max_streams = cfg_obj_asuint32(cfg_max_streams); 11513 } 11514 } 11515 11516 endpoints = isc_mem_allocate(mctx, sizeof(endpoints[0]) * len); 11517 11518 if (http != NULL && eplist != NULL) { 11519 for (elt = cfg_list_first(eplist); elt != NULL; 11520 elt = cfg_list_next(elt)) 11521 { 11522 const cfg_obj_t *ep = cfg_listelt_value(elt); 11523 const char *path = cfg_obj_asstring(ep); 11524 endpoints[i++] = isc_mem_strdup(mctx, path); 11525 } 11526 } else { 11527 endpoints[i++] = isc_mem_strdup(mctx, ISC_NM_HTTP_DEFAULT_PATH); 11528 } 11529 11530 INSIST(i == len); 11531 11532 result = ns_listenelt_create_http(mctx, port, NULL, family, tls, 11533 tls_params, tlsctx_cache, endpoints, 11534 len, max_clients, max_streams, &delt); 11535 if (result != ISC_R_SUCCESS) { 11536 goto error; 11537 } 11538 11539 *target = delt; 11540 11541 return (result); 11542 error: 11543 if (delt != NULL) { 11544 ns_listenelt_destroy(delt); 11545 } 11546 return (result); 11547 } 11548 #endif /* HAVE_LIBNGHTTP2 */ 11549 11550 isc_result_t 11551 named_server_dumpstats(named_server_t *server) { 11552 isc_result_t result; 11553 FILE *fp = NULL; 11554 11555 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), 11556 "could not open statistics dump file", server->statsfile); 11557 11558 result = named_stats_dump(server, fp); 11559 11560 cleanup: 11561 if (fp != NULL) { 11562 (void)isc_stdio_close(fp); 11563 } 11564 if (result == ISC_R_SUCCESS) { 11565 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11566 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11567 "dumpstats complete"); 11568 } else { 11569 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11570 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11571 "dumpstats failed: %s", 11572 isc_result_totext(result)); 11573 } 11574 return (result); 11575 } 11576 11577 static isc_result_t 11578 add_zone_tolist(dns_zone_t *zone, void *uap) { 11579 struct dumpcontext *dctx = uap; 11580 struct zonelistentry *zle; 11581 11582 zle = isc_mem_get(dctx->mctx, sizeof *zle); 11583 zle->zone = NULL; 11584 dns_zone_attach(zone, &zle->zone); 11585 ISC_LINK_INIT(zle, link); 11586 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); 11587 return (ISC_R_SUCCESS); 11588 } 11589 11590 static isc_result_t 11591 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { 11592 struct viewlistentry *vle; 11593 isc_result_t result = ISC_R_SUCCESS; 11594 11595 /* 11596 * Prevent duplicate views. 11597 */ 11598 for (vle = ISC_LIST_HEAD(dctx->viewlist); vle != NULL; 11599 vle = ISC_LIST_NEXT(vle, link)) 11600 { 11601 if (vle->view == view) { 11602 return (ISC_R_SUCCESS); 11603 } 11604 } 11605 11606 vle = isc_mem_get(dctx->mctx, sizeof *vle); 11607 vle->view = NULL; 11608 dns_view_attach(view, &vle->view); 11609 ISC_LINK_INIT(vle, link); 11610 ISC_LIST_INIT(vle->zonelist); 11611 ISC_LIST_APPEND(dctx->viewlist, vle, link); 11612 if (dctx->dumpzones) { 11613 result = dns_zt_apply(view->zonetable, isc_rwlocktype_read, 11614 true, NULL, add_zone_tolist, dctx); 11615 } 11616 return (result); 11617 } 11618 11619 static void 11620 dumpcontext_destroy(struct dumpcontext *dctx) { 11621 struct viewlistentry *vle; 11622 struct zonelistentry *zle; 11623 11624 vle = ISC_LIST_HEAD(dctx->viewlist); 11625 while (vle != NULL) { 11626 ISC_LIST_UNLINK(dctx->viewlist, vle, link); 11627 zle = ISC_LIST_HEAD(vle->zonelist); 11628 while (zle != NULL) { 11629 ISC_LIST_UNLINK(vle->zonelist, zle, link); 11630 dns_zone_detach(&zle->zone); 11631 isc_mem_put(dctx->mctx, zle, sizeof *zle); 11632 zle = ISC_LIST_HEAD(vle->zonelist); 11633 } 11634 dns_view_detach(&vle->view); 11635 isc_mem_put(dctx->mctx, vle, sizeof *vle); 11636 vle = ISC_LIST_HEAD(dctx->viewlist); 11637 } 11638 if (dctx->version != NULL) { 11639 dns_db_closeversion(dctx->db, &dctx->version, false); 11640 } 11641 if (dctx->db != NULL) { 11642 dns_db_detach(&dctx->db); 11643 } 11644 if (dctx->cache != NULL) { 11645 dns_db_detach(&dctx->cache); 11646 } 11647 if (dctx->task != NULL) { 11648 isc_task_detach(&dctx->task); 11649 } 11650 if (dctx->fp != NULL) { 11651 (void)isc_stdio_close(dctx->fp); 11652 } 11653 if (dctx->mdctx != NULL) { 11654 dns_dumpctx_detach(&dctx->mdctx); 11655 } 11656 isc_mem_put(dctx->mctx, dctx, sizeof *dctx); 11657 } 11658 11659 static void 11660 dumpdone(void *arg, isc_result_t result) { 11661 struct dumpcontext *dctx = arg; 11662 char buf[1024 + 32]; 11663 const dns_master_style_t *style; 11664 11665 if (result != ISC_R_SUCCESS) { 11666 goto cleanup; 11667 } 11668 if (dctx->mdctx != NULL) { 11669 dns_dumpctx_detach(&dctx->mdctx); 11670 } 11671 if (dctx->view == NULL) { 11672 dctx->view = ISC_LIST_HEAD(dctx->viewlist); 11673 if (dctx->view == NULL) { 11674 goto done; 11675 } 11676 INSIST(dctx->zone == NULL); 11677 } else { 11678 goto resume; 11679 } 11680 nextview: 11681 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); 11682 resume: 11683 if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { 11684 fprintf(dctx->fp, ";\n; Cache of view '%s' is shared as '%s'\n", 11685 dctx->view->view->name, 11686 dns_cache_getname(dctx->view->view->cache)); 11687 } else if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) 11688 { 11689 if (dctx->dumpexpired) { 11690 style = &dns_master_style_cache_with_expired; 11691 } else { 11692 style = &dns_master_style_cache; 11693 } 11694 /* start cache dump */ 11695 if (dctx->view->view->cachedb != NULL) { 11696 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 11697 } 11698 if (dctx->cache != NULL) { 11699 fprintf(dctx->fp, 11700 ";\n; Cache dump of view '%s' (cache %s)\n;\n", 11701 dctx->view->view->name, 11702 dns_cache_getname(dctx->view->view->cache)); 11703 result = dns_master_dumptostreamasync( 11704 dctx->mctx, dctx->cache, NULL, style, dctx->fp, 11705 dctx->task, dumpdone, dctx, &dctx->mdctx); 11706 if (result == DNS_R_CONTINUE) { 11707 return; 11708 } 11709 if (result == ISC_R_NOTIMPLEMENTED) { 11710 fprintf(dctx->fp, "; %s\n", 11711 isc_result_totext(result)); 11712 } else if (result != ISC_R_SUCCESS) { 11713 goto cleanup; 11714 } 11715 } 11716 } 11717 11718 if ((dctx->dumpadb || dctx->dumpbad || dctx->dumpfail) && 11719 dctx->cache == NULL && dctx->view->view->cachedb != NULL) 11720 { 11721 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 11722 } 11723 11724 if (dctx->cache != NULL) { 11725 if (dctx->dumpadb) { 11726 dns_adb_dump(dctx->view->view->adb, dctx->fp); 11727 } 11728 if (dctx->dumpbad) { 11729 dns_resolver_printbadcache(dctx->view->view->resolver, 11730 dctx->fp); 11731 } 11732 if (dctx->dumpfail) { 11733 dns_badcache_print(dctx->view->view->failcache, 11734 "SERVFAIL cache", dctx->fp); 11735 } 11736 dns_db_detach(&dctx->cache); 11737 } 11738 if (dctx->dumpzones) { 11739 style = &dns_master_style_full; 11740 nextzone: 11741 if (dctx->version != NULL) { 11742 dns_db_closeversion(dctx->db, &dctx->version, false); 11743 } 11744 if (dctx->db != NULL) { 11745 dns_db_detach(&dctx->db); 11746 } 11747 if (dctx->zone == NULL) { 11748 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); 11749 } else { 11750 dctx->zone = ISC_LIST_NEXT(dctx->zone, link); 11751 } 11752 if (dctx->zone != NULL) { 11753 /* start zone dump */ 11754 dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); 11755 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); 11756 result = dns_zone_getdb(dctx->zone->zone, &dctx->db); 11757 if (result != ISC_R_SUCCESS) { 11758 fprintf(dctx->fp, "; %s\n", 11759 isc_result_totext(result)); 11760 goto nextzone; 11761 } 11762 dns_db_currentversion(dctx->db, &dctx->version); 11763 result = dns_master_dumptostreamasync( 11764 dctx->mctx, dctx->db, dctx->version, style, 11765 dctx->fp, dctx->task, dumpdone, dctx, 11766 &dctx->mdctx); 11767 if (result == DNS_R_CONTINUE) { 11768 return; 11769 } 11770 if (result == ISC_R_NOTIMPLEMENTED) { 11771 fprintf(dctx->fp, "; %s\n", 11772 isc_result_totext(result)); 11773 result = ISC_R_SUCCESS; 11774 POST(result); 11775 goto nextzone; 11776 } 11777 if (result != ISC_R_SUCCESS) { 11778 goto cleanup; 11779 } 11780 } 11781 } 11782 if (dctx->view != NULL) { 11783 dctx->view = ISC_LIST_NEXT(dctx->view, link); 11784 if (dctx->view != NULL) { 11785 goto nextview; 11786 } 11787 } 11788 done: 11789 fprintf(dctx->fp, "; Dump complete\n"); 11790 result = isc_stdio_flush(dctx->fp); 11791 if (result == ISC_R_SUCCESS) { 11792 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11793 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11794 "dumpdb complete"); 11795 } 11796 cleanup: 11797 if (result != ISC_R_SUCCESS) { 11798 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11799 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 11800 "dumpdb failed: %s", isc_result_totext(result)); 11801 } 11802 dumpcontext_destroy(dctx); 11803 } 11804 11805 isc_result_t 11806 named_server_dumpdb(named_server_t *server, isc_lex_t *lex, 11807 isc_buffer_t **text) { 11808 struct dumpcontext *dctx = NULL; 11809 dns_view_t *view; 11810 isc_result_t result; 11811 char *ptr; 11812 const char *sep; 11813 bool found; 11814 11815 REQUIRE(text != NULL); 11816 11817 /* Skip the command name. */ 11818 ptr = next_token(lex, NULL); 11819 if (ptr == NULL) { 11820 return (ISC_R_UNEXPECTEDEND); 11821 } 11822 11823 dctx = isc_mem_get(server->mctx, sizeof(*dctx)); 11824 11825 dctx->mctx = server->mctx; 11826 dctx->dumpcache = true; 11827 dctx->dumpadb = true; 11828 dctx->dumpbad = true; 11829 dctx->dumpexpired = false; 11830 dctx->dumpfail = true; 11831 dctx->dumpzones = false; 11832 dctx->fp = NULL; 11833 ISC_LIST_INIT(dctx->viewlist); 11834 dctx->view = NULL; 11835 dctx->zone = NULL; 11836 dctx->cache = NULL; 11837 dctx->mdctx = NULL; 11838 dctx->db = NULL; 11839 dctx->cache = NULL; 11840 dctx->task = NULL; 11841 dctx->version = NULL; 11842 isc_task_attach(server->task, &dctx->task); 11843 11844 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), 11845 "could not open dump file", server->dumpfile); 11846 11847 ptr = next_token(lex, NULL); 11848 sep = (ptr == NULL) ? "" : ": "; 11849 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 11850 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 11851 "dumpdb started%s%s", sep, (ptr != NULL) ? ptr : ""); 11852 11853 if (ptr != NULL && strcmp(ptr, "-all") == 0) { 11854 /* also dump zones */ 11855 dctx->dumpzones = true; 11856 ptr = next_token(lex, NULL); 11857 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { 11858 /* this is the default */ 11859 ptr = next_token(lex, NULL); 11860 } else if (ptr != NULL && strcmp(ptr, "-expired") == 0) { 11861 /* this is the same as -cache but includes expired data */ 11862 dctx->dumpexpired = true; 11863 ptr = next_token(lex, NULL); 11864 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { 11865 /* only dump zones, suppress caches */ 11866 dctx->dumpadb = false; 11867 dctx->dumpbad = false; 11868 dctx->dumpcache = false; 11869 dctx->dumpfail = false; 11870 dctx->dumpzones = true; 11871 ptr = next_token(lex, NULL); 11872 } else if (ptr != NULL && strcmp(ptr, "-adb") == 0) { 11873 /* only dump adb, suppress other caches */ 11874 dctx->dumpbad = false; 11875 dctx->dumpcache = false; 11876 dctx->dumpfail = false; 11877 ptr = next_token(lex, NULL); 11878 } else if (ptr != NULL && strcmp(ptr, "-bad") == 0) { 11879 /* only dump badcache, suppress other caches */ 11880 dctx->dumpadb = false; 11881 dctx->dumpcache = false; 11882 dctx->dumpfail = false; 11883 ptr = next_token(lex, NULL); 11884 } else if (ptr != NULL && strcmp(ptr, "-fail") == 0) { 11885 /* only dump servfail cache, suppress other caches */ 11886 dctx->dumpadb = false; 11887 dctx->dumpbad = false; 11888 dctx->dumpcache = false; 11889 ptr = next_token(lex, NULL); 11890 } 11891 11892 nextview: 11893 found = false; 11894 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 11895 view = ISC_LIST_NEXT(view, link)) 11896 { 11897 if (ptr != NULL && strcmp(view->name, ptr) != 0) { 11898 continue; 11899 } 11900 found = true; 11901 CHECK(add_view_tolist(dctx, view)); 11902 } 11903 if (ptr != NULL) { 11904 if (!found) { 11905 CHECK(putstr(text, "view '")); 11906 CHECK(putstr(text, ptr)); 11907 CHECK(putstr(text, "' not found")); 11908 CHECK(putnull(text)); 11909 result = ISC_R_NOTFOUND; 11910 dumpdone(dctx, result); 11911 return (result); 11912 } 11913 ptr = next_token(lex, NULL); 11914 if (ptr != NULL) { 11915 goto nextview; 11916 } 11917 } 11918 dumpdone(dctx, ISC_R_SUCCESS); 11919 return (ISC_R_SUCCESS); 11920 11921 cleanup: 11922 dumpcontext_destroy(dctx); 11923 return (result); 11924 } 11925 11926 isc_result_t 11927 named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex, 11928 isc_buffer_t **text) { 11929 dns_view_t *view; 11930 dns_keytable_t *secroots = NULL; 11931 dns_ntatable_t *ntatable = NULL; 11932 isc_result_t result; 11933 char *ptr; 11934 FILE *fp = NULL; 11935 isc_time_t now; 11936 char tbuf[64]; 11937 unsigned int used = isc_buffer_usedlength(*text); 11938 bool first = true; 11939 11940 REQUIRE(text != NULL); 11941 11942 /* Skip the command name. */ 11943 ptr = next_token(lex, text); 11944 if (ptr == NULL) { 11945 return (ISC_R_UNEXPECTEDEND); 11946 } 11947 11948 /* "-" here means print the output instead of dumping to file */ 11949 ptr = next_token(lex, text); 11950 if (ptr != NULL && strcmp(ptr, "-") == 0) { 11951 ptr = next_token(lex, text); 11952 } else { 11953 result = isc_stdio_open(server->secrootsfile, "w", &fp); 11954 if (result != ISC_R_SUCCESS) { 11955 (void)putstr(text, "could not open "); 11956 (void)putstr(text, server->secrootsfile); 11957 CHECKMF(result, "could not open secroots dump file", 11958 server->secrootsfile); 11959 } 11960 } 11961 11962 TIME_NOW(&now); 11963 isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); 11964 CHECK(putstr(text, "secure roots as of ")); 11965 CHECK(putstr(text, tbuf)); 11966 CHECK(putstr(text, ":\n")); 11967 used = isc_buffer_usedlength(*text); 11968 11969 do { 11970 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 11971 view = ISC_LIST_NEXT(view, link)) 11972 { 11973 if (ptr != NULL && strcmp(view->name, ptr) != 0) { 11974 continue; 11975 } 11976 if (secroots != NULL) { 11977 dns_keytable_detach(&secroots); 11978 } 11979 result = dns_view_getsecroots(view, &secroots); 11980 if (result == ISC_R_NOTFOUND) { 11981 result = ISC_R_SUCCESS; 11982 continue; 11983 } 11984 if (first || used != isc_buffer_usedlength(*text)) { 11985 CHECK(putstr(text, "\n")); 11986 first = false; 11987 } 11988 CHECK(putstr(text, " Start view ")); 11989 CHECK(putstr(text, view->name)); 11990 CHECK(putstr(text, "\n Secure roots:\n\n")); 11991 used = isc_buffer_usedlength(*text); 11992 CHECK(dns_keytable_totext(secroots, text)); 11993 11994 if (ntatable != NULL) { 11995 dns_ntatable_detach(&ntatable); 11996 } 11997 result = dns_view_getntatable(view, &ntatable); 11998 if (result == ISC_R_NOTFOUND) { 11999 result = ISC_R_SUCCESS; 12000 continue; 12001 } 12002 if (used != isc_buffer_usedlength(*text)) { 12003 CHECK(putstr(text, "\n")); 12004 } 12005 CHECK(putstr(text, " Negative trust anchors:\n\n")); 12006 used = isc_buffer_usedlength(*text); 12007 CHECK(dns_ntatable_totext(ntatable, NULL, text)); 12008 } 12009 12010 if (ptr != NULL) { 12011 ptr = next_token(lex, text); 12012 } 12013 } while (ptr != NULL); 12014 12015 cleanup: 12016 if (secroots != NULL) { 12017 dns_keytable_detach(&secroots); 12018 } 12019 if (ntatable != NULL) { 12020 dns_ntatable_detach(&ntatable); 12021 } 12022 12023 if (fp != NULL) { 12024 if (used != isc_buffer_usedlength(*text)) { 12025 (void)putstr(text, "\n"); 12026 } 12027 fprintf(fp, "%.*s", (int)isc_buffer_usedlength(*text), 12028 (char *)isc_buffer_base(*text)); 12029 isc_buffer_clear(*text); 12030 (void)isc_stdio_close(fp); 12031 } else if (isc_buffer_usedlength(*text) > 0) { 12032 (void)putnull(text); 12033 } 12034 12035 if (result == ISC_R_SUCCESS) { 12036 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12037 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12038 "dumpsecroots complete"); 12039 } else { 12040 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12041 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12042 "dumpsecroots failed: %s", 12043 isc_result_totext(result)); 12044 } 12045 return (result); 12046 } 12047 12048 isc_result_t 12049 named_server_dumprecursing(named_server_t *server) { 12050 FILE *fp = NULL; 12051 dns_view_t *view; 12052 isc_result_t result; 12053 12054 CHECKMF(isc_stdio_open(server->recfile, "w", &fp), 12055 "could not open dump file", server->recfile); 12056 fprintf(fp, ";\n; Recursing Queries\n;\n"); 12057 ns_interfacemgr_dumprecursing(fp, server->interfacemgr); 12058 12059 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12060 view = ISC_LIST_NEXT(view, link)) 12061 { 12062 fprintf(fp, ";\n; Active fetch domains [view: %s]\n;\n", 12063 view->name); 12064 dns_resolver_dumpfetches(view->resolver, isc_statsformat_file, 12065 fp); 12066 } 12067 12068 fprintf(fp, "; Dump complete\n"); 12069 12070 cleanup: 12071 if (fp != NULL) { 12072 result = isc_stdio_close(fp); 12073 } 12074 if (result == ISC_R_SUCCESS) { 12075 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12076 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12077 "dumprecursing complete"); 12078 } else { 12079 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12080 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12081 "dumprecursing failed: %s", 12082 isc_result_totext(result)); 12083 } 12084 return (result); 12085 } 12086 12087 isc_result_t 12088 named_server_setdebuglevel(named_server_t *server, isc_lex_t *lex) { 12089 char *ptr; 12090 char *endp; 12091 long newlevel; 12092 12093 UNUSED(server); 12094 12095 /* Skip the command name. */ 12096 ptr = next_token(lex, NULL); 12097 if (ptr == NULL) { 12098 return (ISC_R_UNEXPECTEDEND); 12099 } 12100 12101 /* Look for the new level name. */ 12102 ptr = next_token(lex, NULL); 12103 if (ptr == NULL) { 12104 if (named_g_debuglevel < 99) { 12105 named_g_debuglevel++; 12106 } 12107 } else { 12108 newlevel = strtol(ptr, &endp, 10); 12109 if (*endp != '\0' || newlevel < 0 || newlevel > 99) { 12110 return (ISC_R_RANGE); 12111 } 12112 named_g_debuglevel = (unsigned int)newlevel; 12113 } 12114 isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel); 12115 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12116 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12117 "debug level is now %u", named_g_debuglevel); 12118 return (ISC_R_SUCCESS); 12119 } 12120 12121 isc_result_t 12122 named_server_validation(named_server_t *server, isc_lex_t *lex, 12123 isc_buffer_t **text) { 12124 char *ptr; 12125 dns_view_t *view; 12126 bool changed = false; 12127 isc_result_t result; 12128 bool enable = true, set = true, first = true; 12129 12130 REQUIRE(text != NULL); 12131 12132 /* Skip the command name. */ 12133 ptr = next_token(lex, text); 12134 if (ptr == NULL) { 12135 return (ISC_R_UNEXPECTEDEND); 12136 } 12137 12138 /* Find out what we are to do. */ 12139 ptr = next_token(lex, text); 12140 if (ptr == NULL) { 12141 return (ISC_R_UNEXPECTEDEND); 12142 } 12143 12144 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 12145 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 12146 { 12147 enable = true; 12148 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 12149 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 12150 { 12151 enable = false; 12152 } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { 12153 set = false; 12154 } else { 12155 return (DNS_R_SYNTAX); 12156 } 12157 12158 /* Look for the view name. */ 12159 ptr = next_token(lex, text); 12160 12161 result = isc_task_beginexclusive(server->task); 12162 RUNTIME_CHECK(result == ISC_R_SUCCESS); 12163 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12164 view = ISC_LIST_NEXT(view, link)) 12165 { 12166 if ((ptr != NULL && strcasecmp(ptr, view->name) != 0) || 12167 strcasecmp("_bind", view->name) == 0) 12168 { 12169 continue; 12170 } 12171 12172 if (set) { 12173 CHECK(dns_view_flushcache(view, false)); 12174 view->enablevalidation = enable; 12175 changed = true; 12176 } else { 12177 if (!first) { 12178 CHECK(putstr(text, "\n")); 12179 } 12180 CHECK(putstr(text, "DNSSEC validation is ")); 12181 CHECK(putstr(text, view->enablevalidation 12182 ? "enabled" 12183 : "disabled")); 12184 CHECK(putstr(text, " (view ")); 12185 CHECK(putstr(text, view->name)); 12186 CHECK(putstr(text, ")")); 12187 first = false; 12188 } 12189 } 12190 CHECK(putnull(text)); 12191 12192 if (!set) { 12193 result = ISC_R_SUCCESS; 12194 } else if (changed) { 12195 result = ISC_R_SUCCESS; 12196 } else { 12197 result = ISC_R_FAILURE; 12198 } 12199 cleanup: 12200 isc_task_endexclusive(server->task); 12201 return (result); 12202 } 12203 12204 isc_result_t 12205 named_server_flushcache(named_server_t *server, isc_lex_t *lex) { 12206 char *ptr; 12207 dns_view_t *view; 12208 bool flushed; 12209 bool found; 12210 isc_result_t result; 12211 named_cache_t *nsc; 12212 12213 /* Skip the command name. */ 12214 ptr = next_token(lex, NULL); 12215 if (ptr == NULL) { 12216 return (ISC_R_UNEXPECTEDEND); 12217 } 12218 12219 /* Look for the view name. */ 12220 ptr = next_token(lex, NULL); 12221 12222 result = isc_task_beginexclusive(server->task); 12223 RUNTIME_CHECK(result == ISC_R_SUCCESS); 12224 flushed = true; 12225 found = false; 12226 12227 /* 12228 * Flushing a cache is tricky when caches are shared by multiple views. 12229 * We first identify which caches should be flushed in the local cache 12230 * list, flush these caches, and then update other views that refer to 12231 * the flushed cache DB. 12232 */ 12233 if (ptr != NULL) { 12234 /* 12235 * Mark caches that need to be flushed. This is an O(#view^2) 12236 * operation in the very worst case, but should be normally 12237 * much more lightweight because only a few (most typically just 12238 * one) views will match. 12239 */ 12240 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12241 view = ISC_LIST_NEXT(view, link)) 12242 { 12243 if (strcasecmp(ptr, view->name) != 0) { 12244 continue; 12245 } 12246 found = true; 12247 for (nsc = ISC_LIST_HEAD(server->cachelist); 12248 nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) 12249 { 12250 if (nsc->cache == view->cache) { 12251 break; 12252 } 12253 } 12254 INSIST(nsc != NULL); 12255 nsc->needflush = true; 12256 } 12257 } else { 12258 found = true; 12259 } 12260 12261 /* Perform flush */ 12262 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12263 nsc = ISC_LIST_NEXT(nsc, link)) 12264 { 12265 if (ptr != NULL && !nsc->needflush) { 12266 continue; 12267 } 12268 nsc->needflush = true; 12269 result = dns_view_flushcache(nsc->primaryview, false); 12270 if (result != ISC_R_SUCCESS) { 12271 flushed = false; 12272 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12273 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12274 "flushing cache in view '%s' failed: %s", 12275 nsc->primaryview->name, 12276 isc_result_totext(result)); 12277 } 12278 } 12279 12280 /* 12281 * Fix up views that share a flushed cache: let the views update the 12282 * cache DB they're referring to. This could also be an expensive 12283 * operation, but should typically be marginal: the inner loop is only 12284 * necessary for views that share a cache, and if there are many such 12285 * views the number of shared cache should normally be small. 12286 * A worst case is that we have n views and n/2 caches, each shared by 12287 * two views. Then this will be a O(n^2/4) operation. 12288 */ 12289 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12290 view = ISC_LIST_NEXT(view, link)) 12291 { 12292 if (!dns_view_iscacheshared(view)) { 12293 continue; 12294 } 12295 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12296 nsc = ISC_LIST_NEXT(nsc, link)) 12297 { 12298 if (!nsc->needflush || nsc->cache != view->cache) { 12299 continue; 12300 } 12301 result = dns_view_flushcache(view, true); 12302 if (result != ISC_R_SUCCESS) { 12303 flushed = false; 12304 isc_log_write( 12305 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12306 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12307 "fixing cache in view '%s' " 12308 "failed: %s", 12309 view->name, isc_result_totext(result)); 12310 } 12311 } 12312 } 12313 12314 /* Cleanup the cache list. */ 12315 for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; 12316 nsc = ISC_LIST_NEXT(nsc, link)) 12317 { 12318 nsc->needflush = false; 12319 } 12320 12321 if (flushed && found) { 12322 if (ptr != NULL) { 12323 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12324 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12325 "flushing cache in view '%s' succeeded", 12326 ptr); 12327 } else { 12328 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12329 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12330 "flushing caches in all views succeeded"); 12331 } 12332 result = ISC_R_SUCCESS; 12333 } else { 12334 if (!found) { 12335 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12336 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12337 "flushing cache in view '%s' failed: " 12338 "view not found", 12339 ptr); 12340 result = ISC_R_NOTFOUND; 12341 } else { 12342 result = ISC_R_FAILURE; 12343 } 12344 } 12345 isc_task_endexclusive(server->task); 12346 return (result); 12347 } 12348 12349 isc_result_t 12350 named_server_flushnode(named_server_t *server, isc_lex_t *lex, bool tree) { 12351 char *ptr, *viewname; 12352 char target[DNS_NAME_FORMATSIZE]; 12353 dns_view_t *view; 12354 bool flushed; 12355 bool found; 12356 isc_result_t result; 12357 isc_buffer_t b; 12358 dns_fixedname_t fixed; 12359 dns_name_t *name; 12360 12361 /* Skip the command name. */ 12362 ptr = next_token(lex, NULL); 12363 if (ptr == NULL) { 12364 return (ISC_R_UNEXPECTEDEND); 12365 } 12366 12367 /* Find the domain name to flush. */ 12368 ptr = next_token(lex, NULL); 12369 if (ptr == NULL) { 12370 return (ISC_R_UNEXPECTEDEND); 12371 } 12372 12373 strlcpy(target, ptr, DNS_NAME_FORMATSIZE); 12374 isc_buffer_constinit(&b, target, strlen(target)); 12375 isc_buffer_add(&b, strlen(target)); 12376 name = dns_fixedname_initname(&fixed); 12377 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 12378 if (result != ISC_R_SUCCESS) { 12379 return (result); 12380 } 12381 12382 /* Look for the view name. */ 12383 viewname = next_token(lex, NULL); 12384 12385 result = isc_task_beginexclusive(server->task); 12386 RUNTIME_CHECK(result == ISC_R_SUCCESS); 12387 flushed = true; 12388 found = false; 12389 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12390 view = ISC_LIST_NEXT(view, link)) 12391 { 12392 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) { 12393 continue; 12394 } 12395 found = true; 12396 /* 12397 * It's a little inefficient to try flushing name for all views 12398 * if some of the views share a single cache. But since the 12399 * operation is lightweight we prefer simplicity here. 12400 */ 12401 result = dns_view_flushnode(view, name, tree); 12402 if (result != ISC_R_SUCCESS) { 12403 flushed = false; 12404 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12405 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12406 "flushing %s '%s' in cache view '%s' " 12407 "failed: %s", 12408 tree ? "tree" : "name", target, 12409 view->name, isc_result_totext(result)); 12410 } 12411 } 12412 if (flushed && found) { 12413 if (viewname != NULL) { 12414 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12415 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12416 "flushing %s '%s' in cache view '%s' " 12417 "succeeded", 12418 tree ? "tree" : "name", target, viewname); 12419 } else { 12420 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12421 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12422 "flushing %s '%s' in all cache views " 12423 "succeeded", 12424 tree ? "tree" : "name", target); 12425 } 12426 result = ISC_R_SUCCESS; 12427 } else { 12428 if (!found) { 12429 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12430 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 12431 "flushing %s '%s' in cache view '%s' " 12432 "failed: view not found", 12433 tree ? "tree" : "name", target, viewname); 12434 } 12435 result = ISC_R_FAILURE; 12436 } 12437 isc_task_endexclusive(server->task); 12438 return (result); 12439 } 12440 12441 isc_result_t 12442 named_server_status(named_server_t *server, isc_buffer_t **text) { 12443 isc_result_t result; 12444 unsigned int zonecount, xferrunning, xferdeferred, soaqueries; 12445 unsigned int automatic; 12446 const char *ob = "", *cb = "", *alt = ""; 12447 char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE]; 12448 char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE]; 12449 char line[1024], hostname[256]; 12450 named_reload_t reload_status; 12451 12452 REQUIRE(text != NULL); 12453 12454 if (named_g_server->version_set) { 12455 ob = " ("; 12456 cb = ")"; 12457 if (named_g_server->version == NULL) { 12458 alt = "version.bind/txt/ch disabled"; 12459 } else { 12460 alt = named_g_server->version; 12461 } 12462 } 12463 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); 12464 xferrunning = dns_zonemgr_getcount(server->zonemgr, 12465 DNS_ZONESTATE_XFERRUNNING); 12466 xferdeferred = dns_zonemgr_getcount(server->zonemgr, 12467 DNS_ZONESTATE_XFERDEFERRED); 12468 soaqueries = dns_zonemgr_getcount(server->zonemgr, 12469 DNS_ZONESTATE_SOAQUERY); 12470 automatic = dns_zonemgr_getcount(server->zonemgr, 12471 DNS_ZONESTATE_AUTOMATIC); 12472 12473 isc_time_formathttptimestamp(&named_g_boottime, boottime, 12474 sizeof(boottime)); 12475 isc_time_formathttptimestamp(&named_g_configtime, configtime, 12476 sizeof(configtime)); 12477 12478 snprintf(line, sizeof(line), "version: %s%s <id:%s>%s%s%s\n", 12479 PACKAGE_STRING, PACKAGE_DESCRIPTION, PACKAGE_SRCID, ob, alt, 12480 cb); 12481 CHECK(putstr(text, line)); 12482 12483 if (gethostname(hostname, sizeof(hostname)) == 0) { 12484 strlcpy(hostname, "localhost", sizeof(hostname)); 12485 } 12486 snprintf(line, sizeof(line), "running on %s: %s\n", hostname, 12487 named_os_uname()); 12488 CHECK(putstr(text, line)); 12489 12490 snprintf(line, sizeof(line), "boot time: %s\n", boottime); 12491 CHECK(putstr(text, line)); 12492 12493 snprintf(line, sizeof(line), "last configured: %s\n", configtime); 12494 CHECK(putstr(text, line)); 12495 12496 if (named_g_chrootdir != NULL) { 12497 snprintf(line, sizeof(line), "configuration file: %s (%s%s)\n", 12498 named_g_conffile, named_g_chrootdir, named_g_conffile); 12499 } else { 12500 snprintf(line, sizeof(line), "configuration file: %s\n", 12501 named_g_conffile); 12502 } 12503 CHECK(putstr(text, line)); 12504 12505 snprintf(line, sizeof(line), "CPUs found: %u\n", named_g_cpus_detected); 12506 CHECK(putstr(text, line)); 12507 12508 snprintf(line, sizeof(line), "worker threads: %u\n", named_g_cpus); 12509 CHECK(putstr(text, line)); 12510 12511 snprintf(line, sizeof(line), "UDP listeners per interface: %u\n", 12512 named_g_udpdisp); 12513 CHECK(putstr(text, line)); 12514 12515 snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n", 12516 zonecount, automatic); 12517 CHECK(putstr(text, line)); 12518 12519 snprintf(line, sizeof(line), "debug level: %u\n", named_g_debuglevel); 12520 CHECK(putstr(text, line)); 12521 12522 snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning); 12523 CHECK(putstr(text, line)); 12524 12525 snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred); 12526 CHECK(putstr(text, line)); 12527 12528 snprintf(line, sizeof(line), "soa queries in progress: %u\n", 12529 soaqueries); 12530 CHECK(putstr(text, line)); 12531 12532 snprintf(line, sizeof(line), "query logging is %s\n", 12533 ns_server_getoption(server->sctx, NS_SERVER_LOGQUERIES) 12534 ? "ON" 12535 : "OFF"); 12536 CHECK(putstr(text, line)); 12537 12538 snprintf(line, sizeof(line), "recursive clients: %u/%u/%u\n", 12539 isc_quota_getused(&server->sctx->recursionquota), 12540 isc_quota_getsoft(&server->sctx->recursionquota), 12541 isc_quota_getmax(&server->sctx->recursionquota)); 12542 CHECK(putstr(text, line)); 12543 12544 snprintf(line, sizeof(line), "tcp clients: %u/%u\n", 12545 isc_quota_getused(&server->sctx->tcpquota), 12546 isc_quota_getmax(&server->sctx->tcpquota)); 12547 CHECK(putstr(text, line)); 12548 12549 snprintf(line, sizeof(line), "TCP high-water: %u\n", 12550 (unsigned)ns_stats_get_counter(server->sctx->nsstats, 12551 ns_statscounter_tcphighwater)); 12552 CHECK(putstr(text, line)); 12553 12554 reload_status = atomic_load(&server->reload_status); 12555 if (reload_status != NAMED_RELOAD_DONE) { 12556 snprintf(line, sizeof(line), "reload/reconfig %s\n", 12557 (reload_status == NAMED_RELOAD_FAILED 12558 ? "failed" 12559 : "in progress")); 12560 CHECK(putstr(text, line)); 12561 } 12562 12563 CHECK(putstr(text, "server is up and running")); 12564 CHECK(putnull(text)); 12565 12566 return (ISC_R_SUCCESS); 12567 cleanup: 12568 return (result); 12569 } 12570 12571 isc_result_t 12572 named_server_testgen(isc_lex_t *lex, isc_buffer_t **text) { 12573 isc_result_t result; 12574 char *ptr; 12575 unsigned long count; 12576 unsigned long i; 12577 const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; 12578 12579 REQUIRE(text != NULL); 12580 12581 /* Skip the command name. */ 12582 ptr = next_token(lex, text); 12583 if (ptr == NULL) { 12584 return (ISC_R_UNEXPECTEDEND); 12585 } 12586 12587 ptr = next_token(lex, text); 12588 if (ptr == NULL) { 12589 count = 26; 12590 } else { 12591 count = strtoul(ptr, NULL, 10); 12592 } 12593 12594 CHECK(isc_buffer_reserve(text, count)); 12595 for (i = 0; i < count; i++) { 12596 CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)])); 12597 } 12598 12599 CHECK(putnull(text)); 12600 12601 cleanup: 12602 return (result); 12603 } 12604 12605 static isc_result_t 12606 delete_keynames(dns_tsig_keyring_t *ring, char *target, 12607 unsigned int *foundkeys) { 12608 char namestr[DNS_NAME_FORMATSIZE]; 12609 isc_result_t result; 12610 dns_rbtnodechain_t chain; 12611 dns_name_t foundname; 12612 dns_fixedname_t fixedorigin; 12613 dns_name_t *origin; 12614 dns_rbtnode_t *node; 12615 dns_tsigkey_t *tkey; 12616 12617 dns_name_init(&foundname, NULL); 12618 origin = dns_fixedname_initname(&fixedorigin); 12619 12620 again: 12621 dns_rbtnodechain_init(&chain); 12622 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, origin); 12623 if (result == ISC_R_NOTFOUND) { 12624 dns_rbtnodechain_invalidate(&chain); 12625 return (ISC_R_SUCCESS); 12626 } 12627 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 12628 dns_rbtnodechain_invalidate(&chain); 12629 return (result); 12630 } 12631 12632 for (;;) { 12633 node = NULL; 12634 dns_rbtnodechain_current(&chain, &foundname, origin, &node); 12635 tkey = node->data; 12636 12637 if (tkey != NULL) { 12638 if (!tkey->generated) { 12639 goto nextkey; 12640 } 12641 12642 dns_name_format(&tkey->name, namestr, sizeof(namestr)); 12643 if (strcmp(namestr, target) == 0) { 12644 (*foundkeys)++; 12645 dns_rbtnodechain_invalidate(&chain); 12646 (void)dns_rbt_deletename(ring->keys, 12647 &tkey->name, false); 12648 goto again; 12649 } 12650 } 12651 12652 nextkey: 12653 result = dns_rbtnodechain_next(&chain, &foundname, origin); 12654 if (result == ISC_R_NOMORE) { 12655 break; 12656 } 12657 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 12658 dns_rbtnodechain_invalidate(&chain); 12659 return (result); 12660 } 12661 } 12662 12663 return (ISC_R_SUCCESS); 12664 } 12665 12666 isc_result_t 12667 named_server_tsigdelete(named_server_t *server, isc_lex_t *lex, 12668 isc_buffer_t **text) { 12669 isc_result_t result; 12670 dns_view_t *view; 12671 unsigned int foundkeys = 0; 12672 char *ptr, *viewname; 12673 char target[DNS_NAME_FORMATSIZE]; 12674 char fbuf[16]; 12675 12676 REQUIRE(text != NULL); 12677 12678 (void)next_token(lex, text); /* skip command name */ 12679 12680 ptr = next_token(lex, text); 12681 if (ptr == NULL) { 12682 return (ISC_R_UNEXPECTEDEND); 12683 } 12684 strlcpy(target, ptr, DNS_NAME_FORMATSIZE); 12685 12686 viewname = next_token(lex, text); 12687 12688 result = isc_task_beginexclusive(server->task); 12689 RUNTIME_CHECK(result == ISC_R_SUCCESS); 12690 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12691 view = ISC_LIST_NEXT(view, link)) 12692 { 12693 if (viewname == NULL || strcmp(view->name, viewname) == 0) { 12694 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write); 12695 result = delete_keynames(view->dynamickeys, target, 12696 &foundkeys); 12697 RWUNLOCK(&view->dynamickeys->lock, 12698 isc_rwlocktype_write); 12699 if (result != ISC_R_SUCCESS) { 12700 isc_task_endexclusive(server->task); 12701 return (result); 12702 } 12703 } 12704 } 12705 isc_task_endexclusive(server->task); 12706 12707 snprintf(fbuf, sizeof(fbuf), "%u", foundkeys); 12708 12709 CHECK(putstr(text, fbuf)); 12710 CHECK(putstr(text, " tsig keys deleted.")); 12711 CHECK(putnull(text)); 12712 12713 cleanup: 12714 return (result); 12715 } 12716 12717 static isc_result_t 12718 list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t **text, 12719 unsigned int *foundkeys) { 12720 char namestr[DNS_NAME_FORMATSIZE]; 12721 char creatorstr[DNS_NAME_FORMATSIZE]; 12722 isc_result_t result; 12723 dns_rbtnodechain_t chain; 12724 dns_name_t foundname; 12725 dns_fixedname_t fixedorigin; 12726 dns_name_t *origin; 12727 dns_rbtnode_t *node; 12728 dns_tsigkey_t *tkey; 12729 const char *viewname; 12730 12731 if (view != NULL) { 12732 viewname = view->name; 12733 } else { 12734 viewname = "(global)"; 12735 } 12736 12737 dns_name_init(&foundname, NULL); 12738 origin = dns_fixedname_initname(&fixedorigin); 12739 dns_rbtnodechain_init(&chain); 12740 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, origin); 12741 if (result == ISC_R_NOTFOUND) { 12742 dns_rbtnodechain_invalidate(&chain); 12743 return (ISC_R_SUCCESS); 12744 } 12745 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 12746 dns_rbtnodechain_invalidate(&chain); 12747 return (result); 12748 } 12749 12750 for (;;) { 12751 node = NULL; 12752 dns_rbtnodechain_current(&chain, &foundname, origin, &node); 12753 tkey = node->data; 12754 12755 if (tkey != NULL) { 12756 dns_name_format(&tkey->name, namestr, sizeof(namestr)); 12757 if (tkey->generated) { 12758 dns_name_format(tkey->creator, creatorstr, 12759 sizeof(creatorstr)); 12760 if (*foundkeys != 0) { 12761 CHECK(putstr(text, "\n")); 12762 } 12763 CHECK(putstr(text, "view \"")); 12764 CHECK(putstr(text, viewname)); 12765 CHECK(putstr(text, "\"; type \"dynamic\"; key " 12766 "\"")); 12767 CHECK(putstr(text, namestr)); 12768 CHECK(putstr(text, "\"; creator \"")); 12769 CHECK(putstr(text, creatorstr)); 12770 CHECK(putstr(text, "\";")); 12771 } else { 12772 if (*foundkeys != 0) { 12773 CHECK(putstr(text, "\n")); 12774 } 12775 CHECK(putstr(text, "view \"")); 12776 CHECK(putstr(text, viewname)); 12777 CHECK(putstr(text, "\"; type \"static\"; key " 12778 "\"")); 12779 CHECK(putstr(text, namestr)); 12780 CHECK(putstr(text, "\";")); 12781 } 12782 (*foundkeys)++; 12783 } 12784 result = dns_rbtnodechain_next(&chain, &foundname, origin); 12785 if (result == ISC_R_NOMORE || result == DNS_R_NEWORIGIN) { 12786 break; 12787 } 12788 } 12789 12790 return (ISC_R_SUCCESS); 12791 cleanup: 12792 dns_rbtnodechain_invalidate(&chain); 12793 return (result); 12794 } 12795 12796 isc_result_t 12797 named_server_tsiglist(named_server_t *server, isc_buffer_t **text) { 12798 isc_result_t result = ISC_R_SUCCESS; 12799 dns_view_t *view; 12800 unsigned int foundkeys = 0; 12801 12802 REQUIRE(text != NULL); 12803 12804 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12805 view = ISC_LIST_NEXT(view, link)) 12806 { 12807 RWLOCK(&view->statickeys->lock, isc_rwlocktype_read); 12808 result = list_keynames(view, view->statickeys, text, 12809 &foundkeys); 12810 RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read); 12811 if (result != ISC_R_SUCCESS) { 12812 return (result); 12813 } 12814 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read); 12815 result = list_keynames(view, view->dynamickeys, text, 12816 &foundkeys); 12817 RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read); 12818 if (result != ISC_R_SUCCESS) { 12819 return (result); 12820 } 12821 } 12822 12823 if (foundkeys == 0) { 12824 CHECK(putstr(text, "no tsig keys found.")); 12825 } 12826 12827 if (isc_buffer_usedlength(*text) > 0) { 12828 CHECK(putnull(text)); 12829 } 12830 12831 cleanup: 12832 return (result); 12833 } 12834 12835 /* 12836 * Act on a "sign" or "loadkeys" command from the command channel. 12837 */ 12838 isc_result_t 12839 named_server_rekey(named_server_t *server, isc_lex_t *lex, 12840 isc_buffer_t **text) { 12841 isc_result_t result; 12842 dns_zone_t *zone = NULL; 12843 dns_zonetype_t type; 12844 uint16_t keyopts; 12845 bool fullsign = false; 12846 char *ptr; 12847 12848 REQUIRE(text != NULL); 12849 12850 ptr = next_token(lex, text); 12851 if (ptr == NULL) { 12852 return (ISC_R_UNEXPECTEDEND); 12853 } 12854 12855 if (strcasecmp(ptr, NAMED_COMMAND_SIGN) == 0) { 12856 fullsign = true; 12857 } 12858 12859 REQUIRE(text != NULL); 12860 12861 result = zone_from_args(server, lex, NULL, &zone, NULL, text, false); 12862 if (result != ISC_R_SUCCESS) { 12863 return (result); 12864 } 12865 if (zone == NULL) { 12866 return (ISC_R_UNEXPECTEDEND); /* XXX: or do all zones? */ 12867 } 12868 12869 type = dns_zone_gettype(zone); 12870 if (type != dns_zone_primary) { 12871 dns_zone_detach(&zone); 12872 return (DNS_R_NOTPRIMARY); 12873 } 12874 12875 keyopts = dns_zone_getkeyopts(zone); 12876 12877 /* 12878 * "rndc loadkeys" requires "auto-dnssec maintain" 12879 * or a "dnssec-policy". 12880 */ 12881 if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) { 12882 result = ISC_R_NOPERM; 12883 } else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) { 12884 result = ISC_R_NOPERM; 12885 } else { 12886 dns_zone_rekey(zone, fullsign); 12887 } 12888 12889 dns_zone_detach(&zone); 12890 return (result); 12891 } 12892 12893 /* 12894 * Act on a "sync" command from the command channel. 12895 */ 12896 static isc_result_t 12897 synczone(dns_zone_t *zone, void *uap) { 12898 bool cleanup = *(bool *)uap; 12899 isc_result_t result; 12900 dns_zone_t *raw = NULL; 12901 char *journal; 12902 12903 dns_zone_getraw(zone, &raw); 12904 if (raw != NULL) { 12905 synczone(raw, uap); 12906 dns_zone_detach(&raw); 12907 } 12908 12909 result = dns_zone_flush(zone); 12910 if (result != ISC_R_SUCCESS) { 12911 cleanup = false; 12912 } 12913 if (cleanup) { 12914 journal = dns_zone_getjournal(zone); 12915 if (journal != NULL) { 12916 (void)isc_file_remove(journal); 12917 } 12918 } 12919 12920 return (result); 12921 } 12922 12923 isc_result_t 12924 named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { 12925 isc_result_t result, tresult; 12926 dns_view_t *view; 12927 dns_zone_t *zone = NULL; 12928 char classstr[DNS_RDATACLASS_FORMATSIZE]; 12929 char zonename[DNS_NAME_FORMATSIZE]; 12930 const char *vname, *sep, *arg; 12931 bool cleanup = false; 12932 12933 REQUIRE(text != NULL); 12934 12935 (void)next_token(lex, text); 12936 12937 arg = next_token(lex, text); 12938 if (arg != NULL && 12939 (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) 12940 { 12941 cleanup = true; 12942 arg = next_token(lex, text); 12943 } 12944 12945 REQUIRE(text != NULL); 12946 12947 result = zone_from_args(server, lex, arg, &zone, NULL, text, false); 12948 if (result != ISC_R_SUCCESS) { 12949 return (result); 12950 } 12951 12952 if (zone == NULL) { 12953 result = isc_task_beginexclusive(server->task); 12954 RUNTIME_CHECK(result == ISC_R_SUCCESS); 12955 tresult = ISC_R_SUCCESS; 12956 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 12957 view = ISC_LIST_NEXT(view, link)) 12958 { 12959 result = dns_zt_apply(view->zonetable, 12960 isc_rwlocktype_none, false, NULL, 12961 synczone, &cleanup); 12962 if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) 12963 { 12964 tresult = result; 12965 } 12966 } 12967 isc_task_endexclusive(server->task); 12968 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 12969 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 12970 "dumping all zones%s: %s", 12971 cleanup ? ", removing journal files" : "", 12972 isc_result_totext(result)); 12973 return (tresult); 12974 } 12975 12976 result = isc_task_beginexclusive(server->task); 12977 RUNTIME_CHECK(result == ISC_R_SUCCESS); 12978 result = synczone(zone, &cleanup); 12979 isc_task_endexclusive(server->task); 12980 12981 view = dns_zone_getview(zone); 12982 if (strcmp(view->name, "_default") == 0 || 12983 strcmp(view->name, "_bind") == 0) 12984 { 12985 vname = ""; 12986 sep = ""; 12987 } else { 12988 vname = view->name; 12989 sep = " "; 12990 } 12991 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 12992 sizeof(classstr)); 12993 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 12994 isc_log_write( 12995 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, 12996 ISC_LOG_INFO, "sync: dumping zone '%s/%s'%s%s%s: %s", zonename, 12997 classstr, sep, vname, cleanup ? ", removing journal file" : "", 12998 isc_result_totext(result)); 12999 dns_zone_detach(&zone); 13000 return (result); 13001 } 13002 13003 /* 13004 * Act on a "freeze" or "thaw" command from the command channel. 13005 */ 13006 isc_result_t 13007 named_server_freeze(named_server_t *server, bool freeze, isc_lex_t *lex, 13008 isc_buffer_t **text) { 13009 isc_result_t result, tresult; 13010 dns_zone_t *mayberaw = NULL, *raw = NULL; 13011 dns_zonetype_t type; 13012 char classstr[DNS_RDATACLASS_FORMATSIZE]; 13013 char zonename[DNS_NAME_FORMATSIZE]; 13014 dns_view_t *view; 13015 const char *vname, *sep; 13016 bool frozen; 13017 const char *msg = NULL; 13018 13019 REQUIRE(text != NULL); 13020 13021 result = zone_from_args(server, lex, NULL, &mayberaw, NULL, text, true); 13022 if (result != ISC_R_SUCCESS) { 13023 return (result); 13024 } 13025 if (mayberaw == NULL) { 13026 result = isc_task_beginexclusive(server->task); 13027 RUNTIME_CHECK(result == ISC_R_SUCCESS); 13028 tresult = ISC_R_SUCCESS; 13029 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 13030 view = ISC_LIST_NEXT(view, link)) 13031 { 13032 result = dns_view_freezezones(view, freeze); 13033 if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) 13034 { 13035 tresult = result; 13036 } 13037 } 13038 isc_task_endexclusive(server->task); 13039 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13040 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13041 "%s all zones: %s", 13042 freeze ? "freezing" : "thawing", 13043 isc_result_totext(tresult)); 13044 return (tresult); 13045 } 13046 dns_zone_getraw(mayberaw, &raw); 13047 if (raw != NULL) { 13048 dns_zone_detach(&mayberaw); 13049 dns_zone_attach(raw, &mayberaw); 13050 dns_zone_detach(&raw); 13051 } 13052 type = dns_zone_gettype(mayberaw); 13053 if (type != dns_zone_primary) { 13054 dns_zone_detach(&mayberaw); 13055 return (DNS_R_NOTPRIMARY); 13056 } 13057 13058 if (freeze && !dns_zone_isdynamic(mayberaw, true)) { 13059 dns_zone_detach(&mayberaw); 13060 return (DNS_R_NOTDYNAMIC); 13061 } 13062 13063 result = isc_task_beginexclusive(server->task); 13064 RUNTIME_CHECK(result == ISC_R_SUCCESS); 13065 frozen = dns_zone_getupdatedisabled(mayberaw); 13066 if (freeze) { 13067 if (frozen) { 13068 msg = "WARNING: The zone was already frozen.\n" 13069 "Someone else may be editing it or " 13070 "it may still be re-loading."; 13071 result = DNS_R_FROZEN; 13072 } 13073 if (result == ISC_R_SUCCESS) { 13074 result = dns_zone_flush(mayberaw); 13075 if (result != ISC_R_SUCCESS) { 13076 msg = "Flushing the zone updates to " 13077 "disk failed."; 13078 } 13079 } 13080 if (result == ISC_R_SUCCESS) { 13081 dns_zone_setupdatedisabled(mayberaw, freeze); 13082 } 13083 } else { 13084 if (frozen) { 13085 result = dns_zone_loadandthaw(mayberaw); 13086 switch (result) { 13087 case ISC_R_SUCCESS: 13088 case DNS_R_UPTODATE: 13089 msg = "The zone reload and thaw was " 13090 "successful."; 13091 result = ISC_R_SUCCESS; 13092 break; 13093 case DNS_R_CONTINUE: 13094 msg = "A zone reload and thaw was started.\n" 13095 "Check the logs to see the result."; 13096 result = ISC_R_SUCCESS; 13097 break; 13098 default: 13099 break; 13100 } 13101 } 13102 } 13103 isc_task_endexclusive(server->task); 13104 13105 if (msg != NULL) { 13106 (void)putstr(text, msg); 13107 (void)putnull(text); 13108 } 13109 13110 view = dns_zone_getview(mayberaw); 13111 if (strcmp(view->name, "_default") == 0 || 13112 strcmp(view->name, "_bind") == 0) 13113 { 13114 vname = ""; 13115 sep = ""; 13116 } else { 13117 vname = view->name; 13118 sep = " "; 13119 } 13120 dns_rdataclass_format(dns_zone_getclass(mayberaw), classstr, 13121 sizeof(classstr)); 13122 dns_name_format(dns_zone_getorigin(mayberaw), zonename, 13123 sizeof(zonename)); 13124 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13125 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13126 "%s zone '%s/%s'%s%s: %s", 13127 freeze ? "freezing" : "thawing", zonename, classstr, sep, 13128 vname, isc_result_totext(result)); 13129 dns_zone_detach(&mayberaw); 13130 return (result); 13131 } 13132 13133 #ifdef HAVE_LIBSCF 13134 /* 13135 * This function adds a message for rndc to echo if named 13136 * is managed by smf and is also running chroot. 13137 */ 13138 isc_result_t 13139 named_smf_add_message(isc_buffer_t **text) { 13140 REQUIRE(text != NULL); 13141 13142 return (putstr(text, "use svcadm(1M) to manage named")); 13143 } 13144 #endif /* HAVE_LIBSCF */ 13145 13146 #ifndef HAVE_LMDB 13147 13148 /* 13149 * Emit a comment at the top of the nzf file containing the viewname 13150 * Expects the fp to already be open for writing 13151 */ 13152 #define HEADER1 "# New zone file for view: " 13153 #define HEADER2 \ 13154 "\n# This file contains configuration for zones added by\n" \ 13155 "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n" 13156 static isc_result_t 13157 add_comment(FILE *fp, const char *viewname) { 13158 isc_result_t result; 13159 CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL)); 13160 CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL)); 13161 CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL)); 13162 cleanup: 13163 return (result); 13164 } 13165 13166 static void 13167 dumpzone(void *arg, const char *buf, int len) { 13168 FILE *fp = arg; 13169 13170 (void)isc_stdio_write(buf, len, 1, fp, NULL); 13171 } 13172 13173 static isc_result_t 13174 nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) { 13175 isc_result_t result; 13176 off_t offset; 13177 FILE *fp = NULL; 13178 bool offsetok = false; 13179 13180 LOCK(&view->new_zone_lock); 13181 13182 CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); 13183 CHECK(isc_stdio_seek(fp, 0, SEEK_END)); 13184 13185 CHECK(isc_stdio_tell(fp, &offset)); 13186 offsetok = true; 13187 if (offset == 0) { 13188 CHECK(add_comment(fp, view->name)); 13189 } 13190 13191 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 13192 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); 13193 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); 13194 CHECK(isc_stdio_flush(fp)); 13195 result = isc_stdio_close(fp); 13196 fp = NULL; 13197 13198 cleanup: 13199 if (fp != NULL) { 13200 (void)isc_stdio_close(fp); 13201 if (offsetok) { 13202 isc_result_t result2; 13203 13204 result2 = isc_file_truncate(view->new_zone_file, 13205 offset); 13206 if (result2 != ISC_R_SUCCESS) { 13207 isc_log_write( 13208 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13209 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13210 "Error truncating NZF file '%s' " 13211 "during rollback from append: " 13212 "%s", 13213 view->new_zone_file, 13214 isc_result_totext(result2)); 13215 } 13216 } 13217 } 13218 UNLOCK(&view->new_zone_lock); 13219 return (result); 13220 } 13221 13222 static isc_result_t 13223 nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { 13224 const cfg_obj_t *zl = NULL; 13225 cfg_list_t *list; 13226 const cfg_listelt_t *elt; 13227 13228 FILE *fp = NULL; 13229 char tmp[1024]; 13230 isc_result_t result; 13231 13232 result = isc_file_template(view->new_zone_file, "nzf-XXXXXXXX", tmp, 13233 sizeof(tmp)); 13234 if (result == ISC_R_SUCCESS) { 13235 result = isc_file_openunique(tmp, &fp); 13236 } 13237 if (result != ISC_R_SUCCESS) { 13238 return (result); 13239 } 13240 13241 cfg_map_get(config, "zone", &zl); 13242 if (!cfg_obj_islist(zl)) { 13243 CHECK(ISC_R_FAILURE); 13244 } 13245 13246 DE_CONST(&zl->value.list, list); 13247 13248 CHECK(add_comment(fp, view->name)); /* force a comment */ 13249 13250 for (elt = ISC_LIST_HEAD(*list); elt != NULL; 13251 elt = ISC_LIST_NEXT(elt, link)) 13252 { 13253 const cfg_obj_t *zconfig = cfg_listelt_value(elt); 13254 13255 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); 13256 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); 13257 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); 13258 } 13259 13260 CHECK(isc_stdio_flush(fp)); 13261 result = isc_stdio_close(fp); 13262 fp = NULL; 13263 if (result != ISC_R_SUCCESS) { 13264 goto cleanup; 13265 } 13266 CHECK(isc_file_rename(tmp, view->new_zone_file)); 13267 return (result); 13268 13269 cleanup: 13270 if (fp != NULL) { 13271 (void)isc_stdio_close(fp); 13272 } 13273 (void)isc_file_remove(tmp); 13274 return (result); 13275 } 13276 13277 #else /* HAVE_LMDB */ 13278 13279 static void 13280 nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) { 13281 dns_fixedname_t fixed; 13282 13283 dns_fixedname_init(&fixed); 13284 dns_name_downcase(name, dns_fixedname_name(&fixed), NULL); 13285 dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen); 13286 13287 key->mv_data = namebuf; 13288 key->mv_size = strlen(namebuf); 13289 } 13290 13291 static void 13292 dumpzone(void *arg, const char *buf, int len) { 13293 ns_dzarg_t *dzarg = arg; 13294 isc_result_t result; 13295 13296 REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); 13297 13298 result = putmem(dzarg->text, buf, len); 13299 if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { 13300 dzarg->result = result; 13301 } 13302 } 13303 13304 static isc_result_t 13305 nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone, 13306 const cfg_obj_t *zconfig) { 13307 isc_result_t result; 13308 int status; 13309 dns_view_t *view; 13310 bool commit = false; 13311 isc_buffer_t *text = NULL; 13312 char namebuf[1024]; 13313 MDB_val key, data; 13314 ns_dzarg_t dzarg; 13315 13316 view = dns_zone_getview(zone); 13317 13318 nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf)); 13319 13320 if (zconfig == NULL) { 13321 /* We're deleting the zone from the database */ 13322 status = mdb_del(*txnp, dbi, &key, NULL); 13323 if (status != MDB_SUCCESS && status != MDB_NOTFOUND) { 13324 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13325 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13326 "Error deleting zone %s " 13327 "from NZD database: %s", 13328 namebuf, mdb_strerror(status)); 13329 result = ISC_R_FAILURE; 13330 goto cleanup; 13331 } else if (status != MDB_NOTFOUND) { 13332 commit = true; 13333 } 13334 } else { 13335 /* We're creating or overwriting the zone */ 13336 const cfg_obj_t *zoptions; 13337 13338 isc_buffer_allocate(view->mctx, &text, 256); 13339 13340 zoptions = cfg_tuple_get(zconfig, "options"); 13341 if (zoptions == NULL) { 13342 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13343 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13344 "Unable to get options from config in " 13345 "nzd_save()"); 13346 result = ISC_R_FAILURE; 13347 goto cleanup; 13348 } 13349 13350 dzarg.magic = DZARG_MAGIC; 13351 dzarg.text = &text; 13352 dzarg.result = ISC_R_SUCCESS; 13353 cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); 13354 if (dzarg.result != ISC_R_SUCCESS) { 13355 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13356 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13357 "Error writing zone config to " 13358 "buffer in nzd_save(): %s", 13359 isc_result_totext(dzarg.result)); 13360 result = dzarg.result; 13361 goto cleanup; 13362 } 13363 13364 data.mv_data = isc_buffer_base(text); 13365 data.mv_size = isc_buffer_usedlength(text); 13366 13367 status = mdb_put(*txnp, dbi, &key, &data, 0); 13368 if (status != MDB_SUCCESS) { 13369 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13370 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13371 "Error inserting zone in " 13372 "NZD database: %s", 13373 mdb_strerror(status)); 13374 result = ISC_R_FAILURE; 13375 goto cleanup; 13376 } 13377 13378 commit = true; 13379 } 13380 13381 result = ISC_R_SUCCESS; 13382 13383 cleanup: 13384 if (!commit || result != ISC_R_SUCCESS) { 13385 (void)mdb_txn_abort(*txnp); 13386 } else { 13387 status = mdb_txn_commit(*txnp); 13388 if (status != MDB_SUCCESS) { 13389 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13390 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13391 "Error committing " 13392 "NZD database: %s", 13393 mdb_strerror(status)); 13394 result = ISC_R_FAILURE; 13395 } 13396 } 13397 *txnp = NULL; 13398 13399 if (text != NULL) { 13400 isc_buffer_free(&text); 13401 } 13402 13403 return (result); 13404 } 13405 13406 /* 13407 * Check whether the new zone database for 'view' can be opened for writing. 13408 * 13409 * Caller must hold 'view->new_zone_lock'. 13410 */ 13411 static isc_result_t 13412 nzd_writable(dns_view_t *view) { 13413 isc_result_t result = ISC_R_SUCCESS; 13414 int status; 13415 MDB_dbi dbi; 13416 MDB_txn *txn = NULL; 13417 13418 REQUIRE(view != NULL); 13419 13420 status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, 0, &txn); 13421 if (status != MDB_SUCCESS) { 13422 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13423 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13424 "mdb_txn_begin: %s", mdb_strerror(status)); 13425 return (ISC_R_FAILURE); 13426 } 13427 13428 status = mdb_dbi_open(txn, NULL, 0, &dbi); 13429 if (status != MDB_SUCCESS) { 13430 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13431 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13432 "mdb_dbi_open: %s", mdb_strerror(status)); 13433 result = ISC_R_FAILURE; 13434 } 13435 13436 mdb_txn_abort(txn); 13437 return (result); 13438 } 13439 13440 /* 13441 * Open the new zone database for 'view' and start a transaction for it. 13442 * 13443 * Caller must hold 'view->new_zone_lock'. 13444 */ 13445 static isc_result_t 13446 nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { 13447 int status; 13448 MDB_txn *txn = NULL; 13449 13450 REQUIRE(view != NULL); 13451 REQUIRE(txnp != NULL && *txnp == NULL); 13452 REQUIRE(dbi != NULL); 13453 13454 status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, flags, &txn); 13455 if (status != MDB_SUCCESS) { 13456 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13457 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13458 "mdb_txn_begin: %s", mdb_strerror(status)); 13459 goto cleanup; 13460 } 13461 13462 status = mdb_dbi_open(txn, NULL, 0, dbi); 13463 if (status != MDB_SUCCESS) { 13464 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13465 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13466 "mdb_dbi_open: %s", mdb_strerror(status)); 13467 goto cleanup; 13468 } 13469 13470 *txnp = txn; 13471 13472 cleanup: 13473 if (status != MDB_SUCCESS) { 13474 if (txn != NULL) { 13475 mdb_txn_abort(txn); 13476 } 13477 return (ISC_R_FAILURE); 13478 } 13479 13480 return (ISC_R_SUCCESS); 13481 } 13482 13483 /* 13484 * nzd_env_close() and nzd_env_reopen are a kluge to address the 13485 * problem of an NZD file possibly being created before we drop 13486 * root privileges. 13487 */ 13488 static void 13489 nzd_env_close(dns_view_t *view) { 13490 const char *dbpath = NULL; 13491 char dbpath_copy[PATH_MAX]; 13492 char lockpath[PATH_MAX]; 13493 int status, ret; 13494 13495 if (view->new_zone_dbenv == NULL) { 13496 return; 13497 } 13498 13499 status = mdb_env_get_path(view->new_zone_dbenv, &dbpath); 13500 INSIST(status == MDB_SUCCESS); 13501 snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath); 13502 strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy)); 13503 mdb_env_close((MDB_env *)view->new_zone_dbenv); 13504 13505 /* 13506 * Database files must be owned by the eventual user, not by root. 13507 */ 13508 ret = chown(dbpath_copy, ns_os_uid(), -1); 13509 UNUSED(ret); 13510 13511 /* 13512 * Some platforms need the lockfile not to exist when we reopen the 13513 * environment. 13514 */ 13515 (void)isc_file_remove(lockpath); 13516 13517 view->new_zone_dbenv = NULL; 13518 } 13519 13520 static isc_result_t 13521 nzd_env_reopen(dns_view_t *view) { 13522 isc_result_t result; 13523 MDB_env *env = NULL; 13524 int status; 13525 13526 if (view->new_zone_db == NULL) { 13527 return (ISC_R_SUCCESS); 13528 } 13529 13530 nzd_env_close(view); 13531 13532 status = mdb_env_create(&env); 13533 if (status != MDB_SUCCESS) { 13534 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13535 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13536 "mdb_env_create failed: %s", 13537 mdb_strerror(status)); 13538 CHECK(ISC_R_FAILURE); 13539 } 13540 13541 if (view->new_zone_mapsize != 0ULL) { 13542 status = mdb_env_set_mapsize(env, view->new_zone_mapsize); 13543 if (status != MDB_SUCCESS) { 13544 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13545 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13546 "mdb_env_set_mapsize failed: %s", 13547 mdb_strerror(status)); 13548 CHECK(ISC_R_FAILURE); 13549 } 13550 } 13551 13552 status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); 13553 if (status != MDB_SUCCESS) { 13554 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 13555 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, 13556 "mdb_env_open of '%s' failed: %s", 13557 view->new_zone_db, mdb_strerror(status)); 13558 CHECK(ISC_R_FAILURE); 13559 } 13560 13561 view->new_zone_dbenv = env; 13562 env = NULL; 13563 result = ISC_R_SUCCESS; 13564 13565 cleanup: 13566 if (env != NULL) { 13567 mdb_env_close(env); 13568 } 13569 return (result); 13570 } 13571 13572 /* 13573 * If 'commit' is true, commit the new zone database transaction pointed to by 13574 * 'txnp'; otherwise, abort that transaction. 13575 * 13576 * Caller must hold 'view->new_zone_lock' for the view that the transaction 13577 * pointed to by 'txnp' was started for. 13578 */ 13579 static isc_result_t 13580 nzd_close(MDB_txn **txnp, bool commit) { 13581 isc_result_t result = ISC_R_SUCCESS; 13582 int status; 13583 13584 REQUIRE(txnp != NULL); 13585 13586 if (*txnp != NULL) { 13587 if (commit) { 13588 status = mdb_txn_commit(*txnp); 13589 if (status != MDB_SUCCESS) { 13590 result = ISC_R_FAILURE; 13591 } 13592 } else { 13593 mdb_txn_abort(*txnp); 13594 } 13595 *txnp = NULL; 13596 } 13597 13598 return (result); 13599 } 13600 13601 /* 13602 * Count the zones configured in the new zone database for 'view' and store the 13603 * result in 'countp'. 13604 * 13605 * Caller must hold 'view->new_zone_lock'. 13606 */ 13607 static isc_result_t 13608 nzd_count(dns_view_t *view, int *countp) { 13609 isc_result_t result; 13610 int status; 13611 MDB_txn *txn = NULL; 13612 MDB_dbi dbi; 13613 MDB_stat statbuf; 13614 13615 REQUIRE(countp != NULL); 13616 13617 result = nzd_open(view, MDB_RDONLY, &txn, &dbi); 13618 if (result != ISC_R_SUCCESS) { 13619 goto cleanup; 13620 } 13621 13622 status = mdb_stat(txn, dbi, &statbuf); 13623 if (status != MDB_SUCCESS) { 13624 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13625 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 13626 "mdb_stat: %s", mdb_strerror(status)); 13627 result = ISC_R_FAILURE; 13628 goto cleanup; 13629 } 13630 13631 *countp = statbuf.ms_entries; 13632 13633 cleanup: 13634 (void)nzd_close(&txn, false); 13635 13636 return (result); 13637 } 13638 13639 /* 13640 * Migrate zone configuration from an NZF file to an NZD database. 13641 * Caller must hold view->new_zone_lock. 13642 */ 13643 static isc_result_t 13644 migrate_nzf(dns_view_t *view) { 13645 isc_result_t result; 13646 cfg_obj_t *nzf_config = NULL; 13647 int status, n; 13648 isc_buffer_t *text = NULL; 13649 bool commit = false; 13650 const cfg_obj_t *zonelist; 13651 const cfg_listelt_t *element; 13652 char tempname[PATH_MAX]; 13653 MDB_txn *txn = NULL; 13654 MDB_dbi dbi; 13655 MDB_val key, data; 13656 ns_dzarg_t dzarg; 13657 13658 /* 13659 * If NZF file doesn't exist, or NZD DB exists and already 13660 * has data, return without attempting migration. 13661 */ 13662 if (!isc_file_exists(view->new_zone_file)) { 13663 result = ISC_R_SUCCESS; 13664 goto cleanup; 13665 } 13666 13667 result = nzd_count(view, &n); 13668 if (result == ISC_R_SUCCESS && n > 0) { 13669 result = ISC_R_SUCCESS; 13670 goto cleanup; 13671 } 13672 13673 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13674 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 13675 "Migrating zones from NZF file '%s' to " 13676 "NZD database '%s'", 13677 view->new_zone_file, view->new_zone_db); 13678 /* 13679 * Instead of blindly copying lines, we parse the NZF file using 13680 * the configuration parser, because it validates it against the 13681 * config type, giving us a guarantee that valid configuration 13682 * will be written to DB. 13683 */ 13684 cfg_parser_reset(named_g_addparser); 13685 result = cfg_parse_file(named_g_addparser, view->new_zone_file, 13686 &cfg_type_addzoneconf, &nzf_config); 13687 if (result != ISC_R_SUCCESS) { 13688 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13689 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13690 "Error parsing NZF file '%s': %s", 13691 view->new_zone_file, isc_result_totext(result)); 13692 goto cleanup; 13693 } 13694 13695 zonelist = NULL; 13696 CHECK(cfg_map_get(nzf_config, "zone", &zonelist)); 13697 if (!cfg_obj_islist(zonelist)) { 13698 CHECK(ISC_R_FAILURE); 13699 } 13700 13701 CHECK(nzd_open(view, 0, &txn, &dbi)); 13702 13703 isc_buffer_allocate(view->mctx, &text, 256); 13704 13705 for (element = cfg_list_first(zonelist); element != NULL; 13706 element = cfg_list_next(element)) 13707 { 13708 const cfg_obj_t *zconfig; 13709 const cfg_obj_t *zoptions; 13710 char zname[DNS_NAME_FORMATSIZE]; 13711 dns_fixedname_t fname; 13712 dns_name_t *name; 13713 const char *origin; 13714 isc_buffer_t b; 13715 13716 zconfig = cfg_listelt_value(element); 13717 13718 origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 13719 if (origin == NULL) { 13720 result = ISC_R_FAILURE; 13721 goto cleanup; 13722 } 13723 13724 /* Normalize zone name */ 13725 isc_buffer_constinit(&b, origin, strlen(origin)); 13726 isc_buffer_add(&b, strlen(origin)); 13727 name = dns_fixedname_initname(&fname); 13728 CHECK(dns_name_fromtext(name, &b, dns_rootname, 13729 DNS_NAME_DOWNCASE, NULL)); 13730 dns_name_format(name, zname, sizeof(zname)); 13731 13732 key.mv_data = zname; 13733 key.mv_size = strlen(zname); 13734 13735 zoptions = cfg_tuple_get(zconfig, "options"); 13736 if (zoptions == NULL) { 13737 result = ISC_R_FAILURE; 13738 goto cleanup; 13739 } 13740 13741 isc_buffer_clear(text); 13742 dzarg.magic = DZARG_MAGIC; 13743 dzarg.text = &text; 13744 dzarg.result = ISC_R_SUCCESS; 13745 cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); 13746 if (dzarg.result != ISC_R_SUCCESS) { 13747 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13748 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13749 "Error writing zone config to " 13750 "buffer in migrate_nzf(): %s", 13751 isc_result_totext(result)); 13752 result = dzarg.result; 13753 goto cleanup; 13754 } 13755 13756 data.mv_data = isc_buffer_base(text); 13757 data.mv_size = isc_buffer_usedlength(text); 13758 13759 status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE); 13760 if (status != MDB_SUCCESS) { 13761 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 13762 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 13763 "Error inserting zone in " 13764 "NZD database: %s", 13765 mdb_strerror(status)); 13766 result = ISC_R_FAILURE; 13767 goto cleanup; 13768 } 13769 13770 commit = true; 13771 } 13772 13773 result = ISC_R_SUCCESS; 13774 13775 /* 13776 * Leaving the NZF file in place is harmless as we won't use it 13777 * if an NZD database is found for the view. But we rename NZF file 13778 * to a backup name here. 13779 */ 13780 strlcpy(tempname, view->new_zone_file, sizeof(tempname)); 13781 if (strlen(tempname) < sizeof(tempname) - 1) { 13782 strlcat(tempname, "~", sizeof(tempname)); 13783 isc_file_rename(view->new_zone_file, tempname); 13784 } 13785 13786 cleanup: 13787 if (result != ISC_R_SUCCESS) { 13788 (void)nzd_close(&txn, false); 13789 } else { 13790 result = nzd_close(&txn, commit); 13791 } 13792 13793 if (text != NULL) { 13794 isc_buffer_free(&text); 13795 } 13796 13797 if (nzf_config != NULL) { 13798 cfg_obj_destroy(named_g_addparser, &nzf_config); 13799 } 13800 13801 return (result); 13802 } 13803 13804 #endif /* HAVE_LMDB */ 13805 13806 static isc_result_t 13807 newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, 13808 cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp, 13809 bool *redirectp, isc_buffer_t **text) { 13810 isc_result_t result; 13811 isc_buffer_t argbuf; 13812 bool redirect = false; 13813 cfg_obj_t *zoneconf = NULL; 13814 const cfg_obj_t *zlist = NULL; 13815 const cfg_obj_t *zoneobj = NULL; 13816 const cfg_obj_t *zoptions = NULL; 13817 const cfg_obj_t *obj = NULL; 13818 const char *viewname = NULL; 13819 dns_rdataclass_t rdclass; 13820 dns_view_t *view = NULL; 13821 const char *bn = NULL; 13822 13823 REQUIRE(viewp != NULL && *viewp == NULL); 13824 REQUIRE(zoneobjp != NULL && *zoneobjp == NULL); 13825 REQUIRE(zoneconfp != NULL && *zoneconfp == NULL); 13826 REQUIRE(redirectp != NULL); 13827 13828 /* Try to parse the argument string */ 13829 isc_buffer_init(&argbuf, command, (unsigned int)strlen(command)); 13830 isc_buffer_add(&argbuf, strlen(command)); 13831 13832 if (strncasecmp(command, "add", 3) == 0) { 13833 bn = "addzone"; 13834 } else if (strncasecmp(command, "mod", 3) == 0) { 13835 bn = "modzone"; 13836 } else { 13837 UNREACHABLE(); 13838 } 13839 13840 /* 13841 * Convert the "addzone" or "modzone" to just "zone", for 13842 * the benefit of the parser 13843 */ 13844 isc_buffer_forward(&argbuf, 3); 13845 13846 cfg_parser_reset(named_g_addparser); 13847 CHECK(cfg_parse_buffer(named_g_addparser, &argbuf, bn, 0, 13848 &cfg_type_addzoneconf, 0, &zoneconf)); 13849 CHECK(cfg_map_get(zoneconf, "zone", &zlist)); 13850 if (!cfg_obj_islist(zlist)) { 13851 CHECK(ISC_R_FAILURE); 13852 } 13853 13854 /* For now we only support adding one zone at a time */ 13855 zoneobj = cfg_listelt_value(cfg_list_first(zlist)); 13856 13857 /* Check the zone type for ones that are not supported by addzone. */ 13858 zoptions = cfg_tuple_get(zoneobj, "options"); 13859 13860 obj = NULL; 13861 (void)cfg_map_get(zoptions, "type", &obj); 13862 if (obj == NULL) { 13863 (void)cfg_map_get(zoptions, "in-view", &obj); 13864 if (obj != NULL) { 13865 (void)putstr(text, "'in-view' zones not supported by "); 13866 (void)putstr(text, bn); 13867 } else { 13868 (void)putstr(text, "zone type not specified"); 13869 } 13870 CHECK(ISC_R_FAILURE); 13871 } 13872 13873 if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 || 13874 strcasecmp(cfg_obj_asstring(obj), "forward") == 0 || 13875 strcasecmp(cfg_obj_asstring(obj), "delegation-only") == 0) 13876 { 13877 (void)putstr(text, "'"); 13878 (void)putstr(text, cfg_obj_asstring(obj)); 13879 (void)putstr(text, "' zones not supported by "); 13880 (void)putstr(text, bn); 13881 CHECK(ISC_R_FAILURE); 13882 } 13883 13884 if (strcasecmp(cfg_obj_asstring(obj), "redirect") == 0) { 13885 redirect = true; 13886 } 13887 13888 /* Make sense of optional class argument */ 13889 obj = cfg_tuple_get(zoneobj, "class"); 13890 CHECK(named_config_getclass(obj, dns_rdataclass_in, &rdclass)); 13891 13892 /* Make sense of optional view argument */ 13893 obj = cfg_tuple_get(zoneobj, "view"); 13894 if (obj && cfg_obj_isstring(obj)) { 13895 viewname = cfg_obj_asstring(obj); 13896 } 13897 if (viewname == NULL || *viewname == '\0') { 13898 viewname = "_default"; 13899 } 13900 result = dns_viewlist_find(&server->viewlist, viewname, rdclass, &view); 13901 if (result == ISC_R_NOTFOUND) { 13902 (void)putstr(text, "no matching view found for '"); 13903 (void)putstr(text, viewname); 13904 (void)putstr(text, "'"); 13905 goto cleanup; 13906 } else if (result != ISC_R_SUCCESS) { 13907 goto cleanup; 13908 } 13909 13910 *viewp = view; 13911 *zoneobjp = zoneobj; 13912 *zoneconfp = zoneconf; 13913 *redirectp = redirect; 13914 13915 return (ISC_R_SUCCESS); 13916 13917 cleanup: 13918 if (zoneconf != NULL) { 13919 cfg_obj_destroy(named_g_addparser, &zoneconf); 13920 } 13921 if (view != NULL) { 13922 dns_view_detach(&view); 13923 } 13924 13925 return (result); 13926 } 13927 13928 static isc_result_t 13929 delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config, 13930 const dns_name_t *zname, nzfwriter_t nzfwriter) { 13931 isc_result_t result = ISC_R_NOTFOUND; 13932 const cfg_listelt_t *elt = NULL; 13933 const cfg_obj_t *zl = NULL; 13934 cfg_list_t *list; 13935 dns_fixedname_t myfixed; 13936 dns_name_t *myname; 13937 13938 REQUIRE(view != NULL); 13939 REQUIRE(pctx != NULL); 13940 REQUIRE(config != NULL); 13941 REQUIRE(zname != NULL); 13942 13943 LOCK(&view->new_zone_lock); 13944 13945 cfg_map_get(config, "zone", &zl); 13946 13947 if (!cfg_obj_islist(zl)) { 13948 CHECK(ISC_R_FAILURE); 13949 } 13950 13951 DE_CONST(&zl->value.list, list); 13952 13953 myname = dns_fixedname_initname(&myfixed); 13954 13955 for (elt = ISC_LIST_HEAD(*list); elt != NULL; 13956 elt = ISC_LIST_NEXT(elt, link)) 13957 { 13958 const cfg_obj_t *zconf = cfg_listelt_value(elt); 13959 const char *zn; 13960 cfg_listelt_t *e; 13961 13962 zn = cfg_obj_asstring(cfg_tuple_get(zconf, "name")); 13963 result = dns_name_fromstring(myname, zn, 0, NULL); 13964 if (result != ISC_R_SUCCESS || !dns_name_equal(zname, myname)) { 13965 continue; 13966 } 13967 13968 DE_CONST(elt, e); 13969 ISC_LIST_UNLINK(*list, e, link); 13970 cfg_obj_destroy(pctx, &e->obj); 13971 isc_mem_put(pctx->mctx, e, sizeof(*e)); 13972 result = ISC_R_SUCCESS; 13973 break; 13974 } 13975 13976 /* 13977 * Write config to NZF file if appropriate 13978 */ 13979 if (nzfwriter != NULL && view->new_zone_file != NULL) { 13980 result = nzfwriter(config, view); 13981 } 13982 13983 cleanup: 13984 UNLOCK(&view->new_zone_lock); 13985 return (result); 13986 } 13987 13988 static isc_result_t 13989 do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, 13990 dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj, 13991 bool redirect, isc_buffer_t **text) { 13992 isc_result_t result, tresult; 13993 dns_zone_t *zone = NULL; 13994 #ifndef HAVE_LMDB 13995 FILE *fp = NULL; 13996 bool cleanup_config = false; 13997 #else /* HAVE_LMDB */ 13998 MDB_txn *txn = NULL; 13999 MDB_dbi dbi; 14000 bool locked = false; 14001 14002 UNUSED(zoneconf); 14003 #endif 14004 14005 /* Zone shouldn't already exist */ 14006 if (redirect) { 14007 result = (view->redirect != NULL) ? ISC_R_SUCCESS 14008 : ISC_R_NOTFOUND; 14009 } else { 14010 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 14011 } 14012 if (result == ISC_R_SUCCESS) { 14013 result = ISC_R_EXISTS; 14014 goto cleanup; 14015 } else if (result == DNS_R_PARTIALMATCH) { 14016 /* Create our sub-zone anyway */ 14017 dns_zone_detach(&zone); 14018 zone = NULL; 14019 } else if (result != ISC_R_NOTFOUND) { 14020 goto cleanup; 14021 } 14022 14023 result = isc_task_beginexclusive(server->task); 14024 RUNTIME_CHECK(result == ISC_R_SUCCESS); 14025 14026 #ifndef HAVE_LMDB 14027 /* 14028 * Make sure we can open the configuration save file 14029 */ 14030 result = isc_stdio_open(view->new_zone_file, "a", &fp); 14031 if (result != ISC_R_SUCCESS) { 14032 isc_task_endexclusive(server->task); 14033 TCHECK(putstr(text, "unable to create '")); 14034 TCHECK(putstr(text, view->new_zone_file)); 14035 TCHECK(putstr(text, "': ")); 14036 TCHECK(putstr(text, isc_result_totext(result))); 14037 goto cleanup; 14038 } 14039 14040 (void)isc_stdio_close(fp); 14041 fp = NULL; 14042 #else /* HAVE_LMDB */ 14043 LOCK(&view->new_zone_lock); 14044 locked = true; 14045 /* Make sure we can open the NZD database */ 14046 result = nzd_writable(view); 14047 if (result != ISC_R_SUCCESS) { 14048 isc_task_endexclusive(server->task); 14049 TCHECK(putstr(text, "unable to open NZD database for '")); 14050 TCHECK(putstr(text, view->new_zone_db)); 14051 TCHECK(putstr(text, "'")); 14052 result = ISC_R_FAILURE; 14053 goto cleanup; 14054 } 14055 #endif /* HAVE_LMDB */ 14056 14057 /* Mark view unfrozen and configure zone */ 14058 dns_view_thaw(view); 14059 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, 14060 server->mctx, view, &server->viewlist, 14061 &server->kasplist, cfg->actx, true, false, 14062 false, false); 14063 dns_view_freeze(view); 14064 14065 isc_task_endexclusive(server->task); 14066 14067 if (result != ISC_R_SUCCESS) { 14068 TCHECK(putstr(text, "configure_zone failed: ")); 14069 TCHECK(putstr(text, isc_result_totext(result))); 14070 goto cleanup; 14071 } 14072 14073 /* Is it there yet? */ 14074 if (redirect) { 14075 if (view->redirect == NULL) { 14076 CHECK(ISC_R_NOTFOUND); 14077 } 14078 dns_zone_attach(view->redirect, &zone); 14079 } else { 14080 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 14081 if (result != ISC_R_SUCCESS) { 14082 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14083 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14084 "added new zone was not found: %s", 14085 isc_result_totext(result)); 14086 goto cleanup; 14087 } 14088 } 14089 14090 #ifndef HAVE_LMDB 14091 /* 14092 * If there wasn't a previous newzone config, just save the one 14093 * we've created. If there was a previous one, merge the new 14094 * zone into it. 14095 */ 14096 if (cfg->nzf_config == NULL) { 14097 cfg_obj_attach(zoneconf, &cfg->nzf_config); 14098 } else { 14099 cfg_obj_t *z; 14100 DE_CONST(zoneobj, z); 14101 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, 14102 "zone")); 14103 } 14104 cleanup_config = true; 14105 #endif /* HAVE_LMDB */ 14106 14107 /* 14108 * Load the zone from the master file. If this fails, we'll 14109 * need to undo the configuration we've done already. 14110 */ 14111 result = dns_zone_load(zone, true); 14112 if (result != ISC_R_SUCCESS) { 14113 dns_db_t *dbp = NULL; 14114 14115 TCHECK(putstr(text, "dns_zone_loadnew failed: ")); 14116 TCHECK(putstr(text, isc_result_totext(result))); 14117 14118 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14119 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14120 "addzone failed; reverting."); 14121 14122 /* If the zone loaded partially, unload it */ 14123 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14124 dns_db_detach(&dbp); 14125 dns_zone_unload(zone); 14126 } 14127 14128 /* Remove the zone from the zone table */ 14129 dns_zt_unmount(view->zonetable, zone); 14130 goto cleanup; 14131 } 14132 14133 /* Flag the zone as having been added at runtime */ 14134 dns_zone_setadded(zone, true); 14135 14136 #ifdef HAVE_LMDB 14137 /* Save the new zone configuration into the NZD */ 14138 CHECK(nzd_open(view, 0, &txn, &dbi)); 14139 CHECK(nzd_save(&txn, dbi, zone, zoneobj)); 14140 #else /* ifdef HAVE_LMDB */ 14141 /* Append the zone configuration to the NZF */ 14142 result = nzf_append(view, zoneobj); 14143 #endif /* HAVE_LMDB */ 14144 14145 cleanup: 14146 14147 #ifndef HAVE_LMDB 14148 if (fp != NULL) { 14149 (void)isc_stdio_close(fp); 14150 } 14151 if (result != ISC_R_SUCCESS && cleanup_config) { 14152 tresult = delete_zoneconf(view, cfg->add_parser, 14153 cfg->nzf_config, name, NULL); 14154 RUNTIME_CHECK(tresult == ISC_R_SUCCESS); 14155 } 14156 #else /* HAVE_LMDB */ 14157 if (txn != NULL) { 14158 (void)nzd_close(&txn, false); 14159 } 14160 if (locked) { 14161 UNLOCK(&view->new_zone_lock); 14162 } 14163 #endif /* HAVE_LMDB */ 14164 14165 if (zone != NULL) { 14166 dns_zone_detach(&zone); 14167 } 14168 14169 return (result); 14170 } 14171 14172 static isc_result_t 14173 do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, 14174 dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj, 14175 bool redirect, isc_buffer_t **text) { 14176 isc_result_t result, tresult; 14177 dns_zone_t *zone = NULL; 14178 bool added; 14179 bool exclusive = false; 14180 #ifndef HAVE_LMDB 14181 FILE *fp = NULL; 14182 cfg_obj_t *z; 14183 #else /* HAVE_LMDB */ 14184 MDB_txn *txn = NULL; 14185 MDB_dbi dbi; 14186 bool locked = false; 14187 #endif /* HAVE_LMDB */ 14188 14189 /* Zone must already exist */ 14190 if (redirect) { 14191 if (view->redirect != NULL) { 14192 dns_zone_attach(view->redirect, &zone); 14193 result = ISC_R_SUCCESS; 14194 } else { 14195 result = ISC_R_NOTFOUND; 14196 } 14197 } else { 14198 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); 14199 } 14200 if (result != ISC_R_SUCCESS) { 14201 goto cleanup; 14202 } 14203 14204 added = dns_zone_getadded(zone); 14205 dns_zone_detach(&zone); 14206 14207 #ifndef HAVE_LMDB 14208 cfg = (ns_cfgctx_t *)view->new_zone_config; 14209 if (cfg == NULL) { 14210 TCHECK(putstr(text, "new zone config is not set")); 14211 CHECK(ISC_R_FAILURE); 14212 } 14213 #endif /* ifndef HAVE_LMDB */ 14214 14215 result = isc_task_beginexclusive(server->task); 14216 RUNTIME_CHECK(result == ISC_R_SUCCESS); 14217 exclusive = true; 14218 14219 #ifndef HAVE_LMDB 14220 /* Make sure we can open the configuration save file */ 14221 result = isc_stdio_open(view->new_zone_file, "a", &fp); 14222 if (result != ISC_R_SUCCESS) { 14223 TCHECK(putstr(text, "unable to open '")); 14224 TCHECK(putstr(text, view->new_zone_file)); 14225 TCHECK(putstr(text, "': ")); 14226 TCHECK(putstr(text, isc_result_totext(result))); 14227 goto cleanup; 14228 } 14229 (void)isc_stdio_close(fp); 14230 fp = NULL; 14231 #else /* HAVE_LMDB */ 14232 LOCK(&view->new_zone_lock); 14233 locked = true; 14234 /* Make sure we can open the NZD database */ 14235 result = nzd_writable(view); 14236 if (result != ISC_R_SUCCESS) { 14237 TCHECK(putstr(text, "unable to open NZD database for '")); 14238 TCHECK(putstr(text, view->new_zone_db)); 14239 TCHECK(putstr(text, "'")); 14240 result = ISC_R_FAILURE; 14241 goto cleanup; 14242 } 14243 #endif /* HAVE_LMDB */ 14244 14245 /* Reconfigure the zone */ 14246 dns_view_thaw(view); 14247 result = configure_zone(cfg->config, zoneobj, cfg->vconfig, 14248 server->mctx, view, &server->viewlist, 14249 &server->kasplist, cfg->actx, true, false, 14250 false, true); 14251 dns_view_freeze(view); 14252 14253 exclusive = false; 14254 isc_task_endexclusive(server->task); 14255 14256 if (result != ISC_R_SUCCESS) { 14257 TCHECK(putstr(text, "configure_zone failed: ")); 14258 TCHECK(putstr(text, isc_result_totext(result))); 14259 goto cleanup; 14260 } 14261 14262 /* Is it there yet? */ 14263 if (redirect) { 14264 if (view->redirect == NULL) { 14265 CHECK(ISC_R_NOTFOUND); 14266 } 14267 dns_zone_attach(view->redirect, &zone); 14268 } else { 14269 CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone)); 14270 } 14271 14272 #ifndef HAVE_LMDB 14273 /* Remove old zone from configuration (and NZF file if applicable) */ 14274 if (added) { 14275 result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, 14276 dns_zone_getorigin(zone), 14277 nzf_writeconf); 14278 if (result != ISC_R_SUCCESS) { 14279 TCHECK(putstr(text, "former zone configuration " 14280 "not deleted: ")); 14281 TCHECK(putstr(text, isc_result_totext(result))); 14282 goto cleanup; 14283 } 14284 } 14285 #endif /* HAVE_LMDB */ 14286 14287 if (!added) { 14288 if (cfg->vconfig == NULL) { 14289 result = delete_zoneconf( 14290 view, cfg->conf_parser, cfg->config, 14291 dns_zone_getorigin(zone), NULL); 14292 } else { 14293 const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, 14294 "options"); 14295 result = delete_zoneconf( 14296 view, cfg->conf_parser, voptions, 14297 dns_zone_getorigin(zone), NULL); 14298 } 14299 14300 if (result != ISC_R_SUCCESS) { 14301 TCHECK(putstr(text, "former zone configuration " 14302 "not deleted: ")); 14303 TCHECK(putstr(text, isc_result_totext(result))); 14304 goto cleanup; 14305 } 14306 } 14307 14308 /* Load the zone from the master file if it needs reloading. */ 14309 result = dns_zone_load(zone, true); 14310 14311 /* 14312 * Dynamic zones need no reloading, so we can pass this result. 14313 */ 14314 if (result == DNS_R_DYNAMIC) { 14315 result = ISC_R_SUCCESS; 14316 } 14317 14318 if (result != ISC_R_SUCCESS) { 14319 dns_db_t *dbp = NULL; 14320 14321 TCHECK(putstr(text, "failed to load zone '")); 14322 TCHECK(putstr(text, zname)); 14323 TCHECK(putstr(text, "': ")); 14324 TCHECK(putstr(text, isc_result_totext(result))); 14325 TCHECK(putstr(text, "\nThe zone is no longer being served. ")); 14326 TCHECK(putstr(text, "Use 'rndc addzone' to correct\n")); 14327 TCHECK(putstr(text, "the problem and restore service.")); 14328 14329 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14330 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14331 "modzone failed; removing zone."); 14332 14333 /* If the zone loaded partially, unload it */ 14334 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14335 dns_db_detach(&dbp); 14336 dns_zone_unload(zone); 14337 } 14338 14339 /* Remove the zone from the zone table */ 14340 dns_zt_unmount(view->zonetable, zone); 14341 goto cleanup; 14342 } 14343 14344 #ifndef HAVE_LMDB 14345 /* Store the new zone configuration; also in NZF if applicable */ 14346 DE_CONST(zoneobj, z); 14347 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone")); 14348 #endif /* HAVE_LMDB */ 14349 14350 if (added) { 14351 #ifdef HAVE_LMDB 14352 CHECK(nzd_open(view, 0, &txn, &dbi)); 14353 CHECK(nzd_save(&txn, dbi, zone, zoneobj)); 14354 #else /* ifdef HAVE_LMDB */ 14355 result = nzf_append(view, zoneobj); 14356 if (result != ISC_R_SUCCESS) { 14357 TCHECK(putstr(text, "\nNew zone config not saved: ")); 14358 TCHECK(putstr(text, isc_result_totext(result))); 14359 goto cleanup; 14360 } 14361 #endif /* HAVE_LMDB */ 14362 14363 TCHECK(putstr(text, "zone '")); 14364 TCHECK(putstr(text, zname)); 14365 TCHECK(putstr(text, "' reconfigured.")); 14366 } else { 14367 TCHECK(putstr(text, "zone '")); 14368 TCHECK(putstr(text, zname)); 14369 TCHECK(putstr(text, "' must also be reconfigured in\n")); 14370 TCHECK(putstr(text, "named.conf to make changes permanent.")); 14371 } 14372 14373 cleanup: 14374 if (exclusive) { 14375 isc_task_endexclusive(server->task); 14376 } 14377 14378 #ifndef HAVE_LMDB 14379 if (fp != NULL) { 14380 (void)isc_stdio_close(fp); 14381 } 14382 #else /* HAVE_LMDB */ 14383 if (txn != NULL) { 14384 (void)nzd_close(&txn, false); 14385 } 14386 if (locked) { 14387 UNLOCK(&view->new_zone_lock); 14388 } 14389 #endif /* HAVE_LMDB */ 14390 14391 if (zone != NULL) { 14392 dns_zone_detach(&zone); 14393 } 14394 14395 return (result); 14396 } 14397 14398 /* 14399 * Act on an "addzone" or "modzone" command from the command channel. 14400 */ 14401 isc_result_t 14402 named_server_changezone(named_server_t *server, char *command, 14403 isc_buffer_t **text) { 14404 isc_result_t result; 14405 bool addzone; 14406 bool redirect = false; 14407 ns_cfgctx_t *cfg = NULL; 14408 cfg_obj_t *zoneconf = NULL; 14409 const cfg_obj_t *zoneobj = NULL; 14410 const char *zonename; 14411 dns_view_t *view = NULL; 14412 isc_buffer_t buf; 14413 dns_fixedname_t fname; 14414 dns_name_t *dnsname; 14415 14416 REQUIRE(text != NULL); 14417 14418 if (strncasecmp(command, "add", 3) == 0) { 14419 addzone = true; 14420 } else { 14421 INSIST(strncasecmp(command, "mod", 3) == 0); 14422 addzone = false; 14423 } 14424 14425 CHECK(newzone_parse(server, command, &view, &zoneconf, &zoneobj, 14426 &redirect, text)); 14427 14428 /* Are we accepting new zones in this view? */ 14429 #ifdef HAVE_LMDB 14430 if (view->new_zone_db == NULL) 14431 #else /* ifdef HAVE_LMDB */ 14432 if (view->new_zone_file == NULL) 14433 #endif /* HAVE_LMDB */ 14434 { 14435 (void)putstr(text, "Not allowing new zones in view '"); 14436 (void)putstr(text, view->name); 14437 (void)putstr(text, "'"); 14438 result = ISC_R_NOPERM; 14439 goto cleanup; 14440 } 14441 14442 cfg = (ns_cfgctx_t *)view->new_zone_config; 14443 if (cfg == NULL) { 14444 result = ISC_R_FAILURE; 14445 goto cleanup; 14446 } 14447 14448 zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name")); 14449 isc_buffer_constinit(&buf, zonename, strlen(zonename)); 14450 isc_buffer_add(&buf, strlen(zonename)); 14451 14452 dnsname = dns_fixedname_initname(&fname); 14453 CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, 0, NULL)); 14454 14455 if (redirect) { 14456 if (!dns_name_equal(dnsname, dns_rootname)) { 14457 (void)putstr(text, "redirect zones must be called " 14458 "\".\""); 14459 CHECK(ISC_R_FAILURE); 14460 } 14461 } 14462 14463 if (addzone) { 14464 CHECK(do_addzone(server, cfg, view, dnsname, zoneconf, zoneobj, 14465 redirect, text)); 14466 } else { 14467 CHECK(do_modzone(server, cfg, view, dnsname, zonename, zoneobj, 14468 redirect, text)); 14469 } 14470 14471 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14472 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14473 "%s zone %s in view %s via %s", 14474 addzone ? "added" : "updated", zonename, view->name, 14475 addzone ? NAMED_COMMAND_ADDZONE : NAMED_COMMAND_MODZONE); 14476 14477 /* Changing a zone counts as reconfiguration */ 14478 CHECK(isc_time_now(&named_g_configtime)); 14479 14480 cleanup: 14481 if (isc_buffer_usedlength(*text) > 0) { 14482 (void)putnull(text); 14483 } 14484 if (zoneconf != NULL) { 14485 cfg_obj_destroy(named_g_addparser, &zoneconf); 14486 } 14487 if (view != NULL) { 14488 dns_view_detach(&view); 14489 } 14490 14491 return (result); 14492 } 14493 14494 static bool 14495 inuse(const char *file, bool first, isc_buffer_t **text) { 14496 if (file != NULL && isc_file_exists(file)) { 14497 if (first) { 14498 (void)putstr(text, "The following files were in use " 14499 "and may now be removed:\n"); 14500 } else { 14501 (void)putstr(text, "\n"); 14502 } 14503 (void)putstr(text, file); 14504 (void)putnull(text); 14505 return (false); 14506 } 14507 return (first); 14508 } 14509 14510 typedef struct { 14511 dns_zone_t *zone; 14512 bool cleanup; 14513 } ns_dzctx_t; 14514 14515 /* 14516 * Carry out a zone deletion scheduled by named_server_delzone(). 14517 */ 14518 static void 14519 rmzone(isc_task_t *task, isc_event_t *event) { 14520 ns_dzctx_t *dz = (ns_dzctx_t *)event->ev_arg; 14521 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; 14522 dns_catz_zone_t *catz = NULL; 14523 char zonename[DNS_NAME_FORMATSIZE]; 14524 dns_view_t *view = NULL; 14525 ns_cfgctx_t *cfg = NULL; 14526 dns_db_t *dbp = NULL; 14527 bool added; 14528 isc_result_t result; 14529 #ifdef HAVE_LMDB 14530 MDB_txn *txn = NULL; 14531 MDB_dbi dbi; 14532 #endif /* ifdef HAVE_LMDB */ 14533 14534 REQUIRE(dz != NULL); 14535 14536 isc_event_free(&event); 14537 14538 /* Dig out configuration for this zone */ 14539 zone = dz->zone; 14540 view = dns_zone_getview(zone); 14541 cfg = (ns_cfgctx_t *)view->new_zone_config; 14542 dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); 14543 14544 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14545 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14546 "deleting zone %s in view %s via delzone", zonename, 14547 view->name); 14548 14549 /* 14550 * Remove the zone from configuration (and NZF file if applicable) 14551 * (If this is a catalog zone member then nzf_config can be NULL) 14552 */ 14553 added = dns_zone_getadded(zone); 14554 catz = dns_zone_get_parentcatz(zone); 14555 14556 if (added && catz == NULL && cfg != NULL) { 14557 #ifdef HAVE_LMDB 14558 /* Make sure we can open the NZD database */ 14559 LOCK(&view->new_zone_lock); 14560 result = nzd_open(view, 0, &txn, &dbi); 14561 if (result != ISC_R_SUCCESS) { 14562 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14563 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14564 "unable to open NZD database for '%s'", 14565 view->new_zone_db); 14566 } else { 14567 result = nzd_save(&txn, dbi, zone, NULL); 14568 } 14569 14570 if (result != ISC_R_SUCCESS) { 14571 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14572 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14573 "unable to delete zone configuration: %s", 14574 isc_result_totext(result)); 14575 } 14576 14577 if (txn != NULL) { 14578 (void)nzd_close(&txn, false); 14579 } 14580 UNLOCK(&view->new_zone_lock); 14581 #else /* ifdef HAVE_LMDB */ 14582 result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, 14583 dns_zone_getorigin(zone), 14584 nzf_writeconf); 14585 if (result != ISC_R_SUCCESS) { 14586 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14587 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14588 "unable to delete zone configuration: %s", 14589 isc_result_totext(result)); 14590 } 14591 #endif /* HAVE_LMDB */ 14592 } 14593 14594 if (!added && cfg != NULL) { 14595 if (cfg->vconfig != NULL) { 14596 const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, 14597 "options"); 14598 result = delete_zoneconf( 14599 view, cfg->conf_parser, voptions, 14600 dns_zone_getorigin(zone), NULL); 14601 } else { 14602 result = delete_zoneconf( 14603 view, cfg->conf_parser, cfg->config, 14604 dns_zone_getorigin(zone), NULL); 14605 } 14606 if (result != ISC_R_SUCCESS) { 14607 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14608 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 14609 "unable to delete zone configuration: %s", 14610 isc_result_totext(result)); 14611 } 14612 } 14613 14614 /* Unload zone database */ 14615 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { 14616 dns_db_detach(&dbp); 14617 dns_zone_unload(zone); 14618 } 14619 14620 /* Clean up stub/secondary zone files if requested to do so */ 14621 dns_zone_getraw(zone, &raw); 14622 mayberaw = (raw != NULL) ? raw : zone; 14623 14624 if (added && dz->cleanup) { 14625 const char *file; 14626 14627 file = dns_zone_getfile(mayberaw); 14628 result = isc_file_remove(file); 14629 if (result != ISC_R_SUCCESS) { 14630 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14631 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14632 "file %s not removed: %s", file, 14633 isc_result_totext(result)); 14634 } 14635 14636 file = dns_zone_getjournal(mayberaw); 14637 result = isc_file_remove(file); 14638 if (result != ISC_R_SUCCESS) { 14639 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14640 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14641 "file %s not removed: %s", file, 14642 isc_result_totext(result)); 14643 } 14644 14645 if (zone != mayberaw) { 14646 file = dns_zone_getfile(zone); 14647 result = isc_file_remove(file); 14648 if (result != ISC_R_SUCCESS) { 14649 isc_log_write( 14650 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14651 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14652 "file %s not removed: %s", file, 14653 isc_result_totext(result)); 14654 } 14655 14656 file = dns_zone_getjournal(zone); 14657 result = isc_file_remove(file); 14658 if (result != ISC_R_SUCCESS) { 14659 isc_log_write( 14660 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14661 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 14662 "file %s not removed: %s", file, 14663 isc_result_totext(result)); 14664 } 14665 } 14666 } 14667 14668 if (raw != NULL) { 14669 dns_zone_detach(&raw); 14670 } 14671 dns_zone_detach(&zone); 14672 isc_mem_put(named_g_mctx, dz, sizeof(*dz)); 14673 isc_task_detach(&task); 14674 } 14675 14676 /* 14677 * Act on a "delzone" command from the command channel. 14678 */ 14679 isc_result_t 14680 named_server_delzone(named_server_t *server, isc_lex_t *lex, 14681 isc_buffer_t **text) { 14682 isc_result_t result, tresult; 14683 dns_zone_t *zone = NULL; 14684 dns_zone_t *raw = NULL; 14685 dns_zone_t *mayberaw; 14686 dns_view_t *view = NULL; 14687 char zonename[DNS_NAME_FORMATSIZE]; 14688 bool cleanup = false; 14689 const char *ptr; 14690 bool added; 14691 ns_dzctx_t *dz = NULL; 14692 isc_event_t *dzevent = NULL; 14693 isc_task_t *task = NULL; 14694 14695 REQUIRE(text != NULL); 14696 14697 /* Skip the command name. */ 14698 ptr = next_token(lex, text); 14699 if (ptr == NULL) { 14700 return (ISC_R_UNEXPECTEDEND); 14701 } 14702 14703 /* Find out what we are to do. */ 14704 ptr = next_token(lex, text); 14705 if (ptr == NULL) { 14706 return (ISC_R_UNEXPECTEDEND); 14707 } 14708 14709 if (strcmp(ptr, "-clean") == 0 || strcmp(ptr, "-clear") == 0) { 14710 cleanup = true; 14711 ptr = next_token(lex, text); 14712 } 14713 14714 CHECK(zone_from_args(server, lex, ptr, &zone, zonename, text, false)); 14715 if (zone == NULL) { 14716 result = ISC_R_UNEXPECTEDEND; 14717 goto cleanup; 14718 } 14719 14720 INSIST(zonename != NULL); 14721 14722 /* Is this a policy zone? */ 14723 if (dns_zone_get_rpz_num(zone) != DNS_RPZ_INVALID_NUM) { 14724 TCHECK(putstr(text, "zone '")); 14725 TCHECK(putstr(text, zonename)); 14726 TCHECK(putstr(text, 14727 "' cannot be deleted: response-policy zone.")); 14728 result = ISC_R_FAILURE; 14729 goto cleanup; 14730 } 14731 14732 view = dns_zone_getview(zone); 14733 if (dns_zone_gettype(zone) == dns_zone_redirect) { 14734 dns_zone_detach(&view->redirect); 14735 } else { 14736 CHECK(dns_zt_unmount(view->zonetable, zone)); 14737 } 14738 14739 /* Send cleanup event */ 14740 dz = isc_mem_get(named_g_mctx, sizeof(*dz)); 14741 14742 dz->cleanup = cleanup; 14743 dz->zone = NULL; 14744 dns_zone_attach(zone, &dz->zone); 14745 dzevent = isc_event_allocate(named_g_mctx, server, NAMED_EVENT_DELZONE, 14746 rmzone, dz, sizeof(isc_event_t)); 14747 14748 dns_zone_gettask(zone, &task); 14749 isc_task_send(task, &dzevent); 14750 dz = NULL; 14751 14752 /* Inform user about cleaning up stub/secondary zone files */ 14753 dns_zone_getraw(zone, &raw); 14754 mayberaw = (raw != NULL) ? raw : zone; 14755 14756 added = dns_zone_getadded(zone); 14757 if (!added) { 14758 TCHECK(putstr(text, "zone '")); 14759 TCHECK(putstr(text, zonename)); 14760 TCHECK(putstr(text, "' is no longer active and will be " 14761 "deleted.\n")); 14762 TCHECK(putstr(text, "To keep it from returning ")); 14763 TCHECK(putstr(text, "when the server is restarted, it\n")); 14764 TCHECK(putstr(text, "must also be removed from named.conf.")); 14765 } else if (cleanup) { 14766 TCHECK(putstr(text, "zone '")); 14767 TCHECK(putstr(text, zonename)); 14768 TCHECK(putstr(text, "' and associated files will be deleted.")); 14769 } else if (dns_zone_gettype(mayberaw) == dns_zone_secondary || 14770 dns_zone_gettype(mayberaw) == dns_zone_mirror || 14771 dns_zone_gettype(mayberaw) == dns_zone_stub) 14772 { 14773 bool first; 14774 const char *file; 14775 14776 TCHECK(putstr(text, "zone '")); 14777 TCHECK(putstr(text, zonename)); 14778 TCHECK(putstr(text, "' will be deleted.")); 14779 14780 file = dns_zone_getfile(mayberaw); 14781 first = inuse(file, true, text); 14782 14783 file = dns_zone_getjournal(mayberaw); 14784 first = inuse(file, first, text); 14785 14786 if (zone != mayberaw) { 14787 file = dns_zone_getfile(zone); 14788 first = inuse(file, first, text); 14789 14790 file = dns_zone_getjournal(zone); 14791 (void)inuse(file, first, text); 14792 } 14793 } 14794 14795 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 14796 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 14797 "zone %s scheduled for removal via delzone", zonename); 14798 14799 /* Removing a zone counts as reconfiguration */ 14800 CHECK(isc_time_now(&named_g_configtime)); 14801 14802 result = ISC_R_SUCCESS; 14803 14804 cleanup: 14805 if (isc_buffer_usedlength(*text) > 0) { 14806 (void)putnull(text); 14807 } 14808 if (raw != NULL) { 14809 dns_zone_detach(&raw); 14810 } 14811 if (zone != NULL) { 14812 dns_zone_detach(&zone); 14813 } 14814 14815 return (result); 14816 } 14817 14818 static const cfg_obj_t * 14819 find_name_in_list_from_map(const cfg_obj_t *config, 14820 const char *map_key_for_list, const char *name, 14821 bool redirect) { 14822 const cfg_obj_t *list = NULL; 14823 const cfg_listelt_t *element; 14824 const cfg_obj_t *obj = NULL; 14825 dns_fixedname_t fixed1, fixed2; 14826 dns_name_t *name1 = NULL, *name2 = NULL; 14827 isc_result_t result; 14828 14829 if (strcmp(map_key_for_list, "zone") == 0) { 14830 name1 = dns_fixedname_initname(&fixed1); 14831 name2 = dns_fixedname_initname(&fixed2); 14832 result = dns_name_fromstring(name1, name, 0, NULL); 14833 RUNTIME_CHECK(result == ISC_R_SUCCESS); 14834 } 14835 14836 cfg_map_get(config, map_key_for_list, &list); 14837 for (element = cfg_list_first(list); element != NULL; 14838 element = cfg_list_next(element)) 14839 { 14840 const char *vname; 14841 14842 obj = cfg_listelt_value(element); 14843 INSIST(obj != NULL); 14844 vname = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 14845 if (vname == NULL) { 14846 obj = NULL; 14847 continue; 14848 } 14849 14850 if (name1 != NULL) { 14851 result = dns_name_fromstring(name2, vname, 0, NULL); 14852 if (result == ISC_R_SUCCESS && 14853 dns_name_equal(name1, name2)) 14854 { 14855 const cfg_obj_t *zoptions; 14856 const cfg_obj_t *typeobj = NULL; 14857 zoptions = cfg_tuple_get(obj, "options"); 14858 14859 if (zoptions != NULL) { 14860 cfg_map_get(zoptions, "type", &typeobj); 14861 } 14862 if (redirect && typeobj != NULL && 14863 strcasecmp(cfg_obj_asstring(typeobj), 14864 "redirect") == 0) 14865 { 14866 break; 14867 } else if (!redirect) { 14868 break; 14869 } 14870 } 14871 } else if (strcasecmp(vname, name) == 0) { 14872 break; 14873 } 14874 14875 obj = NULL; 14876 } 14877 14878 return (obj); 14879 } 14880 14881 static void 14882 emitzone(void *arg, const char *buf, int len) { 14883 ns_dzarg_t *dzarg = arg; 14884 isc_result_t result; 14885 14886 REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); 14887 result = putmem(dzarg->text, buf, len); 14888 if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { 14889 dzarg->result = result; 14890 } 14891 } 14892 14893 /* 14894 * Act on a "showzone" command from the command channel. 14895 */ 14896 isc_result_t 14897 named_server_showzone(named_server_t *server, isc_lex_t *lex, 14898 isc_buffer_t **text) { 14899 isc_result_t result; 14900 const cfg_obj_t *vconfig = NULL, *zconfig = NULL; 14901 char zonename[DNS_NAME_FORMATSIZE]; 14902 const cfg_obj_t *map; 14903 dns_view_t *view = NULL; 14904 dns_zone_t *zone = NULL; 14905 ns_cfgctx_t *cfg = NULL; 14906 #ifdef HAVE_LMDB 14907 cfg_obj_t *nzconfig = NULL; 14908 #endif /* HAVE_LMDB */ 14909 bool added, redirect; 14910 ns_dzarg_t dzarg; 14911 14912 REQUIRE(text != NULL); 14913 14914 /* Parse parameters */ 14915 CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); 14916 if (zone == NULL) { 14917 result = ISC_R_UNEXPECTEDEND; 14918 goto cleanup; 14919 } 14920 14921 redirect = dns_zone_gettype(zone) == dns_zone_redirect; 14922 added = dns_zone_getadded(zone); 14923 view = dns_zone_getview(zone); 14924 dns_zone_detach(&zone); 14925 14926 cfg = (ns_cfgctx_t *)view->new_zone_config; 14927 if (cfg == NULL) { 14928 result = ISC_R_FAILURE; 14929 goto cleanup; 14930 } 14931 14932 if (!added) { 14933 /* Find the view statement */ 14934 vconfig = find_name_in_list_from_map(cfg->config, "view", 14935 view->name, false); 14936 14937 /* Find the zone statement */ 14938 if (vconfig != NULL) { 14939 map = cfg_tuple_get(vconfig, "options"); 14940 } else { 14941 map = cfg->config; 14942 } 14943 14944 zconfig = find_name_in_list_from_map(map, "zone", zonename, 14945 redirect); 14946 } 14947 14948 #ifndef HAVE_LMDB 14949 if (zconfig == NULL && cfg->nzf_config != NULL) { 14950 zconfig = find_name_in_list_from_map(cfg->nzf_config, "zone", 14951 zonename, redirect); 14952 } 14953 #else /* HAVE_LMDB */ 14954 if (zconfig == NULL) { 14955 const cfg_obj_t *zlist = NULL; 14956 CHECK(get_newzone_config(view, zonename, &nzconfig)); 14957 CHECK(cfg_map_get(nzconfig, "zone", &zlist)); 14958 if (!cfg_obj_islist(zlist)) { 14959 CHECK(ISC_R_FAILURE); 14960 } 14961 14962 zconfig = cfg_listelt_value(cfg_list_first(zlist)); 14963 } 14964 #endif /* HAVE_LMDB */ 14965 14966 if (zconfig == NULL) { 14967 CHECK(ISC_R_NOTFOUND); 14968 } 14969 14970 CHECK(putstr(text, "zone ")); 14971 dzarg.magic = DZARG_MAGIC; 14972 dzarg.text = text; 14973 dzarg.result = ISC_R_SUCCESS; 14974 cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, &dzarg); 14975 CHECK(dzarg.result); 14976 14977 CHECK(putstr(text, ";")); 14978 14979 result = ISC_R_SUCCESS; 14980 14981 cleanup: 14982 #ifdef HAVE_LMDB 14983 if (nzconfig != NULL) { 14984 cfg_obj_destroy(named_g_addparser, &nzconfig); 14985 } 14986 #endif /* HAVE_LMDB */ 14987 if (isc_buffer_usedlength(*text) > 0) { 14988 (void)putnull(text); 14989 } 14990 14991 return (result); 14992 } 14993 14994 static void 14995 newzone_cfgctx_destroy(void **cfgp) { 14996 ns_cfgctx_t *cfg; 14997 14998 REQUIRE(cfgp != NULL && *cfgp != NULL); 14999 15000 cfg = *cfgp; 15001 15002 if (cfg->conf_parser != NULL) { 15003 if (cfg->config != NULL) { 15004 cfg_obj_destroy(cfg->conf_parser, &cfg->config); 15005 } 15006 if (cfg->vconfig != NULL) { 15007 cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig); 15008 } 15009 cfg_parser_destroy(&cfg->conf_parser); 15010 } 15011 if (cfg->add_parser != NULL) { 15012 if (cfg->nzf_config != NULL) { 15013 cfg_obj_destroy(cfg->add_parser, &cfg->nzf_config); 15014 } 15015 cfg_parser_destroy(&cfg->add_parser); 15016 } 15017 15018 if (cfg->actx != NULL) { 15019 cfg_aclconfctx_detach(&cfg->actx); 15020 } 15021 15022 isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); 15023 *cfgp = NULL; 15024 } 15025 15026 isc_result_t 15027 named_server_signing(named_server_t *server, isc_lex_t *lex, 15028 isc_buffer_t **text) { 15029 isc_result_t result = ISC_R_SUCCESS; 15030 dns_zone_t *zone = NULL; 15031 dns_name_t *origin; 15032 dns_db_t *db = NULL; 15033 dns_dbnode_t *node = NULL; 15034 dns_dbversion_t *version = NULL; 15035 dns_rdatatype_t privatetype; 15036 dns_rdataset_t privset; 15037 bool first = true; 15038 bool list = false, clear = false; 15039 bool chain = false; 15040 bool setserial = false; 15041 bool resalt = false; 15042 uint32_t serial = 0; 15043 char keystr[DNS_SECALG_FORMATSIZE + 7]; /* <5-digit keyid>/<alg> */ 15044 unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0; 15045 unsigned char salt[255]; 15046 const char *ptr; 15047 size_t n; 15048 15049 REQUIRE(text != NULL); 15050 15051 dns_rdataset_init(&privset); 15052 15053 /* Skip the command name. */ 15054 ptr = next_token(lex, text); 15055 if (ptr == NULL) { 15056 return (ISC_R_UNEXPECTEDEND); 15057 } 15058 15059 /* Find out what we are to do. */ 15060 ptr = next_token(lex, text); 15061 if (ptr == NULL) { 15062 return (ISC_R_UNEXPECTEDEND); 15063 } 15064 15065 if (strcasecmp(ptr, "-list") == 0) { 15066 list = true; 15067 } else if ((strcasecmp(ptr, "-clear") == 0) || 15068 (strcasecmp(ptr, "-clean") == 0)) 15069 { 15070 clear = true; 15071 ptr = next_token(lex, text); 15072 if (ptr == NULL) { 15073 return (ISC_R_UNEXPECTEDEND); 15074 } 15075 strlcpy(keystr, ptr, sizeof(keystr)); 15076 } else if (strcasecmp(ptr, "-nsec3param") == 0) { 15077 char hashbuf[64], flagbuf[64], iterbuf[64]; 15078 char nbuf[256]; 15079 15080 chain = true; 15081 ptr = next_token(lex, text); 15082 if (ptr == NULL) { 15083 return (ISC_R_UNEXPECTEDEND); 15084 } 15085 15086 if (strcasecmp(ptr, "none") == 0) { 15087 hash = 0; 15088 } else { 15089 strlcpy(hashbuf, ptr, sizeof(hashbuf)); 15090 15091 ptr = next_token(lex, text); 15092 if (ptr == NULL) { 15093 return (ISC_R_UNEXPECTEDEND); 15094 } 15095 strlcpy(flagbuf, ptr, sizeof(flagbuf)); 15096 15097 ptr = next_token(lex, text); 15098 if (ptr == NULL) { 15099 return (ISC_R_UNEXPECTEDEND); 15100 } 15101 strlcpy(iterbuf, ptr, sizeof(iterbuf)); 15102 n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", hashbuf, 15103 flagbuf, iterbuf); 15104 if (n == sizeof(nbuf)) { 15105 return (ISC_R_NOSPACE); 15106 } 15107 n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); 15108 if (n != 3U) { 15109 return (ISC_R_BADNUMBER); 15110 } 15111 15112 if (hash > 0xffU || flags > 0xffU || 15113 iter > dns_nsec3_maxiterations()) 15114 { 15115 return (ISC_R_RANGE); 15116 } 15117 15118 ptr = next_token(lex, text); 15119 if (ptr == NULL) { 15120 return (ISC_R_UNEXPECTEDEND); 15121 } else if (strcasecmp(ptr, "auto") == 0) { 15122 /* Auto-generate a random salt. 15123 * XXXMUKS: This currently uses the 15124 * minimum recommended length by RFC 15125 * 5155 (64 bits). It should be made 15126 * configurable. 15127 */ 15128 saltlen = 8; 15129 resalt = true; 15130 } else if (strcmp(ptr, "-") != 0) { 15131 isc_buffer_t buf; 15132 15133 isc_buffer_init(&buf, salt, sizeof(salt)); 15134 CHECK(isc_hex_decodestring(ptr, &buf)); 15135 saltlen = isc_buffer_usedlength(&buf); 15136 } 15137 } 15138 } else if (strcasecmp(ptr, "-serial") == 0) { 15139 ptr = next_token(lex, text); 15140 if (ptr == NULL) { 15141 return (ISC_R_UNEXPECTEDEND); 15142 } 15143 CHECK(isc_parse_uint32(&serial, ptr, 10)); 15144 setserial = true; 15145 } else { 15146 CHECK(DNS_R_SYNTAX); 15147 } 15148 15149 CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); 15150 if (zone == NULL) { 15151 CHECK(ISC_R_UNEXPECTEDEND); 15152 } 15153 15154 if (dns_zone_getkasp(zone) != NULL) { 15155 (void)putstr(text, "zone uses dnssec-policy, use rndc dnssec " 15156 "command instead"); 15157 (void)putnull(text); 15158 goto cleanup; 15159 } 15160 15161 if (clear) { 15162 CHECK(dns_zone_keydone(zone, keystr)); 15163 (void)putstr(text, "request queued"); 15164 (void)putnull(text); 15165 } else if (chain) { 15166 CHECK(dns_zone_setnsec3param( 15167 zone, (uint8_t)hash, (uint8_t)flags, iter, 15168 (uint8_t)saltlen, salt, true, resalt)); 15169 (void)putstr(text, "nsec3param request queued"); 15170 (void)putnull(text); 15171 } else if (setserial) { 15172 CHECK(dns_zone_setserial(zone, serial)); 15173 (void)putstr(text, "serial request queued"); 15174 (void)putnull(text); 15175 } else if (list) { 15176 privatetype = dns_zone_getprivatetype(zone); 15177 origin = dns_zone_getorigin(zone); 15178 CHECK(dns_zone_getdb(zone, &db)); 15179 CHECK(dns_db_findnode(db, origin, false, &node)); 15180 dns_db_currentversion(db, &version); 15181 15182 result = dns_db_findrdataset(db, node, version, privatetype, 15183 dns_rdatatype_none, 0, &privset, 15184 NULL); 15185 if (result == ISC_R_NOTFOUND) { 15186 (void)putstr(text, "No signing records found"); 15187 (void)putnull(text); 15188 result = ISC_R_SUCCESS; 15189 goto cleanup; 15190 } 15191 15192 for (result = dns_rdataset_first(&privset); 15193 result == ISC_R_SUCCESS; 15194 result = dns_rdataset_next(&privset)) 15195 { 15196 dns_rdata_t priv = DNS_RDATA_INIT; 15197 /* 15198 * In theory, the output buffer could hold a full RDATA 15199 * record which is 16-bit and then some text around 15200 * it 15201 */ 15202 char output[UINT16_MAX + BUFSIZ]; 15203 isc_buffer_t buf; 15204 15205 dns_rdataset_current(&privset, &priv); 15206 15207 isc_buffer_init(&buf, output, sizeof(output)); 15208 CHECK(dns_private_totext(&priv, &buf)); 15209 if (!first) { 15210 CHECK(putstr(text, "\n")); 15211 } 15212 CHECK(putstr(text, output)); 15213 first = false; 15214 } 15215 if (!first) { 15216 CHECK(putnull(text)); 15217 } 15218 15219 if (result == ISC_R_NOMORE) { 15220 result = ISC_R_SUCCESS; 15221 } 15222 } 15223 15224 cleanup: 15225 if (dns_rdataset_isassociated(&privset)) { 15226 dns_rdataset_disassociate(&privset); 15227 } 15228 if (node != NULL) { 15229 dns_db_detachnode(db, &node); 15230 } 15231 if (version != NULL) { 15232 dns_db_closeversion(db, &version, false); 15233 } 15234 if (db != NULL) { 15235 dns_db_detach(&db); 15236 } 15237 if (zone != NULL) { 15238 dns_zone_detach(&zone); 15239 } 15240 15241 return (result); 15242 } 15243 15244 static bool 15245 argcheck(char *cmd, const char *full) { 15246 size_t l; 15247 15248 if (cmd == NULL || cmd[0] != '-') { 15249 return (false); 15250 } 15251 15252 cmd++; 15253 l = strlen(cmd); 15254 if (l > strlen(full) || strncasecmp(cmd, full, l) != 0) { 15255 return (false); 15256 } 15257 15258 return (true); 15259 } 15260 15261 isc_result_t 15262 named_server_dnssec(named_server_t *server, isc_lex_t *lex, 15263 isc_buffer_t **text) { 15264 isc_result_t result = ISC_R_SUCCESS; 15265 dns_zone_t *zone = NULL; 15266 dns_kasp_t *kasp = NULL; 15267 dns_dnsseckeylist_t keys; 15268 dns_dnsseckey_t *key; 15269 char *ptr, *zonetext = NULL; 15270 const char *msg = NULL; 15271 /* variables for -checkds */ 15272 bool checkds = false, dspublish = false; 15273 /* variables for -rollover */ 15274 bool rollover = false; 15275 /* variables for -key */ 15276 bool use_keyid = false; 15277 dns_keytag_t keyid = 0; 15278 uint8_t algorithm = 0; 15279 /* variables for -status */ 15280 bool status = false; 15281 char output[4096]; 15282 isc_stdtime_t now, when; 15283 isc_time_t timenow, timewhen; 15284 const char *dir; 15285 dns_db_t *db = NULL; 15286 dns_dbversion_t *version = NULL; 15287 15288 REQUIRE(text != NULL); 15289 15290 /* Skip the command name. */ 15291 ptr = next_token(lex, text); 15292 if (ptr == NULL) { 15293 return (ISC_R_UNEXPECTEDEND); 15294 } 15295 15296 /* Find out what we are to do. */ 15297 ptr = next_token(lex, text); 15298 if (ptr == NULL) { 15299 return (ISC_R_UNEXPECTEDEND); 15300 } 15301 15302 /* Initialize current time and key list. */ 15303 TIME_NOW(&timenow); 15304 now = isc_time_seconds(&timenow); 15305 when = now; 15306 15307 ISC_LIST_INIT(keys); 15308 15309 if (strcasecmp(ptr, "-status") == 0) { 15310 status = true; 15311 } else if (strcasecmp(ptr, "-rollover") == 0) { 15312 rollover = true; 15313 } else if (strcasecmp(ptr, "-checkds") == 0) { 15314 checkds = true; 15315 } else { 15316 CHECK(DNS_R_SYNTAX); 15317 } 15318 15319 if (rollover || checkds) { 15320 /* Check for options */ 15321 for (;;) { 15322 ptr = next_token(lex, text); 15323 if (ptr == NULL) { 15324 msg = "Bad format"; 15325 CHECK(ISC_R_UNEXPECTEDEND); 15326 } else if (argcheck(ptr, "alg")) { 15327 isc_consttextregion_t alg; 15328 ptr = next_token(lex, text); 15329 if (ptr == NULL) { 15330 msg = "No key algorithm specified"; 15331 CHECK(ISC_R_UNEXPECTEDEND); 15332 } 15333 alg.base = ptr; 15334 alg.length = strlen(alg.base); 15335 result = dns_secalg_fromtext( 15336 &algorithm, (isc_textregion_t *)&alg); 15337 if (result != ISC_R_SUCCESS) { 15338 msg = "Bad algorithm"; 15339 CHECK(DNS_R_SYNTAX); 15340 } 15341 continue; 15342 } else if (argcheck(ptr, "key")) { 15343 uint16_t id; 15344 ptr = next_token(lex, text); 15345 if (ptr == NULL) { 15346 msg = "No key identifier specified"; 15347 CHECK(ISC_R_UNEXPECTEDEND); 15348 } 15349 CHECK(isc_parse_uint16(&id, ptr, 10)); 15350 keyid = (dns_keytag_t)id; 15351 use_keyid = true; 15352 continue; 15353 } else if (argcheck(ptr, "when")) { 15354 uint32_t tw; 15355 ptr = next_token(lex, text); 15356 if (ptr == NULL) { 15357 msg = "No time specified"; 15358 CHECK(ISC_R_UNEXPECTEDEND); 15359 } 15360 CHECK(dns_time32_fromtext(ptr, &tw)); 15361 when = (isc_stdtime_t)tw; 15362 continue; 15363 } else if (ptr[0] == '-') { 15364 msg = "Unknown option"; 15365 CHECK(DNS_R_SYNTAX); 15366 } else if (checkds) { 15367 /* 15368 * No arguments provided, so we must be 15369 * parsing "published|withdrawn". 15370 */ 15371 if (strcasecmp(ptr, "published") == 0) { 15372 dspublish = true; 15373 } else if (strcasecmp(ptr, "withdrawn") != 0) { 15374 CHECK(DNS_R_SYNTAX); 15375 } 15376 } else if (rollover) { 15377 /* 15378 * No arguments provided, so we must be 15379 * parsing the zone. 15380 */ 15381 zonetext = ptr; 15382 } 15383 break; 15384 } 15385 15386 if (rollover && !use_keyid) { 15387 msg = "Key id is required when scheduling rollover"; 15388 CHECK(DNS_R_SYNTAX); 15389 } 15390 15391 if (algorithm > 0 && !use_keyid) { 15392 msg = "Key id is required when setting algorithm"; 15393 CHECK(DNS_R_SYNTAX); 15394 } 15395 } 15396 15397 /* Get zone. */ 15398 CHECK(zone_from_args(server, lex, zonetext, &zone, NULL, text, false)); 15399 if (zone == NULL) { 15400 msg = "Zone not found"; 15401 CHECK(ISC_R_UNEXPECTEDEND); 15402 } 15403 15404 /* Trailing garbage? */ 15405 ptr = next_token(lex, text); 15406 if (ptr != NULL) { 15407 msg = "Too many arguments"; 15408 CHECK(DNS_R_SYNTAX); 15409 } 15410 15411 /* Get dnssec-policy. */ 15412 kasp = dns_zone_getkasp(zone); 15413 if (kasp == NULL) { 15414 msg = "Zone does not have dnssec-policy"; 15415 goto cleanup; 15416 } 15417 15418 /* Get DNSSEC keys. */ 15419 dir = dns_zone_getkeydirectory(zone); 15420 CHECK(dns_zone_getdb(zone, &db)); 15421 dns_db_currentversion(db, &version); 15422 LOCK(&kasp->lock); 15423 result = dns_zone_getdnsseckeys(zone, db, version, now, &keys); 15424 UNLOCK(&kasp->lock); 15425 if (result != ISC_R_SUCCESS) { 15426 if (result != ISC_R_NOTFOUND) { 15427 goto cleanup; 15428 } 15429 } 15430 15431 if (status) { 15432 /* 15433 * Output the DNSSEC status of the key and signing policy. 15434 */ 15435 LOCK(&kasp->lock); 15436 dns_keymgr_status(kasp, &keys, now, &output[0], sizeof(output)); 15437 UNLOCK(&kasp->lock); 15438 CHECK(putstr(text, output)); 15439 } else if (checkds) { 15440 /* 15441 * Mark DS record has been seen, so it may move to the 15442 * rumoured state. 15443 */ 15444 char whenbuf[80]; 15445 isc_time_set(&timewhen, when, 0); 15446 isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); 15447 isc_result_t ret; 15448 15449 LOCK(&kasp->lock); 15450 if (use_keyid) { 15451 result = dns_keymgr_checkds_id(kasp, &keys, dir, now, 15452 when, dspublish, keyid, 15453 (unsigned int)algorithm); 15454 } else { 15455 result = dns_keymgr_checkds(kasp, &keys, dir, now, when, 15456 dspublish); 15457 } 15458 UNLOCK(&kasp->lock); 15459 15460 switch (result) { 15461 case ISC_R_SUCCESS: 15462 /* 15463 * Rekey after checkds command because the next key 15464 * event may have changed. 15465 */ 15466 dns_zone_rekey(zone, false); 15467 15468 if (use_keyid) { 15469 char tagbuf[6]; 15470 snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); 15471 CHECK(putstr(text, "KSK ")); 15472 CHECK(putstr(text, tagbuf)); 15473 CHECK(putstr(text, ": ")); 15474 } 15475 CHECK(putstr(text, "Marked DS as ")); 15476 if (dspublish) { 15477 CHECK(putstr(text, "published ")); 15478 } else { 15479 CHECK(putstr(text, "withdrawn ")); 15480 } 15481 CHECK(putstr(text, "since ")); 15482 CHECK(putstr(text, whenbuf)); 15483 break; 15484 case DNS_R_TOOMANYKEYS: 15485 CHECK(putstr(text, 15486 "Error: multiple possible keys found, " 15487 "retry command with -key id")); 15488 break; 15489 default: 15490 ret = result; 15491 CHECK(putstr(text, 15492 "Error executing checkds command: ")); 15493 CHECK(putstr(text, isc_result_totext(ret))); 15494 break; 15495 } 15496 } else if (rollover) { 15497 /* 15498 * Manually rollover a key. 15499 */ 15500 char whenbuf[80]; 15501 isc_time_set(&timewhen, when, 0); 15502 isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); 15503 isc_result_t ret; 15504 15505 LOCK(&kasp->lock); 15506 result = dns_keymgr_rollover(kasp, &keys, dir, now, when, keyid, 15507 (unsigned int)algorithm); 15508 UNLOCK(&kasp->lock); 15509 15510 switch (result) { 15511 case ISC_R_SUCCESS: 15512 /* 15513 * Rekey after rollover command because the next key 15514 * event may have changed. 15515 */ 15516 dns_zone_rekey(zone, false); 15517 15518 if (use_keyid) { 15519 char tagbuf[6]; 15520 snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); 15521 CHECK(putstr(text, "Key ")); 15522 CHECK(putstr(text, tagbuf)); 15523 CHECK(putstr(text, ": ")); 15524 } 15525 CHECK(putstr(text, "Rollover scheduled on ")); 15526 CHECK(putstr(text, whenbuf)); 15527 break; 15528 case DNS_R_TOOMANYKEYS: 15529 CHECK(putstr(text, 15530 "Error: multiple possible keys found, " 15531 "retry command with -alg algorithm")); 15532 break; 15533 default: 15534 ret = result; 15535 CHECK(putstr(text, 15536 "Error executing rollover command: ")); 15537 CHECK(putstr(text, isc_result_totext(ret))); 15538 break; 15539 } 15540 } 15541 CHECK(putnull(text)); 15542 15543 cleanup: 15544 if (msg != NULL) { 15545 (void)putstr(text, msg); 15546 (void)putnull(text); 15547 } 15548 15549 if (version != NULL) { 15550 dns_db_closeversion(db, &version, false); 15551 } 15552 if (db != NULL) { 15553 dns_db_detach(&db); 15554 } 15555 15556 while (!ISC_LIST_EMPTY(keys)) { 15557 key = ISC_LIST_HEAD(keys); 15558 ISC_LIST_UNLINK(keys, key, link); 15559 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key); 15560 } 15561 15562 if (zone != NULL) { 15563 dns_zone_detach(&zone); 15564 } 15565 15566 return (result); 15567 } 15568 15569 static isc_result_t 15570 putmem(isc_buffer_t **b, const char *str, size_t len) { 15571 isc_result_t result; 15572 15573 result = isc_buffer_reserve(b, (unsigned int)len); 15574 if (result != ISC_R_SUCCESS) { 15575 return (ISC_R_NOSPACE); 15576 } 15577 15578 isc_buffer_putmem(*b, (const unsigned char *)str, (unsigned int)len); 15579 return (ISC_R_SUCCESS); 15580 } 15581 15582 static isc_result_t 15583 putstr(isc_buffer_t **b, const char *str) { 15584 return (putmem(b, str, strlen(str))); 15585 } 15586 15587 static isc_result_t 15588 putuint8(isc_buffer_t **b, uint8_t val) { 15589 isc_result_t result; 15590 15591 result = isc_buffer_reserve(b, 1); 15592 if (result != ISC_R_SUCCESS) { 15593 return (ISC_R_NOSPACE); 15594 } 15595 15596 isc_buffer_putuint8(*b, val); 15597 return (ISC_R_SUCCESS); 15598 } 15599 15600 static isc_result_t 15601 putnull(isc_buffer_t **b) { 15602 return (putuint8(b, 0)); 15603 } 15604 15605 isc_result_t 15606 named_server_zonestatus(named_server_t *server, isc_lex_t *lex, 15607 isc_buffer_t **text) { 15608 isc_result_t result = ISC_R_SUCCESS; 15609 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; 15610 const char *type, *file; 15611 char zonename[DNS_NAME_FORMATSIZE]; 15612 uint32_t serial, signed_serial, nodes; 15613 char serbuf[16], sserbuf[16], nodebuf[16]; 15614 char resignbuf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 2]; 15615 char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15616 char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15617 char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15618 char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15619 char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 15620 isc_time_t loadtime, expiretime, refreshtime; 15621 isc_time_t refreshkeytime, resigntime; 15622 dns_zonetype_t zonetype; 15623 bool dynamic = false, frozen = false; 15624 bool hasraw = false; 15625 bool secure, maintain, allow; 15626 dns_db_t *db = NULL, *rawdb = NULL; 15627 char **incfiles = NULL; 15628 int nfiles = 0; 15629 15630 REQUIRE(text != NULL); 15631 15632 isc_time_settoepoch(&loadtime); 15633 isc_time_settoepoch(&refreshtime); 15634 isc_time_settoepoch(&expiretime); 15635 isc_time_settoepoch(&refreshkeytime); 15636 isc_time_settoepoch(&resigntime); 15637 15638 CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); 15639 if (zone == NULL) { 15640 result = ISC_R_UNEXPECTEDEND; 15641 goto cleanup; 15642 } 15643 15644 /* Inline signing? */ 15645 CHECK(dns_zone_getdb(zone, &db)); 15646 dns_zone_getraw(zone, &raw); 15647 hasraw = (raw != NULL); 15648 if (hasraw) { 15649 mayberaw = raw; 15650 zonetype = dns_zone_gettype(raw); 15651 CHECK(dns_zone_getdb(raw, &rawdb)); 15652 } else { 15653 mayberaw = zone; 15654 zonetype = dns_zone_gettype(zone); 15655 } 15656 15657 type = dns_zonetype_name(zonetype); 15658 15659 /* Serial number */ 15660 result = dns_zone_getserial(mayberaw, &serial); 15661 15662 /* This is to mirror old behavior with dns_zone_getserial */ 15663 if (result != ISC_R_SUCCESS) { 15664 serial = 0; 15665 } 15666 15667 snprintf(serbuf, sizeof(serbuf), "%u", serial); 15668 if (hasraw) { 15669 result = dns_zone_getserial(zone, &signed_serial); 15670 if (result != ISC_R_SUCCESS) { 15671 serial = 0; 15672 } 15673 snprintf(sserbuf, sizeof(sserbuf), "%u", signed_serial); 15674 } 15675 15676 /* Database node count */ 15677 nodes = dns_db_nodecount(hasraw ? rawdb : db, dns_dbtree_main); 15678 snprintf(nodebuf, sizeof(nodebuf), "%u", nodes); 15679 15680 /* Security */ 15681 secure = dns_db_issecure(db); 15682 allow = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW) != 0); 15683 maintain = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0); 15684 15685 /* Master files */ 15686 file = dns_zone_getfile(mayberaw); 15687 nfiles = dns_zone_getincludes(mayberaw, &incfiles); 15688 15689 /* Load time */ 15690 dns_zone_getloadtime(zone, &loadtime); 15691 isc_time_formathttptimestamp(&loadtime, lbuf, sizeof(lbuf)); 15692 15693 /* Refresh/expire times */ 15694 if (zonetype == dns_zone_secondary || zonetype == dns_zone_mirror || 15695 zonetype == dns_zone_stub || zonetype == dns_zone_redirect) 15696 { 15697 dns_zone_getexpiretime(mayberaw, &expiretime); 15698 isc_time_formathttptimestamp(&expiretime, xbuf, sizeof(xbuf)); 15699 dns_zone_getrefreshtime(mayberaw, &refreshtime); 15700 isc_time_formathttptimestamp(&refreshtime, rbuf, sizeof(rbuf)); 15701 } 15702 15703 /* Key refresh time */ 15704 if (zonetype == dns_zone_primary || 15705 (zonetype == dns_zone_secondary && hasraw)) 15706 { 15707 dns_zone_getrefreshkeytime(zone, &refreshkeytime); 15708 isc_time_formathttptimestamp(&refreshkeytime, kbuf, 15709 sizeof(kbuf)); 15710 } 15711 15712 /* Dynamic? */ 15713 if (zonetype == dns_zone_primary) { 15714 dynamic = dns_zone_isdynamic(mayberaw, true); 15715 frozen = dynamic && !dns_zone_isdynamic(mayberaw, false); 15716 } 15717 15718 /* Next resign event */ 15719 if (secure && 15720 (zonetype == dns_zone_primary || 15721 (zonetype == dns_zone_secondary && hasraw)) && 15722 ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_NORESIGN) == 0)) 15723 { 15724 dns_name_t *name; 15725 dns_fixedname_t fixed; 15726 dns_rdataset_t next; 15727 15728 dns_rdataset_init(&next); 15729 name = dns_fixedname_initname(&fixed); 15730 15731 result = dns_db_getsigningtime(db, &next, name); 15732 if (result == ISC_R_SUCCESS) { 15733 isc_stdtime_t timenow; 15734 char namebuf[DNS_NAME_FORMATSIZE]; 15735 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 15736 15737 isc_stdtime_get(&timenow); 15738 dns_name_format(name, namebuf, sizeof(namebuf)); 15739 dns_rdatatype_format(next.covers, typebuf, 15740 sizeof(typebuf)); 15741 snprintf(resignbuf, sizeof(resignbuf), "%s/%s", namebuf, 15742 typebuf); 15743 isc_time_set( 15744 &resigntime, 15745 next.resign - 15746 dns_zone_getsigresigninginterval(zone), 15747 0); 15748 isc_time_formathttptimestamp(&resigntime, rtbuf, 15749 sizeof(rtbuf)); 15750 dns_rdataset_disassociate(&next); 15751 } 15752 } 15753 15754 /* Create text */ 15755 CHECK(putstr(text, "name: ")); 15756 CHECK(putstr(text, zonename)); 15757 15758 CHECK(putstr(text, "\ntype: ")); 15759 CHECK(putstr(text, type)); 15760 15761 if (file != NULL) { 15762 int i; 15763 CHECK(putstr(text, "\nfiles: ")); 15764 CHECK(putstr(text, file)); 15765 for (i = 0; i < nfiles; i++) { 15766 CHECK(putstr(text, ", ")); 15767 if (incfiles[i] != NULL) { 15768 CHECK(putstr(text, incfiles[i])); 15769 } 15770 } 15771 } 15772 15773 CHECK(putstr(text, "\nserial: ")); 15774 CHECK(putstr(text, serbuf)); 15775 if (hasraw) { 15776 CHECK(putstr(text, "\nsigned serial: ")); 15777 CHECK(putstr(text, sserbuf)); 15778 } 15779 15780 CHECK(putstr(text, "\nnodes: ")); 15781 CHECK(putstr(text, nodebuf)); 15782 15783 if (!isc_time_isepoch(&loadtime)) { 15784 CHECK(putstr(text, "\nlast loaded: ")); 15785 CHECK(putstr(text, lbuf)); 15786 } 15787 15788 if (!isc_time_isepoch(&refreshtime)) { 15789 CHECK(putstr(text, "\nnext refresh: ")); 15790 CHECK(putstr(text, rbuf)); 15791 } 15792 15793 if (!isc_time_isepoch(&expiretime)) { 15794 CHECK(putstr(text, "\nexpires: ")); 15795 CHECK(putstr(text, xbuf)); 15796 } 15797 15798 if (secure) { 15799 CHECK(putstr(text, "\nsecure: yes")); 15800 if (hasraw) { 15801 CHECK(putstr(text, "\ninline signing: yes")); 15802 } else { 15803 CHECK(putstr(text, "\ninline signing: no")); 15804 } 15805 } else { 15806 CHECK(putstr(text, "\nsecure: no")); 15807 } 15808 15809 if (maintain) { 15810 CHECK(putstr(text, "\nkey maintenance: automatic")); 15811 if (!isc_time_isepoch(&refreshkeytime)) { 15812 CHECK(putstr(text, "\nnext key event: ")); 15813 CHECK(putstr(text, kbuf)); 15814 } 15815 } else if (allow) { 15816 CHECK(putstr(text, "\nkey maintenance: on command")); 15817 } else if (secure || hasraw) { 15818 CHECK(putstr(text, "\nkey maintenance: none")); 15819 } 15820 15821 if (!isc_time_isepoch(&resigntime)) { 15822 CHECK(putstr(text, "\nnext resign node: ")); 15823 CHECK(putstr(text, resignbuf)); 15824 CHECK(putstr(text, "\nnext resign time: ")); 15825 CHECK(putstr(text, rtbuf)); 15826 } 15827 15828 if (dynamic) { 15829 CHECK(putstr(text, "\ndynamic: yes")); 15830 if (frozen) { 15831 CHECK(putstr(text, "\nfrozen: yes")); 15832 } else { 15833 CHECK(putstr(text, "\nfrozen: no")); 15834 } 15835 } else { 15836 CHECK(putstr(text, "\ndynamic: no")); 15837 } 15838 15839 CHECK(putstr(text, "\nreconfigurable via modzone: ")); 15840 CHECK(putstr(text, dns_zone_getadded(zone) ? "yes" : "no")); 15841 15842 cleanup: 15843 /* Indicate truncated output if possible. */ 15844 if (result == ISC_R_NOSPACE) { 15845 (void)putstr(text, "\n..."); 15846 } 15847 if ((result == ISC_R_SUCCESS || result == ISC_R_NOSPACE)) { 15848 (void)putnull(text); 15849 } 15850 15851 if (db != NULL) { 15852 dns_db_detach(&db); 15853 } 15854 if (rawdb != NULL) { 15855 dns_db_detach(&rawdb); 15856 } 15857 if (incfiles != NULL && mayberaw != NULL) { 15858 int i; 15859 isc_mem_t *mctx = dns_zone_getmctx(mayberaw); 15860 15861 for (i = 0; i < nfiles; i++) { 15862 if (incfiles[i] != NULL) { 15863 isc_mem_free(mctx, incfiles[i]); 15864 } 15865 } 15866 isc_mem_free(mctx, incfiles); 15867 } 15868 if (raw != NULL) { 15869 dns_zone_detach(&raw); 15870 } 15871 if (zone != NULL) { 15872 dns_zone_detach(&zone); 15873 } 15874 return (result); 15875 } 15876 15877 isc_result_t 15878 named_server_nta(named_server_t *server, isc_lex_t *lex, bool readonly, 15879 isc_buffer_t **text) { 15880 dns_view_t *view; 15881 dns_ntatable_t *ntatable = NULL; 15882 isc_result_t result = ISC_R_SUCCESS; 15883 char *ptr, *nametext = NULL, *viewname; 15884 char namebuf[DNS_NAME_FORMATSIZE]; 15885 char viewbuf[DNS_NAME_FORMATSIZE]; 15886 isc_stdtime_t now, when; 15887 isc_time_t t; 15888 char tbuf[64]; 15889 const char *msg = NULL; 15890 bool dump = false, force = false; 15891 dns_fixedname_t fn; 15892 const dns_name_t *ntaname; 15893 dns_name_t *fname; 15894 dns_ttl_t ntattl; 15895 bool ttlset = false, excl = false, viewfound = false; 15896 dns_rdataclass_t rdclass = dns_rdataclass_in; 15897 bool first = true; 15898 15899 REQUIRE(text != NULL); 15900 15901 UNUSED(force); 15902 15903 fname = dns_fixedname_initname(&fn); 15904 15905 /* Skip the command name. */ 15906 ptr = next_token(lex, text); 15907 if (ptr == NULL) { 15908 return (ISC_R_UNEXPECTEDEND); 15909 } 15910 15911 for (;;) { 15912 /* Check for options */ 15913 ptr = next_token(lex, text); 15914 if (ptr == NULL) { 15915 return (ISC_R_UNEXPECTEDEND); 15916 } 15917 15918 if (strcmp(ptr, "--") == 0) { 15919 break; 15920 } else if (argcheck(ptr, "dump")) { 15921 dump = true; 15922 } else if (argcheck(ptr, "remove")) { 15923 ntattl = 0; 15924 ttlset = true; 15925 } else if (argcheck(ptr, "force")) { 15926 force = true; 15927 continue; 15928 } else if (argcheck(ptr, "lifetime")) { 15929 isc_textregion_t tr; 15930 15931 ptr = next_token(lex, text); 15932 if (ptr == NULL) { 15933 msg = "No lifetime specified"; 15934 CHECK(ISC_R_UNEXPECTEDEND); 15935 } 15936 15937 tr.base = ptr; 15938 tr.length = strlen(ptr); 15939 result = dns_ttl_fromtext(&tr, &ntattl); 15940 if (result != ISC_R_SUCCESS) { 15941 msg = "could not parse NTA lifetime"; 15942 CHECK(result); 15943 } 15944 15945 if (ntattl > 604800) { 15946 msg = "NTA lifetime cannot exceed one week"; 15947 CHECK(ISC_R_RANGE); 15948 } 15949 15950 ttlset = true; 15951 continue; 15952 } else if (argcheck(ptr, "class")) { 15953 isc_textregion_t tr; 15954 15955 ptr = next_token(lex, text); 15956 if (ptr == NULL) { 15957 msg = "No class specified"; 15958 CHECK(ISC_R_UNEXPECTEDEND); 15959 } 15960 15961 tr.base = ptr; 15962 tr.length = strlen(ptr); 15963 CHECK(dns_rdataclass_fromtext(&rdclass, &tr)); 15964 continue; 15965 } else if (ptr[0] == '-') { 15966 msg = "Unknown option"; 15967 CHECK(DNS_R_SYNTAX); 15968 } else { 15969 nametext = ptr; 15970 } 15971 15972 break; 15973 } 15974 15975 /* 15976 * If -dump was specified, list NTA's and return 15977 */ 15978 if (dump) { 15979 size_t last = 0; 15980 15981 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 15982 view = ISC_LIST_NEXT(view, link)) 15983 { 15984 if (ntatable != NULL) { 15985 dns_ntatable_detach(&ntatable); 15986 } 15987 result = dns_view_getntatable(view, &ntatable); 15988 if (result == ISC_R_NOTFOUND) { 15989 continue; 15990 } 15991 15992 if (last != isc_buffer_usedlength(*text)) { 15993 CHECK(putstr(text, "\n")); 15994 } 15995 15996 last = isc_buffer_usedlength(*text); 15997 15998 CHECK(dns_ntatable_totext(ntatable, view->name, text)); 15999 } 16000 CHECK(putnull(text)); 16001 16002 goto cleanup; 16003 } 16004 16005 if (readonly) { 16006 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16007 NAMED_LOGMODULE_CONTROL, ISC_LOG_INFO, 16008 "rejecting restricted control channel " 16009 "NTA command"); 16010 CHECK(ISC_R_FAILURE); 16011 } 16012 16013 /* Get the NTA name if not found above. */ 16014 if (nametext == NULL) { 16015 nametext = next_token(lex, text); 16016 } 16017 if (nametext == NULL) { 16018 return (ISC_R_UNEXPECTEDEND); 16019 } 16020 16021 /* Copy nametext as it'll be overwritten by next_token() */ 16022 strlcpy(namebuf, nametext, DNS_NAME_FORMATSIZE); 16023 16024 if (strcmp(namebuf, ".") == 0) { 16025 ntaname = dns_rootname; 16026 } else { 16027 isc_buffer_t b; 16028 isc_buffer_init(&b, namebuf, strlen(namebuf)); 16029 isc_buffer_add(&b, strlen(namebuf)); 16030 CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0, NULL)); 16031 ntaname = fname; 16032 } 16033 16034 /* Look for the view name. */ 16035 viewname = next_token(lex, text); 16036 if (viewname != NULL) { 16037 strlcpy(viewbuf, viewname, DNS_NAME_FORMATSIZE); 16038 viewname = viewbuf; 16039 } 16040 16041 if (next_token(lex, text) != NULL) { 16042 CHECK(DNS_R_SYNTAX); 16043 } 16044 16045 isc_stdtime_get(&now); 16046 16047 result = isc_task_beginexclusive(server->task); 16048 RUNTIME_CHECK(result == ISC_R_SUCCESS); 16049 excl = true; 16050 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16051 view = ISC_LIST_NEXT(view, link)) 16052 { 16053 if (viewname != NULL && strcmp(view->name, viewname) != 0) { 16054 continue; 16055 } 16056 viewfound = true; 16057 16058 if (view->rdclass != rdclass && rdclass != dns_rdataclass_any) { 16059 continue; 16060 } 16061 16062 if (view->nta_lifetime == 0) { 16063 continue; 16064 } 16065 16066 if (!ttlset) { 16067 ntattl = view->nta_lifetime; 16068 } 16069 16070 if (ntatable != NULL) { 16071 dns_ntatable_detach(&ntatable); 16072 } 16073 16074 result = dns_view_getntatable(view, &ntatable); 16075 if (result == ISC_R_NOTFOUND) { 16076 result = ISC_R_SUCCESS; 16077 continue; 16078 } 16079 16080 result = dns_view_flushnode(view, ntaname, true); 16081 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16082 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16083 "flush tree '%s' in cache view '%s': %s", namebuf, 16084 view->name, isc_result_totext(result)); 16085 16086 if (ntattl != 0) { 16087 CHECK(dns_ntatable_add(ntatable, ntaname, force, now, 16088 ntattl)); 16089 16090 when = now + ntattl; 16091 isc_time_set(&t, when, 0); 16092 isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); 16093 16094 if (!first) { 16095 CHECK(putstr(text, "\n")); 16096 } 16097 first = false; 16098 16099 CHECK(putstr(text, "Negative trust anchor added: ")); 16100 CHECK(putstr(text, namebuf)); 16101 CHECK(putstr(text, "/")); 16102 CHECK(putstr(text, view->name)); 16103 CHECK(putstr(text, ", expires ")); 16104 CHECK(putstr(text, tbuf)); 16105 16106 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16107 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16108 "added NTA '%s' (%d sec) in view '%s'", 16109 namebuf, ntattl, view->name); 16110 } else { 16111 bool wasremoved; 16112 16113 result = dns_ntatable_delete(ntatable, ntaname); 16114 if (result == ISC_R_SUCCESS) { 16115 wasremoved = true; 16116 } else if (result == ISC_R_NOTFOUND) { 16117 wasremoved = false; 16118 } else { 16119 goto cleanup; 16120 } 16121 16122 if (!first) { 16123 CHECK(putstr(text, "\n")); 16124 } 16125 first = false; 16126 16127 CHECK(putstr(text, "Negative trust anchor ")); 16128 CHECK(putstr(text, 16129 wasremoved ? "removed: " : "not found: ")); 16130 CHECK(putstr(text, namebuf)); 16131 CHECK(putstr(text, "/")); 16132 CHECK(putstr(text, view->name)); 16133 16134 if (wasremoved) { 16135 isc_log_write( 16136 named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16137 NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, 16138 "removed NTA '%s' in view %s", namebuf, 16139 view->name); 16140 } 16141 } 16142 16143 result = dns_view_saventa(view); 16144 if (result != ISC_R_SUCCESS) { 16145 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16146 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16147 "error writing NTA file " 16148 "for view '%s': %s", 16149 view->name, isc_result_totext(result)); 16150 } 16151 } 16152 16153 if (!viewfound) { 16154 msg = "No such view"; 16155 CHECK(ISC_R_NOTFOUND); 16156 } 16157 16158 (void)putnull(text); 16159 16160 cleanup: 16161 if (msg != NULL) { 16162 (void)putstr(text, msg); 16163 (void)putnull(text); 16164 } 16165 16166 if (excl) { 16167 isc_task_endexclusive(server->task); 16168 } 16169 if (ntatable != NULL) { 16170 dns_ntatable_detach(&ntatable); 16171 } 16172 return (result); 16173 } 16174 16175 isc_result_t 16176 named_server_saventa(named_server_t *server) { 16177 dns_view_t *view; 16178 16179 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16180 view = ISC_LIST_NEXT(view, link)) 16181 { 16182 isc_result_t result = dns_view_saventa(view); 16183 16184 if (result != ISC_R_SUCCESS) { 16185 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16186 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16187 "error writing NTA file " 16188 "for view '%s': %s", 16189 view->name, isc_result_totext(result)); 16190 } 16191 } 16192 16193 return (ISC_R_SUCCESS); 16194 } 16195 16196 isc_result_t 16197 named_server_loadnta(named_server_t *server) { 16198 dns_view_t *view; 16199 16200 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16201 view = ISC_LIST_NEXT(view, link)) 16202 { 16203 isc_result_t result = dns_view_loadnta(view); 16204 16205 if ((result != ISC_R_SUCCESS) && 16206 (result != ISC_R_FILENOTFOUND) && 16207 (result != ISC_R_NOTFOUND)) 16208 { 16209 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16210 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, 16211 "error loading NTA file " 16212 "for view '%s': %s", 16213 view->name, isc_result_totext(result)); 16214 } 16215 } 16216 16217 return (ISC_R_SUCCESS); 16218 } 16219 16220 static isc_result_t 16221 mkey_refresh(dns_view_t *view, isc_buffer_t **text) { 16222 isc_result_t result; 16223 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16224 16225 snprintf(msg, sizeof(msg), "refreshing managed keys for '%s'", 16226 view->name); 16227 CHECK(putstr(text, msg)); 16228 CHECK(dns_zone_synckeyzone(view->managed_keys)); 16229 16230 cleanup: 16231 return (result); 16232 } 16233 16234 static isc_result_t 16235 mkey_destroy(named_server_t *server, dns_view_t *view, isc_buffer_t **text) { 16236 isc_result_t result; 16237 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16238 bool exclusive = false; 16239 const char *file = NULL; 16240 dns_db_t *dbp = NULL; 16241 dns_zone_t *mkzone = NULL; 16242 bool removed_a_file = false; 16243 16244 if (view->managed_keys == NULL) { 16245 CHECK(ISC_R_NOTFOUND); 16246 } 16247 16248 snprintf(msg, sizeof(msg), "destroying managed-keys database for '%s'", 16249 view->name); 16250 CHECK(putstr(text, msg)); 16251 16252 result = isc_task_beginexclusive(server->task); 16253 RUNTIME_CHECK(result == ISC_R_SUCCESS); 16254 exclusive = true; 16255 16256 /* Remove and clean up managed keys zone from view */ 16257 mkzone = view->managed_keys; 16258 view->managed_keys = NULL; 16259 (void)dns_zone_flush(mkzone); 16260 16261 /* Unload zone database */ 16262 if (dns_zone_getdb(mkzone, &dbp) == ISC_R_SUCCESS) { 16263 dns_db_detach(&dbp); 16264 dns_zone_unload(mkzone); 16265 } 16266 16267 /* Delete files */ 16268 file = dns_zone_getfile(mkzone); 16269 result = isc_file_remove(file); 16270 if (result == ISC_R_SUCCESS) { 16271 removed_a_file = true; 16272 } else { 16273 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16274 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 16275 "file %s not removed: %s", file, 16276 isc_result_totext(result)); 16277 } 16278 16279 file = dns_zone_getjournal(mkzone); 16280 result = isc_file_remove(file); 16281 if (result == ISC_R_SUCCESS) { 16282 removed_a_file = true; 16283 } else { 16284 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, 16285 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, 16286 "file %s not removed: %s", file, 16287 isc_result_totext(result)); 16288 } 16289 16290 if (!removed_a_file) { 16291 CHECK(putstr(text, "error: no files could be removed")); 16292 CHECK(ISC_R_FAILURE); 16293 } 16294 16295 dns_zone_detach(&mkzone); 16296 result = ISC_R_SUCCESS; 16297 16298 cleanup: 16299 if (exclusive) { 16300 isc_task_endexclusive(server->task); 16301 } 16302 return (result); 16303 } 16304 16305 static isc_result_t 16306 mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) { 16307 isc_result_t result; 16308 dns_db_t *db = NULL; 16309 dns_dbversion_t *ver = NULL; 16310 dns_rriterator_t rrit; 16311 isc_stdtime_t now; 16312 dns_name_t *prevname = NULL; 16313 16314 isc_stdtime_get(&now); 16315 16316 CHECK(dns_zone_getdb(view->managed_keys, &db)); 16317 dns_db_currentversion(db, &ver); 16318 dns_rriterator_init(&rrit, db, ver, 0); 16319 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS; 16320 result = dns_rriterator_nextrrset(&rrit)) 16321 { 16322 char buf[DNS_NAME_FORMATSIZE + 500]; 16323 dns_name_t *name = NULL; 16324 dns_rdataset_t *kdset = NULL; 16325 dns_rdata_t rdata = DNS_RDATA_INIT; 16326 dns_rdata_keydata_t kd; 16327 uint32_t ttl; 16328 16329 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL); 16330 if (kdset == NULL || kdset->type != dns_rdatatype_keydata || 16331 !dns_rdataset_isassociated(kdset)) 16332 { 16333 continue; 16334 } 16335 16336 if (name != prevname) { 16337 char nbuf[DNS_NAME_FORMATSIZE]; 16338 dns_name_format(name, nbuf, sizeof(nbuf)); 16339 snprintf(buf, sizeof(buf), "\n\n name: %s", nbuf); 16340 CHECK(putstr(text, buf)); 16341 } 16342 16343 for (result = dns_rdataset_first(kdset); 16344 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset)) 16345 { 16346 char alg[DNS_SECALG_FORMATSIZE]; 16347 char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 16348 dns_keytag_t keyid; 16349 isc_region_t r; 16350 isc_time_t t; 16351 bool revoked; 16352 16353 dns_rdata_reset(&rdata); 16354 dns_rdataset_current(kdset, &rdata); 16355 result = dns_rdata_tostruct(&rdata, &kd, NULL); 16356 RUNTIME_CHECK(result == ISC_R_SUCCESS); 16357 16358 dns_rdata_toregion(&rdata, &r); 16359 isc_region_consume(&r, 12); 16360 keyid = dst_region_computeid(&r); 16361 16362 snprintf(buf, sizeof(buf), "\n keyid: %u", keyid); 16363 CHECK(putstr(text, buf)); 16364 16365 dns_secalg_format(kd.algorithm, alg, sizeof(alg)); 16366 snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg); 16367 CHECK(putstr(text, buf)); 16368 16369 revoked = ((kd.flags & DNS_KEYFLAG_REVOKE) != 0); 16370 snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s", 16371 revoked ? " REVOKE" : "", 16372 ((kd.flags & DNS_KEYFLAG_KSK) != 0) ? " SEP" 16373 : "", 16374 (kd.flags == 0) ? " (none)" : ""); 16375 CHECK(putstr(text, buf)); 16376 16377 isc_time_set(&t, kd.refresh, 0); 16378 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); 16379 snprintf(buf, sizeof(buf), "\n\tnext refresh: %s", 16380 tbuf); 16381 CHECK(putstr(text, buf)); 16382 16383 if (kd.removehd != 0) { 16384 isc_time_set(&t, kd.removehd, 0); 16385 isc_time_formathttptimestamp(&t, tbuf, 16386 sizeof(tbuf)); 16387 snprintf(buf, sizeof(buf), "\n\tremove at: %s", 16388 tbuf); 16389 CHECK(putstr(text, buf)); 16390 } 16391 16392 isc_time_set(&t, kd.addhd, 0); 16393 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); 16394 if (kd.addhd == 0) { 16395 snprintf(buf, sizeof(buf), "\n\tno trust"); 16396 } else if (revoked) { 16397 snprintf(buf, sizeof(buf), "\n\ttrust revoked"); 16398 } else if (kd.addhd <= now) { 16399 snprintf(buf, sizeof(buf), 16400 "\n\ttrusted since: %s", tbuf); 16401 } else if (kd.addhd > now) { 16402 snprintf(buf, sizeof(buf), 16403 "\n\ttrust pending: %s", tbuf); 16404 } 16405 CHECK(putstr(text, buf)); 16406 } 16407 } 16408 16409 if (result == ISC_R_NOMORE) { 16410 result = ISC_R_SUCCESS; 16411 } 16412 16413 cleanup: 16414 if (ver != NULL) { 16415 dns_rriterator_destroy(&rrit); 16416 dns_db_closeversion(db, &ver, false); 16417 } 16418 if (db != NULL) { 16419 dns_db_detach(&db); 16420 } 16421 16422 return (result); 16423 } 16424 16425 static isc_result_t 16426 mkey_status(dns_view_t *view, isc_buffer_t **text) { 16427 isc_result_t result; 16428 char msg[ISC_FORMATHTTPTIMESTAMP_SIZE]; 16429 isc_time_t t; 16430 16431 CHECK(putstr(text, "view: ")); 16432 CHECK(putstr(text, view->name)); 16433 16434 CHECK(putstr(text, "\nnext scheduled event: ")); 16435 16436 dns_zone_getrefreshkeytime(view->managed_keys, &t); 16437 if (isc_time_isepoch(&t)) { 16438 CHECK(putstr(text, "never")); 16439 } else { 16440 isc_time_formathttptimestamp(&t, msg, sizeof(msg)); 16441 CHECK(putstr(text, msg)); 16442 } 16443 16444 CHECK(mkey_dumpzone(view, text)); 16445 16446 cleanup: 16447 return (result); 16448 } 16449 16450 isc_result_t 16451 named_server_mkeys(named_server_t *server, isc_lex_t *lex, 16452 isc_buffer_t **text) { 16453 char *cmd, *classtxt, *viewtxt = NULL; 16454 isc_result_t result = ISC_R_SUCCESS; 16455 dns_view_t *view = NULL; 16456 dns_rdataclass_t rdclass; 16457 char msg[DNS_NAME_FORMATSIZE + 500] = ""; 16458 enum { NONE, STATUS, REFRESH, SYNC, DESTROY } opt = NONE; 16459 bool found = false; 16460 bool first = true; 16461 16462 REQUIRE(text != NULL); 16463 16464 /* Skip rndc command name */ 16465 cmd = next_token(lex, text); 16466 if (cmd == NULL) { 16467 return (ISC_R_UNEXPECTEDEND); 16468 } 16469 16470 /* Get managed-keys subcommand */ 16471 cmd = next_token(lex, text); 16472 if (cmd == NULL) { 16473 return (ISC_R_UNEXPECTEDEND); 16474 } 16475 16476 if (strcasecmp(cmd, "status") == 0) { 16477 opt = STATUS; 16478 } else if (strcasecmp(cmd, "refresh") == 0) { 16479 opt = REFRESH; 16480 } else if (strcasecmp(cmd, "sync") == 0) { 16481 opt = SYNC; 16482 } else if (strcasecmp(cmd, "destroy") == 0) { 16483 opt = DESTROY; 16484 } else { 16485 snprintf(msg, sizeof(msg), "unknown command '%s'", cmd); 16486 (void)putstr(text, msg); 16487 result = ISC_R_UNEXPECTED; 16488 goto cleanup; 16489 } 16490 16491 /* Look for the optional class name. */ 16492 classtxt = next_token(lex, text); 16493 if (classtxt != NULL) { 16494 isc_textregion_t r; 16495 r.base = classtxt; 16496 r.length = strlen(classtxt); 16497 result = dns_rdataclass_fromtext(&rdclass, &r); 16498 if (result != ISC_R_SUCCESS) { 16499 snprintf(msg, sizeof(msg), "unknown class '%s'", 16500 classtxt); 16501 (void)putstr(text, msg); 16502 goto cleanup; 16503 } 16504 viewtxt = next_token(lex, text); 16505 } 16506 16507 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16508 view = ISC_LIST_NEXT(view, link)) 16509 { 16510 if (viewtxt != NULL && (rdclass != view->rdclass || 16511 strcmp(view->name, viewtxt) != 0)) 16512 { 16513 continue; 16514 } 16515 16516 if (view->managed_keys == NULL) { 16517 if (viewtxt != NULL) { 16518 snprintf(msg, sizeof(msg), 16519 "view '%s': no managed keys", viewtxt); 16520 CHECK(putstr(text, msg)); 16521 goto cleanup; 16522 } else { 16523 continue; 16524 } 16525 } 16526 16527 found = true; 16528 16529 switch (opt) { 16530 case REFRESH: 16531 if (!first) { 16532 CHECK(putstr(text, "\n")); 16533 } 16534 CHECK(mkey_refresh(view, text)); 16535 break; 16536 case STATUS: 16537 if (!first) { 16538 CHECK(putstr(text, "\n\n")); 16539 } 16540 CHECK(mkey_status(view, text)); 16541 break; 16542 case SYNC: 16543 CHECK(dns_zone_flush(view->managed_keys)); 16544 break; 16545 case DESTROY: 16546 if (!first) { 16547 CHECK(putstr(text, "\n")); 16548 } 16549 CHECK(mkey_destroy(server, view, text)); 16550 break; 16551 default: 16552 UNREACHABLE(); 16553 } 16554 16555 if (viewtxt != NULL) { 16556 break; 16557 } 16558 first = false; 16559 } 16560 16561 if (!found) { 16562 CHECK(putstr(text, "no views with managed keys")); 16563 } 16564 16565 cleanup: 16566 if (isc_buffer_usedlength(*text) > 0) { 16567 (void)putnull(text); 16568 } 16569 16570 return (result); 16571 } 16572 16573 isc_result_t 16574 named_server_dnstap(named_server_t *server, isc_lex_t *lex, 16575 isc_buffer_t **text) { 16576 #ifdef HAVE_DNSTAP 16577 char *ptr; 16578 isc_result_t result; 16579 bool reopen = false; 16580 int backups = 0; 16581 16582 REQUIRE(text != NULL); 16583 16584 if (server->dtenv == NULL) { 16585 return (ISC_R_NOTFOUND); 16586 } 16587 16588 /* Check the command name. */ 16589 ptr = next_token(lex, text); 16590 if (ptr == NULL) { 16591 return (ISC_R_UNEXPECTEDEND); 16592 } 16593 16594 /* "dnstap-reopen" was used in 9.11.0b1 */ 16595 if (strcasecmp(ptr, "dnstap-reopen") == 0) { 16596 reopen = true; 16597 } else { 16598 ptr = next_token(lex, text); 16599 if (ptr == NULL) { 16600 return (ISC_R_UNEXPECTEDEND); 16601 } 16602 } 16603 16604 if (reopen || strcasecmp(ptr, "-reopen") == 0) { 16605 backups = ISC_LOG_ROLLNEVER; 16606 } else if ((strcasecmp(ptr, "-roll") == 0)) { 16607 unsigned int n; 16608 ptr = next_token(lex, text); 16609 if (ptr != NULL) { 16610 unsigned int u; 16611 n = sscanf(ptr, "%u", &u); 16612 if (n != 1U || u > INT_MAX) { 16613 return (ISC_R_BADNUMBER); 16614 } 16615 backups = u; 16616 } else { 16617 backups = ISC_LOG_ROLLINFINITE; 16618 } 16619 } else { 16620 return (DNS_R_SYNTAX); 16621 } 16622 16623 result = dns_dt_reopen(server->dtenv, backups); 16624 return (result); 16625 #else /* ifdef HAVE_DNSTAP */ 16626 UNUSED(server); 16627 UNUSED(lex); 16628 UNUSED(text); 16629 return (ISC_R_NOTIMPLEMENTED); 16630 #endif /* ifdef HAVE_DNSTAP */ 16631 } 16632 16633 isc_result_t 16634 named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) { 16635 char *ptr; 16636 isc_result_t result = ISC_R_SUCCESS; 16637 uint32_t initial, idle, keepalive, advertised; 16638 char msg[128]; 16639 16640 /* Skip the command name. */ 16641 ptr = next_token(lex, text); 16642 if (ptr == NULL) { 16643 return (ISC_R_UNEXPECTEDEND); 16644 } 16645 16646 isc_nm_gettimeouts(named_g_netmgr, &initial, &idle, &keepalive, 16647 &advertised); 16648 16649 /* Look for optional arguments. */ 16650 ptr = next_token(lex, NULL); 16651 if (ptr != NULL) { 16652 CHECK(isc_parse_uint32(&initial, ptr, 10)); 16653 initial *= 100; 16654 if (initial > MAX_INITIAL_TIMEOUT) { 16655 CHECK(ISC_R_RANGE); 16656 } 16657 if (initial < MIN_INITIAL_TIMEOUT) { 16658 CHECK(ISC_R_RANGE); 16659 } 16660 16661 ptr = next_token(lex, text); 16662 if (ptr == NULL) { 16663 return (ISC_R_UNEXPECTEDEND); 16664 } 16665 CHECK(isc_parse_uint32(&idle, ptr, 10)); 16666 idle *= 100; 16667 if (idle > MAX_IDLE_TIMEOUT) { 16668 CHECK(ISC_R_RANGE); 16669 } 16670 if (idle < MIN_IDLE_TIMEOUT) { 16671 CHECK(ISC_R_RANGE); 16672 } 16673 16674 ptr = next_token(lex, text); 16675 if (ptr == NULL) { 16676 return (ISC_R_UNEXPECTEDEND); 16677 } 16678 CHECK(isc_parse_uint32(&keepalive, ptr, 10)); 16679 keepalive *= 100; 16680 if (keepalive > MAX_KEEPALIVE_TIMEOUT) { 16681 CHECK(ISC_R_RANGE); 16682 } 16683 if (keepalive < MIN_KEEPALIVE_TIMEOUT) { 16684 CHECK(ISC_R_RANGE); 16685 } 16686 16687 ptr = next_token(lex, text); 16688 if (ptr == NULL) { 16689 return (ISC_R_UNEXPECTEDEND); 16690 } 16691 CHECK(isc_parse_uint32(&advertised, ptr, 10)); 16692 advertised *= 100; 16693 if (advertised > MAX_ADVERTISED_TIMEOUT) { 16694 CHECK(ISC_R_RANGE); 16695 } 16696 16697 result = isc_task_beginexclusive(named_g_server->task); 16698 RUNTIME_CHECK(result == ISC_R_SUCCESS); 16699 16700 isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, 16701 advertised); 16702 16703 isc_task_endexclusive(named_g_server->task); 16704 } 16705 16706 snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial / 100); 16707 CHECK(putstr(text, msg)); 16708 snprintf(msg, sizeof(msg), "tcp-idle-timeout=%u\n", idle / 100); 16709 CHECK(putstr(text, msg)); 16710 snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n", 16711 keepalive / 100); 16712 CHECK(putstr(text, msg)); 16713 snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u", 16714 advertised / 100); 16715 CHECK(putstr(text, msg)); 16716 16717 cleanup: 16718 if (isc_buffer_usedlength(*text) > 0) { 16719 (void)putnull(text); 16720 } 16721 16722 return (result); 16723 } 16724 16725 isc_result_t 16726 named_server_servestale(named_server_t *server, isc_lex_t *lex, 16727 isc_buffer_t **text) { 16728 char *ptr, *classtxt, *viewtxt = NULL; 16729 char msg[128]; 16730 dns_rdataclass_t rdclass = dns_rdataclass_in; 16731 dns_view_t *view; 16732 bool found = false; 16733 dns_stale_answer_t staleanswersok = dns_stale_answer_conf; 16734 bool wantstatus = false; 16735 isc_result_t result = ISC_R_SUCCESS; 16736 bool exclusive = false; 16737 16738 REQUIRE(text != NULL); 16739 16740 /* Skip the command name. */ 16741 ptr = next_token(lex, text); 16742 if (ptr == NULL) { 16743 return (ISC_R_UNEXPECTEDEND); 16744 } 16745 16746 ptr = next_token(lex, NULL); 16747 if (ptr == NULL) { 16748 return (ISC_R_UNEXPECTEDEND); 16749 } 16750 16751 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 16752 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 16753 { 16754 staleanswersok = dns_stale_answer_yes; 16755 } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 16756 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 16757 { 16758 staleanswersok = dns_stale_answer_no; 16759 } else if (strcasecmp(ptr, "reset") == 0) { 16760 staleanswersok = dns_stale_answer_conf; 16761 } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { 16762 wantstatus = true; 16763 } else { 16764 return (DNS_R_SYNTAX); 16765 } 16766 16767 /* Look for the optional class name. */ 16768 classtxt = next_token(lex, text); 16769 if (classtxt != NULL) { 16770 isc_textregion_t r; 16771 16772 /* Look for the optional view name. */ 16773 viewtxt = next_token(lex, text); 16774 16775 /* 16776 * If 'classtext' is not a valid class then it us a view name. 16777 */ 16778 r.base = classtxt; 16779 r.length = strlen(classtxt); 16780 result = dns_rdataclass_fromtext(&rdclass, &r); 16781 if (result != ISC_R_SUCCESS) { 16782 if (viewtxt != NULL) { 16783 snprintf(msg, sizeof(msg), "unknown class '%s'", 16784 classtxt); 16785 (void)putstr(text, msg); 16786 goto cleanup; 16787 } 16788 16789 viewtxt = classtxt; 16790 classtxt = NULL; 16791 } 16792 } 16793 16794 result = isc_task_beginexclusive(server->task); 16795 RUNTIME_CHECK(result == ISC_R_SUCCESS); 16796 exclusive = true; 16797 16798 for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; 16799 view = ISC_LIST_NEXT(view, link)) 16800 { 16801 dns_ttl_t stale_ttl = 0; 16802 uint32_t stale_refresh = 0; 16803 dns_db_t *db = NULL; 16804 16805 if (classtxt != NULL && rdclass != view->rdclass) { 16806 continue; 16807 } 16808 16809 if (viewtxt != NULL && strcmp(view->name, viewtxt) != 0) { 16810 continue; 16811 } 16812 16813 if (!wantstatus) { 16814 view->staleanswersok = staleanswersok; 16815 found = true; 16816 continue; 16817 } 16818 16819 db = NULL; 16820 dns_db_attach(view->cachedb, &db); 16821 (void)dns_db_getservestalettl(db, &stale_ttl); 16822 (void)dns_db_getservestalerefresh(db, &stale_refresh); 16823 dns_db_detach(&db); 16824 if (found) { 16825 CHECK(putstr(text, "\n")); 16826 } 16827 CHECK(putstr(text, view->name)); 16828 CHECK(putstr(text, ": ")); 16829 switch (view->staleanswersok) { 16830 case dns_stale_answer_yes: 16831 if (stale_ttl > 0) { 16832 CHECK(putstr(text, "stale cache enabled; stale " 16833 "answers enabled")); 16834 } else { 16835 CHECK(putstr(text, 16836 "stale cache disabled; stale " 16837 "answers unavailable")); 16838 } 16839 break; 16840 case dns_stale_answer_no: 16841 if (stale_ttl > 0) { 16842 CHECK(putstr(text, "stale cache enabled; stale " 16843 "answers disabled")); 16844 } else { 16845 CHECK(putstr(text, 16846 "stale cache disabled; stale " 16847 "answers unavailable")); 16848 } 16849 break; 16850 case dns_stale_answer_conf: 16851 if (view->staleanswersenable && stale_ttl > 0) { 16852 CHECK(putstr(text, "stale cache enabled; stale " 16853 "answers enabled")); 16854 } else if (stale_ttl > 0) { 16855 CHECK(putstr(text, "stale cache enabled; stale " 16856 "answers disabled")); 16857 } else { 16858 CHECK(putstr(text, 16859 "stale cache disabled; stale " 16860 "answers unavailable")); 16861 } 16862 break; 16863 } 16864 if (stale_ttl > 0) { 16865 snprintf(msg, sizeof(msg), 16866 " (stale-answer-ttl=%u max-stale-ttl=%u " 16867 "stale-refresh-time=%u)", 16868 view->staleanswerttl, stale_ttl, 16869 stale_refresh); 16870 CHECK(putstr(text, msg)); 16871 } 16872 found = true; 16873 } 16874 16875 if (!found) { 16876 result = ISC_R_NOTFOUND; 16877 } 16878 16879 cleanup: 16880 if (exclusive) { 16881 isc_task_endexclusive(named_g_server->task); 16882 } 16883 16884 if (isc_buffer_usedlength(*text) > 0) { 16885 (void)putnull(text); 16886 } 16887 16888 return (result); 16889 } 16890