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