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