nsupdate.c revision 174187
1/* 2 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: nsupdate.c,v 1.130.18.19 2007/08/28 07:20:01 tbox Exp $ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <ctype.h> 25#include <errno.h> 26#include <limits.h> 27#include <stdlib.h> 28#include <unistd.h> 29 30#include <isc/app.h> 31#include <isc/base64.h> 32#include <isc/buffer.h> 33#include <isc/commandline.h> 34#include <isc/entropy.h> 35#include <isc/event.h> 36#include <isc/hash.h> 37#include <isc/lex.h> 38#include <isc/mem.h> 39#include <isc/parseint.h> 40#include <isc/region.h> 41#include <isc/sockaddr.h> 42#include <isc/socket.h> 43#include <isc/stdio.h> 44#include <isc/string.h> 45#include <isc/task.h> 46#include <isc/timer.h> 47#include <isc/types.h> 48#include <isc/util.h> 49 50#include <dns/callbacks.h> 51#include <dns/dispatch.h> 52#include <dns/dnssec.h> 53#include <dns/events.h> 54#include <dns/fixedname.h> 55#include <dns/masterdump.h> 56#include <dns/message.h> 57#include <dns/name.h> 58#include <dns/rcode.h> 59#include <dns/rdata.h> 60#include <dns/rdataclass.h> 61#include <dns/rdatalist.h> 62#include <dns/rdataset.h> 63#include <dns/rdatastruct.h> 64#include <dns/rdatatype.h> 65#include <dns/request.h> 66#include <dns/result.h> 67#include <dns/tsig.h> 68 69#include <dst/dst.h> 70 71#include <lwres/lwres.h> 72#include <lwres/net.h> 73 74#include <bind9/getaddresses.h> 75 76#ifdef HAVE_ADDRINFO 77#ifdef HAVE_GETADDRINFO 78#ifdef HAVE_GAISTRERROR 79#define USE_GETADDRINFO 80#endif 81#endif 82#endif 83 84#ifndef USE_GETADDRINFO 85#ifndef ISC_PLATFORM_NONSTDHERRNO 86extern int h_errno; 87#endif 88#endif 89 90#define MAXCMD (4 * 1024) 91#define MAXWIRE (64 * 1024) 92#define PACKETSIZE ((64 * 1024) - 1) 93#define INITTEXT (2 * 1024) 94#define MAXTEXT (128 * 1024) 95#define FIND_TIMEOUT 5 96#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */ 97 98#define DNSDEFAULTPORT 53 99 100#ifndef RESOLV_CONF 101#define RESOLV_CONF "/etc/resolv.conf" 102#endif 103 104static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE; 105static isc_boolean_t memdebugging = ISC_FALSE; 106static isc_boolean_t have_ipv4 = ISC_FALSE; 107static isc_boolean_t have_ipv6 = ISC_FALSE; 108static isc_boolean_t is_dst_up = ISC_FALSE; 109static isc_boolean_t usevc = ISC_FALSE; 110static isc_taskmgr_t *taskmgr = NULL; 111static isc_task_t *global_task = NULL; 112static isc_event_t *global_event = NULL; 113static isc_mem_t *mctx = NULL; 114static dns_dispatchmgr_t *dispatchmgr = NULL; 115static dns_requestmgr_t *requestmgr = NULL; 116static isc_socketmgr_t *socketmgr = NULL; 117static isc_timermgr_t *timermgr = NULL; 118static dns_dispatch_t *dispatchv4 = NULL; 119static dns_dispatch_t *dispatchv6 = NULL; 120static dns_message_t *updatemsg = NULL; 121static dns_fixedname_t fuserzone; 122static dns_name_t *userzone = NULL; 123static dns_tsigkey_t *tsigkey = NULL; 124static dst_key_t *sig0key; 125static lwres_context_t *lwctx = NULL; 126static lwres_conf_t *lwconf; 127static isc_sockaddr_t *servers; 128static int ns_inuse = 0; 129static int ns_total = 0; 130static isc_sockaddr_t *userserver = NULL; 131static isc_sockaddr_t *localaddr = NULL; 132static char *keystr = NULL, *keyfile = NULL; 133static isc_entropy_t *entp = NULL; 134static isc_boolean_t shuttingdown = ISC_FALSE; 135static FILE *input; 136static isc_boolean_t interactive = ISC_TRUE; 137static isc_boolean_t seenerror = ISC_FALSE; 138static const dns_master_style_t *style; 139static int requests = 0; 140static unsigned int timeout = 300; 141static unsigned int udp_timeout = 3; 142static unsigned int udp_retries = 3; 143static dns_rdataclass_t defaultclass = dns_rdataclass_in; 144static dns_rdataclass_t zoneclass = dns_rdataclass_none; 145static dns_message_t *answer = NULL; 146 147typedef struct nsu_requestinfo { 148 dns_message_t *msg; 149 isc_sockaddr_t *addr; 150} nsu_requestinfo_t; 151 152static void 153sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 154 dns_message_t *msg, dns_request_t **request); 155static void 156fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 157 158static void 159debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 160 161static void 162ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 163 164static void 165error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 166 167#define STATUS_MORE (isc_uint16_t)0 168#define STATUS_SEND (isc_uint16_t)1 169#define STATUS_QUIT (isc_uint16_t)2 170#define STATUS_SYNTAX (isc_uint16_t)3 171 172static dns_rdataclass_t 173getzoneclass(void) { 174 if (zoneclass == dns_rdataclass_none) 175 zoneclass = defaultclass; 176 return (zoneclass); 177} 178 179static isc_boolean_t 180setzoneclass(dns_rdataclass_t rdclass) { 181 if (zoneclass == dns_rdataclass_none || 182 rdclass == dns_rdataclass_none) 183 zoneclass = rdclass; 184 if (zoneclass != rdclass) 185 return (ISC_FALSE); 186 return (ISC_TRUE); 187} 188 189static void 190fatal(const char *format, ...) { 191 va_list args; 192 193 va_start(args, format); 194 vfprintf(stderr, format, args); 195 va_end(args); 196 fprintf(stderr, "\n"); 197 exit(1); 198} 199 200static void 201error(const char *format, ...) { 202 va_list args; 203 204 va_start(args, format); 205 vfprintf(stderr, format, args); 206 va_end(args); 207 fprintf(stderr, "\n"); 208} 209 210static void 211debug(const char *format, ...) { 212 va_list args; 213 214 if (debugging) { 215 va_start(args, format); 216 vfprintf(stderr, format, args); 217 va_end(args); 218 fprintf(stderr, "\n"); 219 } 220} 221 222static void 223ddebug(const char *format, ...) { 224 va_list args; 225 226 if (ddebugging) { 227 va_start(args, format); 228 vfprintf(stderr, format, args); 229 va_end(args); 230 fprintf(stderr, "\n"); 231 } 232} 233 234static inline void 235check_result(isc_result_t result, const char *msg) { 236 if (result != ISC_R_SUCCESS) 237 fatal("%s: %s", msg, isc_result_totext(result)); 238} 239 240static void * 241mem_alloc(void *arg, size_t size) { 242 return (isc_mem_get(arg, size)); 243} 244 245static void 246mem_free(void *arg, void *mem, size_t size) { 247 isc_mem_put(arg, mem, size); 248} 249 250static char * 251nsu_strsep(char **stringp, const char *delim) { 252 char *string = *stringp; 253 char *s; 254 const char *d; 255 char sc, dc; 256 257 if (string == NULL) 258 return (NULL); 259 260 for (; *string != '\0'; string++) { 261 sc = *string; 262 for (d = delim; (dc = *d) != '\0'; d++) { 263 if (sc == dc) 264 break; 265 } 266 if (dc == 0) 267 break; 268 } 269 270 for (s = string; *s != '\0'; s++) { 271 sc = *s; 272 for (d = delim; (dc = *d) != '\0'; d++) { 273 if (sc == dc) { 274 *s++ = '\0'; 275 *stringp = s; 276 return (string); 277 } 278 } 279 } 280 *stringp = NULL; 281 return (string); 282} 283 284static void 285reset_system(void) { 286 isc_result_t result; 287 288 ddebug("reset_system()"); 289 /* If the update message is still around, destroy it */ 290 if (updatemsg != NULL) 291 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER); 292 else { 293 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, 294 &updatemsg); 295 check_result(result, "dns_message_create"); 296 } 297 updatemsg->opcode = dns_opcode_update; 298} 299 300static isc_uint16_t 301parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) { 302 isc_uint16_t digestbits = 0; 303 isc_result_t result; 304 char buf[20]; 305 306 REQUIRE(hmac != NULL && *hmac == NULL); 307 REQUIRE(hmacstr != NULL); 308 309 if (len >= sizeof(buf)) 310 fatal("unknown key type '%.*s'", (int)(len), hmacstr); 311 312 strncpy(buf, hmacstr, len); 313 buf[len] = 0; 314 315 if (strcasecmp(buf, "hmac-md5") == 0) { 316 *hmac = DNS_TSIG_HMACMD5_NAME; 317 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { 318 *hmac = DNS_TSIG_HMACMD5_NAME; 319 result = isc_parse_uint16(&digestbits, &buf[9], 10); 320 if (result != ISC_R_SUCCESS || digestbits > 128) 321 fatal("digest-bits out of range [0..128]"); 322 digestbits = (digestbits +7) & ~0x7U; 323 } else if (strcasecmp(buf, "hmac-sha1") == 0) { 324 *hmac = DNS_TSIG_HMACSHA1_NAME; 325 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { 326 *hmac = DNS_TSIG_HMACSHA1_NAME; 327 result = isc_parse_uint16(&digestbits, &buf[10], 10); 328 if (result != ISC_R_SUCCESS || digestbits > 160) 329 fatal("digest-bits out of range [0..160]"); 330 digestbits = (digestbits +7) & ~0x7U; 331 } else if (strcasecmp(buf, "hmac-sha224") == 0) { 332 *hmac = DNS_TSIG_HMACSHA224_NAME; 333 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { 334 *hmac = DNS_TSIG_HMACSHA224_NAME; 335 result = isc_parse_uint16(&digestbits, &buf[12], 10); 336 if (result != ISC_R_SUCCESS || digestbits > 224) 337 fatal("digest-bits out of range [0..224]"); 338 digestbits = (digestbits +7) & ~0x7U; 339 } else if (strcasecmp(buf, "hmac-sha256") == 0) { 340 *hmac = DNS_TSIG_HMACSHA256_NAME; 341 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { 342 *hmac = DNS_TSIG_HMACSHA256_NAME; 343 result = isc_parse_uint16(&digestbits, &buf[12], 10); 344 if (result != ISC_R_SUCCESS || digestbits > 256) 345 fatal("digest-bits out of range [0..256]"); 346 digestbits = (digestbits +7) & ~0x7U; 347 } else if (strcasecmp(buf, "hmac-sha384") == 0) { 348 *hmac = DNS_TSIG_HMACSHA384_NAME; 349 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { 350 *hmac = DNS_TSIG_HMACSHA384_NAME; 351 result = isc_parse_uint16(&digestbits, &buf[12], 10); 352 if (result != ISC_R_SUCCESS || digestbits > 384) 353 fatal("digest-bits out of range [0..384]"); 354 digestbits = (digestbits +7) & ~0x7U; 355 } else if (strcasecmp(buf, "hmac-sha512") == 0) { 356 *hmac = DNS_TSIG_HMACSHA512_NAME; 357 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { 358 *hmac = DNS_TSIG_HMACSHA512_NAME; 359 result = isc_parse_uint16(&digestbits, &buf[12], 10); 360 if (result != ISC_R_SUCCESS || digestbits > 512) 361 fatal("digest-bits out of range [0..512]"); 362 digestbits = (digestbits +7) & ~0x7U; 363 } else 364 fatal("unknown key type '%s'", buf); 365 return (digestbits); 366} 367 368static void 369setup_keystr(void) { 370 unsigned char *secret = NULL; 371 int secretlen; 372 isc_buffer_t secretbuf; 373 isc_result_t result; 374 isc_buffer_t keynamesrc; 375 char *secretstr; 376 char *s, *n; 377 dns_fixedname_t fkeyname; 378 dns_name_t *keyname; 379 char *name; 380 dns_name_t *hmacname = NULL; 381 isc_uint16_t digestbits = 0; 382 383 dns_fixedname_init(&fkeyname); 384 keyname = dns_fixedname_name(&fkeyname); 385 386 debug("Creating key..."); 387 388 s = strchr(keystr, ':'); 389 if (s == NULL || s == keystr || s[1] == 0) 390 fatal("key option must specify [hmac:]keyname:secret"); 391 secretstr = s + 1; 392 n = strchr(secretstr, ':'); 393 if (n != NULL) { 394 if (n == secretstr || n[1] == 0) 395 fatal("key option must specify [hmac:]keyname:secret"); 396 name = secretstr; 397 secretstr = n + 1; 398 digestbits = parse_hmac(&hmacname, keystr, s - keystr); 399 } else { 400 hmacname = DNS_TSIG_HMACMD5_NAME; 401 name = keystr; 402 n = s; 403 } 404 405 isc_buffer_init(&keynamesrc, name, n - name); 406 isc_buffer_add(&keynamesrc, n - name); 407 408 debug("namefromtext"); 409 result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, 410 ISC_FALSE, NULL); 411 check_result(result, "dns_name_fromtext"); 412 413 secretlen = strlen(secretstr) * 3 / 4; 414 secret = isc_mem_allocate(mctx, secretlen); 415 if (secret == NULL) 416 fatal("out of memory"); 417 418 isc_buffer_init(&secretbuf, secret, secretlen); 419 result = isc_base64_decodestring(secretstr, &secretbuf); 420 if (result != ISC_R_SUCCESS) { 421 fprintf(stderr, "could not create key from %s: %s\n", 422 keystr, isc_result_totext(result)); 423 goto failure; 424 } 425 426 secretlen = isc_buffer_usedlength(&secretbuf); 427 428 debug("keycreate"); 429 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen, 430 ISC_TRUE, NULL, 0, 0, mctx, NULL, &tsigkey); 431 if (result != ISC_R_SUCCESS) 432 fprintf(stderr, "could not create key from %s: %s\n", 433 keystr, dns_result_totext(result)); 434 else 435 dst_key_setbits(tsigkey->key, digestbits); 436 failure: 437 if (secret != NULL) 438 isc_mem_free(mctx, secret); 439} 440 441static void 442setup_keyfile(void) { 443 dst_key_t *dstkey = NULL; 444 isc_result_t result; 445 dns_name_t *hmacname = NULL; 446 447 debug("Creating key..."); 448 449 result = dst_key_fromnamedfile(keyfile, 450 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, 451 &dstkey); 452 if (result != ISC_R_SUCCESS) { 453 fprintf(stderr, "could not read key from %s: %s\n", 454 keyfile, isc_result_totext(result)); 455 return; 456 } 457 switch (dst_key_alg(dstkey)) { 458 case DST_ALG_HMACMD5: 459 hmacname = DNS_TSIG_HMACMD5_NAME; 460 break; 461 case DST_ALG_HMACSHA1: 462 hmacname = DNS_TSIG_HMACSHA1_NAME; 463 break; 464 case DST_ALG_HMACSHA224: 465 hmacname = DNS_TSIG_HMACSHA224_NAME; 466 break; 467 case DST_ALG_HMACSHA256: 468 hmacname = DNS_TSIG_HMACSHA256_NAME; 469 break; 470 case DST_ALG_HMACSHA384: 471 hmacname = DNS_TSIG_HMACSHA384_NAME; 472 break; 473 case DST_ALG_HMACSHA512: 474 hmacname = DNS_TSIG_HMACSHA512_NAME; 475 break; 476 } 477 if (hmacname != NULL) { 478 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), 479 hmacname, dstkey, ISC_FALSE, 480 NULL, 0, 0, mctx, NULL, 481 &tsigkey); 482 if (result != ISC_R_SUCCESS) { 483 fprintf(stderr, "could not create key from %s: %s\n", 484 keyfile, isc_result_totext(result)); 485 dst_key_free(&dstkey); 486 return; 487 } 488 } else 489 sig0key = dstkey; 490} 491 492static void 493doshutdown(void) { 494 isc_task_detach(&global_task); 495 496 if (userserver != NULL) 497 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t)); 498 499 if (localaddr != NULL) 500 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t)); 501 502 if (tsigkey != NULL) { 503 ddebug("Freeing TSIG key"); 504 dns_tsigkey_detach(&tsigkey); 505 } 506 507 if (sig0key != NULL) { 508 ddebug("Freeing SIG(0) key"); 509 dst_key_free(&sig0key); 510 } 511 512 if (updatemsg != NULL) 513 dns_message_destroy(&updatemsg); 514 515 if (is_dst_up) { 516 ddebug("Destroy DST lib"); 517 dst_lib_destroy(); 518 is_dst_up = ISC_FALSE; 519 } 520 521 if (entp != NULL) { 522 ddebug("Detach from entropy"); 523 isc_entropy_detach(&entp); 524 } 525 526 lwres_conf_clear(lwctx); 527 lwres_context_destroy(&lwctx); 528 529 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t)); 530 531 ddebug("Destroying request manager"); 532 dns_requestmgr_detach(&requestmgr); 533 534 ddebug("Freeing the dispatchers"); 535 if (have_ipv4) 536 dns_dispatch_detach(&dispatchv4); 537 if (have_ipv6) 538 dns_dispatch_detach(&dispatchv6); 539 540 ddebug("Shutting down dispatch manager"); 541 dns_dispatchmgr_destroy(&dispatchmgr); 542 543} 544 545static void 546maybeshutdown(void) { 547 ddebug("Shutting down request manager"); 548 dns_requestmgr_shutdown(requestmgr); 549 550 if (requests != 0) 551 return; 552 553 doshutdown(); 554} 555 556static void 557shutdown_program(isc_task_t *task, isc_event_t *event) { 558 REQUIRE(task == global_task); 559 UNUSED(task); 560 561 ddebug("shutdown_program()"); 562 isc_event_free(&event); 563 564 shuttingdown = ISC_TRUE; 565 maybeshutdown(); 566} 567 568static void 569setup_system(void) { 570 isc_result_t result; 571 isc_sockaddr_t bind_any, bind_any6; 572 lwres_result_t lwresult; 573 unsigned int attrs, attrmask; 574 int i; 575 576 ddebug("setup_system()"); 577 578 dns_result_register(); 579 580 result = isc_net_probeipv4(); 581 if (result == ISC_R_SUCCESS) 582 have_ipv4 = ISC_TRUE; 583 584 result = isc_net_probeipv6(); 585 if (result == ISC_R_SUCCESS) 586 have_ipv6 = ISC_TRUE; 587 588 if (!have_ipv4 && !have_ipv6) 589 fatal("could not find either IPv4 or IPv6"); 590 591 result = isc_mem_create(0, 0, &mctx); 592 check_result(result, "isc_mem_create"); 593 594 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1); 595 if (lwresult != LWRES_R_SUCCESS) 596 fatal("lwres_context_create failed"); 597 598 (void)lwres_conf_parse(lwctx, RESOLV_CONF); 599 lwconf = lwres_conf_get(lwctx); 600 601 ns_total = lwconf->nsnext; 602 if (ns_total <= 0) { 603 /* No name servers in resolv.conf; default to loopback. */ 604 struct in_addr localhost; 605 ns_total = 1; 606 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t)); 607 if (servers == NULL) 608 fatal("out of memory"); 609 localhost.s_addr = htonl(INADDR_LOOPBACK); 610 isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT); 611 } else { 612 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t)); 613 if (servers == NULL) 614 fatal("out of memory"); 615 for (i = 0; i < ns_total; i++) { 616 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) { 617 struct in_addr in4; 618 memcpy(&in4, lwconf->nameservers[i].address, 4); 619 isc_sockaddr_fromin(&servers[i], &in4, DNSDEFAULTPORT); 620 } else { 621 struct in6_addr in6; 622 memcpy(&in6, lwconf->nameservers[i].address, 16); 623 isc_sockaddr_fromin6(&servers[i], &in6, 624 DNSDEFAULTPORT); 625 } 626 } 627 } 628 629 result = isc_entropy_create(mctx, &entp); 630 check_result(result, "isc_entropy_create"); 631 632 result = isc_hash_create(mctx, entp, DNS_NAME_MAXWIRE); 633 check_result(result, "isc_hash_create"); 634 isc_hash_init(); 635 636 result = dns_dispatchmgr_create(mctx, entp, &dispatchmgr); 637 check_result(result, "dns_dispatchmgr_create"); 638 639 result = isc_socketmgr_create(mctx, &socketmgr); 640 check_result(result, "dns_socketmgr_create"); 641 642 result = isc_timermgr_create(mctx, &timermgr); 643 check_result(result, "dns_timermgr_create"); 644 645 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr); 646 check_result(result, "isc_taskmgr_create"); 647 648 result = isc_task_create(taskmgr, 0, &global_task); 649 check_result(result, "isc_task_create"); 650 651 result = isc_task_onshutdown(global_task, shutdown_program, NULL); 652 check_result(result, "isc_task_onshutdown"); 653 654 result = dst_lib_init(mctx, entp, 0); 655 check_result(result, "dst_lib_init"); 656 is_dst_up = ISC_TRUE; 657 658 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; 659 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; 660 661 if (have_ipv6) { 662 attrs = DNS_DISPATCHATTR_UDP; 663 attrs |= DNS_DISPATCHATTR_MAKEQUERY; 664 attrs |= DNS_DISPATCHATTR_IPV6; 665 isc_sockaddr_any6(&bind_any6); 666 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, 667 &bind_any6, PACKETSIZE, 668 4, 2, 3, 5, 669 attrs, attrmask, &dispatchv6); 670 check_result(result, "dns_dispatch_getudp (v6)"); 671 } 672 673 if (have_ipv4) { 674 attrs = DNS_DISPATCHATTR_UDP; 675 attrs |= DNS_DISPATCHATTR_MAKEQUERY; 676 attrs |= DNS_DISPATCHATTR_IPV4; 677 isc_sockaddr_any(&bind_any); 678 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, 679 &bind_any, PACKETSIZE, 680 4, 2, 3, 5, 681 attrs, attrmask, &dispatchv4); 682 check_result(result, "dns_dispatch_getudp (v4)"); 683 } 684 685 result = dns_requestmgr_create(mctx, timermgr, 686 socketmgr, taskmgr, dispatchmgr, 687 dispatchv4, dispatchv6, &requestmgr); 688 check_result(result, "dns_requestmgr_create"); 689 690 if (keystr != NULL) 691 setup_keystr(); 692 else if (keyfile != NULL) 693 setup_keyfile(); 694} 695 696static void 697get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) { 698 int count; 699 isc_result_t result; 700 701 isc_app_block(); 702 result = bind9_getaddresses(host, port, sockaddr, 1, &count); 703 isc_app_unblock(); 704 if (result != ISC_R_SUCCESS) 705 fatal("couldn't get address for '%s': %s", 706 host, isc_result_totext(result)); 707 INSIST(count == 1); 708} 709 710static void 711parse_args(int argc, char **argv) { 712 int ch; 713 isc_result_t result; 714 715 debug("parse_args"); 716 while ((ch = isc_commandline_parse(argc, argv, "dDMy:vk:r:t:u:")) != -1) 717 { 718 switch (ch) { 719 case 'd': 720 debugging = ISC_TRUE; 721 break; 722 case 'D': /* was -dd */ 723 debugging = ISC_TRUE; 724 ddebugging = ISC_TRUE; 725 break; 726 case 'M': /* was -dm */ 727 debugging = ISC_TRUE; 728 ddebugging = ISC_TRUE; 729 memdebugging = ISC_TRUE; 730 isc_mem_debugging = ISC_MEM_DEBUGTRACE | 731 ISC_MEM_DEBUGRECORD; 732 break; 733 case 'y': 734 keystr = isc_commandline_argument; 735 break; 736 case 'v': 737 usevc = ISC_TRUE; 738 break; 739 case 'k': 740 keyfile = isc_commandline_argument; 741 break; 742 case 't': 743 result = isc_parse_uint32(&timeout, 744 isc_commandline_argument, 10); 745 if (result != ISC_R_SUCCESS) { 746 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument); 747 exit(1); 748 } 749 if (timeout == 0) 750 timeout = UINT_MAX; 751 break; 752 case 'u': 753 result = isc_parse_uint32(&udp_timeout, 754 isc_commandline_argument, 10); 755 if (result != ISC_R_SUCCESS) { 756 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument); 757 exit(1); 758 } 759 if (udp_timeout == 0) 760 udp_timeout = UINT_MAX; 761 break; 762 case 'r': 763 result = isc_parse_uint32(&udp_retries, 764 isc_commandline_argument, 10); 765 if (result != ISC_R_SUCCESS) { 766 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument); 767 exit(1); 768 } 769 break; 770 default: 771 fprintf(stderr, "%s: invalid argument -%c\n", 772 argv[0], ch); 773 fprintf(stderr, "usage: nsupdate [-d] " 774 "[-y keyname:secret | -k keyfile] [-v] " 775 "[filename]\n"); 776 exit(1); 777 } 778 } 779 if (keyfile != NULL && keystr != NULL) { 780 fprintf(stderr, "%s: cannot specify both -k and -y\n", 781 argv[0]); 782 exit(1); 783 } 784 785 if (argv[isc_commandline_index] != NULL) { 786 if (strcmp(argv[isc_commandline_index], "-") == 0) { 787 input = stdin; 788 } else { 789 result = isc_stdio_open(argv[isc_commandline_index], 790 "r", &input); 791 if (result != ISC_R_SUCCESS) { 792 fprintf(stderr, "could not open '%s': %s\n", 793 argv[isc_commandline_index], 794 isc_result_totext(result)); 795 exit(1); 796 } 797 } 798 interactive = ISC_FALSE; 799 } 800} 801 802static isc_uint16_t 803parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) { 804 isc_result_t result; 805 char *word; 806 isc_buffer_t *namebuf = NULL; 807 isc_buffer_t source; 808 809 word = nsu_strsep(cmdlinep, " \t\r\n"); 810 if (*word == 0) { 811 fprintf(stderr, "could not read owner name\n"); 812 return (STATUS_SYNTAX); 813 } 814 815 result = dns_message_gettempname(msg, namep); 816 check_result(result, "dns_message_gettempname"); 817 result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE); 818 check_result(result, "isc_buffer_allocate"); 819 dns_name_init(*namep, NULL); 820 dns_name_setbuffer(*namep, namebuf); 821 dns_message_takebuffer(msg, &namebuf); 822 isc_buffer_init(&source, word, strlen(word)); 823 isc_buffer_add(&source, strlen(word)); 824 result = dns_name_fromtext(*namep, &source, dns_rootname, 825 ISC_FALSE, NULL); 826 check_result(result, "dns_name_fromtext"); 827 isc_buffer_invalidate(&source); 828 return (STATUS_MORE); 829} 830 831static isc_uint16_t 832parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass, 833 dns_rdatatype_t rdatatype, dns_message_t *msg, 834 dns_rdata_t *rdata) 835{ 836 char *cmdline = *cmdlinep; 837 isc_buffer_t source, *buf = NULL, *newbuf = NULL; 838 isc_region_t r; 839 isc_lex_t *lex = NULL; 840 dns_rdatacallbacks_t callbacks; 841 isc_result_t result; 842 843 while (*cmdline != 0 && isspace((unsigned char)*cmdline)) 844 cmdline++; 845 846 if (*cmdline != 0) { 847 dns_rdatacallbacks_init(&callbacks); 848 result = isc_lex_create(mctx, strlen(cmdline), &lex); 849 check_result(result, "isc_lex_create"); 850 isc_buffer_init(&source, cmdline, strlen(cmdline)); 851 isc_buffer_add(&source, strlen(cmdline)); 852 result = isc_lex_openbuffer(lex, &source); 853 check_result(result, "isc_lex_openbuffer"); 854 result = isc_buffer_allocate(mctx, &buf, MAXWIRE); 855 check_result(result, "isc_buffer_allocate"); 856 result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex, 857 dns_rootname, 0, mctx, buf, 858 &callbacks); 859 isc_lex_destroy(&lex); 860 if (result == ISC_R_SUCCESS) { 861 isc_buffer_usedregion(buf, &r); 862 result = isc_buffer_allocate(mctx, &newbuf, r.length); 863 check_result(result, "isc_buffer_allocate"); 864 isc_buffer_putmem(newbuf, r.base, r.length); 865 isc_buffer_usedregion(newbuf, &r); 866 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); 867 isc_buffer_free(&buf); 868 dns_message_takebuffer(msg, &newbuf); 869 } else { 870 fprintf(stderr, "invalid rdata format: %s\n", 871 isc_result_totext(result)); 872 isc_buffer_free(&buf); 873 return (STATUS_SYNTAX); 874 } 875 } else { 876 rdata->flags = DNS_RDATA_UPDATE; 877 } 878 *cmdlinep = cmdline; 879 return (STATUS_MORE); 880} 881 882static isc_uint16_t 883make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) { 884 isc_result_t result; 885 char *word; 886 dns_name_t *name = NULL; 887 isc_textregion_t region; 888 dns_rdataset_t *rdataset = NULL; 889 dns_rdatalist_t *rdatalist = NULL; 890 dns_rdataclass_t rdataclass; 891 dns_rdatatype_t rdatatype; 892 dns_rdata_t *rdata = NULL; 893 isc_uint16_t retval; 894 895 ddebug("make_prereq()"); 896 897 /* 898 * Read the owner name 899 */ 900 retval = parse_name(&cmdline, updatemsg, &name); 901 if (retval != STATUS_MORE) 902 return (retval); 903 904 /* 905 * If this is an rrset prereq, read the class or type. 906 */ 907 if (isrrset) { 908 word = nsu_strsep(&cmdline, " \t\r\n"); 909 if (*word == 0) { 910 fprintf(stderr, "could not read class or type\n"); 911 goto failure; 912 } 913 region.base = word; 914 region.length = strlen(word); 915 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 916 if (result == ISC_R_SUCCESS) { 917 if (!setzoneclass(rdataclass)) { 918 fprintf(stderr, "class mismatch: %s\n", word); 919 goto failure; 920 } 921 /* 922 * Now read the type. 923 */ 924 word = nsu_strsep(&cmdline, " \t\r\n"); 925 if (*word == 0) { 926 fprintf(stderr, "could not read type\n"); 927 goto failure; 928 } 929 region.base = word; 930 region.length = strlen(word); 931 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 932 if (result != ISC_R_SUCCESS) { 933 fprintf(stderr, "invalid type: %s\n", word); 934 goto failure; 935 } 936 } else { 937 rdataclass = getzoneclass(); 938 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 939 if (result != ISC_R_SUCCESS) { 940 fprintf(stderr, "invalid type: %s\n", word); 941 goto failure; 942 } 943 } 944 } else 945 rdatatype = dns_rdatatype_any; 946 947 result = dns_message_gettemprdata(updatemsg, &rdata); 948 check_result(result, "dns_message_gettemprdata"); 949 950 rdata->data = NULL; 951 rdata->length = 0; 952 953 if (isrrset && ispositive) { 954 retval = parse_rdata(&cmdline, rdataclass, rdatatype, 955 updatemsg, rdata); 956 if (retval != STATUS_MORE) 957 goto failure; 958 } else 959 rdata->flags = DNS_RDATA_UPDATE; 960 961 result = dns_message_gettemprdatalist(updatemsg, &rdatalist); 962 check_result(result, "dns_message_gettemprdatalist"); 963 result = dns_message_gettemprdataset(updatemsg, &rdataset); 964 check_result(result, "dns_message_gettemprdataset"); 965 dns_rdatalist_init(rdatalist); 966 rdatalist->type = rdatatype; 967 if (ispositive) { 968 if (isrrset && rdata->data != NULL) 969 rdatalist->rdclass = rdataclass; 970 else 971 rdatalist->rdclass = dns_rdataclass_any; 972 } else 973 rdatalist->rdclass = dns_rdataclass_none; 974 rdatalist->covers = 0; 975 rdatalist->ttl = 0; 976 rdata->rdclass = rdatalist->rdclass; 977 rdata->type = rdatatype; 978 ISC_LIST_INIT(rdatalist->rdata); 979 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 980 dns_rdataset_init(rdataset); 981 dns_rdatalist_tordataset(rdatalist, rdataset); 982 ISC_LIST_INIT(name->list); 983 ISC_LIST_APPEND(name->list, rdataset, link); 984 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE); 985 return (STATUS_MORE); 986 987 failure: 988 if (name != NULL) 989 dns_message_puttempname(updatemsg, &name); 990 return (STATUS_SYNTAX); 991} 992 993static isc_uint16_t 994evaluate_prereq(char *cmdline) { 995 char *word; 996 isc_boolean_t ispositive, isrrset; 997 998 ddebug("evaluate_prereq()"); 999 word = nsu_strsep(&cmdline, " \t\r\n"); 1000 if (*word == 0) { 1001 fprintf(stderr, "could not read operation code\n"); 1002 return (STATUS_SYNTAX); 1003 } 1004 if (strcasecmp(word, "nxdomain") == 0) { 1005 ispositive = ISC_FALSE; 1006 isrrset = ISC_FALSE; 1007 } else if (strcasecmp(word, "yxdomain") == 0) { 1008 ispositive = ISC_TRUE; 1009 isrrset = ISC_FALSE; 1010 } else if (strcasecmp(word, "nxrrset") == 0) { 1011 ispositive = ISC_FALSE; 1012 isrrset = ISC_TRUE; 1013 } else if (strcasecmp(word, "yxrrset") == 0) { 1014 ispositive = ISC_TRUE; 1015 isrrset = ISC_TRUE; 1016 } else { 1017 fprintf(stderr, "incorrect operation code: %s\n", word); 1018 return (STATUS_SYNTAX); 1019 } 1020 return (make_prereq(cmdline, ispositive, isrrset)); 1021} 1022 1023static isc_uint16_t 1024evaluate_server(char *cmdline) { 1025 char *word, *server; 1026 long port; 1027 1028 word = nsu_strsep(&cmdline, " \t\r\n"); 1029 if (*word == 0) { 1030 fprintf(stderr, "could not read server name\n"); 1031 return (STATUS_SYNTAX); 1032 } 1033 server = word; 1034 1035 word = nsu_strsep(&cmdline, " \t\r\n"); 1036 if (*word == 0) 1037 port = DNSDEFAULTPORT; 1038 else { 1039 char *endp; 1040 port = strtol(word, &endp, 10); 1041 if (*endp != 0) { 1042 fprintf(stderr, "port '%s' is not numeric\n", word); 1043 return (STATUS_SYNTAX); 1044 } else if (port < 1 || port > 65535) { 1045 fprintf(stderr, "port '%s' is out of range " 1046 "(1 to 65535)\n", word); 1047 return (STATUS_SYNTAX); 1048 } 1049 } 1050 1051 if (userserver == NULL) { 1052 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 1053 if (userserver == NULL) 1054 fatal("out of memory"); 1055 } 1056 1057 get_address(server, (in_port_t)port, userserver); 1058 1059 return (STATUS_MORE); 1060} 1061 1062static isc_uint16_t 1063evaluate_local(char *cmdline) { 1064 char *word, *local; 1065 long port; 1066 struct in_addr in4; 1067 struct in6_addr in6; 1068 1069 word = nsu_strsep(&cmdline, " \t\r\n"); 1070 if (*word == 0) { 1071 fprintf(stderr, "could not read server name\n"); 1072 return (STATUS_SYNTAX); 1073 } 1074 local = word; 1075 1076 word = nsu_strsep(&cmdline, " \t\r\n"); 1077 if (*word == 0) 1078 port = 0; 1079 else { 1080 char *endp; 1081 port = strtol(word, &endp, 10); 1082 if (*endp != 0) { 1083 fprintf(stderr, "port '%s' is not numeric\n", word); 1084 return (STATUS_SYNTAX); 1085 } else if (port < 1 || port > 65535) { 1086 fprintf(stderr, "port '%s' is out of range " 1087 "(1 to 65535)\n", word); 1088 return (STATUS_SYNTAX); 1089 } 1090 } 1091 1092 if (localaddr == NULL) { 1093 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 1094 if (localaddr == NULL) 1095 fatal("out of memory"); 1096 } 1097 1098 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) 1099 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port); 1100 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) 1101 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port); 1102 else { 1103 fprintf(stderr, "invalid address %s", local); 1104 return (STATUS_SYNTAX); 1105 } 1106 1107 return (STATUS_MORE); 1108} 1109 1110static isc_uint16_t 1111evaluate_key(char *cmdline) { 1112 char *namestr; 1113 char *secretstr; 1114 isc_buffer_t b; 1115 isc_result_t result; 1116 dns_fixedname_t fkeyname; 1117 dns_name_t *keyname; 1118 int secretlen; 1119 unsigned char *secret = NULL; 1120 isc_buffer_t secretbuf; 1121 dns_name_t *hmacname = NULL; 1122 isc_uint16_t digestbits = 0; 1123 char *n; 1124 1125 namestr = nsu_strsep(&cmdline, " \t\r\n"); 1126 if (*namestr == 0) { 1127 fprintf(stderr, "could not read key name\n"); 1128 return (STATUS_SYNTAX); 1129 } 1130 1131 dns_fixedname_init(&fkeyname); 1132 keyname = dns_fixedname_name(&fkeyname); 1133 1134 n = strchr(namestr, ':'); 1135 if (n != NULL) { 1136 digestbits = parse_hmac(&hmacname, namestr, n - namestr); 1137 namestr = n + 1; 1138 } else 1139 hmacname = DNS_TSIG_HMACMD5_NAME; 1140 1141 isc_buffer_init(&b, namestr, strlen(namestr)); 1142 isc_buffer_add(&b, strlen(namestr)); 1143 result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL); 1144 if (result != ISC_R_SUCCESS) { 1145 fprintf(stderr, "could not parse key name\n"); 1146 return (STATUS_SYNTAX); 1147 } 1148 1149 secretstr = nsu_strsep(&cmdline, "\r\n"); 1150 if (*secretstr == 0) { 1151 fprintf(stderr, "could not read key secret\n"); 1152 return (STATUS_SYNTAX); 1153 } 1154 secretlen = strlen(secretstr) * 3 / 4; 1155 secret = isc_mem_allocate(mctx, secretlen); 1156 if (secret == NULL) 1157 fatal("out of memory"); 1158 1159 isc_buffer_init(&secretbuf, secret, secretlen); 1160 result = isc_base64_decodestring(secretstr, &secretbuf); 1161 if (result != ISC_R_SUCCESS) { 1162 fprintf(stderr, "could not create key from %s: %s\n", 1163 secretstr, isc_result_totext(result)); 1164 isc_mem_free(mctx, secret); 1165 return (STATUS_SYNTAX); 1166 } 1167 secretlen = isc_buffer_usedlength(&secretbuf); 1168 1169 if (tsigkey != NULL) 1170 dns_tsigkey_detach(&tsigkey); 1171 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen, 1172 ISC_TRUE, NULL, 0, 0, mctx, NULL, 1173 &tsigkey); 1174 isc_mem_free(mctx, secret); 1175 if (result != ISC_R_SUCCESS) { 1176 fprintf(stderr, "could not create key from %s %s: %s\n", 1177 namestr, secretstr, dns_result_totext(result)); 1178 return (STATUS_SYNTAX); 1179 } 1180 dst_key_setbits(tsigkey->key, digestbits); 1181 return (STATUS_MORE); 1182} 1183 1184static isc_uint16_t 1185evaluate_zone(char *cmdline) { 1186 char *word; 1187 isc_buffer_t b; 1188 isc_result_t result; 1189 1190 word = nsu_strsep(&cmdline, " \t\r\n"); 1191 if (*word == 0) { 1192 fprintf(stderr, "could not read zone name\n"); 1193 return (STATUS_SYNTAX); 1194 } 1195 1196 dns_fixedname_init(&fuserzone); 1197 userzone = dns_fixedname_name(&fuserzone); 1198 isc_buffer_init(&b, word, strlen(word)); 1199 isc_buffer_add(&b, strlen(word)); 1200 result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE, 1201 NULL); 1202 if (result != ISC_R_SUCCESS) { 1203 userzone = NULL; /* Lest it point to an invalid name */ 1204 fprintf(stderr, "could not parse zone name\n"); 1205 return (STATUS_SYNTAX); 1206 } 1207 1208 return (STATUS_MORE); 1209} 1210 1211static isc_uint16_t 1212evaluate_class(char *cmdline) { 1213 char *word; 1214 isc_textregion_t r; 1215 isc_result_t result; 1216 dns_rdataclass_t rdclass; 1217 1218 word = nsu_strsep(&cmdline, " \t\r\n"); 1219 if (*word == 0) { 1220 fprintf(stderr, "could not read class name\n"); 1221 return (STATUS_SYNTAX); 1222 } 1223 1224 r.base = word; 1225 r.length = strlen(word); 1226 result = dns_rdataclass_fromtext(&rdclass, &r); 1227 if (result != ISC_R_SUCCESS) { 1228 fprintf(stderr, "could not parse class name: %s\n", word); 1229 return (STATUS_SYNTAX); 1230 } 1231 switch (rdclass) { 1232 case dns_rdataclass_none: 1233 case dns_rdataclass_any: 1234 case dns_rdataclass_reserved0: 1235 fprintf(stderr, "bad default class: %s\n", word); 1236 return (STATUS_SYNTAX); 1237 default: 1238 defaultclass = rdclass; 1239 } 1240 1241 return (STATUS_MORE); 1242} 1243 1244static isc_uint16_t 1245update_addordelete(char *cmdline, isc_boolean_t isdelete) { 1246 isc_result_t result; 1247 dns_name_t *name = NULL; 1248 isc_uint32_t ttl; 1249 char *word; 1250 dns_rdataclass_t rdataclass; 1251 dns_rdatatype_t rdatatype; 1252 dns_rdata_t *rdata = NULL; 1253 dns_rdatalist_t *rdatalist = NULL; 1254 dns_rdataset_t *rdataset = NULL; 1255 isc_textregion_t region; 1256 isc_uint16_t retval; 1257 1258 ddebug("update_addordelete()"); 1259 1260 /* 1261 * Read the owner name. 1262 */ 1263 retval = parse_name(&cmdline, updatemsg, &name); 1264 if (retval != STATUS_MORE) 1265 return (retval); 1266 1267 result = dns_message_gettemprdata(updatemsg, &rdata); 1268 check_result(result, "dns_message_gettemprdata"); 1269 1270 rdata->rdclass = 0; 1271 rdata->type = 0; 1272 rdata->data = NULL; 1273 rdata->length = 0; 1274 1275 /* 1276 * If this is an add, read the TTL and verify that it's in range. 1277 * If it's a delete, ignore a TTL if present (for compatibility). 1278 */ 1279 word = nsu_strsep(&cmdline, " \t\r\n"); 1280 if (*word == 0) { 1281 if (!isdelete) { 1282 fprintf(stderr, "could not read owner ttl\n"); 1283 goto failure; 1284 } 1285 else { 1286 ttl = 0; 1287 rdataclass = dns_rdataclass_any; 1288 rdatatype = dns_rdatatype_any; 1289 rdata->flags = DNS_RDATA_UPDATE; 1290 goto doneparsing; 1291 } 1292 } 1293 result = isc_parse_uint32(&ttl, word, 10); 1294 if (result != ISC_R_SUCCESS) { 1295 if (isdelete) { 1296 ttl = 0; 1297 goto parseclass; 1298 } else { 1299 fprintf(stderr, "ttl '%s': %s\n", word, 1300 isc_result_totext(result)); 1301 goto failure; 1302 } 1303 } 1304 1305 if (isdelete) 1306 ttl = 0; 1307 else if (ttl > TTL_MAX) { 1308 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", 1309 word, TTL_MAX); 1310 goto failure; 1311 } 1312 1313 /* 1314 * Read the class or type. 1315 */ 1316 word = nsu_strsep(&cmdline, " \t\r\n"); 1317 parseclass: 1318 if (*word == 0) { 1319 if (isdelete) { 1320 rdataclass = dns_rdataclass_any; 1321 rdatatype = dns_rdatatype_any; 1322 rdata->flags = DNS_RDATA_UPDATE; 1323 goto doneparsing; 1324 } else { 1325 fprintf(stderr, "could not read class or type\n"); 1326 goto failure; 1327 } 1328 } 1329 region.base = word; 1330 region.length = strlen(word); 1331 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 1332 if (result == ISC_R_SUCCESS) { 1333 if (!setzoneclass(rdataclass)) { 1334 fprintf(stderr, "class mismatch: %s\n", word); 1335 goto failure; 1336 } 1337 /* 1338 * Now read the type. 1339 */ 1340 word = nsu_strsep(&cmdline, " \t\r\n"); 1341 if (*word == 0) { 1342 if (isdelete) { 1343 rdataclass = dns_rdataclass_any; 1344 rdatatype = dns_rdatatype_any; 1345 rdata->flags = DNS_RDATA_UPDATE; 1346 goto doneparsing; 1347 } else { 1348 fprintf(stderr, "could not read type\n"); 1349 goto failure; 1350 } 1351 } 1352 region.base = word; 1353 region.length = strlen(word); 1354 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1355 if (result != ISC_R_SUCCESS) { 1356 fprintf(stderr, "'%s' is not a valid type: %s\n", 1357 word, isc_result_totext(result)); 1358 goto failure; 1359 } 1360 } else { 1361 rdataclass = getzoneclass(); 1362 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1363 if (result != ISC_R_SUCCESS) { 1364 fprintf(stderr, "'%s' is not a valid class or type: " 1365 "%s\n", word, isc_result_totext(result)); 1366 goto failure; 1367 } 1368 } 1369 1370 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, 1371 rdata); 1372 if (retval != STATUS_MORE) 1373 goto failure; 1374 1375 if (isdelete) { 1376 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) 1377 rdataclass = dns_rdataclass_any; 1378 else 1379 rdataclass = dns_rdataclass_none; 1380 } else { 1381 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 1382 fprintf(stderr, "could not read rdata\n"); 1383 goto failure; 1384 } 1385 } 1386 1387 doneparsing: 1388 1389 result = dns_message_gettemprdatalist(updatemsg, &rdatalist); 1390 check_result(result, "dns_message_gettemprdatalist"); 1391 result = dns_message_gettemprdataset(updatemsg, &rdataset); 1392 check_result(result, "dns_message_gettemprdataset"); 1393 dns_rdatalist_init(rdatalist); 1394 rdatalist->type = rdatatype; 1395 rdatalist->rdclass = rdataclass; 1396 rdatalist->covers = rdatatype; 1397 rdatalist->ttl = (dns_ttl_t)ttl; 1398 ISC_LIST_INIT(rdatalist->rdata); 1399 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1400 dns_rdataset_init(rdataset); 1401 dns_rdatalist_tordataset(rdatalist, rdataset); 1402 ISC_LIST_INIT(name->list); 1403 ISC_LIST_APPEND(name->list, rdataset, link); 1404 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE); 1405 return (STATUS_MORE); 1406 1407 failure: 1408 if (name != NULL) 1409 dns_message_puttempname(updatemsg, &name); 1410 if (rdata != NULL) 1411 dns_message_puttemprdata(updatemsg, &rdata); 1412 return (STATUS_SYNTAX); 1413} 1414 1415static isc_uint16_t 1416evaluate_update(char *cmdline) { 1417 char *word; 1418 isc_boolean_t isdelete; 1419 1420 ddebug("evaluate_update()"); 1421 word = nsu_strsep(&cmdline, " \t\r\n"); 1422 if (*word == 0) { 1423 fprintf(stderr, "could not read operation code\n"); 1424 return (STATUS_SYNTAX); 1425 } 1426 if (strcasecmp(word, "delete") == 0) 1427 isdelete = ISC_TRUE; 1428 else if (strcasecmp(word, "add") == 0) 1429 isdelete = ISC_FALSE; 1430 else { 1431 fprintf(stderr, "incorrect operation code: %s\n", word); 1432 return (STATUS_SYNTAX); 1433 } 1434 return (update_addordelete(cmdline, isdelete)); 1435} 1436 1437static void 1438setzone(dns_name_t *zonename) { 1439 isc_result_t result; 1440 dns_name_t *name = NULL; 1441 dns_rdataset_t *rdataset = NULL; 1442 1443 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE); 1444 if (result == ISC_R_SUCCESS) { 1445 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name); 1446 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE); 1447 for (rdataset = ISC_LIST_HEAD(name->list); 1448 rdataset != NULL; 1449 rdataset = ISC_LIST_HEAD(name->list)) { 1450 ISC_LIST_UNLINK(name->list, rdataset, link); 1451 dns_rdataset_disassociate(rdataset); 1452 dns_message_puttemprdataset(updatemsg, &rdataset); 1453 } 1454 dns_message_puttempname(updatemsg, &name); 1455 } 1456 1457 if (zonename != NULL) { 1458 result = dns_message_gettempname(updatemsg, &name); 1459 check_result(result, "dns_message_gettempname"); 1460 dns_name_init(name, NULL); 1461 dns_name_clone(zonename, name); 1462 result = dns_message_gettemprdataset(updatemsg, &rdataset); 1463 check_result(result, "dns_message_gettemprdataset"); 1464 dns_rdataset_makequestion(rdataset, getzoneclass(), 1465 dns_rdatatype_soa); 1466 ISC_LIST_INIT(name->list); 1467 ISC_LIST_APPEND(name->list, rdataset, link); 1468 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); 1469 } 1470} 1471 1472static void 1473show_message(dns_message_t *msg) { 1474 isc_result_t result; 1475 isc_buffer_t *buf = NULL; 1476 int bufsz; 1477 1478 ddebug("show_message()"); 1479 1480 setzone(userzone); 1481 1482 bufsz = INITTEXT; 1483 do { 1484 if (bufsz > MAXTEXT) { 1485 fprintf(stderr, "could not allocate large enough " 1486 "buffer to display message\n"); 1487 exit(1); 1488 } 1489 if (buf != NULL) 1490 isc_buffer_free(&buf); 1491 result = isc_buffer_allocate(mctx, &buf, bufsz); 1492 check_result(result, "isc_buffer_allocate"); 1493 result = dns_message_totext(msg, style, 0, buf); 1494 bufsz *= 2; 1495 } while (result == ISC_R_NOSPACE); 1496 if (result != ISC_R_SUCCESS) { 1497 fprintf(stderr, "could not convert message to text format.\n"); 1498 isc_buffer_free(&buf); 1499 return; 1500 } 1501 printf("Outgoing update query:\n%.*s", 1502 (int)isc_buffer_usedlength(buf), 1503 (char*)isc_buffer_base(buf)); 1504 isc_buffer_free(&buf); 1505} 1506 1507 1508static isc_uint16_t 1509get_next_command(void) { 1510 char cmdlinebuf[MAXCMD]; 1511 char *cmdline; 1512 char *word; 1513 1514 ddebug("get_next_command()"); 1515 if (interactive) { 1516 fprintf(stdout, "> "); 1517 fflush(stdout); 1518 } 1519 isc_app_block(); 1520 cmdline = fgets(cmdlinebuf, MAXCMD, input); 1521 isc_app_unblock(); 1522 if (cmdline == NULL) 1523 return (STATUS_QUIT); 1524 word = nsu_strsep(&cmdline, " \t\r\n"); 1525 1526 if (feof(input)) 1527 return (STATUS_QUIT); 1528 if (*word == 0) 1529 return (STATUS_SEND); 1530 if (word[0] == ';') 1531 return (STATUS_MORE); 1532 if (strcasecmp(word, "quit") == 0) 1533 return (STATUS_QUIT); 1534 if (strcasecmp(word, "prereq") == 0) 1535 return (evaluate_prereq(cmdline)); 1536 if (strcasecmp(word, "update") == 0) 1537 return (evaluate_update(cmdline)); 1538 if (strcasecmp(word, "server") == 0) 1539 return (evaluate_server(cmdline)); 1540 if (strcasecmp(word, "local") == 0) 1541 return (evaluate_local(cmdline)); 1542 if (strcasecmp(word, "zone") == 0) 1543 return (evaluate_zone(cmdline)); 1544 if (strcasecmp(word, "class") == 0) 1545 return (evaluate_class(cmdline)); 1546 if (strcasecmp(word, "send") == 0) 1547 return (STATUS_SEND); 1548 if (strcasecmp(word, "show") == 0) { 1549 show_message(updatemsg); 1550 return (STATUS_MORE); 1551 } 1552 if (strcasecmp(word, "answer") == 0) { 1553 if (answer != NULL) 1554 show_message(answer); 1555 return (STATUS_MORE); 1556 } 1557 if (strcasecmp(word, "key") == 0) 1558 return (evaluate_key(cmdline)); 1559 fprintf(stderr, "incorrect section name: %s\n", word); 1560 return (STATUS_SYNTAX); 1561} 1562 1563static isc_boolean_t 1564user_interaction(void) { 1565 isc_uint16_t result = STATUS_MORE; 1566 1567 ddebug("user_interaction()"); 1568 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) { 1569 result = get_next_command(); 1570 if (!interactive && result == STATUS_SYNTAX) 1571 fatal("syntax error"); 1572 } 1573 if (result == STATUS_SEND) 1574 return (ISC_TRUE); 1575 return (ISC_FALSE); 1576 1577} 1578 1579static void 1580done_update(void) { 1581 isc_event_t *event = global_event; 1582 ddebug("done_update()"); 1583 isc_task_send(global_task, &event); 1584} 1585 1586static void 1587check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) { 1588 isc_result_t result; 1589 dns_rdata_t rdata = DNS_RDATA_INIT; 1590 dns_rdata_any_tsig_t tsig; 1591 1592 result = dns_rdataset_first(rdataset); 1593 check_result(result, "dns_rdataset_first"); 1594 dns_rdataset_current(rdataset, &rdata); 1595 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 1596 check_result(result, "dns_rdata_tostruct"); 1597 if (tsig.error != 0) { 1598 if (isc_buffer_remaininglength(b) < 1) 1599 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); 1600 isc__buffer_putstr(b, "(" /*)*/); 1601 result = dns_tsigrcode_totext(tsig.error, b); 1602 check_result(result, "dns_tsigrcode_totext"); 1603 if (isc_buffer_remaininglength(b) < 1) 1604 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); 1605 isc__buffer_putstr(b, /*(*/ ")"); 1606 } 1607} 1608 1609static void 1610update_completed(isc_task_t *task, isc_event_t *event) { 1611 dns_requestevent_t *reqev = NULL; 1612 isc_result_t result; 1613 dns_request_t *request; 1614 1615 UNUSED(task); 1616 1617 ddebug("update_completed()"); 1618 1619 requests--; 1620 1621 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 1622 reqev = (dns_requestevent_t *)event; 1623 request = reqev->request; 1624 1625 if (shuttingdown) { 1626 dns_request_destroy(&request); 1627 isc_event_free(&event); 1628 maybeshutdown(); 1629 return; 1630 } 1631 1632 if (reqev->result != ISC_R_SUCCESS) { 1633 fprintf(stderr, "; Communication with server failed: %s\n", 1634 isc_result_totext(reqev->result)); 1635 seenerror = ISC_TRUE; 1636 goto done; 1637 } 1638 1639 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer); 1640 check_result(result, "dns_message_create"); 1641 result = dns_request_getresponse(request, answer, 1642 DNS_MESSAGEPARSE_PRESERVEORDER); 1643 switch (result) { 1644 case ISC_R_SUCCESS: 1645 break; 1646 case DNS_R_CLOCKSKEW: 1647 case DNS_R_EXPECTEDTSIG: 1648 case DNS_R_TSIGERRORSET: 1649 case DNS_R_TSIGVERIFYFAILURE: 1650 case DNS_R_UNEXPECTEDTSIG: 1651 fprintf(stderr, "; TSIG error with server: %s\n", 1652 isc_result_totext(result)); 1653 seenerror = ISC_TRUE; 1654 break; 1655 default: 1656 check_result(result, "dns_request_getresponse"); 1657 } 1658 1659 if (answer->rcode != dns_rcode_noerror) { 1660 seenerror = ISC_TRUE; 1661 if (!debugging) { 1662 char buf[64]; 1663 isc_buffer_t b; 1664 dns_rdataset_t *rds; 1665 1666 isc_buffer_init(&b, buf, sizeof(buf) - 1); 1667 result = dns_rcode_totext(answer->rcode, &b); 1668 check_result(result, "dns_rcode_totext"); 1669 rds = dns_message_gettsig(answer, NULL); 1670 if (rds != NULL) 1671 check_tsig_error(rds, &b); 1672 fprintf(stderr, "update failed: %.*s\n", 1673 (int)isc_buffer_usedlength(&b), buf); 1674 } 1675 } 1676 if (debugging) { 1677 isc_buffer_t *buf = NULL; 1678 int bufsz; 1679 1680 bufsz = INITTEXT; 1681 do { 1682 if (bufsz > MAXTEXT) { 1683 fprintf(stderr, "could not allocate large " 1684 "enough buffer to display message\n"); 1685 exit(1); 1686 } 1687 if (buf != NULL) 1688 isc_buffer_free(&buf); 1689 result = isc_buffer_allocate(mctx, &buf, bufsz); 1690 check_result(result, "isc_buffer_allocate"); 1691 result = dns_message_totext(answer, style, 0, buf); 1692 bufsz *= 2; 1693 } while (result == ISC_R_NOSPACE); 1694 check_result(result, "dns_message_totext"); 1695 fprintf(stderr, "\nReply from update query:\n%.*s\n", 1696 (int)isc_buffer_usedlength(buf), 1697 (char*)isc_buffer_base(buf)); 1698 isc_buffer_free(&buf); 1699 } 1700 done: 1701 dns_request_destroy(&request); 1702 isc_event_free(&event); 1703 done_update(); 1704} 1705 1706static void 1707send_update(dns_name_t *zonename, isc_sockaddr_t *master, 1708 isc_sockaddr_t *srcaddr) 1709{ 1710 isc_result_t result; 1711 dns_request_t *request = NULL; 1712 unsigned int options = 0; 1713 1714 ddebug("send_update()"); 1715 1716 setzone(zonename); 1717 1718 if (usevc) 1719 options |= DNS_REQUESTOPT_TCP; 1720 if (tsigkey == NULL && sig0key != NULL) { 1721 result = dns_message_setsig0key(updatemsg, sig0key); 1722 check_result(result, "dns_message_setsig0key"); 1723 } 1724 if (debugging) { 1725 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 1726 1727 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf)); 1728 fprintf(stderr, "Sending update to %s\n", addrbuf); 1729 } 1730 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr, 1731 master, options, tsigkey, timeout, 1732 udp_timeout, udp_retries, global_task, 1733 update_completed, NULL, &request); 1734 check_result(result, "dns_request_createvia3"); 1735 1736 if (debugging) 1737 show_message(updatemsg); 1738 1739 requests++; 1740} 1741 1742static void 1743recvsoa(isc_task_t *task, isc_event_t *event) { 1744 dns_requestevent_t *reqev = NULL; 1745 dns_request_t *request = NULL; 1746 isc_result_t result, eresult; 1747 dns_message_t *rcvmsg = NULL; 1748 dns_section_t section; 1749 dns_name_t *name = NULL; 1750 dns_rdataset_t *soaset = NULL; 1751 dns_rdata_soa_t soa; 1752 dns_rdata_t soarr = DNS_RDATA_INIT; 1753 int pass = 0; 1754 dns_name_t master; 1755 isc_sockaddr_t *serveraddr, tempaddr; 1756 dns_name_t *zonename; 1757 nsu_requestinfo_t *reqinfo; 1758 dns_message_t *soaquery = NULL; 1759 isc_sockaddr_t *addr; 1760 isc_boolean_t seencname = ISC_FALSE; 1761 dns_name_t tname; 1762 unsigned int nlabels; 1763 1764 UNUSED(task); 1765 1766 ddebug("recvsoa()"); 1767 1768 requests--; 1769 1770 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 1771 reqev = (dns_requestevent_t *)event; 1772 request = reqev->request; 1773 eresult = reqev->result; 1774 reqinfo = reqev->ev_arg; 1775 soaquery = reqinfo->msg; 1776 addr = reqinfo->addr; 1777 1778 if (shuttingdown) { 1779 dns_request_destroy(&request); 1780 dns_message_destroy(&soaquery); 1781 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 1782 isc_event_free(&event); 1783 maybeshutdown(); 1784 return; 1785 } 1786 1787 if (eresult != ISC_R_SUCCESS) { 1788 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 1789 1790 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 1791 fprintf(stderr, "; Communication with %s failed: %s\n", 1792 addrbuf, isc_result_totext(eresult)); 1793 if (userserver != NULL) 1794 fatal("could not talk to specified name server"); 1795 else if (++ns_inuse >= lwconf->nsnext) 1796 fatal("could not talk to any default name server"); 1797 ddebug("Destroying request [%p]", request); 1798 dns_request_destroy(&request); 1799 dns_message_renderreset(soaquery); 1800 dns_message_settsigkey(soaquery, NULL); 1801 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 1802 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 1803 isc_event_free(&event); 1804 setzoneclass(dns_rdataclass_none); 1805 return; 1806 } 1807 1808 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 1809 reqinfo = NULL; 1810 isc_event_free(&event); 1811 reqev = NULL; 1812 1813 ddebug("About to create rcvmsg"); 1814 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 1815 check_result(result, "dns_message_create"); 1816 result = dns_request_getresponse(request, rcvmsg, 1817 DNS_MESSAGEPARSE_PRESERVEORDER); 1818 if (result == DNS_R_TSIGERRORSET && userserver != NULL) { 1819 dns_message_destroy(&rcvmsg); 1820 ddebug("Destroying request [%p]", request); 1821 dns_request_destroy(&request); 1822 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t)); 1823 if (reqinfo == NULL) 1824 fatal("out of memory"); 1825 reqinfo->msg = soaquery; 1826 reqinfo->addr = addr; 1827 dns_message_renderreset(soaquery); 1828 ddebug("retrying soa request without TSIG"); 1829 result = dns_request_createvia3(requestmgr, soaquery, 1830 localaddr, addr, 0, NULL, 1831 FIND_TIMEOUT * 20, 1832 FIND_TIMEOUT, 3, 1833 global_task, recvsoa, reqinfo, 1834 &request); 1835 check_result(result, "dns_request_createvia"); 1836 requests++; 1837 return; 1838 } 1839 check_result(result, "dns_request_getresponse"); 1840 section = DNS_SECTION_ANSWER; 1841 if (debugging) { 1842 isc_buffer_t *buf = NULL; 1843 int bufsz; 1844 bufsz = INITTEXT; 1845 do { 1846 if (buf != NULL) 1847 isc_buffer_free(&buf); 1848 if (bufsz > MAXTEXT) { 1849 fprintf(stderr, "could not allocate enough " 1850 "space for debugging message\n"); 1851 exit(1); 1852 } 1853 result = isc_buffer_allocate(mctx, &buf, bufsz); 1854 check_result(result, "isc_buffer_allocate"); 1855 result = dns_message_totext(rcvmsg, style, 0, buf); 1856 } while (result == ISC_R_NOSPACE); 1857 check_result(result, "dns_message_totext"); 1858 fprintf(stderr, "Reply from SOA query:\n%.*s\n", 1859 (int)isc_buffer_usedlength(buf), 1860 (char*)isc_buffer_base(buf)); 1861 isc_buffer_free(&buf); 1862 } 1863 1864 if (rcvmsg->rcode != dns_rcode_noerror && 1865 rcvmsg->rcode != dns_rcode_nxdomain) 1866 fatal("response to SOA query was unsuccessful"); 1867 1868 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) { 1869 char namebuf[DNS_NAME_FORMATSIZE]; 1870 dns_name_format(userzone, namebuf, sizeof(namebuf)); 1871 error("specified zone '%s' does not exist (NXDOMAIN)", 1872 namebuf); 1873 dns_message_destroy(&rcvmsg); 1874 dns_request_destroy(&request); 1875 dns_message_destroy(&soaquery); 1876 ddebug("Out of recvsoa"); 1877 done_update(); 1878 return; 1879 } 1880 1881 lookforsoa: 1882 if (pass == 0) 1883 section = DNS_SECTION_ANSWER; 1884 else if (pass == 1) 1885 section = DNS_SECTION_AUTHORITY; 1886 else 1887 goto droplabel; 1888 1889 result = dns_message_firstname(rcvmsg, section); 1890 if (result != ISC_R_SUCCESS) { 1891 pass++; 1892 goto lookforsoa; 1893 } 1894 while (result == ISC_R_SUCCESS) { 1895 name = NULL; 1896 dns_message_currentname(rcvmsg, section, &name); 1897 soaset = NULL; 1898 result = dns_message_findtype(name, dns_rdatatype_soa, 0, 1899 &soaset); 1900 if (result == ISC_R_SUCCESS) 1901 break; 1902 if (section == DNS_SECTION_ANSWER) { 1903 dns_rdataset_t *tset = NULL; 1904 if (dns_message_findtype(name, dns_rdatatype_cname, 0, 1905 &tset) == ISC_R_SUCCESS 1906 || 1907 dns_message_findtype(name, dns_rdatatype_dname, 0, 1908 &tset) == ISC_R_SUCCESS 1909 ) 1910 { 1911 seencname = ISC_TRUE; 1912 break; 1913 } 1914 } 1915 1916 result = dns_message_nextname(rcvmsg, section); 1917 } 1918 1919 if (soaset == NULL && !seencname) { 1920 pass++; 1921 goto lookforsoa; 1922 } 1923 1924 if (seencname) 1925 goto droplabel; 1926 1927 if (debugging) { 1928 char namestr[DNS_NAME_FORMATSIZE]; 1929 dns_name_format(name, namestr, sizeof(namestr)); 1930 fprintf(stderr, "Found zone name: %s\n", namestr); 1931 } 1932 1933 result = dns_rdataset_first(soaset); 1934 check_result(result, "dns_rdataset_first"); 1935 1936 dns_rdata_init(&soarr); 1937 dns_rdataset_current(soaset, &soarr); 1938 result = dns_rdata_tostruct(&soarr, &soa, NULL); 1939 check_result(result, "dns_rdata_tostruct"); 1940 1941 dns_name_init(&master, NULL); 1942 dns_name_clone(&soa.origin, &master); 1943 1944 if (userzone != NULL) 1945 zonename = userzone; 1946 else 1947 zonename = name; 1948 1949 if (debugging) { 1950 char namestr[DNS_NAME_FORMATSIZE]; 1951 dns_name_format(&master, namestr, sizeof(namestr)); 1952 fprintf(stderr, "The master is: %s\n", namestr); 1953 } 1954 1955 if (userserver != NULL) 1956 serveraddr = userserver; 1957 else { 1958 char serverstr[DNS_NAME_MAXTEXT+1]; 1959 isc_buffer_t buf; 1960 1961 isc_buffer_init(&buf, serverstr, sizeof(serverstr)); 1962 result = dns_name_totext(&master, ISC_TRUE, &buf); 1963 check_result(result, "dns_name_totext"); 1964 serverstr[isc_buffer_usedlength(&buf)] = 0; 1965 get_address(serverstr, DNSDEFAULTPORT, &tempaddr); 1966 serveraddr = &tempaddr; 1967 } 1968 dns_rdata_freestruct(&soa); 1969 1970 send_update(zonename, serveraddr, localaddr); 1971 setzoneclass(dns_rdataclass_none); 1972 1973 dns_message_destroy(&soaquery); 1974 dns_request_destroy(&request); 1975 1976 out: 1977 dns_message_destroy(&rcvmsg); 1978 ddebug("Out of recvsoa"); 1979 return; 1980 1981 droplabel: 1982 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); 1983 INSIST(result == ISC_R_SUCCESS); 1984 name = NULL; 1985 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); 1986 nlabels = dns_name_countlabels(name); 1987 if (nlabels == 1) 1988 fatal("could not find enclosing zone"); 1989 dns_name_init(&tname, NULL); 1990 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname); 1991 dns_name_clone(&tname, name); 1992 dns_request_destroy(&request); 1993 dns_message_renderreset(soaquery); 1994 dns_message_settsigkey(soaquery, NULL); 1995 if (userserver != NULL) 1996 sendrequest(localaddr, userserver, soaquery, &request); 1997 else 1998 sendrequest(localaddr, &servers[ns_inuse], soaquery, 1999 &request); 2000 goto out; 2001} 2002 2003static void 2004sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 2005 dns_message_t *msg, dns_request_t **request) 2006{ 2007 isc_result_t result; 2008 nsu_requestinfo_t *reqinfo; 2009 2010 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t)); 2011 if (reqinfo == NULL) 2012 fatal("out of memory"); 2013 reqinfo->msg = msg; 2014 reqinfo->addr = destaddr; 2015 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0, 2016 (userserver != NULL) ? tsigkey : NULL, 2017 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, 2018 global_task, recvsoa, reqinfo, request); 2019 check_result(result, "dns_request_createvia"); 2020 requests++; 2021} 2022 2023static void 2024start_update(void) { 2025 isc_result_t result; 2026 dns_rdataset_t *rdataset = NULL; 2027 dns_name_t *name = NULL; 2028 dns_request_t *request = NULL; 2029 dns_message_t *soaquery = NULL; 2030 dns_name_t *firstname; 2031 dns_section_t section = DNS_SECTION_UPDATE; 2032 2033 ddebug("start_update()"); 2034 2035 if (answer != NULL) 2036 dns_message_destroy(&answer); 2037 2038 if (userzone != NULL && userserver != NULL) { 2039 send_update(userzone, userserver, localaddr); 2040 setzoneclass(dns_rdataclass_none); 2041 return; 2042 } 2043 2044 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, 2045 &soaquery); 2046 check_result(result, "dns_message_create"); 2047 2048 if (userserver == NULL) 2049 soaquery->flags |= DNS_MESSAGEFLAG_RD; 2050 2051 result = dns_message_gettempname(soaquery, &name); 2052 check_result(result, "dns_message_gettempname"); 2053 2054 result = dns_message_gettemprdataset(soaquery, &rdataset); 2055 check_result(result, "dns_message_gettemprdataset"); 2056 2057 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); 2058 2059 if (userzone != NULL) { 2060 dns_name_init(name, NULL); 2061 dns_name_clone(userzone, name); 2062 } else { 2063 result = dns_message_firstname(updatemsg, section); 2064 if (result == ISC_R_NOMORE) { 2065 section = DNS_SECTION_PREREQUISITE; 2066 result = dns_message_firstname(updatemsg, section); 2067 } 2068 if (result != ISC_R_SUCCESS) { 2069 dns_message_puttempname(soaquery, &name); 2070 dns_rdataset_disassociate(rdataset); 2071 dns_message_puttemprdataset(soaquery, &rdataset); 2072 dns_message_destroy(&soaquery); 2073 done_update(); 2074 return; 2075 } 2076 firstname = NULL; 2077 dns_message_currentname(updatemsg, section, &firstname); 2078 dns_name_init(name, NULL); 2079 dns_name_clone(firstname, name); 2080 } 2081 2082 ISC_LIST_INIT(name->list); 2083 ISC_LIST_APPEND(name->list, rdataset, link); 2084 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); 2085 2086 if (userserver != NULL) 2087 sendrequest(localaddr, userserver, soaquery, &request); 2088 else { 2089 ns_inuse = 0; 2090 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 2091 } 2092} 2093 2094static void 2095cleanup(void) { 2096 ddebug("cleanup()"); 2097 2098 if (answer != NULL) 2099 dns_message_destroy(&answer); 2100 ddebug("Shutting down task manager"); 2101 isc_taskmgr_destroy(&taskmgr); 2102 2103 ddebug("Destroying event"); 2104 isc_event_free(&global_event); 2105 2106 ddebug("Shutting down socket manager"); 2107 isc_socketmgr_destroy(&socketmgr); 2108 2109 ddebug("Shutting down timer manager"); 2110 isc_timermgr_destroy(&timermgr); 2111 2112 ddebug("Destroying hash context"); 2113 isc_hash_destroy(); 2114 2115 ddebug("Destroying name state"); 2116 dns_name_destroy(); 2117 2118 ddebug("Destroying memory context"); 2119 if (memdebugging) 2120 isc_mem_stats(mctx, stderr); 2121 isc_mem_destroy(&mctx); 2122} 2123 2124static void 2125getinput(isc_task_t *task, isc_event_t *event) { 2126 isc_boolean_t more; 2127 2128 UNUSED(task); 2129 2130 if (shuttingdown) { 2131 maybeshutdown(); 2132 return; 2133 } 2134 2135 if (global_event == NULL) 2136 global_event = event; 2137 2138 reset_system(); 2139 more = user_interaction(); 2140 if (!more) { 2141 isc_app_shutdown(); 2142 return; 2143 } 2144 start_update(); 2145 return; 2146} 2147 2148int 2149main(int argc, char **argv) { 2150 isc_result_t result; 2151 style = &dns_master_style_debug; 2152 2153 input = stdin; 2154 2155 interactive = ISC_TF(isatty(0)); 2156 2157 isc_app_start(); 2158 2159 parse_args(argc, argv); 2160 2161 setup_system(); 2162 2163 result = isc_app_onrun(mctx, global_task, getinput, NULL); 2164 check_result(result, "isc_app_onrun"); 2165 2166 (void)isc_app_run(); 2167 2168 cleanup(); 2169 2170 isc_app_finish(); 2171 2172 if (seenerror) 2173 return (2); 2174 else 2175 return (0); 2176} 2177