1 /* $NetBSD: nsupdate.c,v 1.12 2023/01/25 21:43:23 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 done_update(); 2711 seenerror = true; 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 exit(1); 2819 } 2820 master_inuse = 0; 2821 } else { 2822 master_from_servers(); 2823 } 2824 dns_rdata_freestruct(&soa); 2825 2826 #ifdef GSSAPI 2827 if (usegsstsig) { 2828 dns_name_init(&tmpzonename, NULL); 2829 dns_name_dup(zname, gmctx, &tmpzonename); 2830 dns_name_init(&restart_master, NULL); 2831 dns_name_dup(&master, gmctx, &restart_master); 2832 start_gssrequest(&master); 2833 } else { 2834 send_update(zname, &master_servers[master_inuse]); 2835 setzoneclass(dns_rdataclass_none); 2836 } 2837 #else /* ifdef GSSAPI */ 2838 send_update(zname, &master_servers[master_inuse]); 2839 setzoneclass(dns_rdataclass_none); 2840 #endif /* ifdef GSSAPI */ 2841 2842 dns_message_detach(&soaquery); 2843 dns_request_destroy(&request); 2844 2845 out: 2846 dns_message_detach(&rcvmsg); 2847 ddebug("Out of recvsoa"); 2848 return; 2849 2850 droplabel: 2851 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); 2852 INSIST(result == ISC_R_SUCCESS); 2853 name = NULL; 2854 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); 2855 nlabels = dns_name_countlabels(name); 2856 if (nlabels == 1) { 2857 fatal("could not find enclosing zone"); 2858 } 2859 dns_name_init(&tname, NULL); 2860 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname); 2861 dns_name_clone(&tname, name); 2862 dns_request_destroy(&request); 2863 dns_message_renderreset(soaquery); 2864 dns_message_settsigkey(soaquery, NULL); 2865 sendrequest(&servers[ns_inuse], soaquery, &request); 2866 goto out; 2867 } 2868 2869 static void 2870 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, 2871 dns_request_t **request) { 2872 isc_result_t result; 2873 nsu_requestinfo_t *reqinfo; 2874 isc_sockaddr_t *srcaddr; 2875 2876 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t)); 2877 reqinfo->msg = msg; 2878 reqinfo->addr = destaddr; 2879 2880 if (isc_sockaddr_pf(destaddr) == AF_INET6) { 2881 srcaddr = localaddr6; 2882 } else { 2883 srcaddr = localaddr4; 2884 } 2885 2886 result = dns_request_createvia(requestmgr, msg, srcaddr, destaddr, -1, 2887 0, default_servers ? NULL : tsigkey, 2888 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, 2889 global_task, recvsoa, reqinfo, request); 2890 check_result(result, "dns_request_createvia"); 2891 requests++; 2892 } 2893 2894 #ifdef GSSAPI 2895 2896 /* 2897 * Get the realm from the users kerberos ticket if possible 2898 */ 2899 static void 2900 get_ticket_realm(isc_mem_t *mctx) { 2901 krb5_context ctx; 2902 krb5_error_code rc; 2903 krb5_ccache ccache; 2904 krb5_principal princ; 2905 char *name; 2906 const char *ticket_realm; 2907 2908 rc = krb5_init_context(&ctx); 2909 if (rc != 0) { 2910 return; 2911 } 2912 2913 rc = krb5_cc_default(ctx, &ccache); 2914 if (rc != 0) { 2915 krb5_free_context(ctx); 2916 return; 2917 } 2918 2919 rc = krb5_cc_get_principal(ctx, ccache, &princ); 2920 if (rc != 0) { 2921 krb5_cc_close(ctx, ccache); 2922 krb5_free_context(ctx); 2923 return; 2924 } 2925 2926 rc = krb5_unparse_name(ctx, princ, &name); 2927 if (rc != 0) { 2928 krb5_free_principal(ctx, princ); 2929 krb5_cc_close(ctx, ccache); 2930 krb5_free_context(ctx); 2931 return; 2932 } 2933 2934 ticket_realm = strrchr(name, '@'); 2935 if (ticket_realm != NULL) { 2936 realm = isc_mem_strdup(mctx, ticket_realm); 2937 } 2938 2939 free(name); 2940 krb5_free_principal(ctx, princ); 2941 krb5_cc_close(ctx, ccache); 2942 krb5_free_context(ctx); 2943 if (realm != NULL && debugging) { 2944 fprintf(stderr, "Found realm from ticket: %s\n", realm + 1); 2945 } 2946 } 2947 2948 static void 2949 failed_gssrequest(void) { 2950 seenerror = true; 2951 2952 dns_name_free(&tmpzonename, gmctx); 2953 dns_name_free(&restart_master, gmctx); 2954 dns_name_init(&tmpzonename, NULL); 2955 dns_name_init(&restart_master, NULL); 2956 2957 done_update(); 2958 } 2959 2960 static void 2961 start_gssrequest(dns_name_t *master) { 2962 dns_gss_ctx_id_t context; 2963 isc_buffer_t buf; 2964 isc_result_t result; 2965 uint32_t val = 0; 2966 dns_message_t *rmsg = NULL; 2967 dns_request_t *request = NULL; 2968 dns_name_t *servname; 2969 dns_fixedname_t fname; 2970 char namestr[DNS_NAME_FORMATSIZE]; 2971 char mykeystr[DNS_NAME_FORMATSIZE]; 2972 char *err_message = NULL; 2973 2974 debug("start_gssrequest"); 2975 usevc = true; 2976 2977 if (gssring != NULL) { 2978 dns_tsigkeyring_detach(&gssring); 2979 } 2980 gssring = NULL; 2981 result = dns_tsigkeyring_create(gmctx, &gssring); 2982 2983 if (result != ISC_R_SUCCESS) { 2984 fatal("dns_tsigkeyring_create failed: %s", 2985 isc_result_totext(result)); 2986 } 2987 2988 dns_name_format(master, namestr, sizeof(namestr)); 2989 if (kserver == NULL) { 2990 kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); 2991 } 2992 2993 memmove(kserver, &master_servers[master_inuse], sizeof(isc_sockaddr_t)); 2994 2995 servname = dns_fixedname_initname(&fname); 2996 2997 if (realm == NULL) { 2998 get_ticket_realm(gmctx); 2999 } 3000 3001 result = snprintf(servicename, sizeof(servicename), "DNS/%s%s", namestr, 3002 realm ? realm : ""); 3003 RUNTIME_CHECK(result < sizeof(servicename)); 3004 isc_buffer_init(&buf, servicename, strlen(servicename)); 3005 isc_buffer_add(&buf, strlen(servicename)); 3006 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); 3007 if (result != ISC_R_SUCCESS) { 3008 fatal("dns_name_fromtext(servname) failed: %s", 3009 isc_result_totext(result)); 3010 } 3011 3012 keyname = dns_fixedname_initname(&fkname); 3013 3014 isc_nonce_buf(&val, sizeof(val)); 3015 3016 result = snprintf(mykeystr, sizeof(mykeystr), "%u.sig-%s", val, 3017 namestr); 3018 RUNTIME_CHECK(result <= sizeof(mykeystr)); 3019 3020 isc_buffer_init(&buf, mykeystr, strlen(mykeystr)); 3021 isc_buffer_add(&buf, strlen(mykeystr)); 3022 3023 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); 3024 if (result != ISC_R_SUCCESS) { 3025 fatal("dns_name_fromtext(keyname) failed: %s", 3026 isc_result_totext(result)); 3027 } 3028 3029 /* Windows doesn't recognize name compression in the key name. */ 3030 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 3031 3032 rmsg = NULL; 3033 dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &rmsg); 3034 3035 /* Build first request. */ 3036 context = GSS_C_NO_CONTEXT; 3037 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0, 3038 &context, use_win2k_gsstsig, gmctx, 3039 &err_message); 3040 if (result == ISC_R_FAILURE) { 3041 fprintf(stderr, "tkey query failed: %s\n", 3042 err_message != NULL ? err_message : "unknown error"); 3043 goto failure; 3044 } 3045 if (result != ISC_R_SUCCESS) { 3046 fatal("dns_tkey_buildgssquery failed: %s", 3047 isc_result_totext(result)); 3048 } 3049 3050 send_gssrequest(kserver, rmsg, &request, context); 3051 return; 3052 3053 failure: 3054 if (rmsg != NULL) { 3055 dns_message_detach(&rmsg); 3056 } 3057 if (err_message != NULL) { 3058 isc_mem_free(gmctx, err_message); 3059 } 3060 failed_gssrequest(); 3061 } 3062 3063 static void 3064 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, 3065 dns_request_t **request, dns_gss_ctx_id_t context) { 3066 isc_result_t result; 3067 nsu_gssinfo_t *reqinfo; 3068 unsigned int options = 0; 3069 isc_sockaddr_t *srcaddr; 3070 3071 debug("send_gssrequest"); 3072 REQUIRE(destaddr != NULL); 3073 3074 reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t)); 3075 reqinfo->msg = msg; 3076 reqinfo->addr = destaddr; 3077 reqinfo->context = context; 3078 3079 options |= DNS_REQUESTOPT_TCP; 3080 3081 if (isc_sockaddr_pf(destaddr) == AF_INET6) { 3082 srcaddr = localaddr6; 3083 } else { 3084 srcaddr = localaddr4; 3085 } 3086 3087 result = dns_request_createvia(requestmgr, msg, srcaddr, destaddr, -1, 3088 options, tsigkey, FIND_TIMEOUT * 20, 3089 FIND_TIMEOUT, 3, global_task, recvgss, 3090 reqinfo, request); 3091 check_result(result, "dns_request_createvia"); 3092 if (debugging) { 3093 show_message(stdout, msg, "Outgoing update query:"); 3094 } 3095 requests++; 3096 } 3097 3098 static void 3099 recvgss(isc_task_t *task, isc_event_t *event) { 3100 dns_requestevent_t *reqev = NULL; 3101 dns_request_t *request = NULL; 3102 isc_result_t result, eresult; 3103 dns_message_t *rcvmsg = NULL; 3104 nsu_gssinfo_t *reqinfo; 3105 dns_message_t *tsigquery = NULL; 3106 isc_sockaddr_t *addr; 3107 dns_gss_ctx_id_t context; 3108 isc_buffer_t buf; 3109 dns_name_t *servname; 3110 dns_fixedname_t fname; 3111 char *err_message = NULL; 3112 3113 UNUSED(task); 3114 3115 ddebug("recvgss()"); 3116 3117 requests--; 3118 3119 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 3120 reqev = (dns_requestevent_t *)event; 3121 request = reqev->request; 3122 eresult = reqev->result; 3123 reqinfo = reqev->ev_arg; 3124 tsigquery = reqinfo->msg; 3125 context = reqinfo->context; 3126 addr = reqinfo->addr; 3127 3128 if (shuttingdown) { 3129 dns_request_destroy(&request); 3130 dns_message_detach(&tsigquery); 3131 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); 3132 isc_event_free(&event); 3133 maybeshutdown(); 3134 return; 3135 } 3136 3137 if (eresult != ISC_R_SUCCESS) { 3138 ddebug("Destroying request [%p]", request); 3139 dns_request_destroy(&request); 3140 if (!next_master("recvgss", addr, eresult)) { 3141 dns_message_detach(&tsigquery); 3142 failed_gssrequest(); 3143 } else { 3144 dns_message_renderreset(tsigquery); 3145 memmove(kserver, &master_servers[master_inuse], 3146 sizeof(isc_sockaddr_t)); 3147 send_gssrequest(kserver, tsigquery, &request, context); 3148 } 3149 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); 3150 isc_event_free(&event); 3151 return; 3152 } 3153 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); 3154 3155 isc_event_free(&event); 3156 reqev = NULL; 3157 3158 ddebug("recvgss creating rcvmsg"); 3159 dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 3160 3161 result = dns_request_getresponse(request, rcvmsg, 3162 DNS_MESSAGEPARSE_PRESERVEORDER); 3163 check_result(result, "dns_request_getresponse"); 3164 3165 if (debugging) { 3166 show_message(stderr, rcvmsg, 3167 "recvmsg reply from GSS-TSIG query"); 3168 } 3169 3170 if (rcvmsg->opcode != dns_opcode_query) { 3171 fatal("invalid OPCODE in response to GSS-TSIG query"); 3172 } 3173 3174 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) { 3175 ddebug("recvgss trying %s GSS-TSIG", 3176 use_win2k_gsstsig ? "Standard" : "Win2k"); 3177 if (use_win2k_gsstsig) { 3178 use_win2k_gsstsig = false; 3179 } else { 3180 use_win2k_gsstsig = true; 3181 } 3182 tried_other_gsstsig = true; 3183 start_gssrequest(&restart_master); 3184 goto done; 3185 } 3186 3187 if (rcvmsg->rcode != dns_rcode_noerror && 3188 rcvmsg->rcode != dns_rcode_nxdomain) 3189 { 3190 fatal("response to GSS-TSIG query was unsuccessful"); 3191 } 3192 3193 servname = dns_fixedname_initname(&fname); 3194 isc_buffer_init(&buf, servicename, strlen(servicename)); 3195 isc_buffer_add(&buf, strlen(servicename)); 3196 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); 3197 check_result(result, "dns_name_fromtext"); 3198 3199 tsigkey = NULL; 3200 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context, 3201 &tsigkey, gssring, use_win2k_gsstsig, 3202 &err_message); 3203 switch (result) { 3204 case DNS_R_CONTINUE: 3205 dns_message_detach(&rcvmsg); 3206 dns_request_destroy(&request); 3207 send_gssrequest(kserver, tsigquery, &request, context); 3208 ddebug("Out of recvgss"); 3209 return; 3210 3211 case ISC_R_SUCCESS: 3212 /* 3213 * XXXSRA Waaay too much fun here. There's no good 3214 * reason why we need a TSIG here (the people who put 3215 * it into the spec admitted at the time that it was 3216 * not a security issue), and Windows clients don't 3217 * seem to work if named complies with the spec and 3218 * includes the gratuitous TSIG. So we're in the 3219 * bizarre situation of having to choose between 3220 * complying with a useless requirement in the spec 3221 * and interoperating. This is nuts. If we can 3222 * confirm this behavior, we should ask the WG to 3223 * consider removing the requirement for the 3224 * gratuitous TSIG here. For the moment, we ignore 3225 * the TSIG -- this too is a spec violation, but it's 3226 * the least insane thing to do. 3227 */ 3228 #if 0 3229 /* 3230 * Verify the signature. 3231 */ 3232 rcvmsg->state = DNS_SECTION_ANY; 3233 dns_message_setquerytsig(rcvmsg, NULL); 3234 result = dns_message_settsigkey(rcvmsg, tsigkey); 3235 check_result(result, "dns_message_settsigkey"); 3236 result = dns_message_checksig(rcvmsg, NULL); 3237 ddebug("tsig verification: %s", dns_result_totext(result)); 3238 check_result(result, "dns_message_checksig"); 3239 #endif /* 0 */ 3240 3241 send_update(&tmpzonename, &master_servers[master_inuse]); 3242 setzoneclass(dns_rdataclass_none); 3243 break; 3244 3245 default: 3246 fatal("dns_tkey_gssnegotiate: %s %s", isc_result_totext(result), 3247 err_message != NULL ? err_message : ""); 3248 } 3249 3250 done: 3251 dns_request_destroy(&request); 3252 dns_message_detach(&tsigquery); 3253 3254 dns_message_detach(&rcvmsg); 3255 ddebug("Out of recvgss"); 3256 } 3257 #endif /* ifdef GSSAPI */ 3258 3259 static void 3260 start_update(void) { 3261 isc_result_t result; 3262 dns_rdataset_t *rdataset = NULL; 3263 dns_name_t *name = NULL; 3264 dns_request_t *request = NULL; 3265 dns_message_t *soaquery = NULL; 3266 dns_name_t *firstname; 3267 dns_section_t section = DNS_SECTION_UPDATE; 3268 3269 ddebug("start_update()"); 3270 3271 LOCK(&answer_lock); 3272 if (answer != NULL) { 3273 dns_message_detach(&answer); 3274 } 3275 UNLOCK(&answer_lock); 3276 3277 /* 3278 * If we have both the zone and the servers we have enough information 3279 * to send the update straight away otherwise we need to discover 3280 * the zone and / or the master server. 3281 */ 3282 if (userzone != NULL && !default_servers && !usegsstsig) { 3283 master_from_servers(); 3284 send_update(userzone, &master_servers[master_inuse]); 3285 setzoneclass(dns_rdataclass_none); 3286 return; 3287 } 3288 3289 dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &soaquery); 3290 3291 if (default_servers) { 3292 soaquery->flags |= DNS_MESSAGEFLAG_RD; 3293 } 3294 3295 result = dns_message_gettempname(soaquery, &name); 3296 check_result(result, "dns_message_gettempname"); 3297 3298 result = dns_message_gettemprdataset(soaquery, &rdataset); 3299 check_result(result, "dns_message_gettemprdataset"); 3300 3301 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); 3302 3303 if (userzone != NULL) { 3304 dns_name_clone(userzone, name); 3305 } else { 3306 dns_rdataset_t *tmprdataset; 3307 result = dns_message_firstname(updatemsg, section); 3308 if (result == ISC_R_NOMORE) { 3309 section = DNS_SECTION_PREREQUISITE; 3310 result = dns_message_firstname(updatemsg, section); 3311 } 3312 if (result != ISC_R_SUCCESS) { 3313 dns_message_puttempname(soaquery, &name); 3314 dns_rdataset_disassociate(rdataset); 3315 dns_message_puttemprdataset(soaquery, &rdataset); 3316 dns_message_detach(&soaquery); 3317 done_update(); 3318 return; 3319 } 3320 firstname = NULL; 3321 dns_message_currentname(updatemsg, section, &firstname); 3322 dns_name_clone(firstname, name); 3323 /* 3324 * Looks to see if the first name references a DS record 3325 * and if that name is not the root remove a label as DS 3326 * records live in the parent zone so we need to start our 3327 * search one label up. 3328 */ 3329 tmprdataset = ISC_LIST_HEAD(firstname->list); 3330 if (section == DNS_SECTION_UPDATE && 3331 !dns_name_equal(firstname, dns_rootname) && 3332 tmprdataset->type == dns_rdatatype_ds) 3333 { 3334 unsigned int labels = dns_name_countlabels(name); 3335 dns_name_getlabelsequence(name, 1, labels - 1, name); 3336 } 3337 } 3338 3339 ISC_LIST_INIT(name->list); 3340 ISC_LIST_APPEND(name->list, rdataset, link); 3341 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); 3342 3343 ns_inuse = 0; 3344 sendrequest(&servers[ns_inuse], soaquery, &request); 3345 } 3346 3347 static void 3348 cleanup(void) { 3349 ddebug("cleanup()"); 3350 3351 LOCK(&answer_lock); 3352 if (answer != NULL) { 3353 dns_message_detach(&answer); 3354 } 3355 UNLOCK(&answer_lock); 3356 3357 #ifdef GSSAPI 3358 if (tsigkey != NULL) { 3359 ddebug("detach tsigkey x%p", tsigkey); 3360 dns_tsigkey_detach(&tsigkey); 3361 } 3362 if (gssring != NULL) { 3363 ddebug("Detaching GSS-TSIG keyring"); 3364 dns_tsigkeyring_detach(&gssring); 3365 } 3366 #endif /* ifdef GSSAPI */ 3367 3368 if (sig0key != NULL) { 3369 dst_key_free(&sig0key); 3370 } 3371 3372 ddebug("Shutting down task manager"); 3373 isc_managers_destroy(&netmgr, &taskmgr); 3374 3375 ddebug("Destroying event"); 3376 isc_event_free(&global_event); 3377 3378 ddebug("Shutting down socket manager"); 3379 isc_socketmgr_destroy(&socketmgr); 3380 3381 ddebug("Shutting down timer manager"); 3382 isc_timermgr_destroy(&timermgr); 3383 3384 #ifdef GSSAPI 3385 /* 3386 * Cleanup GSSAPI resources after taskmgr has been destroyed. 3387 */ 3388 if (kserver != NULL) { 3389 isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t)); 3390 kserver = NULL; 3391 } 3392 if (realm != NULL) { 3393 isc_mem_free(gmctx, realm); 3394 realm = NULL; 3395 } 3396 if (dns_name_dynamic(&tmpzonename)) { 3397 dns_name_free(&tmpzonename, gmctx); 3398 } 3399 if (dns_name_dynamic(&restart_master)) { 3400 dns_name_free(&restart_master, gmctx); 3401 } 3402 #endif /* ifdef GSSAPI */ 3403 3404 ddebug("Removing log context"); 3405 isc_log_destroy(&glctx); 3406 3407 ddebug("Destroying memory context"); 3408 if (memdebugging) { 3409 isc_mem_stats(gmctx, stderr); 3410 } 3411 isc_mem_destroy(&gmctx); 3412 3413 isc_mutex_destroy(&answer_lock); 3414 } 3415 3416 static void 3417 getinput(isc_task_t *task, isc_event_t *event) { 3418 bool more; 3419 3420 UNUSED(task); 3421 3422 if (shuttingdown) { 3423 maybeshutdown(); 3424 return; 3425 } 3426 3427 if (global_event == NULL) { 3428 global_event = event; 3429 } 3430 3431 reset_system(); 3432 more = user_interaction(); 3433 if (!more) { 3434 isc_app_shutdown(); 3435 return; 3436 } 3437 start_update(); 3438 return; 3439 } 3440 3441 int 3442 main(int argc, char **argv) { 3443 isc_result_t result; 3444 style = &dns_master_style_debug; 3445 3446 input = stdin; 3447 3448 interactive = isatty(0); 3449 3450 isc_app_start(); 3451 3452 if (isc_net_probeipv4() == ISC_R_SUCCESS) { 3453 have_ipv4 = true; 3454 } 3455 if (isc_net_probeipv6() == ISC_R_SUCCESS) { 3456 have_ipv6 = true; 3457 } 3458 if (!have_ipv4 && !have_ipv6) { 3459 fatal("could not find either IPv4 or IPv6"); 3460 } 3461 3462 pre_parse_args(argc, argv); 3463 3464 isc_mem_create(&gmctx); 3465 3466 parse_args(argc, argv); 3467 3468 setup_system(); 3469 3470 result = isc_app_onrun(gmctx, global_task, getinput, NULL); 3471 check_result(result, "isc_app_onrun"); 3472 3473 (void)isc_app_run(); 3474 3475 cleanup(); 3476 3477 isc_app_finish(); 3478 3479 if (seenerror) { 3480 return (2); 3481 } else { 3482 return (0); 3483 } 3484 } 3485