1 /* $NetBSD: nsupdate.c,v 1.16 2025/01/26 16:24:34 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 <errno.h> 20 #include <inttypes.h> 21 #include <limits.h> 22 #include <stdbool.h> 23 #include <stdlib.h> 24 #include <unistd.h> 25 26 #include <isc/async.h> 27 #include <isc/attributes.h> 28 #include <isc/base64.h> 29 #include <isc/buffer.h> 30 #include <isc/commandline.h> 31 #include <isc/file.h> 32 #include <isc/getaddresses.h> 33 #include <isc/hash.h> 34 #include <isc/lex.h> 35 #include <isc/log.h> 36 #include <isc/loop.h> 37 #include <isc/managers.h> 38 #include <isc/mem.h> 39 #include <isc/netmgr.h> 40 #include <isc/nonce.h> 41 #include <isc/parseint.h> 42 #include <isc/portset.h> 43 #include <isc/random.h> 44 #include <isc/region.h> 45 #include <isc/result.h> 46 #include <isc/sockaddr.h> 47 #include <isc/stdio.h> 48 #include <isc/string.h> 49 #include <isc/tls.h> 50 #include <isc/types.h> 51 #include <isc/util.h> 52 53 #include <dns/callbacks.h> 54 #include <dns/dispatch.h> 55 #include <dns/dnssec.h> 56 #include <dns/fixedname.h> 57 #include <dns/log.h> 58 #include <dns/masterdump.h> 59 #include <dns/message.h> 60 #include <dns/name.h> 61 #include <dns/nsec3.h> 62 #include <dns/rcode.h> 63 #include <dns/rdata.h> 64 #include <dns/rdataclass.h> 65 #include <dns/rdatalist.h> 66 #include <dns/rdataset.h> 67 #include <dns/rdatastruct.h> 68 #include <dns/rdatatype.h> 69 #include <dns/request.h> 70 #include <dns/tkey.h> 71 #include <dns/transport.h> 72 #include <dns/tsig.h> 73 74 #include <dst/dst.h> 75 76 #include <isccfg/namedconf.h> 77 78 #include <irs/resconf.h> 79 80 #if HAVE_GSSAPI 81 #include <dst/gssapi.h> 82 83 #if HAVE_KRB5_KRB5_H 84 #include <krb5/krb5.h> 85 #elif HAVE_KRB5_H 86 #include <krb5.h> 87 #endif 88 89 #if HAVE_GSSAPI_GSSAPI_H 90 #include <gssapi/gssapi.h> 91 #elif HAVE_GSSAPI_H 92 #include <gssapi.h> 93 #endif 94 95 #endif /* HAVE_GSSAPI */ 96 97 #include "../dig/readline.h" 98 99 #define MAXCMD (128 * 1024) 100 #define MAXWIRE (64 * 1024) 101 #define INITTEXT (2 * 1024) 102 #define MAXTEXT (128 * 1024) 103 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */ 104 105 #define DNSDEFAULTPORT 53 106 107 #define DEFAULT_EDNS_BUFSIZE 1232 108 109 /* Number of addresses to request from isc_getaddresses() */ 110 #define MAX_SERVERADDRS 4 111 112 static uint16_t dnsport = DNSDEFAULTPORT; 113 114 #ifndef RESOLV_CONF 115 #define RESOLV_CONF "/etc/resolv.conf" 116 #endif /* ifndef RESOLV_CONF */ 117 118 static bool debugging = false, ddebugging = false; 119 static bool memdebugging = false; 120 static bool have_ipv4 = false; 121 static bool have_ipv6 = false; 122 static bool is_dst_up = false; 123 static bool use_tls = false; 124 static bool usevc = false; 125 static bool usegsstsig = false; 126 static bool local_only = false; 127 static isc_nm_t *netmgr = NULL; 128 static isc_loopmgr_t *loopmgr = NULL; 129 static isc_log_t *glctx = NULL; 130 static isc_mem_t *gmctx = NULL; 131 static dns_dispatchmgr_t *dispatchmgr = NULL; 132 static dns_requestmgr_t *requestmgr = NULL; 133 static dns_dispatch_t *dispatchv4 = NULL; 134 static dns_dispatch_t *dispatchv6 = NULL; 135 static dns_message_t *updatemsg = NULL; 136 static dns_fixedname_t fuserzone; 137 static dns_fixedname_t fzname; 138 static dns_name_t *userzone = NULL; 139 static dns_name_t *zname = NULL; 140 static dns_name_t tmpzonename = DNS_NAME_INITEMPTY; 141 static dns_name_t restart_primary = DNS_NAME_INITEMPTY; 142 static dns_tsigkeyring_t *gssring = NULL; 143 static dns_tsigkey_t *tsigkey = NULL; 144 static dst_key_t *sig0key = NULL; 145 static isc_sockaddr_t *servers = NULL; 146 static isc_sockaddr_t *primary_servers = NULL; 147 static dns_transport_list_t *transport_list = NULL; 148 static dns_transport_t *transport = NULL; 149 static isc_tlsctx_cache_t *tls_ctx_cache = NULL; 150 static char *tls_hostname = NULL; 151 static char *tls_client_key_file = NULL; 152 static char *tls_client_cert_file = NULL; 153 static char *tls_ca_file = NULL; 154 static bool tls_always_verify_remote = true; 155 static bool default_servers = true; 156 static int ns_inuse = 0; 157 static int primary_inuse = 0; 158 static int ns_total = 0; 159 static int ns_alloc = 0; 160 static int primary_total = 0; 161 static int primary_alloc = 0; 162 static isc_sockaddr_t *localaddr4 = NULL; 163 static isc_sockaddr_t *localaddr6 = NULL; 164 static const char *keyfile = NULL; 165 static char *keystr = NULL; 166 static bool shuttingdown = false; 167 static FILE *input; 168 static bool interactive = true; 169 static bool seenerror = false; 170 static const dns_master_style_t *style; 171 static int requests = 0; 172 static unsigned int logdebuglevel = 0; 173 static unsigned int timeout = 300; 174 static unsigned int udp_timeout = 3; 175 static unsigned int udp_retries = 3; 176 static dns_rdataclass_t defaultclass = dns_rdataclass_in; 177 static dns_rdataclass_t zoneclass = dns_rdataclass_none; 178 static isc_mutex_t answer_lock; 179 static dns_message_t *answer = NULL; 180 static uint32_t default_ttl = 0; 181 static bool default_ttl_set = false; 182 static uint32_t lease = 0, keylease = 0; 183 static bool lease_set = false, keylease_set = false; 184 static bool checknames = true; 185 static bool checksvcb = true; 186 static const char *resolvconf = RESOLV_CONF; 187 188 bool done = false; 189 190 typedef struct nsu_requestinfo { 191 dns_message_t *msg; 192 isc_sockaddr_t *addr; 193 } nsu_requestinfo_t; 194 195 static void 196 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, 197 dns_request_t **request); 198 static void 199 send_update(dns_name_t *zonename, isc_sockaddr_t *primary); 200 201 static void 202 getinput(void *arg); 203 204 noreturn static void 205 fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 206 207 static void 208 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 209 210 static void 211 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 212 213 #if HAVE_GSSAPI 214 static dns_fixedname_t fkname; 215 static isc_sockaddr_t *kserver = NULL; 216 static char *realm = NULL; 217 static char servicename[DNS_NAME_FORMATSIZE]; 218 static dns_name_t *keyname; 219 typedef struct nsu_gssinfo { 220 dns_message_t *msg; 221 isc_sockaddr_t *addr; 222 gss_ctx_id_t context; 223 } nsu_gssinfo_t; 224 225 static void 226 failed_gssrequest(void); 227 static void 228 start_gssrequest(dns_name_t *primary); 229 static void 230 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, 231 dns_request_t **request, gss_ctx_id_t context); 232 static void 233 recvgss(void *arg); 234 #endif /* HAVE_GSSAPI */ 235 236 static void 237 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 238 239 #define STATUS_MORE (uint16_t)0 240 #define STATUS_SEND (uint16_t)1 241 #define STATUS_QUIT (uint16_t)2 242 #define STATUS_SYNTAX (uint16_t)3 243 244 static void 245 primary_from_servers(void) { 246 if (primary_servers != NULL && primary_servers != servers) { 247 isc_mem_cput(gmctx, primary_servers, primary_alloc, 248 sizeof(isc_sockaddr_t)); 249 } 250 primary_servers = servers; 251 primary_total = ns_total; 252 primary_alloc = ns_alloc; 253 primary_inuse = ns_inuse; 254 } 255 256 static dns_rdataclass_t 257 getzoneclass(void) { 258 if (zoneclass == dns_rdataclass_none) { 259 zoneclass = defaultclass; 260 } 261 return zoneclass; 262 } 263 264 static bool 265 setzoneclass(dns_rdataclass_t rdclass) { 266 if (zoneclass == dns_rdataclass_none || rdclass == dns_rdataclass_none) 267 { 268 zoneclass = rdclass; 269 } 270 if (zoneclass != rdclass) { 271 return false; 272 } 273 return true; 274 } 275 276 static void 277 fatal(const char *format, ...) { 278 va_list args; 279 280 va_start(args, format); 281 vfprintf(stderr, format, args); 282 va_end(args); 283 fprintf(stderr, "\n"); 284 _exit(EXIT_FAILURE); 285 } 286 287 static void 288 error(const char *format, ...) { 289 va_list args; 290 291 va_start(args, format); 292 vfprintf(stderr, format, args); 293 va_end(args); 294 fprintf(stderr, "\n"); 295 } 296 297 static void 298 debug(const char *format, ...) { 299 va_list args; 300 301 if (debugging) { 302 va_start(args, format); 303 vfprintf(stderr, format, args); 304 va_end(args); 305 fprintf(stderr, "\n"); 306 } 307 } 308 309 static void 310 ddebug(const char *format, ...) { 311 va_list args; 312 313 if (ddebugging) { 314 va_start(args, format); 315 vfprintf(stderr, format, args); 316 va_end(args); 317 fprintf(stderr, "\n"); 318 } 319 } 320 321 ISC_NO_SANITIZE_ADDRESS static void 322 check_result(isc_result_t result, const char *msg) { 323 if (result != ISC_R_SUCCESS) { 324 fatal("%s: %s", msg, isc_result_totext(result)); 325 } 326 } 327 328 static char * 329 nsu_strsep(char **stringp, const char *delim) { 330 char *string = *stringp; 331 *stringp = NULL; 332 char *s; 333 const char *d; 334 char sc, dc; 335 336 if (string == NULL) { 337 return NULL; 338 } 339 340 for (; *string != '\0'; string++) { 341 sc = *string; 342 for (d = delim; (dc = *d) != '\0'; d++) { 343 if (sc == dc) { 344 break; 345 } 346 } 347 if (dc == 0) { 348 break; 349 } 350 } 351 352 for (s = string; *s != '\0'; s++) { 353 sc = *s; 354 for (d = delim; (dc = *d) != '\0'; d++) { 355 if (sc == dc) { 356 *s++ = '\0'; 357 *stringp = s; 358 return string; 359 } 360 } 361 } 362 return string; 363 } 364 365 static void 366 reset_system(void) { 367 ddebug("reset_system()"); 368 /* If the update message is still around, destroy it */ 369 if (updatemsg != NULL) { 370 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER); 371 } else { 372 dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, 373 &updatemsg); 374 } 375 updatemsg->opcode = dns_opcode_update; 376 if (usegsstsig) { 377 if (tsigkey != NULL) { 378 dns_tsigkey_detach(&tsigkey); 379 } 380 if (gssring != NULL) { 381 dns_tsigkeyring_detach(&gssring); 382 } 383 } 384 } 385 386 static bool 387 parse_hmac(const char *hmacstr, size_t len, dst_algorithm_t *hmac_alg, 388 uint16_t *digestbitsp) { 389 uint16_t digestbits = 0; 390 isc_result_t result; 391 char buf[20]; 392 393 REQUIRE(hmac_alg != NULL); 394 REQUIRE(hmacstr != NULL); 395 396 if (len >= sizeof(buf)) { 397 error("unknown key type '%.*s'", (int)(len), hmacstr); 398 return false; 399 } 400 401 /* Copy len bytes and NUL terminate. */ 402 strlcpy(buf, hmacstr, ISC_MIN(len + 1, sizeof(buf))); 403 404 if (strcasecmp(buf, "hmac-md5") == 0) { 405 *hmac_alg = DST_ALG_HMACMD5; 406 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { 407 *hmac_alg = DST_ALG_HMACMD5; 408 result = isc_parse_uint16(&digestbits, &buf[9], 10); 409 if (result != ISC_R_SUCCESS || digestbits > 128) { 410 error("digest-bits out of range [0..128]"); 411 return false; 412 } 413 *digestbitsp = (digestbits + 7) & ~0x7U; 414 } else if (strcasecmp(buf, "hmac-sha1") == 0) { 415 *hmac_alg = DST_ALG_HMACSHA1; 416 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { 417 *hmac_alg = DST_ALG_HMACSHA1; 418 result = isc_parse_uint16(&digestbits, &buf[10], 10); 419 if (result != ISC_R_SUCCESS || digestbits > 160) { 420 error("digest-bits out of range [0..160]"); 421 return false; 422 } 423 *digestbitsp = (digestbits + 7) & ~0x7U; 424 } else if (strcasecmp(buf, "hmac-sha224") == 0) { 425 *hmac_alg = DST_ALG_HMACSHA224; 426 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { 427 *hmac_alg = DST_ALG_HMACSHA224; 428 result = isc_parse_uint16(&digestbits, &buf[12], 10); 429 if (result != ISC_R_SUCCESS || digestbits > 224) { 430 error("digest-bits out of range [0..224]"); 431 return false; 432 } 433 *digestbitsp = (digestbits + 7) & ~0x7U; 434 } else if (strcasecmp(buf, "hmac-sha256") == 0) { 435 *hmac_alg = DST_ALG_HMACSHA256; 436 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { 437 *hmac_alg = DST_ALG_HMACSHA256; 438 result = isc_parse_uint16(&digestbits, &buf[12], 10); 439 if (result != ISC_R_SUCCESS || digestbits > 256) { 440 error("digest-bits out of range [0..256]"); 441 return false; 442 } 443 *digestbitsp = (digestbits + 7) & ~0x7U; 444 } else if (strcasecmp(buf, "hmac-sha384") == 0) { 445 *hmac_alg = DST_ALG_HMACSHA384; 446 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { 447 *hmac_alg = DST_ALG_HMACSHA384; 448 result = isc_parse_uint16(&digestbits, &buf[12], 10); 449 if (result != ISC_R_SUCCESS || digestbits > 384) { 450 error("digest-bits out of range [0..384]"); 451 return false; 452 } 453 *digestbitsp = (digestbits + 7) & ~0x7U; 454 } else if (strcasecmp(buf, "hmac-sha512") == 0) { 455 *hmac_alg = DST_ALG_HMACSHA512; 456 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { 457 *hmac_alg = DST_ALG_HMACSHA512; 458 result = isc_parse_uint16(&digestbits, &buf[12], 10); 459 if (result != ISC_R_SUCCESS || digestbits > 512) { 460 error("digest-bits out of range [0..512]"); 461 return false; 462 } 463 *digestbitsp = (digestbits + 7) & ~0x7U; 464 } else { 465 error("unknown key type '%s'", buf); 466 return false; 467 } 468 return true; 469 } 470 471 static int 472 basenamelen(const char *file) { 473 int len = strlen(file); 474 475 if (len > 1 && file[len - 1] == '.') { 476 len -= 1; 477 } else if (len > 8 && strcmp(file + len - 8, ".private") == 0) { 478 len -= 8; 479 } else if (len > 4 && strcmp(file + len - 4, ".key") == 0) { 480 len -= 4; 481 } 482 return len; 483 } 484 485 static void 486 setup_keystr(void) { 487 unsigned char *secret = NULL; 488 int secretlen; 489 isc_buffer_t secretbuf; 490 isc_result_t result; 491 isc_buffer_t keynamesrc; 492 char *secretstr = NULL; 493 char *s = NULL, *n = NULL; 494 dns_fixedname_t fkeyname; 495 dns_name_t *mykeyname = NULL; 496 char *name = NULL; 497 dst_algorithm_t hmac_alg; 498 uint16_t digestbits = 0; 499 500 mykeyname = dns_fixedname_initname(&fkeyname); 501 502 debug("Creating key..."); 503 504 s = strchr(keystr, ':'); 505 if (s == NULL || s == keystr || s[1] == 0) { 506 fatal("key option must specify [hmac:]keyname:secret"); 507 } 508 secretstr = s + 1; 509 n = strchr(secretstr, ':'); 510 if (n != NULL) { 511 if (n == secretstr || n[1] == 0) { 512 fatal("key option must specify [hmac:]keyname:secret"); 513 } 514 name = secretstr; 515 secretstr = n + 1; 516 if (!parse_hmac(keystr, s - keystr, &hmac_alg, &digestbits)) { 517 exit(EXIT_FAILURE); 518 } 519 } else { 520 hmac_alg = DST_ALG_HMACMD5; 521 name = keystr; 522 n = s; 523 } 524 525 isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name)); 526 isc_buffer_add(&keynamesrc, (unsigned int)(n - name)); 527 528 debug("namefromtext"); 529 result = dns_name_fromtext(mykeyname, &keynamesrc, dns_rootname, 0, 530 NULL); 531 check_result(result, "dns_name_fromtext"); 532 533 secretlen = strlen(secretstr) * 3 / 4; 534 secret = isc_mem_allocate(gmctx, secretlen); 535 536 isc_buffer_init(&secretbuf, secret, secretlen); 537 result = isc_base64_decodestring(secretstr, &secretbuf); 538 if (result != ISC_R_SUCCESS) { 539 fprintf(stderr, "could not create key from %s: %s\n", keystr, 540 isc_result_totext(result)); 541 goto failure; 542 } 543 544 secretlen = isc_buffer_usedlength(&secretbuf); 545 546 debug("keycreate"); 547 result = dns_tsigkey_create(mykeyname, hmac_alg, secret, secretlen, 548 gmctx, &tsigkey); 549 if (result != ISC_R_SUCCESS) { 550 fprintf(stderr, "could not create key from %s: %s\n", keystr, 551 isc_result_totext(result)); 552 } else { 553 dst_key_setbits(tsigkey->key, digestbits); 554 } 555 failure: 556 if (secret != NULL) { 557 isc_mem_free(gmctx, secret); 558 } 559 } 560 561 /* 562 * Get a key from a named.conf format keyfile 563 */ 564 static isc_result_t 565 read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) { 566 cfg_parser_t *pctx = NULL; 567 cfg_obj_t *sessionkey = NULL; 568 const cfg_obj_t *key = NULL; 569 const cfg_obj_t *secretobj = NULL; 570 const cfg_obj_t *algorithmobj = NULL; 571 const char *mykeyname; 572 const char *secretstr; 573 const char *algorithm; 574 isc_result_t result; 575 int len; 576 577 if (!isc_file_exists(keyfile)) { 578 return ISC_R_FILENOTFOUND; 579 } 580 581 result = cfg_parser_create(mctx, lctx, &pctx); 582 if (result != ISC_R_SUCCESS) { 583 goto cleanup; 584 } 585 586 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, 587 &sessionkey); 588 if (result != ISC_R_SUCCESS) { 589 goto cleanup; 590 } 591 592 result = cfg_map_get(sessionkey, "key", &key); 593 if (result != ISC_R_SUCCESS) { 594 goto cleanup; 595 } 596 597 (void)cfg_map_get(key, "secret", &secretobj); 598 (void)cfg_map_get(key, "algorithm", &algorithmobj); 599 if (secretobj == NULL || algorithmobj == NULL) { 600 fatal("key must have algorithm and secret"); 601 } 602 603 mykeyname = cfg_obj_asstring(cfg_map_getname(key)); 604 secretstr = cfg_obj_asstring(secretobj); 605 algorithm = cfg_obj_asstring(algorithmobj); 606 607 len = strlen(algorithm) + strlen(mykeyname) + strlen(secretstr) + 3; 608 keystr = isc_mem_allocate(mctx, len); 609 snprintf(keystr, len, "%s:%s:%s", algorithm, mykeyname, secretstr); 610 setup_keystr(); 611 612 cleanup: 613 if (pctx != NULL) { 614 if (sessionkey != NULL) { 615 cfg_obj_destroy(pctx, &sessionkey); 616 } 617 cfg_parser_destroy(&pctx); 618 } 619 620 if (keystr != NULL) { 621 isc_mem_free(mctx, keystr); 622 } 623 624 return result; 625 } 626 627 static void 628 setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { 629 dst_key_t *dstkey = NULL; 630 isc_result_t result; 631 dst_algorithm_t hmac_alg = DST_ALG_UNKNOWN; 632 633 debug("Creating key..."); 634 635 if (sig0key != NULL) { 636 dst_key_free(&sig0key); 637 } 638 639 /* Try reading the key from a K* pair */ 640 result = dst_key_fromnamedfile( 641 keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); 642 643 /* If that didn't work, try reading it as a session.key keyfile */ 644 if (result != ISC_R_SUCCESS) { 645 result = read_sessionkey(mctx, lctx); 646 if (result == ISC_R_SUCCESS) { 647 return; 648 } 649 } 650 651 if (result != ISC_R_SUCCESS) { 652 fprintf(stderr, 653 "could not read key from %.*s.{private,key}: " 654 "%s\n", 655 basenamelen(keyfile), keyfile, 656 isc_result_totext(result)); 657 return; 658 } 659 660 switch (dst_key_alg(dstkey)) { 661 case DST_ALG_HMACMD5: 662 case DST_ALG_HMACSHA1: 663 case DST_ALG_HMACSHA224: 664 case DST_ALG_HMACSHA256: 665 case DST_ALG_HMACSHA384: 666 case DST_ALG_HMACSHA512: 667 hmac_alg = dst_key_alg(dstkey); 668 break; 669 default: 670 dst_key_attach(dstkey, &sig0key); 671 dst_key_free(&dstkey); 672 return; 673 } 674 675 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmac_alg, 676 dstkey, false, false, NULL, 0, 0, 677 mctx, &tsigkey); 678 dst_key_free(&dstkey); 679 if (result != ISC_R_SUCCESS) { 680 fprintf(stderr, "could not create key from %s: %s\n", keyfile, 681 isc_result_totext(result)); 682 } 683 } 684 685 static void 686 doshutdown(void) { 687 /* 688 * The isc_mem_put of primary_servers must be before the 689 * isc_mem_put of servers as it sets the servers pointer 690 * to NULL. 691 */ 692 if (primary_servers != NULL && primary_servers != servers) { 693 isc_mem_cput(gmctx, primary_servers, primary_alloc, 694 sizeof(isc_sockaddr_t)); 695 } 696 697 if (servers != NULL) { 698 isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t)); 699 } 700 701 if (localaddr4 != NULL) { 702 isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t)); 703 } 704 705 if (localaddr6 != NULL) { 706 isc_mem_put(gmctx, localaddr6, sizeof(isc_sockaddr_t)); 707 } 708 709 if (tsigkey != NULL) { 710 ddebug("Freeing TSIG key"); 711 dns_tsigkey_detach(&tsigkey); 712 } 713 714 if (sig0key != NULL) { 715 ddebug("Freeing SIG(0) key"); 716 dst_key_free(&sig0key); 717 } 718 719 if (updatemsg != NULL) { 720 dns_message_detach(&updatemsg); 721 } 722 723 ddebug("Destroying request manager"); 724 dns_requestmgr_detach(&requestmgr); 725 726 ddebug("Freeing the dispatchers"); 727 if (have_ipv4) { 728 dns_dispatch_detach(&dispatchv4); 729 } 730 if (have_ipv6) { 731 dns_dispatch_detach(&dispatchv6); 732 } 733 734 ddebug("Shutting down dispatch manager"); 735 dns_dispatchmgr_detach(&dispatchmgr); 736 } 737 738 static void 739 maybeshutdown(void) { 740 /* when called from getinput, doshutdown might be already finished */ 741 if (requestmgr == NULL) { 742 return; 743 } 744 745 ddebug("Shutting down request manager"); 746 dns_requestmgr_shutdown(requestmgr); 747 748 if (requests != 0) { 749 return; 750 } 751 752 doshutdown(); 753 } 754 755 static void 756 shutdown_program(void *arg) { 757 UNUSED(arg); 758 759 ddebug("shutdown_program()"); 760 761 shuttingdown = true; 762 maybeshutdown(); 763 } 764 765 /* 766 * Try honoring the operating system's preferred ephemeral port range. 767 */ 768 static void 769 set_source_ports(dns_dispatchmgr_t *manager) { 770 isc_portset_t *v4portset = NULL, *v6portset = NULL; 771 in_port_t udpport_low, udpport_high; 772 isc_result_t result; 773 774 result = isc_portset_create(gmctx, &v4portset); 775 check_result(result, "isc_portset_create (v4)"); 776 result = isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high); 777 check_result(result, "isc_net_getudpportrange (v4)"); 778 isc_portset_addrange(v4portset, udpport_low, udpport_high); 779 780 result = isc_portset_create(gmctx, &v6portset); 781 check_result(result, "isc_portset_create (v6)"); 782 result = isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high); 783 check_result(result, "isc_net_getudpportrange (v6)"); 784 isc_portset_addrange(v6portset, udpport_low, udpport_high); 785 786 result = dns_dispatchmgr_setavailports(manager, v4portset, v6portset); 787 check_result(result, "dns_dispatchmgr_setavailports"); 788 789 isc_portset_destroy(gmctx, &v4portset); 790 isc_portset_destroy(gmctx, &v6portset); 791 } 792 793 static isc_result_t 794 create_name(const char *str, char *namedata, size_t len, dns_name_t *name) { 795 isc_buffer_t namesrc, namebuf; 796 797 dns_name_init(name, NULL); 798 isc_buffer_constinit(&namesrc, str, strlen(str)); 799 isc_buffer_add(&namesrc, strlen(str)); 800 isc_buffer_init(&namebuf, namedata, len); 801 802 return dns_name_fromtext(name, &namesrc, dns_rootname, 803 DNS_NAME_DOWNCASE, &namebuf); 804 } 805 806 static void 807 setup_system(void *arg ISC_ATTR_UNUSED) { 808 isc_result_t result; 809 isc_sockaddr_t bind_any, bind_any6; 810 isc_sockaddrlist_t *nslist; 811 isc_logconfig_t *logconfig = NULL; 812 irs_resconf_t *resconf = NULL; 813 dns_name_t tlsname; 814 char namedata[DNS_NAME_FORMATSIZE + 1]; 815 816 ddebug("setup_system()"); 817 818 isc_log_create(gmctx, &glctx, &logconfig); 819 isc_log_setcontext(glctx); 820 dns_log_init(glctx); 821 dns_log_setcontext(glctx); 822 823 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); 824 check_result(result, "isc_log_usechannel"); 825 826 isc_log_setdebuglevel(glctx, logdebuglevel); 827 828 result = irs_resconf_load(gmctx, resolvconf, &resconf); 829 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { 830 fatal("parse of %s failed", resolvconf); 831 } 832 833 nslist = irs_resconf_getnameservers(resconf); 834 835 if (servers != NULL) { 836 if (primary_servers == servers) { 837 primary_servers = NULL; 838 } 839 isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t)); 840 } 841 842 ns_inuse = 0; 843 if (local_only || ISC_LIST_EMPTY(*nslist)) { 844 struct in_addr in; 845 struct in6_addr in6; 846 847 if (local_only && keyfile == NULL) { 848 keyfile = SESSION_KEYFILE; 849 } 850 851 default_servers = !local_only; 852 853 ns_total = ns_alloc = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0); 854 servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t)); 855 856 if (have_ipv6) { 857 memset(&in6, 0, sizeof(in6)); 858 in6.s6_addr[15] = 1; 859 isc_sockaddr_fromin6(&servers[0], &in6, dnsport); 860 } 861 if (have_ipv4) { 862 in.s_addr = htonl(INADDR_LOOPBACK); 863 isc_sockaddr_fromin(&servers[(have_ipv6 ? 1 : 0)], &in, 864 dnsport); 865 } 866 } else { 867 isc_sockaddr_t *sa; 868 int i; 869 870 /* 871 * Count the nameservers (skipping any that we can't use 872 * because of address family restrictions) and allocate 873 * the servers array. 874 */ 875 ns_total = 0; 876 for (sa = ISC_LIST_HEAD(*nslist); sa != NULL; 877 sa = ISC_LIST_NEXT(sa, link)) 878 { 879 switch (sa->type.sa.sa_family) { 880 case AF_INET: 881 if (have_ipv4) { 882 ns_total++; 883 } 884 break; 885 case AF_INET6: 886 if (have_ipv6) { 887 ns_total++; 888 } 889 break; 890 default: 891 fatal("bad family"); 892 } 893 } 894 895 ns_alloc = ns_total; 896 servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t)); 897 898 i = 0; 899 for (sa = ISC_LIST_HEAD(*nslist); sa != NULL; 900 sa = ISC_LIST_NEXT(sa, link)) 901 { 902 switch (sa->type.sa.sa_family) { 903 case AF_INET: 904 if (have_ipv4) { 905 sa->type.sin.sin_port = htons(dnsport); 906 } else { 907 continue; 908 } 909 break; 910 case AF_INET6: 911 if (have_ipv6) { 912 sa->type.sin6.sin6_port = 913 htons(dnsport); 914 } else { 915 continue; 916 } 917 break; 918 default: 919 fatal("bad family"); 920 } 921 INSIST(i < ns_alloc); 922 servers[i++] = *sa; 923 } 924 } 925 926 irs_resconf_destroy(&resconf); 927 928 result = dns_dispatchmgr_create(gmctx, loopmgr, netmgr, &dispatchmgr); 929 check_result(result, "dns_dispatchmgr_create"); 930 931 result = dst_lib_init(gmctx, NULL); 932 check_result(result, "dst_lib_init"); 933 is_dst_up = true; 934 935 set_source_ports(dispatchmgr); 936 937 if (have_ipv6) { 938 isc_sockaddr_any6(&bind_any6); 939 result = dns_dispatch_createudp(dispatchmgr, &bind_any6, 940 &dispatchv6); 941 check_result(result, "dns_dispatch_createudp (v6)"); 942 } 943 944 if (have_ipv4) { 945 isc_sockaddr_any(&bind_any); 946 result = dns_dispatch_createudp(dispatchmgr, &bind_any, 947 &dispatchv4); 948 check_result(result, "dns_dispatch_createudp (v4)"); 949 } 950 transport_list = dns_transport_list_new(gmctx); 951 952 isc_tlsctx_cache_create(gmctx, &tls_ctx_cache); 953 954 if (tls_client_key_file == NULL) { 955 result = create_name("tls-non-auth-client", namedata, 956 sizeof(namedata), &tlsname); 957 check_result(result, "create_name (tls-non-auth-client)"); 958 transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, 959 transport_list); 960 dns_transport_set_tlsname(transport, "tls-non-auth-client"); 961 } else { 962 result = create_name("tls-auth-client", namedata, 963 sizeof(namedata), &tlsname); 964 check_result(result, "create_name (tls-auth-client)"); 965 transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, 966 transport_list); 967 dns_transport_set_tlsname(transport, "tls-auth-client"); 968 dns_transport_set_keyfile(transport, tls_client_key_file); 969 dns_transport_set_certfile(transport, tls_client_cert_file); 970 } 971 dns_transport_set_cafile(transport, tls_ca_file); 972 dns_transport_set_remote_hostname(transport, tls_hostname); 973 dns_transport_set_always_verify_remote(transport, 974 tls_always_verify_remote); 975 976 result = dns_requestmgr_create(gmctx, loopmgr, dispatchmgr, dispatchv4, 977 dispatchv6, &requestmgr); 978 check_result(result, "dns_requestmgr_create"); 979 980 if (keystr != NULL) { 981 setup_keystr(); 982 } else if (local_only) { 983 result = read_sessionkey(gmctx, glctx); 984 if (result != ISC_R_SUCCESS) { 985 fatal("can't read key from %s: %s\n", keyfile, 986 isc_result_totext(result)); 987 } 988 } else if (keyfile != NULL) { 989 setup_keyfile(gmctx, glctx); 990 } 991 992 isc_mutex_init(&answer_lock); 993 } 994 995 static int 996 get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr, 997 int naddrs) { 998 int count = 0; 999 isc_result_t result; 1000 1001 isc_loopmgr_blocking(loopmgr); 1002 result = isc_getaddresses(host, port, sockaddr, naddrs, &count); 1003 isc_loopmgr_nonblocking(loopmgr); 1004 if (result != ISC_R_SUCCESS) { 1005 error("couldn't get address for '%s': %s", host, 1006 isc_result_totext(result)); 1007 } 1008 return count; 1009 } 1010 1011 #define PARSE_ARGS_FMT "46A:C:dDE:ghH:iK:lL:MoOk:p:Pr:R:St:Tu:vVy:" 1012 1013 static void 1014 pre_parse_args(int argc, char **argv) { 1015 dns_rdatatype_t t; 1016 int ch; 1017 char buf[100]; 1018 bool doexit = false; 1019 bool ipv4only = false, ipv6only = false; 1020 1021 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) { 1022 switch (ch) { 1023 case 'M': /* was -dm */ 1024 debugging = true; 1025 ddebugging = true; 1026 memdebugging = true; 1027 isc_mem_debugging = ISC_MEM_DEBUGTRACE | 1028 ISC_MEM_DEBUGRECORD; 1029 break; 1030 1031 case '4': 1032 if (ipv6only) { 1033 fatal("only one of -4 and -6 allowed"); 1034 } 1035 ipv4only = true; 1036 break; 1037 1038 case '6': 1039 if (ipv4only) { 1040 fatal("only one of -4 and -6 allowed"); 1041 } 1042 ipv6only = true; 1043 break; 1044 1045 case '?': 1046 case 'h': 1047 if (isc_commandline_option != '?') { 1048 fprintf(stderr, "%s: invalid argument -%c\n", 1049 argv[0], isc_commandline_option); 1050 } 1051 fprintf(stderr, "usage: nsupdate [-CdDi] [-L level] " 1052 "[-l] [-g | -o | -y keyname:secret " 1053 "| -k keyfile] [-p port] " 1054 "[ -S [-K tlskeyfile] [-E tlscertfile] " 1055 "[-A tlscafile] [-H tlshostname] " 1056 "[-O] ] [-v] [-V] [-P] [-T] [-4 | -6] " 1057 "[filename]\n"); 1058 exit(EXIT_FAILURE); 1059 1060 case 'P': 1061 for (t = 0xff00; t <= 0xfffe; t++) { 1062 if (dns_rdatatype_ismeta(t)) { 1063 continue; 1064 } 1065 dns_rdatatype_format(t, buf, sizeof(buf)); 1066 if (strncmp(buf, "TYPE", 4) != 0) { 1067 fprintf(stdout, "%s\n", buf); 1068 } 1069 } 1070 doexit = true; 1071 break; 1072 1073 case 'T': 1074 for (t = 1; t <= 0xfeff; t++) { 1075 if (dns_rdatatype_ismeta(t)) { 1076 continue; 1077 } 1078 dns_rdatatype_format(t, buf, sizeof(buf)); 1079 if (strncmp(buf, "TYPE", 4) != 0) { 1080 fprintf(stdout, "%s\n", buf); 1081 } 1082 } 1083 doexit = true; 1084 break; 1085 1086 case 'V': 1087 printf("nsupdate %s\n", PACKAGE_VERSION); 1088 doexit = true; 1089 break; 1090 1091 default: 1092 break; 1093 } 1094 } 1095 if (doexit) { 1096 exit(EXIT_SUCCESS); 1097 } 1098 isc_commandline_reset = true; 1099 isc_commandline_index = 1; 1100 } 1101 1102 static void 1103 parse_args(int argc, char **argv) { 1104 int ch; 1105 uint32_t i; 1106 isc_result_t result; 1107 bool force_interactive = false; 1108 1109 debug("parse_args"); 1110 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) { 1111 switch (ch) { 1112 case '4': 1113 if (have_ipv4) { 1114 isc_net_disableipv6(); 1115 have_ipv6 = false; 1116 } else { 1117 fatal("can't find IPv4 networking"); 1118 } 1119 break; 1120 case '6': 1121 if (have_ipv6) { 1122 isc_net_disableipv4(); 1123 have_ipv4 = false; 1124 } else { 1125 fatal("can't find IPv6 networking"); 1126 } 1127 break; 1128 case 'A': 1129 use_tls = true; 1130 tls_ca_file = isc_commandline_argument; 1131 break; 1132 case 'C': 1133 resolvconf = isc_commandline_argument; 1134 break; 1135 case 'd': 1136 debugging = true; 1137 break; 1138 case 'D': /* was -dd */ 1139 debugging = true; 1140 ddebugging = true; 1141 break; 1142 case 'E': 1143 use_tls = true; 1144 tls_client_cert_file = isc_commandline_argument; 1145 break; 1146 case 'H': 1147 use_tls = true; 1148 tls_hostname = isc_commandline_argument; 1149 break; 1150 case 'M': 1151 break; 1152 case 'i': 1153 force_interactive = true; 1154 interactive = true; 1155 break; 1156 case 'K': 1157 use_tls = true; 1158 tls_client_key_file = isc_commandline_argument; 1159 break; 1160 case 'l': 1161 local_only = true; 1162 break; 1163 case 'L': 1164 result = isc_parse_uint32(&i, isc_commandline_argument, 1165 10); 1166 if (result != ISC_R_SUCCESS) { 1167 fprintf(stderr, 1168 "bad library debug value " 1169 "'%s'\n", 1170 isc_commandline_argument); 1171 exit(EXIT_FAILURE); 1172 } 1173 logdebuglevel = i; 1174 break; 1175 case 'y': 1176 keystr = isc_commandline_argument; 1177 break; 1178 case 'v': 1179 usevc = true; 1180 break; 1181 case 'k': 1182 keyfile = isc_commandline_argument; 1183 break; 1184 case 'g': 1185 usegsstsig = true; 1186 break; 1187 case 'o': 1188 usegsstsig = true; 1189 break; 1190 case 'O': 1191 use_tls = true; 1192 tls_always_verify_remote = false; 1193 break; 1194 case 'p': 1195 result = isc_parse_uint16(&dnsport, 1196 isc_commandline_argument, 10); 1197 if (result != ISC_R_SUCCESS) { 1198 fprintf(stderr, 1199 "bad port number " 1200 "'%s'\n", 1201 isc_commandline_argument); 1202 exit(EXIT_FAILURE); 1203 } 1204 break; 1205 case 'S': 1206 use_tls = true; 1207 break; 1208 case 't': 1209 result = isc_parse_uint32(&timeout, 1210 isc_commandline_argument, 10); 1211 if (result != ISC_R_SUCCESS) { 1212 fprintf(stderr, "bad timeout '%s'\n", 1213 isc_commandline_argument); 1214 exit(EXIT_FAILURE); 1215 } 1216 if (timeout == 0) { 1217 timeout = UINT_MAX; 1218 } 1219 break; 1220 case 'u': 1221 result = isc_parse_uint32(&udp_timeout, 1222 isc_commandline_argument, 10); 1223 if (result != ISC_R_SUCCESS) { 1224 fprintf(stderr, "bad udp timeout '%s'\n", 1225 isc_commandline_argument); 1226 exit(EXIT_FAILURE); 1227 } 1228 break; 1229 case 'r': 1230 result = isc_parse_uint32(&udp_retries, 1231 isc_commandline_argument, 10); 1232 if (result != ISC_R_SUCCESS) { 1233 fprintf(stderr, "bad udp retries '%s'\n", 1234 isc_commandline_argument); 1235 exit(EXIT_FAILURE); 1236 } 1237 break; 1238 1239 case 'R': 1240 fatal("The -R option has been deprecated."); 1241 break; 1242 1243 default: 1244 fprintf(stderr, "%s: unhandled option: %c\n", argv[0], 1245 isc_commandline_option); 1246 exit(EXIT_FAILURE); 1247 } 1248 } 1249 if (keyfile != NULL && keystr != NULL) { 1250 fprintf(stderr, "%s: cannot specify both -k and -y\n", argv[0]); 1251 exit(EXIT_FAILURE); 1252 } 1253 1254 #if HAVE_GSSAPI 1255 if (usegsstsig && (keyfile != NULL || keystr != NULL)) { 1256 fprintf(stderr, "%s: cannot specify -g with -k or -y\n", 1257 argv[0]); 1258 exit(EXIT_FAILURE); 1259 } 1260 #else /* HAVE_GSSAPI */ 1261 if (usegsstsig) { 1262 fprintf(stderr, 1263 "%s: cannot specify -g or -o, " 1264 "program not linked with GSS API Library\n", 1265 argv[0]); 1266 exit(EXIT_FAILURE); 1267 } 1268 #endif /* HAVE_GSSAPI */ 1269 1270 if (use_tls) { 1271 usevc = true; 1272 if ((tls_client_key_file == NULL) != 1273 (tls_client_cert_file == NULL)) 1274 { 1275 fprintf(stderr, 1276 "%s: cannot specify the -K option without" 1277 "the -E option, and vice versa.\n", 1278 argv[0]); 1279 exit(EXIT_FAILURE); 1280 } 1281 if (tls_ca_file != NULL && tls_always_verify_remote == false) { 1282 fprintf(stderr, 1283 "%s: cannot specify the -A option in " 1284 "conjuction with the -O option.\n", 1285 argv[0]); 1286 exit(EXIT_FAILURE); 1287 } 1288 } 1289 1290 if (argv[isc_commandline_index] != NULL) { 1291 if (strcmp(argv[isc_commandline_index], "-") == 0) { 1292 input = stdin; 1293 } else { 1294 result = isc_stdio_open(argv[isc_commandline_index], 1295 "r", &input); 1296 if (result != ISC_R_SUCCESS) { 1297 fprintf(stderr, "could not open '%s': %s\n", 1298 argv[isc_commandline_index], 1299 isc_result_totext(result)); 1300 exit(EXIT_FAILURE); 1301 } 1302 } 1303 if (!force_interactive) { 1304 interactive = false; 1305 } 1306 } 1307 } 1308 1309 static uint16_t 1310 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) { 1311 isc_result_t result; 1312 char *word; 1313 isc_buffer_t source; 1314 1315 word = nsu_strsep(cmdlinep, " \t\r\n"); 1316 if (word == NULL || *word == 0) { 1317 fprintf(stderr, "could not read owner name\n"); 1318 return STATUS_SYNTAX; 1319 } 1320 1321 dns_message_gettempname(msg, namep); 1322 isc_buffer_init(&source, word, strlen(word)); 1323 isc_buffer_add(&source, strlen(word)); 1324 result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL); 1325 if (result != ISC_R_SUCCESS) { 1326 error("invalid owner name: %s", isc_result_totext(result)); 1327 isc_buffer_invalidate(&source); 1328 dns_message_puttempname(msg, namep); 1329 return STATUS_SYNTAX; 1330 } 1331 isc_buffer_invalidate(&source); 1332 return STATUS_MORE; 1333 } 1334 1335 static uint16_t 1336 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass, 1337 dns_rdatatype_t rdatatype, dns_message_t *msg, dns_rdata_t *rdata) { 1338 char *cmdline = *cmdlinep; 1339 isc_buffer_t source, *buf = NULL, *newbuf = NULL; 1340 isc_region_t r; 1341 isc_lex_t *lex = NULL; 1342 dns_rdatacallbacks_t callbacks; 1343 isc_result_t result; 1344 1345 if (cmdline == NULL) { 1346 rdata->flags = DNS_RDATA_UPDATE; 1347 return STATUS_MORE; 1348 } 1349 1350 while (*cmdline != 0 && isspace((unsigned char)*cmdline)) { 1351 cmdline++; 1352 } 1353 1354 if (*cmdline != 0) { 1355 dns_rdatacallbacks_init(&callbacks); 1356 isc_lex_create(gmctx, strlen(cmdline), &lex); 1357 isc_buffer_init(&source, cmdline, strlen(cmdline)); 1358 isc_buffer_add(&source, strlen(cmdline)); 1359 result = isc_lex_openbuffer(lex, &source); 1360 check_result(result, "isc_lex_openbuffer"); 1361 isc_buffer_allocate(gmctx, &buf, MAXWIRE); 1362 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex, 1363 dns_rootname, 0, gmctx, buf, 1364 &callbacks); 1365 isc_lex_destroy(&lex); 1366 if (result == ISC_R_SUCCESS) { 1367 isc_buffer_usedregion(buf, &r); 1368 isc_buffer_allocate(gmctx, &newbuf, r.length); 1369 isc_buffer_putmem(newbuf, r.base, r.length); 1370 isc_buffer_usedregion(newbuf, &r); 1371 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); 1372 isc_buffer_free(&buf); 1373 dns_message_takebuffer(msg, &newbuf); 1374 } else { 1375 fprintf(stderr, "invalid rdata format: %s\n", 1376 isc_result_totext(result)); 1377 isc_buffer_free(&buf); 1378 return STATUS_SYNTAX; 1379 } 1380 } else { 1381 rdata->flags = DNS_RDATA_UPDATE; 1382 } 1383 *cmdlinep = cmdline; 1384 return STATUS_MORE; 1385 } 1386 1387 static uint16_t 1388 make_prereq(char *cmdline, bool ispositive, bool isrrset) { 1389 isc_result_t result; 1390 char *word; 1391 dns_name_t *name = NULL; 1392 isc_textregion_t region; 1393 dns_rdataset_t *rdataset = NULL; 1394 dns_rdatalist_t *rdatalist = NULL; 1395 dns_rdataclass_t rdataclass; 1396 dns_rdatatype_t rdatatype; 1397 dns_rdata_t *rdata = NULL; 1398 uint16_t retval; 1399 1400 ddebug("make_prereq()"); 1401 1402 /* 1403 * Read the owner name 1404 */ 1405 retval = parse_name(&cmdline, updatemsg, &name); 1406 if (retval != STATUS_MORE) { 1407 return retval; 1408 } 1409 1410 /* 1411 * If this is an rrset prereq, read the class or type. 1412 */ 1413 if (isrrset) { 1414 word = nsu_strsep(&cmdline, " \t\r\n"); 1415 if (word == NULL || *word == 0) { 1416 fprintf(stderr, "could not read class or type\n"); 1417 goto failure; 1418 } 1419 region.base = word; 1420 region.length = strlen(word); 1421 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 1422 if (result == ISC_R_SUCCESS) { 1423 if (!setzoneclass(rdataclass)) { 1424 fprintf(stderr, "class mismatch: %s\n", word); 1425 goto failure; 1426 } 1427 /* 1428 * Now read the type. 1429 */ 1430 word = nsu_strsep(&cmdline, " \t\r\n"); 1431 if (word == NULL || *word == 0) { 1432 fprintf(stderr, "could not read type\n"); 1433 goto failure; 1434 } 1435 region.base = word; 1436 region.length = strlen(word); 1437 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1438 if (result != ISC_R_SUCCESS) { 1439 fprintf(stderr, "invalid type: %s\n", word); 1440 goto failure; 1441 } 1442 } else { 1443 rdataclass = getzoneclass(); 1444 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1445 if (result != ISC_R_SUCCESS) { 1446 fprintf(stderr, "invalid type: %s\n", word); 1447 goto failure; 1448 } 1449 } 1450 } else { 1451 rdatatype = dns_rdatatype_any; 1452 } 1453 1454 dns_message_gettemprdata(updatemsg, &rdata); 1455 1456 dns_rdata_init(rdata); 1457 1458 if (isrrset && ispositive) { 1459 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, 1460 rdata); 1461 if (retval != STATUS_MORE) { 1462 goto failure; 1463 } 1464 } else { 1465 rdata->flags = DNS_RDATA_UPDATE; 1466 } 1467 1468 dns_message_gettemprdatalist(updatemsg, &rdatalist); 1469 dns_message_gettemprdataset(updatemsg, &rdataset); 1470 rdatalist->type = rdatatype; 1471 if (ispositive) { 1472 if (isrrset && rdata->data != NULL) { 1473 rdatalist->rdclass = rdataclass; 1474 } else { 1475 rdatalist->rdclass = dns_rdataclass_any; 1476 } 1477 } else { 1478 rdatalist->rdclass = dns_rdataclass_none; 1479 } 1480 rdata->rdclass = rdatalist->rdclass; 1481 rdata->type = rdatatype; 1482 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1483 dns_rdatalist_tordataset(rdatalist, rdataset); 1484 ISC_LIST_INIT(name->list); 1485 ISC_LIST_APPEND(name->list, rdataset, link); 1486 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE); 1487 return STATUS_MORE; 1488 1489 failure: 1490 if (name != NULL) { 1491 dns_message_puttempname(updatemsg, &name); 1492 } 1493 return STATUS_SYNTAX; 1494 } 1495 1496 static uint16_t 1497 evaluate_prereq(char *cmdline) { 1498 char *word; 1499 bool ispositive, isrrset; 1500 1501 ddebug("evaluate_prereq()"); 1502 word = nsu_strsep(&cmdline, " \t\r\n"); 1503 if (word == NULL || *word == 0) { 1504 fprintf(stderr, "could not read operation code\n"); 1505 return STATUS_SYNTAX; 1506 } 1507 if (strcasecmp(word, "nxdomain") == 0) { 1508 ispositive = false; 1509 isrrset = false; 1510 } else if (strcasecmp(word, "yxdomain") == 0) { 1511 ispositive = true; 1512 isrrset = false; 1513 } else if (strcasecmp(word, "nxrrset") == 0) { 1514 ispositive = false; 1515 isrrset = true; 1516 } else if (strcasecmp(word, "yxrrset") == 0) { 1517 ispositive = true; 1518 isrrset = true; 1519 } else { 1520 fprintf(stderr, "incorrect operation code: %s\n", word); 1521 return STATUS_SYNTAX; 1522 } 1523 return make_prereq(cmdline, ispositive, isrrset); 1524 } 1525 1526 static void 1527 updateopt(void) { 1528 isc_result_t result; 1529 dns_ednsopt_t ednsopts[1]; 1530 unsigned char ul[8]; 1531 unsigned int count = 0; 1532 1533 if (lease_set) { 1534 isc_buffer_t b; 1535 INSIST(count < ARRAY_SIZE(ednsopts)); 1536 ednsopts[count++] = (dns_ednsopt_t){ .code = DNS_OPT_UL, 1537 .length = keylease_set ? 8 1538 : 4, 1539 .value = ul }; 1540 1541 isc_buffer_init(&b, ul, sizeof(ul)); 1542 isc_buffer_putuint32(&b, lease); 1543 isc_buffer_putuint32(&b, keylease); 1544 } 1545 1546 if (count != 0) { 1547 dns_rdataset_t *opt = NULL; 1548 result = dns_message_buildopt(updatemsg, &opt, 0, 1549 DEFAULT_EDNS_BUFSIZE, 0, ednsopts, 1550 count); 1551 check_result(result, "dns_message_buildopt"); 1552 result = dns_message_setopt(updatemsg, opt); 1553 check_result(result, "dns_message_setopt"); 1554 } else { 1555 result = dns_message_setopt(updatemsg, NULL); 1556 check_result(result, "dns_message_setopt"); 1557 } 1558 } 1559 1560 static uint16_t 1561 evaluate_lease(char *cmdline) { 1562 char *word; 1563 isc_result_t result; 1564 uint32_t value1, value2; 1565 1566 word = nsu_strsep(&cmdline, " \t\r\n"); 1567 if (word == NULL || *word == 0) { 1568 fprintf(stderr, "could not read ttl\n"); 1569 return STATUS_SYNTAX; 1570 } 1571 1572 if (!strcasecmp(word, "none")) { 1573 lease = 0; 1574 lease_set = false; 1575 keylease = 0; 1576 keylease_set = false; 1577 updateopt(); 1578 return STATUS_MORE; 1579 } 1580 1581 result = isc_parse_uint32(&value1, word, 10); 1582 if (result != ISC_R_SUCCESS) { 1583 return STATUS_SYNTAX; 1584 } 1585 1586 word = nsu_strsep(&cmdline, " \t\r\n"); 1587 if (word == NULL || *word == 0) { 1588 lease = value1; 1589 lease_set = true; 1590 keylease = 0; 1591 keylease_set = false; 1592 updateopt(); 1593 return STATUS_MORE; 1594 } 1595 1596 result = isc_parse_uint32(&value2, word, 10); 1597 if (result != ISC_R_SUCCESS) { 1598 return STATUS_SYNTAX; 1599 } 1600 1601 lease = value1; 1602 lease_set = true; 1603 keylease = value2; 1604 keylease_set = true; 1605 updateopt(); 1606 1607 return STATUS_MORE; 1608 } 1609 1610 static uint16_t 1611 evaluate_server(char *cmdline) { 1612 char *word, *server; 1613 long port; 1614 1615 if (local_only) { 1616 fprintf(stderr, "cannot reset server in localhost-only mode\n"); 1617 return STATUS_SYNTAX; 1618 } 1619 1620 word = nsu_strsep(&cmdline, " \t\r\n"); 1621 if (word == NULL || *word == 0) { 1622 fprintf(stderr, "could not read server name\n"); 1623 return STATUS_SYNTAX; 1624 } 1625 server = word; 1626 1627 word = nsu_strsep(&cmdline, " \t\r\n"); 1628 if (word == NULL || *word == 0) { 1629 port = dnsport; 1630 } else { 1631 char *endp; 1632 port = strtol(word, &endp, 10); 1633 if (*endp != 0) { 1634 fprintf(stderr, "port '%s' is not numeric\n", word); 1635 return STATUS_SYNTAX; 1636 } else if (port < 1 || port > 65535) { 1637 fprintf(stderr, 1638 "port '%s' is out of range " 1639 "(1 to 65535)\n", 1640 word); 1641 return STATUS_SYNTAX; 1642 } 1643 } 1644 1645 if (servers != NULL) { 1646 if (primary_servers == servers) { 1647 primary_servers = NULL; 1648 } 1649 isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t)); 1650 } 1651 1652 default_servers = false; 1653 1654 ns_alloc = MAX_SERVERADDRS; 1655 ns_inuse = 0; 1656 servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t)); 1657 ns_total = get_addresses(server, (in_port_t)port, servers, ns_alloc); 1658 if (ns_total == 0) { 1659 return STATUS_SYNTAX; 1660 } 1661 1662 return STATUS_MORE; 1663 } 1664 1665 static uint16_t 1666 evaluate_local(char *cmdline) { 1667 char *word, *local; 1668 long port; 1669 struct in_addr in4; 1670 struct in6_addr in6; 1671 1672 word = nsu_strsep(&cmdline, " \t\r\n"); 1673 if (word == NULL || *word == 0) { 1674 fprintf(stderr, "could not read server name\n"); 1675 return STATUS_SYNTAX; 1676 } 1677 local = word; 1678 1679 word = nsu_strsep(&cmdline, " \t\r\n"); 1680 if (word == NULL || *word == 0) { 1681 port = 0; 1682 } else { 1683 char *endp; 1684 port = strtol(word, &endp, 10); 1685 if (*endp != 0) { 1686 fprintf(stderr, "port '%s' is not numeric\n", word); 1687 return STATUS_SYNTAX; 1688 } else if (port < 1 || port > 65535) { 1689 fprintf(stderr, 1690 "port '%s' is out of range " 1691 "(1 to 65535)\n", 1692 word); 1693 return STATUS_SYNTAX; 1694 } 1695 } 1696 1697 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) { 1698 if (localaddr6 == NULL) { 1699 localaddr6 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); 1700 } 1701 isc_sockaddr_fromin6(localaddr6, &in6, (in_port_t)port); 1702 } else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) { 1703 if (localaddr4 == NULL) { 1704 localaddr4 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); 1705 } 1706 isc_sockaddr_fromin(localaddr4, &in4, (in_port_t)port); 1707 } else { 1708 fprintf(stderr, "invalid address %s", local); 1709 return STATUS_SYNTAX; 1710 } 1711 1712 return STATUS_MORE; 1713 } 1714 1715 static uint16_t 1716 evaluate_key(char *cmdline) { 1717 char *namestr; 1718 char *secretstr; 1719 isc_buffer_t b; 1720 isc_result_t result; 1721 dns_fixedname_t fkeyname; 1722 dns_name_t *mykeyname; 1723 int secretlen; 1724 unsigned char *secret = NULL; 1725 isc_buffer_t secretbuf; 1726 dst_algorithm_t hmac_alg = DST_ALG_UNKNOWN; 1727 uint16_t digestbits = 0; 1728 char *n; 1729 1730 namestr = nsu_strsep(&cmdline, " \t\r\n"); 1731 if (namestr == NULL || *namestr == 0) { 1732 fprintf(stderr, "could not read key name\n"); 1733 return STATUS_SYNTAX; 1734 } 1735 1736 mykeyname = dns_fixedname_initname(&fkeyname); 1737 1738 n = strchr(namestr, ':'); 1739 if (n != NULL) { 1740 if (!parse_hmac(namestr, n - namestr, &hmac_alg, &digestbits)) { 1741 return STATUS_SYNTAX; 1742 } 1743 namestr = n + 1; 1744 } else { 1745 hmac_alg = DST_ALG_HMACMD5; 1746 } 1747 1748 isc_buffer_init(&b, namestr, strlen(namestr)); 1749 isc_buffer_add(&b, strlen(namestr)); 1750 result = dns_name_fromtext(mykeyname, &b, dns_rootname, 0, NULL); 1751 if (result != ISC_R_SUCCESS) { 1752 fprintf(stderr, "could not parse key name\n"); 1753 return STATUS_SYNTAX; 1754 } 1755 1756 secretstr = nsu_strsep(&cmdline, "\r\n"); 1757 if (secretstr == NULL || *secretstr == 0) { 1758 fprintf(stderr, "could not read key secret\n"); 1759 return STATUS_SYNTAX; 1760 } 1761 secretlen = strlen(secretstr) * 3 / 4; 1762 secret = isc_mem_allocate(gmctx, secretlen); 1763 1764 isc_buffer_init(&secretbuf, secret, secretlen); 1765 result = isc_base64_decodestring(secretstr, &secretbuf); 1766 if (result != ISC_R_SUCCESS) { 1767 fprintf(stderr, "could not create key from %s: %s\n", secretstr, 1768 isc_result_totext(result)); 1769 isc_mem_free(gmctx, secret); 1770 return STATUS_SYNTAX; 1771 } 1772 secretlen = isc_buffer_usedlength(&secretbuf); 1773 1774 if (tsigkey != NULL) { 1775 dns_tsigkey_detach(&tsigkey); 1776 } 1777 result = dns_tsigkey_create(mykeyname, hmac_alg, secret, secretlen, 1778 gmctx, &tsigkey); 1779 isc_mem_free(gmctx, secret); 1780 if (result != ISC_R_SUCCESS) { 1781 fprintf(stderr, "could not create key from %s %s: %s\n", 1782 namestr, secretstr, isc_result_totext(result)); 1783 return STATUS_SYNTAX; 1784 } 1785 dst_key_setbits(tsigkey->key, digestbits); 1786 return STATUS_MORE; 1787 } 1788 1789 static uint16_t 1790 evaluate_zone(char *cmdline) { 1791 char *word; 1792 isc_buffer_t b; 1793 isc_result_t result; 1794 1795 word = nsu_strsep(&cmdline, " \t\r\n"); 1796 if (word == NULL || *word == 0) { 1797 fprintf(stderr, "could not read zone name\n"); 1798 return STATUS_SYNTAX; 1799 } 1800 1801 userzone = dns_fixedname_initname(&fuserzone); 1802 isc_buffer_init(&b, word, strlen(word)); 1803 isc_buffer_add(&b, strlen(word)); 1804 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL); 1805 if (result != ISC_R_SUCCESS) { 1806 userzone = NULL; /* Lest it point to an invalid name */ 1807 fprintf(stderr, "could not parse zone name\n"); 1808 return STATUS_SYNTAX; 1809 } 1810 1811 return STATUS_MORE; 1812 } 1813 1814 static uint16_t 1815 evaluate_realm(char *cmdline) { 1816 #if HAVE_GSSAPI 1817 char *word; 1818 char buf[1024]; 1819 int n; 1820 1821 if (realm != NULL) { 1822 isc_mem_free(gmctx, realm); 1823 realm = NULL; 1824 } 1825 1826 word = nsu_strsep(&cmdline, " \t\r\n"); 1827 if (word == NULL || *word == 0) { 1828 return STATUS_MORE; 1829 } 1830 1831 n = snprintf(buf, sizeof(buf), "@%s", word); 1832 if (n < 0 || (size_t)n >= sizeof(buf)) { 1833 error("realm is too long"); 1834 return STATUS_SYNTAX; 1835 } 1836 realm = isc_mem_strdup(gmctx, buf); 1837 return STATUS_MORE; 1838 #else /* HAVE_GSSAPI */ 1839 UNUSED(cmdline); 1840 return STATUS_SYNTAX; 1841 #endif /* HAVE_GSSAPI */ 1842 } 1843 1844 static uint16_t 1845 evaluate_ttl(char *cmdline) { 1846 char *word; 1847 isc_result_t result; 1848 uint32_t ttl; 1849 1850 word = nsu_strsep(&cmdline, " \t\r\n"); 1851 if (word == NULL || *word == 0) { 1852 fprintf(stderr, "could not read ttl\n"); 1853 return STATUS_SYNTAX; 1854 } 1855 1856 if (!strcasecmp(word, "none")) { 1857 default_ttl = 0; 1858 default_ttl_set = false; 1859 return STATUS_MORE; 1860 } 1861 1862 result = isc_parse_uint32(&ttl, word, 10); 1863 if (result != ISC_R_SUCCESS) { 1864 return STATUS_SYNTAX; 1865 } 1866 1867 if (ttl > TTL_MAX) { 1868 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word, 1869 TTL_MAX); 1870 return STATUS_SYNTAX; 1871 } 1872 default_ttl = ttl; 1873 default_ttl_set = true; 1874 1875 return STATUS_MORE; 1876 } 1877 1878 static uint16_t 1879 evaluate_class(char *cmdline) { 1880 char *word; 1881 isc_textregion_t r; 1882 isc_result_t result; 1883 dns_rdataclass_t rdclass; 1884 1885 word = nsu_strsep(&cmdline, " \t\r\n"); 1886 if (word == NULL || *word == 0) { 1887 fprintf(stderr, "could not read class name\n"); 1888 return STATUS_SYNTAX; 1889 } 1890 1891 r.base = word; 1892 r.length = strlen(word); 1893 result = dns_rdataclass_fromtext(&rdclass, &r); 1894 if (result != ISC_R_SUCCESS) { 1895 fprintf(stderr, "could not parse class name: %s\n", word); 1896 return STATUS_SYNTAX; 1897 } 1898 switch (rdclass) { 1899 case dns_rdataclass_none: 1900 case dns_rdataclass_any: 1901 case dns_rdataclass_reserved0: 1902 fprintf(stderr, "bad default class: %s\n", word); 1903 return STATUS_SYNTAX; 1904 default: 1905 defaultclass = rdclass; 1906 } 1907 1908 return STATUS_MORE; 1909 } 1910 1911 static uint16_t 1912 update_addordelete(char *cmdline, bool isdelete) { 1913 isc_result_t result; 1914 dns_name_t *name = NULL; 1915 uint32_t ttl; 1916 char *word; 1917 dns_rdataclass_t rdataclass; 1918 dns_rdatatype_t rdatatype; 1919 dns_rdata_t *rdata = NULL; 1920 dns_rdatalist_t *rdatalist = NULL; 1921 dns_rdataset_t *rdataset = NULL; 1922 isc_textregion_t region; 1923 uint16_t retval; 1924 1925 ddebug("update_addordelete()"); 1926 1927 /* 1928 * Read the owner name. 1929 */ 1930 retval = parse_name(&cmdline, updatemsg, &name); 1931 if (retval != STATUS_MORE) { 1932 return retval; 1933 } 1934 1935 dns_message_gettemprdata(updatemsg, &rdata); 1936 1937 dns_rdata_init(rdata); 1938 1939 /* 1940 * If this is an add, read the TTL and verify that it's in range. 1941 * If it's a delete, ignore a TTL if present (for compatibility). 1942 */ 1943 word = nsu_strsep(&cmdline, " \t\r\n"); 1944 if (word == NULL || *word == 0) { 1945 if (!isdelete) { 1946 fprintf(stderr, "could not read owner ttl\n"); 1947 goto failure; 1948 } else { 1949 ttl = 0; 1950 rdataclass = dns_rdataclass_any; 1951 rdatatype = dns_rdatatype_any; 1952 rdata->flags = DNS_RDATA_UPDATE; 1953 goto doneparsing; 1954 } 1955 } 1956 result = isc_parse_uint32(&ttl, word, 10); 1957 if (result != ISC_R_SUCCESS) { 1958 if (isdelete) { 1959 ttl = 0; 1960 goto parseclass; 1961 } else if (default_ttl_set) { 1962 ttl = default_ttl; 1963 goto parseclass; 1964 } else { 1965 fprintf(stderr, "ttl '%s': %s\n", word, 1966 isc_result_totext(result)); 1967 goto failure; 1968 } 1969 } 1970 1971 if (isdelete) { 1972 ttl = 0; 1973 } else if (ttl > TTL_MAX) { 1974 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word, 1975 TTL_MAX); 1976 goto failure; 1977 } 1978 1979 /* 1980 * Read the class or type. 1981 */ 1982 word = nsu_strsep(&cmdline, " \t\r\n"); 1983 parseclass: 1984 if (word == NULL || *word == 0) { 1985 if (isdelete) { 1986 rdataclass = dns_rdataclass_any; 1987 rdatatype = dns_rdatatype_any; 1988 rdata->flags = DNS_RDATA_UPDATE; 1989 goto doneparsing; 1990 } else { 1991 fprintf(stderr, "could not read class or type\n"); 1992 goto failure; 1993 } 1994 } 1995 region.base = word; 1996 region.length = strlen(word); 1997 rdataclass = dns_rdataclass_any; 1998 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 1999 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) { 2000 if (!setzoneclass(rdataclass)) { 2001 fprintf(stderr, "class mismatch: %s\n", word); 2002 goto failure; 2003 } 2004 /* 2005 * Now read the type. 2006 */ 2007 word = nsu_strsep(&cmdline, " \t\r\n"); 2008 if (word == NULL || *word == 0) { 2009 if (isdelete) { 2010 rdataclass = dns_rdataclass_any; 2011 rdatatype = dns_rdatatype_any; 2012 rdata->flags = DNS_RDATA_UPDATE; 2013 goto doneparsing; 2014 } else { 2015 fprintf(stderr, "could not read type\n"); 2016 goto failure; 2017 } 2018 } 2019 region.base = word; 2020 region.length = strlen(word); 2021 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 2022 if (result != ISC_R_SUCCESS) { 2023 fprintf(stderr, "'%s' is not a valid type: %s\n", word, 2024 isc_result_totext(result)); 2025 goto failure; 2026 } 2027 } else { 2028 rdataclass = getzoneclass(); 2029 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 2030 if (result != ISC_R_SUCCESS) { 2031 fprintf(stderr, 2032 "'%s' is not a valid class or type: " 2033 "%s\n", 2034 word, isc_result_totext(result)); 2035 goto failure; 2036 } 2037 } 2038 2039 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, rdata); 2040 if (retval != STATUS_MORE) { 2041 goto failure; 2042 } 2043 2044 if (isdelete) { 2045 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 2046 rdataclass = dns_rdataclass_any; 2047 } else { 2048 rdataclass = dns_rdataclass_none; 2049 } 2050 } else { 2051 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 2052 fprintf(stderr, "could not read rdata\n"); 2053 goto failure; 2054 } 2055 } 2056 2057 if (!isdelete && checknames) { 2058 dns_fixedname_t fixed; 2059 dns_name_t *bad; 2060 2061 if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type, 2062 true)) 2063 { 2064 char namebuf[DNS_NAME_FORMATSIZE]; 2065 2066 dns_name_format(name, namebuf, sizeof(namebuf)); 2067 fprintf(stderr, "check-names failed: bad owner '%s'\n", 2068 namebuf); 2069 goto failure; 2070 } 2071 2072 bad = dns_fixedname_initname(&fixed); 2073 if (!dns_rdata_checknames(rdata, name, bad)) { 2074 char namebuf[DNS_NAME_FORMATSIZE]; 2075 2076 dns_name_format(bad, namebuf, sizeof(namebuf)); 2077 fprintf(stderr, "check-names failed: bad name '%s'\n", 2078 namebuf); 2079 goto failure; 2080 } 2081 } 2082 2083 if (!isdelete && checksvcb && rdata->type == dns_rdatatype_svcb) { 2084 result = dns_rdata_checksvcb(name, rdata); 2085 if (result != ISC_R_SUCCESS) { 2086 fprintf(stderr, "check-svcb failed: %s\n", 2087 isc_result_totext(result)); 2088 goto failure; 2089 } 2090 } 2091 2092 if (!isdelete && rdata->type == dns_rdatatype_nsec3param) { 2093 dns_rdata_nsec3param_t nsec3param; 2094 2095 result = dns_rdata_tostruct(rdata, &nsec3param, NULL); 2096 check_result(result, "dns_rdata_tostruct"); 2097 if (nsec3param.iterations > dns_nsec3_maxiterations()) { 2098 fprintf(stderr, 2099 "NSEC3PARAM has excessive iterations (> %u)\n", 2100 dns_nsec3_maxiterations()); 2101 goto failure; 2102 } 2103 } 2104 2105 doneparsing: 2106 2107 dns_message_gettemprdatalist(updatemsg, &rdatalist); 2108 dns_message_gettemprdataset(updatemsg, &rdataset); 2109 rdatalist->type = rdatatype; 2110 rdatalist->rdclass = rdataclass; 2111 rdatalist->covers = rdatatype; 2112 rdatalist->ttl = (dns_ttl_t)ttl; 2113 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 2114 dns_rdatalist_tordataset(rdatalist, rdataset); 2115 ISC_LIST_INIT(name->list); 2116 ISC_LIST_APPEND(name->list, rdataset, link); 2117 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE); 2118 return STATUS_MORE; 2119 2120 failure: 2121 if (name != NULL) { 2122 dns_message_puttempname(updatemsg, &name); 2123 } 2124 dns_message_puttemprdata(updatemsg, &rdata); 2125 return STATUS_SYNTAX; 2126 } 2127 2128 static uint16_t 2129 evaluate_update(char *cmdline) { 2130 char *word; 2131 bool isdelete; 2132 2133 ddebug("evaluate_update()"); 2134 word = nsu_strsep(&cmdline, " \t\r\n"); 2135 if (word == NULL || *word == 0) { 2136 fprintf(stderr, "could not read operation code\n"); 2137 return STATUS_SYNTAX; 2138 } 2139 if (strcasecmp(word, "delete") == 0) { 2140 isdelete = true; 2141 } else if (strcasecmp(word, "del") == 0) { 2142 isdelete = true; 2143 } else if (strcasecmp(word, "add") == 0) { 2144 isdelete = false; 2145 } else { 2146 fprintf(stderr, "incorrect operation code: %s\n", word); 2147 return STATUS_SYNTAX; 2148 } 2149 return update_addordelete(cmdline, isdelete); 2150 } 2151 2152 static uint16_t 2153 evaluate_checknames(char *cmdline) { 2154 char *word; 2155 2156 ddebug("evaluate_checknames()"); 2157 word = nsu_strsep(&cmdline, " \t\r\n"); 2158 if (word == NULL || *word == 0) { 2159 fprintf(stderr, "could not read check-names directive\n"); 2160 return STATUS_SYNTAX; 2161 } 2162 if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 || 2163 strcasecmp(word, "on") == 0) 2164 { 2165 checknames = true; 2166 } else if (strcasecmp(word, "no") == 0 || 2167 strcasecmp(word, "false") == 0 || 2168 strcasecmp(word, "off") == 0) 2169 { 2170 checknames = false; 2171 } else { 2172 fprintf(stderr, "incorrect check-names directive: %s\n", word); 2173 return STATUS_SYNTAX; 2174 } 2175 return STATUS_MORE; 2176 } 2177 2178 static uint16_t 2179 evaluate_checksvcb(char *cmdline) { 2180 char *word; 2181 2182 ddebug("evaluate_checksvcb()"); 2183 word = nsu_strsep(&cmdline, " \t\r\n"); 2184 if (word == NULL || *word == 0) { 2185 fprintf(stderr, "could not read check-svcb directive\n"); 2186 return STATUS_SYNTAX; 2187 } 2188 if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 || 2189 strcasecmp(word, "on") == 0) 2190 { 2191 checksvcb = true; 2192 } else if (strcasecmp(word, "no") == 0 || 2193 strcasecmp(word, "false") == 0 || 2194 strcasecmp(word, "off") == 0) 2195 { 2196 checksvcb = false; 2197 } else { 2198 fprintf(stderr, "incorrect check-svcb directive: %s\n", word); 2199 return STATUS_SYNTAX; 2200 } 2201 return STATUS_MORE; 2202 } 2203 2204 static void 2205 setzone(dns_name_t *zonename) { 2206 isc_result_t result; 2207 dns_name_t *name = NULL; 2208 dns_rdataset_t *rdataset = NULL; 2209 2210 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE); 2211 if (result == ISC_R_SUCCESS) { 2212 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name); 2213 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE); 2214 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; 2215 rdataset = ISC_LIST_HEAD(name->list)) 2216 { 2217 ISC_LIST_UNLINK(name->list, rdataset, link); 2218 dns_rdataset_disassociate(rdataset); 2219 dns_message_puttemprdataset(updatemsg, &rdataset); 2220 } 2221 dns_message_puttempname(updatemsg, &name); 2222 } 2223 2224 if (zonename != NULL) { 2225 dns_message_gettempname(updatemsg, &name); 2226 dns_name_clone(zonename, name); 2227 dns_message_gettemprdataset(updatemsg, &rdataset); 2228 dns_rdataset_makequestion(rdataset, getzoneclass(), 2229 dns_rdatatype_soa); 2230 ISC_LIST_INIT(name->list); 2231 ISC_LIST_APPEND(name->list, rdataset, link); 2232 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); 2233 } 2234 } 2235 2236 static void 2237 show_message(FILE *stream, dns_message_t *msg, const char *description) { 2238 isc_result_t result; 2239 isc_buffer_t *buf = NULL; 2240 int bufsz; 2241 2242 ddebug("show_message()"); 2243 2244 setzone(userzone); 2245 2246 bufsz = INITTEXT; 2247 do { 2248 if (bufsz > MAXTEXT) { 2249 fprintf(stderr, "could not allocate large enough " 2250 "buffer to display message\n"); 2251 exit(EXIT_FAILURE); 2252 } 2253 if (buf != NULL) { 2254 isc_buffer_free(&buf); 2255 } 2256 isc_buffer_allocate(gmctx, &buf, bufsz); 2257 result = dns_message_totext(msg, style, 0, buf); 2258 bufsz *= 2; 2259 } while (result == ISC_R_NOSPACE); 2260 if (result != ISC_R_SUCCESS) { 2261 fprintf(stderr, "could not convert message to text format.\n"); 2262 isc_buffer_free(&buf); 2263 return; 2264 } 2265 fprintf(stream, "%s\n%.*s", description, 2266 (int)isc_buffer_usedlength(buf), (char *)isc_buffer_base(buf)); 2267 fflush(stream); 2268 isc_buffer_free(&buf); 2269 } 2270 2271 static uint16_t 2272 do_next_command(char *cmdline) { 2273 char *word; 2274 2275 ddebug("do_next_command()"); 2276 word = nsu_strsep(&cmdline, " \t\r\n"); 2277 2278 if (word == NULL || *word == 0) { 2279 return STATUS_SEND; 2280 } 2281 if (word[0] == ';') { 2282 return STATUS_MORE; 2283 } 2284 if (strcasecmp(word, "quit") == 0) { 2285 return STATUS_QUIT; 2286 } 2287 if (strcasecmp(word, "prereq") == 0) { 2288 return evaluate_prereq(cmdline); 2289 } 2290 if (strcasecmp(word, "nxdomain") == 0) { 2291 return make_prereq(cmdline, false, false); 2292 } 2293 if (strcasecmp(word, "yxdomain") == 0) { 2294 return make_prereq(cmdline, true, false); 2295 } 2296 if (strcasecmp(word, "nxrrset") == 0) { 2297 return make_prereq(cmdline, false, true); 2298 } 2299 if (strcasecmp(word, "yxrrset") == 0) { 2300 return make_prereq(cmdline, true, true); 2301 } 2302 if (strcasecmp(word, "update") == 0) { 2303 return evaluate_update(cmdline); 2304 } 2305 if (strcasecmp(word, "delete") == 0) { 2306 return update_addordelete(cmdline, true); 2307 } 2308 if (strcasecmp(word, "del") == 0) { 2309 return update_addordelete(cmdline, true); 2310 } 2311 if (strcasecmp(word, "add") == 0) { 2312 return update_addordelete(cmdline, false); 2313 } 2314 if (strcasecmp(word, "lease") == 0) { 2315 return evaluate_lease(cmdline); 2316 } 2317 if (strcasecmp(word, "server") == 0) { 2318 return evaluate_server(cmdline); 2319 } 2320 if (strcasecmp(word, "local") == 0) { 2321 return evaluate_local(cmdline); 2322 } 2323 if (strcasecmp(word, "zone") == 0) { 2324 return evaluate_zone(cmdline); 2325 } 2326 if (strcasecmp(word, "class") == 0) { 2327 return evaluate_class(cmdline); 2328 } 2329 if (strcasecmp(word, "send") == 0) { 2330 return STATUS_SEND; 2331 } 2332 if (strcasecmp(word, "debug") == 0) { 2333 if (debugging) { 2334 ddebugging = true; 2335 } else { 2336 debugging = true; 2337 } 2338 return STATUS_MORE; 2339 } 2340 if (strcasecmp(word, "ttl") == 0) { 2341 return evaluate_ttl(cmdline); 2342 } 2343 if (strcasecmp(word, "show") == 0) { 2344 show_message(stdout, updatemsg, "Outgoing update query:"); 2345 return STATUS_MORE; 2346 } 2347 if (strcasecmp(word, "answer") == 0) { 2348 LOCK(&answer_lock); 2349 if (answer != NULL) { 2350 show_message(stdout, answer, "Answer:"); 2351 } 2352 UNLOCK(&answer_lock); 2353 return STATUS_MORE; 2354 } 2355 if (strcasecmp(word, "key") == 0) { 2356 usegsstsig = false; 2357 return evaluate_key(cmdline); 2358 } 2359 if (strcasecmp(word, "realm") == 0) { 2360 return evaluate_realm(cmdline); 2361 } 2362 if (strcasecmp(word, "check-names") == 0 || 2363 strcasecmp(word, "checknames") == 0) 2364 { 2365 return evaluate_checknames(cmdline); 2366 } 2367 if (strcasecmp(word, "check-svcb") == 0 || 2368 strcasecmp(word, "checksvcb") == 0) 2369 { 2370 return evaluate_checksvcb(cmdline); 2371 } 2372 if (strcasecmp(word, "gsstsig") == 0) { 2373 #if HAVE_GSSAPI 2374 usegsstsig = true; 2375 #else /* HAVE_GSSAPI */ 2376 fprintf(stderr, "gsstsig not supported\n"); 2377 #endif /* HAVE_GSSAPI */ 2378 return STATUS_MORE; 2379 } 2380 if (strcasecmp(word, "oldgsstsig") == 0) { 2381 #if HAVE_GSSAPI 2382 usegsstsig = true; 2383 #else /* HAVE_GSSAPI */ 2384 fprintf(stderr, "gsstsig not supported\n"); 2385 #endif /* HAVE_GSSAPI */ 2386 return STATUS_MORE; 2387 } 2388 if (strcasecmp(word, "help") == 0) { 2389 fprintf(stdout, "nsupdate " PACKAGE_VERSION ":\n" 2390 "local address [port] (set local " 2391 "resolver)\n" 2392 "server address [port] (set primary server " 2393 "for zone)\n" 2394 "send (send the update " 2395 "request)\n" 2396 "show (show the update " 2397 "request)\n" 2398 "answer (show the answer to " 2399 "the last request)\n" 2400 "quit (quit, any pending " 2401 "update is not sent)\n" 2402 "help (display this " 2403 "message)\n" 2404 "key [hmac:]keyname secret (use TSIG to sign " 2405 "the request)\n" 2406 "gsstsig (use GSS_TSIG to " 2407 "sign the request)\n" 2408 "zone name (set the zone to be " 2409 "updated)\n" 2410 "class CLASS (set the zone's DNS " 2411 "class, e.g. IN (default), CH)\n" 2412 "check-names { on | off } (enable / disable " 2413 "check-names)\n" 2414 "[prereq] nxdomain name (require that this " 2415 "name does not exist)\n" 2416 "[prereq] yxdomain name (require that this " 2417 "name exists)\n" 2418 "[prereq] nxrrset .... (require that this " 2419 "RRset does not exist)\n" 2420 "[prereq] yxrrset .... (require that this " 2421 "RRset exists)\n" 2422 "[update] add .... (add the given " 2423 "record to the zone)\n" 2424 "[update] del[ete] .... (remove the given " 2425 "record(s) from the zone)\n"); 2426 return STATUS_MORE; 2427 } 2428 if (strcasecmp(word, "version") == 0) { 2429 fprintf(stdout, "nsupdate " PACKAGE_VERSION "\n"); 2430 return STATUS_MORE; 2431 } 2432 fprintf(stderr, "incorrect section name: %s\n", word); 2433 return STATUS_SYNTAX; 2434 } 2435 2436 static uint16_t 2437 get_next_command(void) { 2438 uint16_t result = STATUS_QUIT; 2439 char cmdlinebuf[MAXCMD]; 2440 char *cmdline = NULL, *ptr = NULL; 2441 2442 if (interactive) { 2443 cmdline = ptr = readline("> "); 2444 if (ptr != NULL && *ptr != 0) { 2445 add_history(ptr); 2446 } 2447 } else { 2448 cmdline = fgets(cmdlinebuf, MAXCMD, input); 2449 } 2450 2451 if (cmdline != NULL) { 2452 char *tmp = cmdline; 2453 2454 /* 2455 * Normalize input by removing any eol as readline() 2456 * removes eol but fgets doesn't. 2457 */ 2458 (void)nsu_strsep(&tmp, "\r\n"); 2459 result = do_next_command(cmdline); 2460 } 2461 if (ptr != NULL) { 2462 free(ptr); 2463 } 2464 2465 return result; 2466 } 2467 2468 static bool 2469 user_interaction(void) { 2470 uint16_t result = STATUS_MORE; 2471 2472 ddebug("user_interaction()"); 2473 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) { 2474 result = get_next_command(); 2475 if (!interactive && result == STATUS_SYNTAX) { 2476 fatal("syntax error"); 2477 } 2478 } 2479 if (result == STATUS_SEND) { 2480 return true; 2481 } 2482 return false; 2483 } 2484 2485 static void 2486 done_update(void) { 2487 ddebug("done_update()"); 2488 2489 isc_async_current(getinput, NULL); 2490 } 2491 2492 static void 2493 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) { 2494 isc_result_t result; 2495 dns_rdata_t rdata = DNS_RDATA_INIT; 2496 dns_rdata_any_tsig_t tsig; 2497 2498 result = dns_rdataset_first(rdataset); 2499 check_result(result, "dns_rdataset_first"); 2500 dns_rdataset_current(rdataset, &rdata); 2501 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 2502 check_result(result, "dns_rdata_tostruct"); 2503 if (tsig.error != 0) { 2504 if (isc_buffer_remaininglength(b) < 1) { 2505 check_result(ISC_R_NOSPACE, "isc_buffer_" 2506 "remaininglength"); 2507 } 2508 isc_buffer_putstr(b, "(" /*)*/); 2509 result = dns_tsigrcode_totext(tsig.error, b); 2510 check_result(result, "dns_tsigrcode_totext"); 2511 if (isc_buffer_remaininglength(b) < 1) { 2512 check_result(ISC_R_NOSPACE, "isc_buffer_" 2513 "remaininglength"); 2514 } 2515 isc_buffer_putstr(b, /*(*/ ")"); 2516 } 2517 } 2518 2519 static bool 2520 next_primary(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) { 2521 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2522 2523 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 2524 fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf, 2525 isc_result_totext(eresult)); 2526 if (++primary_inuse >= primary_total) { 2527 return false; 2528 } 2529 ddebug("%s: trying next server", caller); 2530 return true; 2531 } 2532 2533 static void 2534 update_completed(void *arg) { 2535 dns_request_t *request = (dns_request_t *)arg; 2536 isc_result_t result; 2537 2538 ddebug("update_completed()"); 2539 2540 requests--; 2541 2542 if (shuttingdown) { 2543 dns_request_destroy(&request); 2544 maybeshutdown(); 2545 return; 2546 } 2547 2548 result = dns_request_getresult(request); 2549 if (result != ISC_R_SUCCESS) { 2550 if (!next_primary("update_completed", 2551 &primary_servers[primary_inuse], result)) 2552 { 2553 seenerror = true; 2554 goto done; 2555 } 2556 2557 ddebug("Destroying request [%p]", request); 2558 dns_request_destroy(&request); 2559 dns_message_renderreset(updatemsg); 2560 dns_message_settsigkey(updatemsg, NULL); 2561 send_update(zname, &primary_servers[primary_inuse]); 2562 return; 2563 } 2564 2565 LOCK(&answer_lock); 2566 dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &answer); 2567 result = dns_request_getresponse(request, answer, 2568 DNS_MESSAGEPARSE_PRESERVEORDER); 2569 switch (result) { 2570 case ISC_R_SUCCESS: 2571 if (answer->verify_attempted) { 2572 ddebug("tsig verification successful"); 2573 } 2574 break; 2575 case DNS_R_CLOCKSKEW: 2576 case DNS_R_EXPECTEDTSIG: 2577 case DNS_R_TSIGERRORSET: 2578 case DNS_R_TSIGVERIFYFAILURE: 2579 case DNS_R_UNEXPECTEDTSIG: 2580 case ISC_R_FAILURE: 2581 #if 0 2582 if (usegsstsig && answer->rcode == dns_rcode_noerror) { 2583 /* 2584 * For MS DNS that violates RFC 2845, section 4.2 2585 */ 2586 break; 2587 } 2588 #endif /* if 0 */ 2589 fprintf(stderr, "; TSIG error with server: %s\n", 2590 isc_result_totext(result)); 2591 seenerror = true; 2592 break; 2593 default: 2594 check_result(result, "dns_request_getresponse"); 2595 } 2596 2597 if (answer->opcode != dns_opcode_update) { 2598 fatal("invalid OPCODE in response to UPDATE request"); 2599 } 2600 2601 if (answer->rcode != dns_rcode_noerror) { 2602 seenerror = true; 2603 if (!debugging) { 2604 char buf[64]; 2605 isc_buffer_t b; 2606 dns_rdataset_t *rds; 2607 2608 isc_buffer_init(&b, buf, sizeof(buf) - 1); 2609 result = dns_rcode_totext(answer->rcode, &b); 2610 check_result(result, "dns_rcode_totext"); 2611 rds = dns_message_gettsig(answer, NULL); 2612 if (rds != NULL) { 2613 check_tsig_error(rds, &b); 2614 } 2615 fprintf(stderr, "update failed: %.*s\n", 2616 (int)isc_buffer_usedlength(&b), buf); 2617 } 2618 } 2619 if (debugging) { 2620 show_message(stderr, answer, "\nReply from update query:"); 2621 } 2622 UNLOCK(&answer_lock); 2623 2624 done: 2625 dns_request_destroy(&request); 2626 if (usegsstsig) { 2627 dns_name_free(&tmpzonename, gmctx); 2628 dns_name_free(&restart_primary, gmctx); 2629 dns_name_init(&tmpzonename, 0); 2630 dns_name_init(&restart_primary, 0); 2631 } 2632 done_update(); 2633 } 2634 2635 static void 2636 send_update(dns_name_t *zone, isc_sockaddr_t *primary) { 2637 isc_result_t result; 2638 dns_request_t *request = NULL; 2639 isc_sockaddr_t *srcaddr; 2640 unsigned int options = DNS_REQUESTOPT_CASE | DNS_REQUESTOPT_LARGE; 2641 dns_transport_t *req_transport = NULL; 2642 isc_tlsctx_cache_t *req_tls_ctx_cache = NULL; 2643 2644 ddebug("send_update()"); 2645 2646 setzone(zone); 2647 2648 if (usevc) { 2649 options |= DNS_REQUESTOPT_TCP; 2650 if (use_tls) { 2651 req_transport = transport; 2652 req_tls_ctx_cache = tls_ctx_cache; 2653 } 2654 } 2655 2656 if (tsigkey == NULL && sig0key != NULL) { 2657 result = dns_message_setsig0key(updatemsg, sig0key); 2658 check_result(result, "dns_message_setsig0key"); 2659 } 2660 if (debugging) { 2661 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2662 2663 isc_sockaddr_format(primary, addrbuf, sizeof(addrbuf)); 2664 fprintf(stderr, "Sending update to %s\n", addrbuf); 2665 } 2666 2667 if (isc_sockaddr_pf(primary) == AF_INET6) { 2668 srcaddr = localaddr6; 2669 } else { 2670 srcaddr = localaddr4; 2671 } 2672 2673 /* Windows doesn't like the tsig name to be compressed. */ 2674 if (updatemsg->tsigname) { 2675 updatemsg->tsigname->attributes.nocompress = true; 2676 } 2677 2678 result = dns_request_create(requestmgr, updatemsg, srcaddr, primary, 2679 req_transport, req_tls_ctx_cache, options, 2680 tsigkey, timeout, udp_timeout, udp_retries, 2681 isc_loop_main(loopmgr), update_completed, 2682 NULL, &request); 2683 check_result(result, "dns_request_create"); 2684 2685 if (debugging) { 2686 show_message(stdout, updatemsg, "Outgoing update query:"); 2687 } 2688 2689 requests++; 2690 } 2691 2692 static void 2693 next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) { 2694 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2695 2696 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 2697 fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf, 2698 isc_result_totext(eresult)); 2699 if (++ns_inuse >= ns_total) { 2700 fatal("could not reach any name server"); 2701 } else { 2702 ddebug("%s: trying next server", caller); 2703 } 2704 } 2705 2706 static void 2707 recvsoa(void *arg) { 2708 dns_request_t *request = (dns_request_t *)arg; 2709 isc_result_t result, eresult = dns_request_getresult(request); 2710 nsu_requestinfo_t *reqinfo = dns_request_getarg(request); 2711 dns_message_t *soaquery = reqinfo->msg; 2712 dns_message_t *rcvmsg = NULL; 2713 dns_section_t section; 2714 dns_name_t *name = NULL; 2715 dns_rdataset_t *soaset = NULL; 2716 dns_rdata_soa_t soa; 2717 dns_rdata_t soarr = DNS_RDATA_INIT; 2718 int pass = 0; 2719 dns_name_t primary; 2720 isc_sockaddr_t *addr = reqinfo->addr; 2721 isc_sockaddr_t *srcaddr = NULL; 2722 bool seencname = false; 2723 dns_name_t tname; 2724 unsigned int nlabels; 2725 2726 ddebug("recvsoa()"); 2727 2728 requests--; 2729 2730 if (shuttingdown) { 2731 dns_request_destroy(&request); 2732 dns_message_detach(&soaquery); 2733 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); 2734 maybeshutdown(); 2735 return; 2736 } 2737 2738 if (eresult != ISC_R_SUCCESS) { 2739 next_server("recvsoa", addr, eresult); 2740 ddebug("Destroying request [%p]", request); 2741 dns_request_destroy(&request); 2742 dns_message_renderreset(soaquery); 2743 dns_message_settsigkey(soaquery, NULL); 2744 sendrequest(&servers[ns_inuse], soaquery, &request); 2745 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); 2746 setzoneclass(dns_rdataclass_none); 2747 return; 2748 } 2749 2750 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); 2751 reqinfo = NULL; 2752 2753 ddebug("About to create rcvmsg"); 2754 dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 2755 result = dns_request_getresponse(request, rcvmsg, 2756 DNS_MESSAGEPARSE_PRESERVEORDER); 2757 if (result == DNS_R_TSIGERRORSET && servers != NULL) { 2758 unsigned int options = DNS_REQUESTOPT_CASE; 2759 dns_transport_t *req_transport = NULL; 2760 isc_tlsctx_cache_t *req_tls_ctx_cache = NULL; 2761 2762 dns_message_detach(&rcvmsg); 2763 ddebug("Destroying request [%p]", request); 2764 dns_request_destroy(&request); 2765 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t)); 2766 reqinfo->msg = soaquery; 2767 reqinfo->addr = addr; 2768 dns_message_renderreset(soaquery); 2769 ddebug("retrying soa request without TSIG"); 2770 2771 if (!default_servers && usevc) { 2772 options |= DNS_REQUESTOPT_TCP; 2773 if (use_tls) { 2774 req_transport = transport; 2775 req_tls_ctx_cache = tls_ctx_cache; 2776 } 2777 } 2778 2779 if (isc_sockaddr_pf(addr) == AF_INET6) { 2780 srcaddr = localaddr6; 2781 } else { 2782 srcaddr = localaddr4; 2783 } 2784 2785 result = dns_request_create(requestmgr, soaquery, srcaddr, addr, 2786 req_transport, req_tls_ctx_cache, 2787 options, NULL, timeout, udp_timeout, 2788 udp_retries, isc_loop_main(loopmgr), 2789 recvsoa, reqinfo, &request); 2790 check_result(result, "dns_request_create"); 2791 requests++; 2792 return; 2793 } 2794 check_result(result, "dns_request_getresponse"); 2795 2796 if (rcvmsg->rcode == dns_rcode_refused) { 2797 next_server("recvsoa", addr, DNS_R_REFUSED); 2798 dns_message_detach(&rcvmsg); 2799 dns_request_destroy(&request); 2800 dns_message_renderreset(soaquery); 2801 dns_message_settsigkey(soaquery, NULL); 2802 sendrequest(&servers[ns_inuse], soaquery, &request); 2803 return; 2804 } 2805 2806 section = DNS_SECTION_ANSWER; 2807 POST(section); 2808 if (debugging) { 2809 show_message(stderr, rcvmsg, "Reply from SOA query:"); 2810 } 2811 2812 if (rcvmsg->opcode != dns_opcode_query) { 2813 fatal("invalid OPCODE in response to SOA query"); 2814 } 2815 2816 if (rcvmsg->rcode != dns_rcode_noerror && 2817 rcvmsg->rcode != dns_rcode_nxdomain) 2818 { 2819 fatal("response to SOA query was unsuccessful"); 2820 } 2821 2822 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) { 2823 char namebuf[DNS_NAME_FORMATSIZE]; 2824 dns_name_format(userzone, namebuf, sizeof(namebuf)); 2825 error("specified zone '%s' does not exist (NXDOMAIN)", namebuf); 2826 dns_message_detach(&rcvmsg); 2827 dns_request_destroy(&request); 2828 dns_message_detach(&soaquery); 2829 ddebug("Out of recvsoa"); 2830 seenerror = true; 2831 done_update(); 2832 return; 2833 } 2834 2835 lookforsoa: 2836 if (pass == 0) { 2837 section = DNS_SECTION_ANSWER; 2838 } else if (pass == 1) { 2839 section = DNS_SECTION_AUTHORITY; 2840 } else { 2841 goto droplabel; 2842 } 2843 2844 result = dns_message_firstname(rcvmsg, section); 2845 if (result != ISC_R_SUCCESS) { 2846 pass++; 2847 goto lookforsoa; 2848 } 2849 while (result == ISC_R_SUCCESS) { 2850 name = NULL; 2851 dns_message_currentname(rcvmsg, section, &name); 2852 soaset = NULL; 2853 result = dns_message_findtype(name, dns_rdatatype_soa, 0, 2854 &soaset); 2855 if (result == ISC_R_SUCCESS) { 2856 break; 2857 } 2858 if (section == DNS_SECTION_ANSWER) { 2859 dns_rdataset_t *tset = NULL; 2860 if (dns_message_findtype(name, dns_rdatatype_cname, 0, 2861 &tset) == ISC_R_SUCCESS || 2862 dns_message_findtype(name, dns_rdatatype_dname, 0, 2863 &tset) == ISC_R_SUCCESS) 2864 { 2865 seencname = true; 2866 break; 2867 } 2868 } 2869 2870 result = dns_message_nextname(rcvmsg, section); 2871 } 2872 2873 if (soaset == NULL && !seencname) { 2874 pass++; 2875 goto lookforsoa; 2876 } 2877 2878 if (seencname) { 2879 goto droplabel; 2880 } 2881 2882 if (debugging) { 2883 char namestr[DNS_NAME_FORMATSIZE]; 2884 dns_name_format(name, namestr, sizeof(namestr)); 2885 fprintf(stderr, "Found zone name: %s\n", namestr); 2886 } 2887 2888 result = dns_rdataset_first(soaset); 2889 check_result(result, "dns_rdataset_first"); 2890 2891 dns_rdata_init(&soarr); 2892 dns_rdataset_current(soaset, &soarr); 2893 result = dns_rdata_tostruct(&soarr, &soa, NULL); 2894 check_result(result, "dns_rdata_tostruct"); 2895 2896 dns_name_init(&primary, NULL); 2897 dns_name_clone(&soa.origin, &primary); 2898 2899 if (userzone != NULL) { 2900 zname = userzone; 2901 } else { 2902 /* 2903 * Save the zone name in case we need to try a second 2904 * address. 2905 */ 2906 zname = dns_fixedname_initname(&fzname); 2907 dns_name_copy(name, zname); 2908 } 2909 2910 if (debugging) { 2911 char namestr[DNS_NAME_FORMATSIZE]; 2912 dns_name_format(&primary, namestr, sizeof(namestr)); 2913 fprintf(stderr, "The primary is: %s\n", namestr); 2914 } 2915 2916 if (default_servers) { 2917 char serverstr[DNS_NAME_MAXTEXT + 1]; 2918 isc_buffer_t buf; 2919 2920 isc_buffer_init(&buf, serverstr, sizeof(serverstr)); 2921 result = dns_name_totext(&primary, DNS_NAME_OMITFINALDOT, &buf); 2922 check_result(result, "dns_name_totext"); 2923 serverstr[isc_buffer_usedlength(&buf)] = 0; 2924 2925 if (primary_servers != NULL && primary_servers != servers) { 2926 isc_mem_cput(gmctx, primary_servers, primary_alloc, 2927 sizeof(isc_sockaddr_t)); 2928 } 2929 primary_alloc = MAX_SERVERADDRS; 2930 primary_servers = isc_mem_cget(gmctx, primary_alloc, 2931 sizeof(isc_sockaddr_t)); 2932 primary_total = get_addresses(serverstr, dnsport, 2933 primary_servers, primary_alloc); 2934 if (primary_total == 0) { 2935 seenerror = true; 2936 dns_rdata_freestruct(&soa); 2937 dns_message_detach(&soaquery); 2938 dns_request_destroy(&request); 2939 dns_message_detach(&rcvmsg); 2940 ddebug("Out of recvsoa"); 2941 done_update(); 2942 return; 2943 } 2944 primary_inuse = 0; 2945 } else { 2946 primary_from_servers(); 2947 } 2948 dns_rdata_freestruct(&soa); 2949 2950 #if HAVE_GSSAPI 2951 if (usegsstsig) { 2952 dns_name_init(&tmpzonename, NULL); 2953 dns_name_dup(zname, gmctx, &tmpzonename); 2954 dns_name_init(&restart_primary, NULL); 2955 dns_name_dup(&primary, gmctx, &restart_primary); 2956 start_gssrequest(&primary); 2957 } else { 2958 send_update(zname, &primary_servers[primary_inuse]); 2959 setzoneclass(dns_rdataclass_none); 2960 } 2961 #else /* HAVE_GSSAPI */ 2962 send_update(zname, &primary_servers[primary_inuse]); 2963 setzoneclass(dns_rdataclass_none); 2964 #endif /* HAVE_GSSAPI */ 2965 2966 dns_message_detach(&soaquery); 2967 dns_request_destroy(&request); 2968 2969 out: 2970 dns_message_detach(&rcvmsg); 2971 ddebug("Out of recvsoa"); 2972 return; 2973 2974 droplabel: 2975 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); 2976 INSIST(result == ISC_R_SUCCESS); 2977 name = NULL; 2978 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); 2979 nlabels = dns_name_countlabels(name); 2980 if (nlabels == 1) { 2981 fatal("could not find enclosing zone"); 2982 } 2983 dns_name_init(&tname, NULL); 2984 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname); 2985 dns_name_clone(&tname, name); 2986 dns_request_destroy(&request); 2987 dns_message_renderreset(soaquery); 2988 dns_message_settsigkey(soaquery, NULL); 2989 sendrequest(&servers[ns_inuse], soaquery, &request); 2990 goto out; 2991 } 2992 2993 static void 2994 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, 2995 dns_request_t **request) { 2996 isc_result_t result; 2997 nsu_requestinfo_t *reqinfo; 2998 isc_sockaddr_t *srcaddr; 2999 unsigned int options = DNS_REQUESTOPT_CASE; 3000 dns_transport_t *req_transport = NULL; 3001 isc_tlsctx_cache_t *req_tls_ctx_cache = NULL; 3002 3003 if (!default_servers && usevc) { 3004 options |= DNS_REQUESTOPT_TCP; 3005 if (use_tls) { 3006 req_transport = transport; 3007 req_tls_ctx_cache = tls_ctx_cache; 3008 } 3009 } 3010 3011 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t)); 3012 reqinfo->msg = msg; 3013 reqinfo->addr = destaddr; 3014 3015 if (isc_sockaddr_pf(destaddr) == AF_INET6) { 3016 srcaddr = localaddr6; 3017 } else { 3018 srcaddr = localaddr4; 3019 } 3020 3021 result = dns_request_create( 3022 requestmgr, msg, srcaddr, destaddr, req_transport, 3023 req_tls_ctx_cache, options, default_servers ? NULL : tsigkey, 3024 timeout, udp_timeout, udp_retries, isc_loop_main(loopmgr), 3025 recvsoa, reqinfo, request); 3026 check_result(result, "dns_request_create"); 3027 requests++; 3028 } 3029 3030 #if HAVE_GSSAPI 3031 3032 /* 3033 * Get the realm from the users kerberos ticket if possible 3034 */ 3035 static void 3036 get_ticket_realm(isc_mem_t *mctx) { 3037 krb5_context ctx; 3038 krb5_error_code rc; 3039 krb5_ccache ccache; 3040 krb5_principal princ; 3041 char *name; 3042 const char *ticket_realm; 3043 3044 rc = krb5_init_context(&ctx); 3045 if (rc != 0) { 3046 return; 3047 } 3048 3049 rc = krb5_cc_default(ctx, &ccache); 3050 if (rc != 0) { 3051 krb5_free_context(ctx); 3052 return; 3053 } 3054 3055 rc = krb5_cc_get_principal(ctx, ccache, &princ); 3056 if (rc != 0) { 3057 krb5_cc_close(ctx, ccache); 3058 krb5_free_context(ctx); 3059 return; 3060 } 3061 3062 rc = krb5_unparse_name(ctx, princ, &name); 3063 if (rc != 0) { 3064 krb5_free_principal(ctx, princ); 3065 krb5_cc_close(ctx, ccache); 3066 krb5_free_context(ctx); 3067 return; 3068 } 3069 3070 ticket_realm = strrchr(name, '@'); 3071 if (ticket_realm != NULL) { 3072 realm = isc_mem_strdup(mctx, ticket_realm); 3073 } 3074 3075 free(name); 3076 krb5_free_principal(ctx, princ); 3077 krb5_cc_close(ctx, ccache); 3078 krb5_free_context(ctx); 3079 if (realm != NULL && debugging) { 3080 fprintf(stderr, "Found realm from ticket: %s\n", realm + 1); 3081 } 3082 } 3083 3084 static void 3085 failed_gssrequest(void) { 3086 seenerror = true; 3087 3088 dns_name_free(&tmpzonename, gmctx); 3089 dns_name_free(&restart_primary, gmctx); 3090 dns_name_init(&tmpzonename, NULL); 3091 dns_name_init(&restart_primary, NULL); 3092 3093 done_update(); 3094 } 3095 3096 static void 3097 start_gssrequest(dns_name_t *primary) { 3098 dns_gss_ctx_id_t context; 3099 isc_buffer_t buf; 3100 isc_result_t result; 3101 uint32_t val = 0; 3102 dns_message_t *rmsg = NULL; 3103 dns_request_t *request = NULL; 3104 dns_name_t *servname; 3105 dns_fixedname_t fname; 3106 char namestr[DNS_NAME_FORMATSIZE]; 3107 char mykeystr[DNS_NAME_FORMATSIZE]; 3108 char *err_message = NULL; 3109 3110 debug("start_gssrequest"); 3111 usevc = true; 3112 3113 if (gssring != NULL) { 3114 dns_tsigkeyring_detach(&gssring); 3115 } 3116 3117 dns_tsigkeyring_create(gmctx, &gssring); 3118 3119 dns_name_format(primary, namestr, sizeof(namestr)); 3120 if (kserver == NULL) { 3121 kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); 3122 } 3123 3124 memmove(kserver, &primary_servers[primary_inuse], 3125 sizeof(isc_sockaddr_t)); 3126 3127 servname = dns_fixedname_initname(&fname); 3128 3129 if (realm == NULL) { 3130 get_ticket_realm(gmctx); 3131 } 3132 3133 result = snprintf(servicename, sizeof(servicename), "DNS/%s%s", namestr, 3134 realm ? realm : ""); 3135 RUNTIME_CHECK(result < sizeof(servicename)); 3136 isc_buffer_init(&buf, servicename, strlen(servicename)); 3137 isc_buffer_add(&buf, strlen(servicename)); 3138 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); 3139 if (result != ISC_R_SUCCESS) { 3140 fatal("dns_name_fromtext(servname) failed: %s", 3141 isc_result_totext(result)); 3142 } 3143 3144 keyname = dns_fixedname_initname(&fkname); 3145 3146 isc_nonce_buf(&val, sizeof(val)); 3147 3148 result = snprintf(mykeystr, sizeof(mykeystr), "%u.sig-%s", val, 3149 namestr); 3150 RUNTIME_CHECK(result <= sizeof(mykeystr)); 3151 3152 isc_buffer_init(&buf, mykeystr, strlen(mykeystr)); 3153 isc_buffer_add(&buf, strlen(mykeystr)); 3154 3155 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); 3156 if (result != ISC_R_SUCCESS) { 3157 fatal("dns_name_fromtext(keyname) failed: %s", 3158 isc_result_totext(result)); 3159 } 3160 3161 /* Windows doesn't recognize name compression in the key name. */ 3162 keyname->attributes.nocompress = true; 3163 3164 rmsg = NULL; 3165 dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, &rmsg); 3166 3167 /* Build first request. */ 3168 context = GSS_C_NO_CONTEXT; 3169 result = dns_tkey_buildgssquery(rmsg, keyname, servname, 0, &context, 3170 gmctx, &err_message); 3171 if (result == ISC_R_FAILURE) { 3172 fprintf(stderr, "tkey query failed: %s\n", 3173 err_message != NULL ? err_message : "unknown error"); 3174 goto failure; 3175 } 3176 if (result != ISC_R_SUCCESS) { 3177 fatal("dns_tkey_buildgssquery failed: %s", 3178 isc_result_totext(result)); 3179 } 3180 3181 send_gssrequest(kserver, rmsg, &request, context); 3182 return; 3183 3184 failure: 3185 if (rmsg != NULL) { 3186 dns_message_detach(&rmsg); 3187 } 3188 if (err_message != NULL) { 3189 isc_mem_free(gmctx, err_message); 3190 } 3191 failed_gssrequest(); 3192 } 3193 3194 static void 3195 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, 3196 dns_request_t **request, gss_ctx_id_t context) { 3197 isc_result_t result; 3198 nsu_gssinfo_t *reqinfo = NULL; 3199 isc_sockaddr_t *srcaddr = NULL; 3200 unsigned int options = DNS_REQUESTOPT_CASE | DNS_REQUESTOPT_TCP; 3201 dns_transport_t *req_transport = NULL; 3202 isc_tlsctx_cache_t *req_tls_ctx_cache = NULL; 3203 3204 if (!default_servers && use_tls) { 3205 req_transport = transport; 3206 req_tls_ctx_cache = tls_ctx_cache; 3207 } 3208 3209 debug("send_gssrequest"); 3210 REQUIRE(destaddr != NULL); 3211 3212 reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t)); 3213 *reqinfo = (nsu_gssinfo_t){ 3214 .msg = msg, 3215 .addr = destaddr, 3216 .context = context, 3217 }; 3218 3219 if (isc_sockaddr_pf(destaddr) == AF_INET6) { 3220 srcaddr = localaddr6; 3221 } else { 3222 srcaddr = localaddr4; 3223 } 3224 3225 result = dns_request_create( 3226 requestmgr, msg, srcaddr, destaddr, req_transport, 3227 req_tls_ctx_cache, options, tsigkey, timeout, udp_timeout, 3228 udp_retries, isc_loop_main(loopmgr), recvgss, reqinfo, request); 3229 check_result(result, "dns_request_create"); 3230 if (debugging) { 3231 show_message(stdout, msg, "Outgoing update query:"); 3232 } 3233 requests++; 3234 } 3235 3236 static void 3237 recvgss(void *arg) { 3238 dns_request_t *request = (dns_request_t *)arg; 3239 nsu_gssinfo_t *reqinfo = dns_request_getarg(request); 3240 isc_result_t result, eresult = dns_request_getresult(request); 3241 dns_message_t *rcvmsg = NULL; 3242 dns_message_t *tsigquery = reqinfo->msg; 3243 dns_gss_ctx_id_t context = reqinfo->context; 3244 isc_sockaddr_t *addr = reqinfo->addr; 3245 isc_buffer_t buf; 3246 dns_name_t *servname = NULL; 3247 dns_fixedname_t fname; 3248 char *err_message = NULL; 3249 3250 ddebug("recvgss()"); 3251 3252 requests--; 3253 3254 if (shuttingdown) { 3255 dns_request_destroy(&request); 3256 dns_message_detach(&tsigquery); 3257 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); 3258 maybeshutdown(); 3259 return; 3260 } 3261 3262 if (eresult != ISC_R_SUCCESS) { 3263 ddebug("Destroying request [%p]", request); 3264 dns_request_destroy(&request); 3265 if (!next_primary("recvgss", addr, eresult)) { 3266 dns_message_detach(&tsigquery); 3267 failed_gssrequest(); 3268 } else { 3269 dns_message_renderreset(tsigquery); 3270 memmove(kserver, &primary_servers[primary_inuse], 3271 sizeof(isc_sockaddr_t)); 3272 send_gssrequest(kserver, tsigquery, &request, context); 3273 } 3274 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); 3275 return; 3276 } 3277 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); 3278 3279 ddebug("recvgss creating rcvmsg"); 3280 dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 3281 3282 result = dns_request_getresponse(request, rcvmsg, 3283 DNS_MESSAGEPARSE_PRESERVEORDER); 3284 check_result(result, "dns_request_getresponse"); 3285 3286 if (debugging) { 3287 show_message(stderr, rcvmsg, 3288 "recvmsg reply from GSS-TSIG query"); 3289 } 3290 3291 if (rcvmsg->opcode != dns_opcode_query) { 3292 fatal("invalid OPCODE in response to GSS-TSIG query"); 3293 } 3294 3295 if (rcvmsg->rcode != dns_rcode_noerror && 3296 rcvmsg->rcode != dns_rcode_nxdomain) 3297 { 3298 char rcode[64]; 3299 isc_buffer_t b; 3300 3301 isc_buffer_init(&b, rcode, sizeof(rcode) - 1); 3302 result = dns_rcode_totext(rcvmsg->rcode, &b); 3303 check_result(result, "dns_rcode_totext"); 3304 rcode[isc_buffer_usedlength(&b)] = 0; 3305 3306 fatal("response to GSS-TSIG query was unsuccessful (%s)", 3307 rcode); 3308 } 3309 3310 servname = dns_fixedname_initname(&fname); 3311 isc_buffer_init(&buf, servicename, strlen(servicename)); 3312 isc_buffer_add(&buf, strlen(servicename)); 3313 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); 3314 check_result(result, "dns_name_fromtext"); 3315 3316 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context, 3317 &tsigkey, gssring, &err_message); 3318 switch (result) { 3319 case DNS_R_CONTINUE: 3320 dns_message_detach(&rcvmsg); 3321 dns_request_destroy(&request); 3322 send_gssrequest(kserver, tsigquery, &request, context); 3323 ddebug("Out of recvgss"); 3324 return; 3325 3326 case ISC_R_SUCCESS: 3327 /* 3328 * XXXSRA Waaay too much fun here. There's no good 3329 * reason why we need a TSIG here (the people who put 3330 * it into the spec admitted at the time that it was 3331 * not a security issue), and Windows clients don't 3332 * seem to work if named complies with the spec and 3333 * includes the gratuitous TSIG. So we're in the 3334 * bizarre situation of having to choose between 3335 * complying with a useless requirement in the spec 3336 * and interoperating. This is nuts. If we can 3337 * confirm this behavior, we should ask the WG to 3338 * consider removing the requirement for the 3339 * gratuitous TSIG here. For the moment, we ignore 3340 * the TSIG -- this too is a spec violation, but it's 3341 * the least insane thing to do. 3342 */ 3343 3344 send_update(&tmpzonename, &primary_servers[primary_inuse]); 3345 setzoneclass(dns_rdataclass_none); 3346 break; 3347 3348 default: 3349 fatal("dns_tkey_gssnegotiate: %s %s", isc_result_totext(result), 3350 err_message != NULL ? err_message : ""); 3351 } 3352 3353 dns_request_destroy(&request); 3354 dns_message_detach(&tsigquery); 3355 3356 dns_message_detach(&rcvmsg); 3357 ddebug("Out of recvgss"); 3358 } 3359 #endif /* HAVE_GSSAPI */ 3360 3361 static void 3362 start_update(void) { 3363 isc_result_t result; 3364 dns_rdataset_t *rdataset = NULL; 3365 dns_name_t *name = NULL; 3366 dns_request_t *request = NULL; 3367 dns_message_t *soaquery = NULL; 3368 dns_name_t *firstname; 3369 dns_section_t section = DNS_SECTION_UPDATE; 3370 3371 ddebug("start_update()"); 3372 3373 LOCK(&answer_lock); 3374 if (answer != NULL) { 3375 dns_message_detach(&answer); 3376 } 3377 UNLOCK(&answer_lock); 3378 3379 /* 3380 * If we have both the zone and the servers we have enough information 3381 * to send the update straight away otherwise we need to discover 3382 * the zone and / or the primary server. 3383 */ 3384 if (userzone != NULL && !default_servers && !usegsstsig) { 3385 primary_from_servers(); 3386 send_update(userzone, &primary_servers[primary_inuse]); 3387 setzoneclass(dns_rdataclass_none); 3388 return; 3389 } 3390 3391 dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, 3392 &soaquery); 3393 3394 if (default_servers) { 3395 soaquery->flags |= DNS_MESSAGEFLAG_RD; 3396 } 3397 3398 dns_message_gettempname(soaquery, &name); 3399 3400 dns_message_gettemprdataset(soaquery, &rdataset); 3401 3402 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); 3403 3404 if (userzone != NULL) { 3405 dns_name_clone(userzone, name); 3406 } else { 3407 dns_rdataset_t *tmprdataset; 3408 result = dns_message_firstname(updatemsg, section); 3409 if (result == ISC_R_NOMORE) { 3410 section = DNS_SECTION_PREREQUISITE; 3411 result = dns_message_firstname(updatemsg, section); 3412 } 3413 if (result != ISC_R_SUCCESS) { 3414 dns_message_puttempname(soaquery, &name); 3415 dns_rdataset_disassociate(rdataset); 3416 dns_message_puttemprdataset(soaquery, &rdataset); 3417 dns_message_detach(&soaquery); 3418 done_update(); 3419 return; 3420 } 3421 firstname = NULL; 3422 dns_message_currentname(updatemsg, section, &firstname); 3423 dns_name_clone(firstname, name); 3424 /* 3425 * Looks to see if the first name references a DS record 3426 * and if that name is not the root remove a label as DS 3427 * records live in the parent zone so we need to start our 3428 * search one label up. 3429 */ 3430 tmprdataset = ISC_LIST_HEAD(firstname->list); 3431 if (section == DNS_SECTION_UPDATE && 3432 !dns_name_equal(firstname, dns_rootname) && 3433 tmprdataset->type == dns_rdatatype_ds) 3434 { 3435 unsigned int labels = dns_name_countlabels(name); 3436 dns_name_getlabelsequence(name, 1, labels - 1, name); 3437 } 3438 } 3439 3440 ISC_LIST_INIT(name->list); 3441 ISC_LIST_APPEND(name->list, rdataset, link); 3442 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); 3443 3444 ns_inuse = 0; 3445 sendrequest(&servers[ns_inuse], soaquery, &request); 3446 } 3447 3448 static void 3449 cleanup(void) { 3450 ddebug("cleanup()"); 3451 3452 if (tls_ctx_cache != NULL) { 3453 isc_tlsctx_cache_detach(&tls_ctx_cache); 3454 } 3455 3456 if (transport_list != NULL) { 3457 dns_transport_list_detach(&transport_list); 3458 } 3459 3460 LOCK(&answer_lock); 3461 if (answer != NULL) { 3462 dns_message_detach(&answer); 3463 } 3464 UNLOCK(&answer_lock); 3465 3466 #if HAVE_GSSAPI 3467 if (tsigkey != NULL) { 3468 ddebug("detach tsigkey x%p", tsigkey); 3469 dns_tsigkey_detach(&tsigkey); 3470 } 3471 if (gssring != NULL) { 3472 ddebug("Detaching GSS-TSIG keyring"); 3473 dns_tsigkeyring_detach(&gssring); 3474 } 3475 #endif /* ifdef HAVE_GSSAPI */ 3476 3477 if (sig0key != NULL) { 3478 dst_key_free(&sig0key); 3479 } 3480 3481 #ifdef HAVE_GSSAPI 3482 if (kserver != NULL) { 3483 isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t)); 3484 kserver = NULL; 3485 } 3486 if (realm != NULL) { 3487 isc_mem_free(gmctx, realm); 3488 realm = NULL; 3489 } 3490 if (dns_name_dynamic(&tmpzonename)) { 3491 dns_name_free(&tmpzonename, gmctx); 3492 } 3493 if (dns_name_dynamic(&restart_primary)) { 3494 dns_name_free(&restart_primary, gmctx); 3495 } 3496 #endif /* ifdef HAVE_GSSAPI */ 3497 3498 ddebug("Removing log context"); 3499 isc_log_destroy(&glctx); 3500 3501 ddebug("Destroying memory context"); 3502 if (memdebugging) { 3503 isc_mem_stats(gmctx, stderr); 3504 } 3505 3506 isc_mutex_destroy(&answer_lock); 3507 3508 if (is_dst_up) { 3509 ddebug("Destroy DST lib"); 3510 dst_lib_destroy(); 3511 is_dst_up = false; 3512 } 3513 3514 ddebug("Shutting down managers"); 3515 isc_managers_destroy(&gmctx, &loopmgr, &netmgr); 3516 } 3517 3518 static void 3519 getinput(void *arg) { 3520 bool more; 3521 3522 UNUSED(arg); 3523 3524 if (shuttingdown) { 3525 maybeshutdown(); 3526 return; 3527 } 3528 3529 reset_system(); 3530 isc_loopmgr_blocking(loopmgr); 3531 more = user_interaction(); 3532 isc_loopmgr_nonblocking(loopmgr); 3533 if (!more) { 3534 isc_loopmgr_shutdown(loopmgr); 3535 return; 3536 } 3537 3538 done = false; 3539 start_update(); 3540 } 3541 3542 int 3543 main(int argc, char **argv) { 3544 uint32_t timeoutms; 3545 3546 style = &dns_master_style_debug; 3547 3548 input = stdin; 3549 3550 interactive = isatty(0); 3551 3552 if (isc_net_probeipv4() == ISC_R_SUCCESS) { 3553 have_ipv4 = true; 3554 } 3555 if (isc_net_probeipv6() == ISC_R_SUCCESS) { 3556 have_ipv6 = true; 3557 } 3558 if (!have_ipv4 && !have_ipv6) { 3559 fatal("could not find either IPv4 or IPv6"); 3560 } 3561 3562 pre_parse_args(argc, argv); 3563 3564 isc_managers_create(&gmctx, 1, &loopmgr, &netmgr); 3565 3566 parse_args(argc, argv); 3567 3568 /* Set the network manager timeouts in milliseconds. */ 3569 timeoutms = timeout * 1000; 3570 isc_nm_settimeouts(netmgr, timeoutms, timeoutms, timeoutms, timeoutms); 3571 3572 isc_loopmgr_setup(loopmgr, setup_system, NULL); 3573 isc_loopmgr_setup(loopmgr, getinput, NULL); 3574 isc_loopmgr_teardown(loopmgr, shutdown_program, NULL); 3575 isc_loopmgr_run(loopmgr); 3576 3577 cleanup(); 3578 3579 if (seenerror) { 3580 return 2; 3581 } 3582 3583 return 0; 3584 } 3585