nsupdate.c revision 170222
1/* 2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and 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.15 2006/12/07 05:39:45 marka 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 (result == STATUS_SEND) 1571 return (ISC_TRUE); 1572 return (ISC_FALSE); 1573 1574} 1575 1576static void 1577done_update(void) { 1578 isc_event_t *event = global_event; 1579 ddebug("done_update()"); 1580 isc_task_send(global_task, &event); 1581} 1582 1583static void 1584check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) { 1585 isc_result_t result; 1586 dns_rdata_t rdata = DNS_RDATA_INIT; 1587 dns_rdata_any_tsig_t tsig; 1588 1589 result = dns_rdataset_first(rdataset); 1590 check_result(result, "dns_rdataset_first"); 1591 dns_rdataset_current(rdataset, &rdata); 1592 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 1593 check_result(result, "dns_rdata_tostruct"); 1594 if (tsig.error != 0) { 1595 if (isc_buffer_remaininglength(b) < 1) 1596 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); 1597 isc__buffer_putstr(b, "(" /*)*/); 1598 result = dns_tsigrcode_totext(tsig.error, b); 1599 check_result(result, "dns_tsigrcode_totext"); 1600 if (isc_buffer_remaininglength(b) < 1) 1601 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); 1602 isc__buffer_putstr(b, /*(*/ ")"); 1603 } 1604} 1605 1606static void 1607update_completed(isc_task_t *task, isc_event_t *event) { 1608 dns_requestevent_t *reqev = NULL; 1609 isc_result_t result; 1610 dns_request_t *request; 1611 1612 UNUSED(task); 1613 1614 ddebug("update_completed()"); 1615 1616 requests--; 1617 1618 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 1619 reqev = (dns_requestevent_t *)event; 1620 request = reqev->request; 1621 1622 if (shuttingdown) { 1623 dns_request_destroy(&request); 1624 isc_event_free(&event); 1625 maybeshutdown(); 1626 return; 1627 } 1628 1629 if (reqev->result != ISC_R_SUCCESS) { 1630 fprintf(stderr, "; Communication with server failed: %s\n", 1631 isc_result_totext(reqev->result)); 1632 seenerror = ISC_TRUE; 1633 goto done; 1634 } 1635 1636 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer); 1637 check_result(result, "dns_message_create"); 1638 result = dns_request_getresponse(request, answer, 1639 DNS_MESSAGEPARSE_PRESERVEORDER); 1640 switch (result) { 1641 case ISC_R_SUCCESS: 1642 break; 1643 case DNS_R_CLOCKSKEW: 1644 case DNS_R_EXPECTEDTSIG: 1645 case DNS_R_TSIGERRORSET: 1646 case DNS_R_TSIGVERIFYFAILURE: 1647 case DNS_R_UNEXPECTEDTSIG: 1648 fprintf(stderr, "; TSIG error with server: %s\n", 1649 isc_result_totext(result)); 1650 seenerror = ISC_TRUE; 1651 break; 1652 default: 1653 check_result(result, "dns_request_getresponse"); 1654 } 1655 1656 if (answer->rcode != dns_rcode_noerror) { 1657 seenerror = ISC_TRUE; 1658 if (!debugging) { 1659 char buf[64]; 1660 isc_buffer_t b; 1661 dns_rdataset_t *rds; 1662 1663 isc_buffer_init(&b, buf, sizeof(buf) - 1); 1664 result = dns_rcode_totext(answer->rcode, &b); 1665 check_result(result, "dns_rcode_totext"); 1666 rds = dns_message_gettsig(answer, NULL); 1667 if (rds != NULL) 1668 check_tsig_error(rds, &b); 1669 fprintf(stderr, "update failed: %.*s\n", 1670 (int)isc_buffer_usedlength(&b), buf); 1671 } 1672 } 1673 if (debugging) { 1674 isc_buffer_t *buf = NULL; 1675 int bufsz; 1676 1677 bufsz = INITTEXT; 1678 do { 1679 if (bufsz > MAXTEXT) { 1680 fprintf(stderr, "could not allocate large " 1681 "enough buffer to display message\n"); 1682 exit(1); 1683 } 1684 if (buf != NULL) 1685 isc_buffer_free(&buf); 1686 result = isc_buffer_allocate(mctx, &buf, bufsz); 1687 check_result(result, "isc_buffer_allocate"); 1688 result = dns_message_totext(answer, style, 0, buf); 1689 bufsz *= 2; 1690 } while (result == ISC_R_NOSPACE); 1691 check_result(result, "dns_message_totext"); 1692 fprintf(stderr, "\nReply from update query:\n%.*s\n", 1693 (int)isc_buffer_usedlength(buf), 1694 (char*)isc_buffer_base(buf)); 1695 isc_buffer_free(&buf); 1696 } 1697 done: 1698 dns_request_destroy(&request); 1699 isc_event_free(&event); 1700 done_update(); 1701} 1702 1703static void 1704send_update(dns_name_t *zonename, isc_sockaddr_t *master, 1705 isc_sockaddr_t *srcaddr) 1706{ 1707 isc_result_t result; 1708 dns_request_t *request = NULL; 1709 unsigned int options = 0; 1710 1711 ddebug("send_update()"); 1712 1713 setzone(zonename); 1714 1715 if (usevc) 1716 options |= DNS_REQUESTOPT_TCP; 1717 if (tsigkey == NULL && sig0key != NULL) { 1718 result = dns_message_setsig0key(updatemsg, sig0key); 1719 check_result(result, "dns_message_setsig0key"); 1720 } 1721 if (debugging) { 1722 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 1723 1724 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf)); 1725 fprintf(stderr, "Sending update to %s\n", addrbuf); 1726 } 1727 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr, 1728 master, options, tsigkey, timeout, 1729 udp_timeout, udp_retries, global_task, 1730 update_completed, NULL, &request); 1731 check_result(result, "dns_request_createvia3"); 1732 1733 if (debugging) 1734 show_message(updatemsg); 1735 1736 requests++; 1737} 1738 1739static void 1740recvsoa(isc_task_t *task, isc_event_t *event) { 1741 dns_requestevent_t *reqev = NULL; 1742 dns_request_t *request = NULL; 1743 isc_result_t result, eresult; 1744 dns_message_t *rcvmsg = NULL; 1745 dns_section_t section; 1746 dns_name_t *name = NULL; 1747 dns_rdataset_t *soaset = NULL; 1748 dns_rdata_soa_t soa; 1749 dns_rdata_t soarr = DNS_RDATA_INIT; 1750 int pass = 0; 1751 dns_name_t master; 1752 isc_sockaddr_t *serveraddr, tempaddr; 1753 dns_name_t *zonename; 1754 nsu_requestinfo_t *reqinfo; 1755 dns_message_t *soaquery = NULL; 1756 isc_sockaddr_t *addr; 1757 isc_boolean_t seencname = ISC_FALSE; 1758 dns_name_t tname; 1759 unsigned int nlabels; 1760 1761 UNUSED(task); 1762 1763 ddebug("recvsoa()"); 1764 1765 requests--; 1766 1767 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 1768 reqev = (dns_requestevent_t *)event; 1769 request = reqev->request; 1770 eresult = reqev->result; 1771 reqinfo = reqev->ev_arg; 1772 soaquery = reqinfo->msg; 1773 addr = reqinfo->addr; 1774 1775 if (shuttingdown) { 1776 dns_request_destroy(&request); 1777 dns_message_destroy(&soaquery); 1778 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 1779 isc_event_free(&event); 1780 maybeshutdown(); 1781 return; 1782 } 1783 1784 if (eresult != ISC_R_SUCCESS) { 1785 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 1786 1787 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 1788 fprintf(stderr, "; Communication with %s failed: %s\n", 1789 addrbuf, isc_result_totext(eresult)); 1790 if (userserver != NULL) 1791 fatal("could not talk to specified name server"); 1792 else if (++ns_inuse >= lwconf->nsnext) 1793 fatal("could not talk to any default name server"); 1794 ddebug("Destroying request [%p]", request); 1795 dns_request_destroy(&request); 1796 dns_message_renderreset(soaquery); 1797 dns_message_settsigkey(soaquery, NULL); 1798 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 1799 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 1800 isc_event_free(&event); 1801 setzoneclass(dns_rdataclass_none); 1802 return; 1803 } 1804 1805 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 1806 reqinfo = NULL; 1807 isc_event_free(&event); 1808 reqev = NULL; 1809 1810 ddebug("About to create rcvmsg"); 1811 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 1812 check_result(result, "dns_message_create"); 1813 result = dns_request_getresponse(request, rcvmsg, 1814 DNS_MESSAGEPARSE_PRESERVEORDER); 1815 if (result == DNS_R_TSIGERRORSET && userserver != NULL) { 1816 dns_message_destroy(&rcvmsg); 1817 ddebug("Destroying request [%p]", request); 1818 dns_request_destroy(&request); 1819 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t)); 1820 if (reqinfo == NULL) 1821 fatal("out of memory"); 1822 reqinfo->msg = soaquery; 1823 reqinfo->addr = addr; 1824 dns_message_renderreset(soaquery); 1825 ddebug("retrying soa request without TSIG"); 1826 result = dns_request_createvia3(requestmgr, soaquery, 1827 localaddr, addr, 0, NULL, 1828 FIND_TIMEOUT * 20, 1829 FIND_TIMEOUT, 3, 1830 global_task, recvsoa, reqinfo, 1831 &request); 1832 check_result(result, "dns_request_createvia"); 1833 requests++; 1834 return; 1835 } 1836 check_result(result, "dns_request_getresponse"); 1837 section = DNS_SECTION_ANSWER; 1838 if (debugging) { 1839 isc_buffer_t *buf = NULL; 1840 int bufsz; 1841 bufsz = INITTEXT; 1842 do { 1843 if (buf != NULL) 1844 isc_buffer_free(&buf); 1845 if (bufsz > MAXTEXT) { 1846 fprintf(stderr, "could not allocate enough " 1847 "space for debugging message\n"); 1848 exit(1); 1849 } 1850 result = isc_buffer_allocate(mctx, &buf, bufsz); 1851 check_result(result, "isc_buffer_allocate"); 1852 result = dns_message_totext(rcvmsg, style, 0, buf); 1853 } while (result == ISC_R_NOSPACE); 1854 check_result(result, "dns_message_totext"); 1855 fprintf(stderr, "Reply from SOA query:\n%.*s\n", 1856 (int)isc_buffer_usedlength(buf), 1857 (char*)isc_buffer_base(buf)); 1858 isc_buffer_free(&buf); 1859 } 1860 1861 if (rcvmsg->rcode != dns_rcode_noerror && 1862 rcvmsg->rcode != dns_rcode_nxdomain) 1863 fatal("response to SOA query was unsuccessful"); 1864 1865 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) { 1866 char namebuf[DNS_NAME_FORMATSIZE]; 1867 dns_name_format(userzone, namebuf, sizeof(namebuf)); 1868 error("specified zone '%s' does not exist (NXDOMAIN)", 1869 namebuf); 1870 dns_message_destroy(&rcvmsg); 1871 dns_request_destroy(&request); 1872 dns_message_destroy(&soaquery); 1873 ddebug("Out of recvsoa"); 1874 done_update(); 1875 return; 1876 } 1877 1878 lookforsoa: 1879 if (pass == 0) 1880 section = DNS_SECTION_ANSWER; 1881 else if (pass == 1) 1882 section = DNS_SECTION_AUTHORITY; 1883 else 1884 goto droplabel; 1885 1886 result = dns_message_firstname(rcvmsg, section); 1887 if (result != ISC_R_SUCCESS) { 1888 pass++; 1889 goto lookforsoa; 1890 } 1891 while (result == ISC_R_SUCCESS) { 1892 name = NULL; 1893 dns_message_currentname(rcvmsg, section, &name); 1894 soaset = NULL; 1895 result = dns_message_findtype(name, dns_rdatatype_soa, 0, 1896 &soaset); 1897 if (result == ISC_R_SUCCESS) 1898 break; 1899 if (section == DNS_SECTION_ANSWER) { 1900 dns_rdataset_t *tset = NULL; 1901 if (dns_message_findtype(name, dns_rdatatype_cname, 0, 1902 &tset) == ISC_R_SUCCESS 1903 || 1904 dns_message_findtype(name, dns_rdatatype_dname, 0, 1905 &tset) == ISC_R_SUCCESS 1906 ) 1907 { 1908 seencname = ISC_TRUE; 1909 break; 1910 } 1911 } 1912 1913 result = dns_message_nextname(rcvmsg, section); 1914 } 1915 1916 if (soaset == NULL && !seencname) { 1917 pass++; 1918 goto lookforsoa; 1919 } 1920 1921 if (seencname) 1922 goto droplabel; 1923 1924 if (debugging) { 1925 char namestr[DNS_NAME_FORMATSIZE]; 1926 dns_name_format(name, namestr, sizeof(namestr)); 1927 fprintf(stderr, "Found zone name: %s\n", namestr); 1928 } 1929 1930 result = dns_rdataset_first(soaset); 1931 check_result(result, "dns_rdataset_first"); 1932 1933 dns_rdata_init(&soarr); 1934 dns_rdataset_current(soaset, &soarr); 1935 result = dns_rdata_tostruct(&soarr, &soa, NULL); 1936 check_result(result, "dns_rdata_tostruct"); 1937 1938 dns_name_init(&master, NULL); 1939 dns_name_clone(&soa.origin, &master); 1940 1941 if (userzone != NULL) 1942 zonename = userzone; 1943 else 1944 zonename = name; 1945 1946 if (debugging) { 1947 char namestr[DNS_NAME_FORMATSIZE]; 1948 dns_name_format(&master, namestr, sizeof(namestr)); 1949 fprintf(stderr, "The master is: %s\n", namestr); 1950 } 1951 1952 if (userserver != NULL) 1953 serveraddr = userserver; 1954 else { 1955 char serverstr[DNS_NAME_MAXTEXT+1]; 1956 isc_buffer_t buf; 1957 1958 isc_buffer_init(&buf, serverstr, sizeof(serverstr)); 1959 result = dns_name_totext(&master, ISC_TRUE, &buf); 1960 check_result(result, "dns_name_totext"); 1961 serverstr[isc_buffer_usedlength(&buf)] = 0; 1962 get_address(serverstr, DNSDEFAULTPORT, &tempaddr); 1963 serveraddr = &tempaddr; 1964 } 1965 dns_rdata_freestruct(&soa); 1966 1967 send_update(zonename, serveraddr, localaddr); 1968 setzoneclass(dns_rdataclass_none); 1969 1970 dns_message_destroy(&soaquery); 1971 dns_request_destroy(&request); 1972 1973 out: 1974 dns_message_destroy(&rcvmsg); 1975 ddebug("Out of recvsoa"); 1976 return; 1977 1978 droplabel: 1979 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); 1980 INSIST(result == ISC_R_SUCCESS); 1981 name = NULL; 1982 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); 1983 nlabels = dns_name_countlabels(name); 1984 if (nlabels == 1) 1985 fatal("could not find enclosing zone"); 1986 dns_name_init(&tname, NULL); 1987 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname); 1988 dns_name_clone(&tname, name); 1989 dns_request_destroy(&request); 1990 dns_message_renderreset(soaquery); 1991 dns_message_settsigkey(soaquery, NULL); 1992 if (userserver != NULL) 1993 sendrequest(localaddr, userserver, soaquery, &request); 1994 else 1995 sendrequest(localaddr, &servers[ns_inuse], soaquery, 1996 &request); 1997 goto out; 1998} 1999 2000static void 2001sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 2002 dns_message_t *msg, dns_request_t **request) 2003{ 2004 isc_result_t result; 2005 nsu_requestinfo_t *reqinfo; 2006 2007 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t)); 2008 if (reqinfo == NULL) 2009 fatal("out of memory"); 2010 reqinfo->msg = msg; 2011 reqinfo->addr = destaddr; 2012 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0, 2013 (userserver != NULL) ? tsigkey : NULL, 2014 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, 2015 global_task, recvsoa, reqinfo, request); 2016 check_result(result, "dns_request_createvia"); 2017 requests++; 2018} 2019 2020static void 2021start_update(void) { 2022 isc_result_t result; 2023 dns_rdataset_t *rdataset = NULL; 2024 dns_name_t *name = NULL; 2025 dns_request_t *request = NULL; 2026 dns_message_t *soaquery = NULL; 2027 dns_name_t *firstname; 2028 dns_section_t section = DNS_SECTION_UPDATE; 2029 2030 ddebug("start_update()"); 2031 2032 if (answer != NULL) 2033 dns_message_destroy(&answer); 2034 2035 if (userzone != NULL && userserver != NULL) { 2036 send_update(userzone, userserver, localaddr); 2037 setzoneclass(dns_rdataclass_none); 2038 return; 2039 } 2040 2041 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, 2042 &soaquery); 2043 check_result(result, "dns_message_create"); 2044 2045 if (userserver == NULL) 2046 soaquery->flags |= DNS_MESSAGEFLAG_RD; 2047 2048 result = dns_message_gettempname(soaquery, &name); 2049 check_result(result, "dns_message_gettempname"); 2050 2051 result = dns_message_gettemprdataset(soaquery, &rdataset); 2052 check_result(result, "dns_message_gettemprdataset"); 2053 2054 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); 2055 2056 if (userzone != NULL) { 2057 dns_name_init(name, NULL); 2058 dns_name_clone(userzone, name); 2059 } else { 2060 result = dns_message_firstname(updatemsg, section); 2061 if (result == ISC_R_NOMORE) { 2062 section = DNS_SECTION_PREREQUISITE; 2063 result = dns_message_firstname(updatemsg, section); 2064 } 2065 if (result != ISC_R_SUCCESS) { 2066 done_update(); 2067 return; 2068 } 2069 firstname = NULL; 2070 dns_message_currentname(updatemsg, section, &firstname); 2071 dns_name_init(name, NULL); 2072 dns_name_clone(firstname, name); 2073 } 2074 2075 ISC_LIST_INIT(name->list); 2076 ISC_LIST_APPEND(name->list, rdataset, link); 2077 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); 2078 2079 if (userserver != NULL) 2080 sendrequest(localaddr, userserver, soaquery, &request); 2081 else { 2082 ns_inuse = 0; 2083 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 2084 } 2085} 2086 2087static void 2088cleanup(void) { 2089 ddebug("cleanup()"); 2090 2091 if (answer != NULL) 2092 dns_message_destroy(&answer); 2093 ddebug("Shutting down task manager"); 2094 isc_taskmgr_destroy(&taskmgr); 2095 2096 ddebug("Destroying event"); 2097 isc_event_free(&global_event); 2098 2099 ddebug("Shutting down socket manager"); 2100 isc_socketmgr_destroy(&socketmgr); 2101 2102 ddebug("Shutting down timer manager"); 2103 isc_timermgr_destroy(&timermgr); 2104 2105 ddebug("Destroying hash context"); 2106 isc_hash_destroy(); 2107 2108 ddebug("Destroying name state"); 2109 dns_name_destroy(); 2110 2111 ddebug("Destroying memory context"); 2112 if (memdebugging) 2113 isc_mem_stats(mctx, stderr); 2114 isc_mem_destroy(&mctx); 2115} 2116 2117static void 2118getinput(isc_task_t *task, isc_event_t *event) { 2119 isc_boolean_t more; 2120 2121 UNUSED(task); 2122 2123 if (shuttingdown) { 2124 maybeshutdown(); 2125 return; 2126 } 2127 2128 if (global_event == NULL) 2129 global_event = event; 2130 2131 reset_system(); 2132 more = user_interaction(); 2133 if (!more) { 2134 isc_app_shutdown(); 2135 return; 2136 } 2137 start_update(); 2138 return; 2139} 2140 2141int 2142main(int argc, char **argv) { 2143 isc_result_t result; 2144 style = &dns_master_style_debug; 2145 2146 input = stdin; 2147 2148 interactive = ISC_TF(isatty(0)); 2149 2150 isc_app_start(); 2151 2152 parse_args(argc, argv); 2153 2154 setup_system(); 2155 2156 result = isc_app_onrun(mctx, global_task, getinput, NULL); 2157 check_result(result, "isc_app_onrun"); 2158 2159 (void)isc_app_run(); 2160 2161 cleanup(); 2162 2163 isc_app_finish(); 2164 2165 if (seenerror) 2166 return (2); 2167 else 2168 return (0); 2169} 2170