PageRenderTime 130ms CodeModel.GetById 23ms app.highlight 92ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bind9/bin/nsupdate/nsupdate.c

https://bitbucket.org/freebsd/freebsd-head/
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, &region);
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, &region);
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, &region);
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, &region);
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, &region);
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, &region);
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