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