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