xref: /netbsd-src/external/mpl/bind/dist/bin/nsupdate/nsupdate.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: nsupdate.c,v 1.16 2025/01/26 16:24:34 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /*! \file */
17 
18 #include <ctype.h>
19 #include <errno.h>
20 #include <inttypes.h>
21 #include <limits.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 
26 #include <isc/async.h>
27 #include <isc/attributes.h>
28 #include <isc/base64.h>
29 #include <isc/buffer.h>
30 #include <isc/commandline.h>
31 #include <isc/file.h>
32 #include <isc/getaddresses.h>
33 #include <isc/hash.h>
34 #include <isc/lex.h>
35 #include <isc/log.h>
36 #include <isc/loop.h>
37 #include <isc/managers.h>
38 #include <isc/mem.h>
39 #include <isc/netmgr.h>
40 #include <isc/nonce.h>
41 #include <isc/parseint.h>
42 #include <isc/portset.h>
43 #include <isc/random.h>
44 #include <isc/region.h>
45 #include <isc/result.h>
46 #include <isc/sockaddr.h>
47 #include <isc/stdio.h>
48 #include <isc/string.h>
49 #include <isc/tls.h>
50 #include <isc/types.h>
51 #include <isc/util.h>
52 
53 #include <dns/callbacks.h>
54 #include <dns/dispatch.h>
55 #include <dns/dnssec.h>
56 #include <dns/fixedname.h>
57 #include <dns/log.h>
58 #include <dns/masterdump.h>
59 #include <dns/message.h>
60 #include <dns/name.h>
61 #include <dns/nsec3.h>
62 #include <dns/rcode.h>
63 #include <dns/rdata.h>
64 #include <dns/rdataclass.h>
65 #include <dns/rdatalist.h>
66 #include <dns/rdataset.h>
67 #include <dns/rdatastruct.h>
68 #include <dns/rdatatype.h>
69 #include <dns/request.h>
70 #include <dns/tkey.h>
71 #include <dns/transport.h>
72 #include <dns/tsig.h>
73 
74 #include <dst/dst.h>
75 
76 #include <isccfg/namedconf.h>
77 
78 #include <irs/resconf.h>
79 
80 #if HAVE_GSSAPI
81 #include <dst/gssapi.h>
82 
83 #if HAVE_KRB5_KRB5_H
84 #include <krb5/krb5.h>
85 #elif HAVE_KRB5_H
86 #include <krb5.h>
87 #endif
88 
89 #if HAVE_GSSAPI_GSSAPI_H
90 #include <gssapi/gssapi.h>
91 #elif HAVE_GSSAPI_H
92 #include <gssapi.h>
93 #endif
94 
95 #endif /* HAVE_GSSAPI */
96 
97 #include "../dig/readline.h"
98 
99 #define MAXCMD	 (128 * 1024)
100 #define MAXWIRE	 (64 * 1024)
101 #define INITTEXT (2 * 1024)
102 #define MAXTEXT	 (128 * 1024)
103 #define TTL_MAX	 2147483647U /* Maximum signed 32 bit integer. */
104 
105 #define DNSDEFAULTPORT 53
106 
107 #define DEFAULT_EDNS_BUFSIZE 1232
108 
109 /* Number of addresses to request from isc_getaddresses() */
110 #define MAX_SERVERADDRS 4
111 
112 static uint16_t dnsport = DNSDEFAULTPORT;
113 
114 #ifndef RESOLV_CONF
115 #define RESOLV_CONF "/etc/resolv.conf"
116 #endif /* ifndef RESOLV_CONF */
117 
118 static bool debugging = false, ddebugging = false;
119 static bool memdebugging = false;
120 static bool have_ipv4 = false;
121 static bool have_ipv6 = false;
122 static bool is_dst_up = false;
123 static bool use_tls = false;
124 static bool usevc = false;
125 static bool usegsstsig = false;
126 static bool local_only = false;
127 static isc_nm_t *netmgr = NULL;
128 static isc_loopmgr_t *loopmgr = NULL;
129 static isc_log_t *glctx = NULL;
130 static isc_mem_t *gmctx = NULL;
131 static dns_dispatchmgr_t *dispatchmgr = NULL;
132 static dns_requestmgr_t *requestmgr = NULL;
133 static dns_dispatch_t *dispatchv4 = NULL;
134 static dns_dispatch_t *dispatchv6 = NULL;
135 static dns_message_t *updatemsg = NULL;
136 static dns_fixedname_t fuserzone;
137 static dns_fixedname_t fzname;
138 static dns_name_t *userzone = NULL;
139 static dns_name_t *zname = NULL;
140 static dns_name_t tmpzonename = DNS_NAME_INITEMPTY;
141 static dns_name_t restart_primary = DNS_NAME_INITEMPTY;
142 static dns_tsigkeyring_t *gssring = NULL;
143 static dns_tsigkey_t *tsigkey = NULL;
144 static dst_key_t *sig0key = NULL;
145 static isc_sockaddr_t *servers = NULL;
146 static isc_sockaddr_t *primary_servers = NULL;
147 static dns_transport_list_t *transport_list = NULL;
148 static dns_transport_t *transport = NULL;
149 static isc_tlsctx_cache_t *tls_ctx_cache = NULL;
150 static char *tls_hostname = NULL;
151 static char *tls_client_key_file = NULL;
152 static char *tls_client_cert_file = NULL;
153 static char *tls_ca_file = NULL;
154 static bool tls_always_verify_remote = true;
155 static bool default_servers = true;
156 static int ns_inuse = 0;
157 static int primary_inuse = 0;
158 static int ns_total = 0;
159 static int ns_alloc = 0;
160 static int primary_total = 0;
161 static int primary_alloc = 0;
162 static isc_sockaddr_t *localaddr4 = NULL;
163 static isc_sockaddr_t *localaddr6 = NULL;
164 static const char *keyfile = NULL;
165 static char *keystr = NULL;
166 static bool shuttingdown = false;
167 static FILE *input;
168 static bool interactive = true;
169 static bool seenerror = false;
170 static const dns_master_style_t *style;
171 static int requests = 0;
172 static unsigned int logdebuglevel = 0;
173 static unsigned int timeout = 300;
174 static unsigned int udp_timeout = 3;
175 static unsigned int udp_retries = 3;
176 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
177 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
178 static isc_mutex_t answer_lock;
179 static dns_message_t *answer = NULL;
180 static uint32_t default_ttl = 0;
181 static bool default_ttl_set = false;
182 static uint32_t lease = 0, keylease = 0;
183 static bool lease_set = false, keylease_set = false;
184 static bool checknames = true;
185 static bool checksvcb = true;
186 static const char *resolvconf = RESOLV_CONF;
187 
188 bool done = false;
189 
190 typedef struct nsu_requestinfo {
191 	dns_message_t *msg;
192 	isc_sockaddr_t *addr;
193 } nsu_requestinfo_t;
194 
195 static void
196 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
197 	    dns_request_t **request);
198 static void
199 send_update(dns_name_t *zonename, isc_sockaddr_t *primary);
200 
201 static void
202 getinput(void *arg);
203 
204 noreturn static void
205 fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
206 
207 static void
208 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
209 
210 static void
211 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
212 
213 #if HAVE_GSSAPI
214 static dns_fixedname_t fkname;
215 static isc_sockaddr_t *kserver = NULL;
216 static char *realm = NULL;
217 static char servicename[DNS_NAME_FORMATSIZE];
218 static dns_name_t *keyname;
219 typedef struct nsu_gssinfo {
220 	dns_message_t *msg;
221 	isc_sockaddr_t *addr;
222 	gss_ctx_id_t context;
223 } nsu_gssinfo_t;
224 
225 static void
226 failed_gssrequest(void);
227 static void
228 start_gssrequest(dns_name_t *primary);
229 static void
230 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
231 		dns_request_t **request, gss_ctx_id_t context);
232 static void
233 recvgss(void *arg);
234 #endif /* HAVE_GSSAPI */
235 
236 static void
237 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
238 
239 #define STATUS_MORE   (uint16_t)0
240 #define STATUS_SEND   (uint16_t)1
241 #define STATUS_QUIT   (uint16_t)2
242 #define STATUS_SYNTAX (uint16_t)3
243 
244 static void
245 primary_from_servers(void) {
246 	if (primary_servers != NULL && primary_servers != servers) {
247 		isc_mem_cput(gmctx, primary_servers, primary_alloc,
248 			     sizeof(isc_sockaddr_t));
249 	}
250 	primary_servers = servers;
251 	primary_total = ns_total;
252 	primary_alloc = ns_alloc;
253 	primary_inuse = ns_inuse;
254 }
255 
256 static dns_rdataclass_t
257 getzoneclass(void) {
258 	if (zoneclass == dns_rdataclass_none) {
259 		zoneclass = defaultclass;
260 	}
261 	return zoneclass;
262 }
263 
264 static bool
265 setzoneclass(dns_rdataclass_t rdclass) {
266 	if (zoneclass == dns_rdataclass_none || rdclass == dns_rdataclass_none)
267 	{
268 		zoneclass = rdclass;
269 	}
270 	if (zoneclass != rdclass) {
271 		return false;
272 	}
273 	return true;
274 }
275 
276 static void
277 fatal(const char *format, ...) {
278 	va_list args;
279 
280 	va_start(args, format);
281 	vfprintf(stderr, format, args);
282 	va_end(args);
283 	fprintf(stderr, "\n");
284 	_exit(EXIT_FAILURE);
285 }
286 
287 static void
288 error(const char *format, ...) {
289 	va_list args;
290 
291 	va_start(args, format);
292 	vfprintf(stderr, format, args);
293 	va_end(args);
294 	fprintf(stderr, "\n");
295 }
296 
297 static void
298 debug(const char *format, ...) {
299 	va_list args;
300 
301 	if (debugging) {
302 		va_start(args, format);
303 		vfprintf(stderr, format, args);
304 		va_end(args);
305 		fprintf(stderr, "\n");
306 	}
307 }
308 
309 static void
310 ddebug(const char *format, ...) {
311 	va_list args;
312 
313 	if (ddebugging) {
314 		va_start(args, format);
315 		vfprintf(stderr, format, args);
316 		va_end(args);
317 		fprintf(stderr, "\n");
318 	}
319 }
320 
321 ISC_NO_SANITIZE_ADDRESS static void
322 check_result(isc_result_t result, const char *msg) {
323 	if (result != ISC_R_SUCCESS) {
324 		fatal("%s: %s", msg, isc_result_totext(result));
325 	}
326 }
327 
328 static char *
329 nsu_strsep(char **stringp, const char *delim) {
330 	char *string = *stringp;
331 	*stringp = NULL;
332 	char *s;
333 	const char *d;
334 	char sc, dc;
335 
336 	if (string == NULL) {
337 		return NULL;
338 	}
339 
340 	for (; *string != '\0'; string++) {
341 		sc = *string;
342 		for (d = delim; (dc = *d) != '\0'; d++) {
343 			if (sc == dc) {
344 				break;
345 			}
346 		}
347 		if (dc == 0) {
348 			break;
349 		}
350 	}
351 
352 	for (s = string; *s != '\0'; s++) {
353 		sc = *s;
354 		for (d = delim; (dc = *d) != '\0'; d++) {
355 			if (sc == dc) {
356 				*s++ = '\0';
357 				*stringp = s;
358 				return string;
359 			}
360 		}
361 	}
362 	return string;
363 }
364 
365 static void
366 reset_system(void) {
367 	ddebug("reset_system()");
368 	/* If the update message is still around, destroy it */
369 	if (updatemsg != NULL) {
370 		dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
371 	} else {
372 		dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
373 				   &updatemsg);
374 	}
375 	updatemsg->opcode = dns_opcode_update;
376 	if (usegsstsig) {
377 		if (tsigkey != NULL) {
378 			dns_tsigkey_detach(&tsigkey);
379 		}
380 		if (gssring != NULL) {
381 			dns_tsigkeyring_detach(&gssring);
382 		}
383 	}
384 }
385 
386 static bool
387 parse_hmac(const char *hmacstr, size_t len, dst_algorithm_t *hmac_alg,
388 	   uint16_t *digestbitsp) {
389 	uint16_t digestbits = 0;
390 	isc_result_t result;
391 	char buf[20];
392 
393 	REQUIRE(hmac_alg != NULL);
394 	REQUIRE(hmacstr != NULL);
395 
396 	if (len >= sizeof(buf)) {
397 		error("unknown key type '%.*s'", (int)(len), hmacstr);
398 		return false;
399 	}
400 
401 	/* Copy len bytes and NUL terminate. */
402 	strlcpy(buf, hmacstr, ISC_MIN(len + 1, sizeof(buf)));
403 
404 	if (strcasecmp(buf, "hmac-md5") == 0) {
405 		*hmac_alg = DST_ALG_HMACMD5;
406 	} else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
407 		*hmac_alg = DST_ALG_HMACMD5;
408 		result = isc_parse_uint16(&digestbits, &buf[9], 10);
409 		if (result != ISC_R_SUCCESS || digestbits > 128) {
410 			error("digest-bits out of range [0..128]");
411 			return false;
412 		}
413 		*digestbitsp = (digestbits + 7) & ~0x7U;
414 	} else if (strcasecmp(buf, "hmac-sha1") == 0) {
415 		*hmac_alg = DST_ALG_HMACSHA1;
416 	} else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
417 		*hmac_alg = DST_ALG_HMACSHA1;
418 		result = isc_parse_uint16(&digestbits, &buf[10], 10);
419 		if (result != ISC_R_SUCCESS || digestbits > 160) {
420 			error("digest-bits out of range [0..160]");
421 			return false;
422 		}
423 		*digestbitsp = (digestbits + 7) & ~0x7U;
424 	} else if (strcasecmp(buf, "hmac-sha224") == 0) {
425 		*hmac_alg = DST_ALG_HMACSHA224;
426 	} else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
427 		*hmac_alg = DST_ALG_HMACSHA224;
428 		result = isc_parse_uint16(&digestbits, &buf[12], 10);
429 		if (result != ISC_R_SUCCESS || digestbits > 224) {
430 			error("digest-bits out of range [0..224]");
431 			return false;
432 		}
433 		*digestbitsp = (digestbits + 7) & ~0x7U;
434 	} else if (strcasecmp(buf, "hmac-sha256") == 0) {
435 		*hmac_alg = DST_ALG_HMACSHA256;
436 	} else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
437 		*hmac_alg = DST_ALG_HMACSHA256;
438 		result = isc_parse_uint16(&digestbits, &buf[12], 10);
439 		if (result != ISC_R_SUCCESS || digestbits > 256) {
440 			error("digest-bits out of range [0..256]");
441 			return false;
442 		}
443 		*digestbitsp = (digestbits + 7) & ~0x7U;
444 	} else if (strcasecmp(buf, "hmac-sha384") == 0) {
445 		*hmac_alg = DST_ALG_HMACSHA384;
446 	} else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
447 		*hmac_alg = DST_ALG_HMACSHA384;
448 		result = isc_parse_uint16(&digestbits, &buf[12], 10);
449 		if (result != ISC_R_SUCCESS || digestbits > 384) {
450 			error("digest-bits out of range [0..384]");
451 			return false;
452 		}
453 		*digestbitsp = (digestbits + 7) & ~0x7U;
454 	} else if (strcasecmp(buf, "hmac-sha512") == 0) {
455 		*hmac_alg = DST_ALG_HMACSHA512;
456 	} else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
457 		*hmac_alg = DST_ALG_HMACSHA512;
458 		result = isc_parse_uint16(&digestbits, &buf[12], 10);
459 		if (result != ISC_R_SUCCESS || digestbits > 512) {
460 			error("digest-bits out of range [0..512]");
461 			return false;
462 		}
463 		*digestbitsp = (digestbits + 7) & ~0x7U;
464 	} else {
465 		error("unknown key type '%s'", buf);
466 		return false;
467 	}
468 	return true;
469 }
470 
471 static int
472 basenamelen(const char *file) {
473 	int len = strlen(file);
474 
475 	if (len > 1 && file[len - 1] == '.') {
476 		len -= 1;
477 	} else if (len > 8 && strcmp(file + len - 8, ".private") == 0) {
478 		len -= 8;
479 	} else if (len > 4 && strcmp(file + len - 4, ".key") == 0) {
480 		len -= 4;
481 	}
482 	return len;
483 }
484 
485 static void
486 setup_keystr(void) {
487 	unsigned char *secret = NULL;
488 	int secretlen;
489 	isc_buffer_t secretbuf;
490 	isc_result_t result;
491 	isc_buffer_t keynamesrc;
492 	char *secretstr = NULL;
493 	char *s = NULL, *n = NULL;
494 	dns_fixedname_t fkeyname;
495 	dns_name_t *mykeyname = NULL;
496 	char *name = NULL;
497 	dst_algorithm_t hmac_alg;
498 	uint16_t digestbits = 0;
499 
500 	mykeyname = dns_fixedname_initname(&fkeyname);
501 
502 	debug("Creating key...");
503 
504 	s = strchr(keystr, ':');
505 	if (s == NULL || s == keystr || s[1] == 0) {
506 		fatal("key option must specify [hmac:]keyname:secret");
507 	}
508 	secretstr = s + 1;
509 	n = strchr(secretstr, ':');
510 	if (n != NULL) {
511 		if (n == secretstr || n[1] == 0) {
512 			fatal("key option must specify [hmac:]keyname:secret");
513 		}
514 		name = secretstr;
515 		secretstr = n + 1;
516 		if (!parse_hmac(keystr, s - keystr, &hmac_alg, &digestbits)) {
517 			exit(EXIT_FAILURE);
518 		}
519 	} else {
520 		hmac_alg = DST_ALG_HMACMD5;
521 		name = keystr;
522 		n = s;
523 	}
524 
525 	isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name));
526 	isc_buffer_add(&keynamesrc, (unsigned int)(n - name));
527 
528 	debug("namefromtext");
529 	result = dns_name_fromtext(mykeyname, &keynamesrc, dns_rootname, 0,
530 				   NULL);
531 	check_result(result, "dns_name_fromtext");
532 
533 	secretlen = strlen(secretstr) * 3 / 4;
534 	secret = isc_mem_allocate(gmctx, secretlen);
535 
536 	isc_buffer_init(&secretbuf, secret, secretlen);
537 	result = isc_base64_decodestring(secretstr, &secretbuf);
538 	if (result != ISC_R_SUCCESS) {
539 		fprintf(stderr, "could not create key from %s: %s\n", keystr,
540 			isc_result_totext(result));
541 		goto failure;
542 	}
543 
544 	secretlen = isc_buffer_usedlength(&secretbuf);
545 
546 	debug("keycreate");
547 	result = dns_tsigkey_create(mykeyname, hmac_alg, secret, secretlen,
548 				    gmctx, &tsigkey);
549 	if (result != ISC_R_SUCCESS) {
550 		fprintf(stderr, "could not create key from %s: %s\n", keystr,
551 			isc_result_totext(result));
552 	} else {
553 		dst_key_setbits(tsigkey->key, digestbits);
554 	}
555 failure:
556 	if (secret != NULL) {
557 		isc_mem_free(gmctx, secret);
558 	}
559 }
560 
561 /*
562  * Get a key from a named.conf format keyfile
563  */
564 static isc_result_t
565 read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) {
566 	cfg_parser_t *pctx = NULL;
567 	cfg_obj_t *sessionkey = NULL;
568 	const cfg_obj_t *key = NULL;
569 	const cfg_obj_t *secretobj = NULL;
570 	const cfg_obj_t *algorithmobj = NULL;
571 	const char *mykeyname;
572 	const char *secretstr;
573 	const char *algorithm;
574 	isc_result_t result;
575 	int len;
576 
577 	if (!isc_file_exists(keyfile)) {
578 		return ISC_R_FILENOTFOUND;
579 	}
580 
581 	result = cfg_parser_create(mctx, lctx, &pctx);
582 	if (result != ISC_R_SUCCESS) {
583 		goto cleanup;
584 	}
585 
586 	result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
587 				&sessionkey);
588 	if (result != ISC_R_SUCCESS) {
589 		goto cleanup;
590 	}
591 
592 	result = cfg_map_get(sessionkey, "key", &key);
593 	if (result != ISC_R_SUCCESS) {
594 		goto cleanup;
595 	}
596 
597 	(void)cfg_map_get(key, "secret", &secretobj);
598 	(void)cfg_map_get(key, "algorithm", &algorithmobj);
599 	if (secretobj == NULL || algorithmobj == NULL) {
600 		fatal("key must have algorithm and secret");
601 	}
602 
603 	mykeyname = cfg_obj_asstring(cfg_map_getname(key));
604 	secretstr = cfg_obj_asstring(secretobj);
605 	algorithm = cfg_obj_asstring(algorithmobj);
606 
607 	len = strlen(algorithm) + strlen(mykeyname) + strlen(secretstr) + 3;
608 	keystr = isc_mem_allocate(mctx, len);
609 	snprintf(keystr, len, "%s:%s:%s", algorithm, mykeyname, secretstr);
610 	setup_keystr();
611 
612 cleanup:
613 	if (pctx != NULL) {
614 		if (sessionkey != NULL) {
615 			cfg_obj_destroy(pctx, &sessionkey);
616 		}
617 		cfg_parser_destroy(&pctx);
618 	}
619 
620 	if (keystr != NULL) {
621 		isc_mem_free(mctx, keystr);
622 	}
623 
624 	return result;
625 }
626 
627 static void
628 setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
629 	dst_key_t *dstkey = NULL;
630 	isc_result_t result;
631 	dst_algorithm_t hmac_alg = DST_ALG_UNKNOWN;
632 
633 	debug("Creating key...");
634 
635 	if (sig0key != NULL) {
636 		dst_key_free(&sig0key);
637 	}
638 
639 	/* Try reading the key from a K* pair */
640 	result = dst_key_fromnamedfile(
641 		keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey);
642 
643 	/* If that didn't work, try reading it as a session.key keyfile */
644 	if (result != ISC_R_SUCCESS) {
645 		result = read_sessionkey(mctx, lctx);
646 		if (result == ISC_R_SUCCESS) {
647 			return;
648 		}
649 	}
650 
651 	if (result != ISC_R_SUCCESS) {
652 		fprintf(stderr,
653 			"could not read key from %.*s.{private,key}: "
654 			"%s\n",
655 			basenamelen(keyfile), keyfile,
656 			isc_result_totext(result));
657 		return;
658 	}
659 
660 	switch (dst_key_alg(dstkey)) {
661 	case DST_ALG_HMACMD5:
662 	case DST_ALG_HMACSHA1:
663 	case DST_ALG_HMACSHA224:
664 	case DST_ALG_HMACSHA256:
665 	case DST_ALG_HMACSHA384:
666 	case DST_ALG_HMACSHA512:
667 		hmac_alg = dst_key_alg(dstkey);
668 		break;
669 	default:
670 		dst_key_attach(dstkey, &sig0key);
671 		dst_key_free(&dstkey);
672 		return;
673 	}
674 
675 	result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmac_alg,
676 					   dstkey, false, false, NULL, 0, 0,
677 					   mctx, &tsigkey);
678 	dst_key_free(&dstkey);
679 	if (result != ISC_R_SUCCESS) {
680 		fprintf(stderr, "could not create key from %s: %s\n", keyfile,
681 			isc_result_totext(result));
682 	}
683 }
684 
685 static void
686 doshutdown(void) {
687 	/*
688 	 * The isc_mem_put of primary_servers must be before the
689 	 * isc_mem_put of servers as it sets the servers pointer
690 	 * to NULL.
691 	 */
692 	if (primary_servers != NULL && primary_servers != servers) {
693 		isc_mem_cput(gmctx, primary_servers, primary_alloc,
694 			     sizeof(isc_sockaddr_t));
695 	}
696 
697 	if (servers != NULL) {
698 		isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t));
699 	}
700 
701 	if (localaddr4 != NULL) {
702 		isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t));
703 	}
704 
705 	if (localaddr6 != NULL) {
706 		isc_mem_put(gmctx, localaddr6, sizeof(isc_sockaddr_t));
707 	}
708 
709 	if (tsigkey != NULL) {
710 		ddebug("Freeing TSIG key");
711 		dns_tsigkey_detach(&tsigkey);
712 	}
713 
714 	if (sig0key != NULL) {
715 		ddebug("Freeing SIG(0) key");
716 		dst_key_free(&sig0key);
717 	}
718 
719 	if (updatemsg != NULL) {
720 		dns_message_detach(&updatemsg);
721 	}
722 
723 	ddebug("Destroying request manager");
724 	dns_requestmgr_detach(&requestmgr);
725 
726 	ddebug("Freeing the dispatchers");
727 	if (have_ipv4) {
728 		dns_dispatch_detach(&dispatchv4);
729 	}
730 	if (have_ipv6) {
731 		dns_dispatch_detach(&dispatchv6);
732 	}
733 
734 	ddebug("Shutting down dispatch manager");
735 	dns_dispatchmgr_detach(&dispatchmgr);
736 }
737 
738 static void
739 maybeshutdown(void) {
740 	/* when called from getinput, doshutdown might be already finished */
741 	if (requestmgr == NULL) {
742 		return;
743 	}
744 
745 	ddebug("Shutting down request manager");
746 	dns_requestmgr_shutdown(requestmgr);
747 
748 	if (requests != 0) {
749 		return;
750 	}
751 
752 	doshutdown();
753 }
754 
755 static void
756 shutdown_program(void *arg) {
757 	UNUSED(arg);
758 
759 	ddebug("shutdown_program()");
760 
761 	shuttingdown = true;
762 	maybeshutdown();
763 }
764 
765 /*
766  * Try honoring the operating system's preferred ephemeral port range.
767  */
768 static void
769 set_source_ports(dns_dispatchmgr_t *manager) {
770 	isc_portset_t *v4portset = NULL, *v6portset = NULL;
771 	in_port_t udpport_low, udpport_high;
772 	isc_result_t result;
773 
774 	result = isc_portset_create(gmctx, &v4portset);
775 	check_result(result, "isc_portset_create (v4)");
776 	result = isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high);
777 	check_result(result, "isc_net_getudpportrange (v4)");
778 	isc_portset_addrange(v4portset, udpport_low, udpport_high);
779 
780 	result = isc_portset_create(gmctx, &v6portset);
781 	check_result(result, "isc_portset_create (v6)");
782 	result = isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high);
783 	check_result(result, "isc_net_getudpportrange (v6)");
784 	isc_portset_addrange(v6portset, udpport_low, udpport_high);
785 
786 	result = dns_dispatchmgr_setavailports(manager, v4portset, v6portset);
787 	check_result(result, "dns_dispatchmgr_setavailports");
788 
789 	isc_portset_destroy(gmctx, &v4portset);
790 	isc_portset_destroy(gmctx, &v6portset);
791 }
792 
793 static isc_result_t
794 create_name(const char *str, char *namedata, size_t len, dns_name_t *name) {
795 	isc_buffer_t namesrc, namebuf;
796 
797 	dns_name_init(name, NULL);
798 	isc_buffer_constinit(&namesrc, str, strlen(str));
799 	isc_buffer_add(&namesrc, strlen(str));
800 	isc_buffer_init(&namebuf, namedata, len);
801 
802 	return dns_name_fromtext(name, &namesrc, dns_rootname,
803 				 DNS_NAME_DOWNCASE, &namebuf);
804 }
805 
806 static void
807 setup_system(void *arg ISC_ATTR_UNUSED) {
808 	isc_result_t result;
809 	isc_sockaddr_t bind_any, bind_any6;
810 	isc_sockaddrlist_t *nslist;
811 	isc_logconfig_t *logconfig = NULL;
812 	irs_resconf_t *resconf = NULL;
813 	dns_name_t tlsname;
814 	char namedata[DNS_NAME_FORMATSIZE + 1];
815 
816 	ddebug("setup_system()");
817 
818 	isc_log_create(gmctx, &glctx, &logconfig);
819 	isc_log_setcontext(glctx);
820 	dns_log_init(glctx);
821 	dns_log_setcontext(glctx);
822 
823 	result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
824 	check_result(result, "isc_log_usechannel");
825 
826 	isc_log_setdebuglevel(glctx, logdebuglevel);
827 
828 	result = irs_resconf_load(gmctx, resolvconf, &resconf);
829 	if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
830 		fatal("parse of %s failed", resolvconf);
831 	}
832 
833 	nslist = irs_resconf_getnameservers(resconf);
834 
835 	if (servers != NULL) {
836 		if (primary_servers == servers) {
837 			primary_servers = NULL;
838 		}
839 		isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t));
840 	}
841 
842 	ns_inuse = 0;
843 	if (local_only || ISC_LIST_EMPTY(*nslist)) {
844 		struct in_addr in;
845 		struct in6_addr in6;
846 
847 		if (local_only && keyfile == NULL) {
848 			keyfile = SESSION_KEYFILE;
849 		}
850 
851 		default_servers = !local_only;
852 
853 		ns_total = ns_alloc = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0);
854 		servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t));
855 
856 		if (have_ipv6) {
857 			memset(&in6, 0, sizeof(in6));
858 			in6.s6_addr[15] = 1;
859 			isc_sockaddr_fromin6(&servers[0], &in6, dnsport);
860 		}
861 		if (have_ipv4) {
862 			in.s_addr = htonl(INADDR_LOOPBACK);
863 			isc_sockaddr_fromin(&servers[(have_ipv6 ? 1 : 0)], &in,
864 					    dnsport);
865 		}
866 	} else {
867 		isc_sockaddr_t *sa;
868 		int i;
869 
870 		/*
871 		 * Count the nameservers (skipping any that we can't use
872 		 * because of address family restrictions) and allocate
873 		 * the servers array.
874 		 */
875 		ns_total = 0;
876 		for (sa = ISC_LIST_HEAD(*nslist); sa != NULL;
877 		     sa = ISC_LIST_NEXT(sa, link))
878 		{
879 			switch (sa->type.sa.sa_family) {
880 			case AF_INET:
881 				if (have_ipv4) {
882 					ns_total++;
883 				}
884 				break;
885 			case AF_INET6:
886 				if (have_ipv6) {
887 					ns_total++;
888 				}
889 				break;
890 			default:
891 				fatal("bad family");
892 			}
893 		}
894 
895 		ns_alloc = ns_total;
896 		servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t));
897 
898 		i = 0;
899 		for (sa = ISC_LIST_HEAD(*nslist); sa != NULL;
900 		     sa = ISC_LIST_NEXT(sa, link))
901 		{
902 			switch (sa->type.sa.sa_family) {
903 			case AF_INET:
904 				if (have_ipv4) {
905 					sa->type.sin.sin_port = htons(dnsport);
906 				} else {
907 					continue;
908 				}
909 				break;
910 			case AF_INET6:
911 				if (have_ipv6) {
912 					sa->type.sin6.sin6_port =
913 						htons(dnsport);
914 				} else {
915 					continue;
916 				}
917 				break;
918 			default:
919 				fatal("bad family");
920 			}
921 			INSIST(i < ns_alloc);
922 			servers[i++] = *sa;
923 		}
924 	}
925 
926 	irs_resconf_destroy(&resconf);
927 
928 	result = dns_dispatchmgr_create(gmctx, loopmgr, netmgr, &dispatchmgr);
929 	check_result(result, "dns_dispatchmgr_create");
930 
931 	result = dst_lib_init(gmctx, NULL);
932 	check_result(result, "dst_lib_init");
933 	is_dst_up = true;
934 
935 	set_source_ports(dispatchmgr);
936 
937 	if (have_ipv6) {
938 		isc_sockaddr_any6(&bind_any6);
939 		result = dns_dispatch_createudp(dispatchmgr, &bind_any6,
940 						&dispatchv6);
941 		check_result(result, "dns_dispatch_createudp (v6)");
942 	}
943 
944 	if (have_ipv4) {
945 		isc_sockaddr_any(&bind_any);
946 		result = dns_dispatch_createudp(dispatchmgr, &bind_any,
947 						&dispatchv4);
948 		check_result(result, "dns_dispatch_createudp (v4)");
949 	}
950 	transport_list = dns_transport_list_new(gmctx);
951 
952 	isc_tlsctx_cache_create(gmctx, &tls_ctx_cache);
953 
954 	if (tls_client_key_file == NULL) {
955 		result = create_name("tls-non-auth-client", namedata,
956 				     sizeof(namedata), &tlsname);
957 		check_result(result, "create_name (tls-non-auth-client)");
958 		transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS,
959 					      transport_list);
960 		dns_transport_set_tlsname(transport, "tls-non-auth-client");
961 	} else {
962 		result = create_name("tls-auth-client", namedata,
963 				     sizeof(namedata), &tlsname);
964 		check_result(result, "create_name (tls-auth-client)");
965 		transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS,
966 					      transport_list);
967 		dns_transport_set_tlsname(transport, "tls-auth-client");
968 		dns_transport_set_keyfile(transport, tls_client_key_file);
969 		dns_transport_set_certfile(transport, tls_client_cert_file);
970 	}
971 	dns_transport_set_cafile(transport, tls_ca_file);
972 	dns_transport_set_remote_hostname(transport, tls_hostname);
973 	dns_transport_set_always_verify_remote(transport,
974 					       tls_always_verify_remote);
975 
976 	result = dns_requestmgr_create(gmctx, loopmgr, dispatchmgr, dispatchv4,
977 				       dispatchv6, &requestmgr);
978 	check_result(result, "dns_requestmgr_create");
979 
980 	if (keystr != NULL) {
981 		setup_keystr();
982 	} else if (local_only) {
983 		result = read_sessionkey(gmctx, glctx);
984 		if (result != ISC_R_SUCCESS) {
985 			fatal("can't read key from %s: %s\n", keyfile,
986 			      isc_result_totext(result));
987 		}
988 	} else if (keyfile != NULL) {
989 		setup_keyfile(gmctx, glctx);
990 	}
991 
992 	isc_mutex_init(&answer_lock);
993 }
994 
995 static int
996 get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr,
997 	      int naddrs) {
998 	int count = 0;
999 	isc_result_t result;
1000 
1001 	isc_loopmgr_blocking(loopmgr);
1002 	result = isc_getaddresses(host, port, sockaddr, naddrs, &count);
1003 	isc_loopmgr_nonblocking(loopmgr);
1004 	if (result != ISC_R_SUCCESS) {
1005 		error("couldn't get address for '%s': %s", host,
1006 		      isc_result_totext(result));
1007 	}
1008 	return count;
1009 }
1010 
1011 #define PARSE_ARGS_FMT "46A:C:dDE:ghH:iK:lL:MoOk:p:Pr:R:St:Tu:vVy:"
1012 
1013 static void
1014 pre_parse_args(int argc, char **argv) {
1015 	dns_rdatatype_t t;
1016 	int ch;
1017 	char buf[100];
1018 	bool doexit = false;
1019 	bool ipv4only = false, ipv6only = false;
1020 
1021 	while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
1022 		switch (ch) {
1023 		case 'M': /* was -dm */
1024 			debugging = true;
1025 			ddebugging = true;
1026 			memdebugging = true;
1027 			isc_mem_debugging = ISC_MEM_DEBUGTRACE |
1028 					    ISC_MEM_DEBUGRECORD;
1029 			break;
1030 
1031 		case '4':
1032 			if (ipv6only) {
1033 				fatal("only one of -4 and -6 allowed");
1034 			}
1035 			ipv4only = true;
1036 			break;
1037 
1038 		case '6':
1039 			if (ipv4only) {
1040 				fatal("only one of -4 and -6 allowed");
1041 			}
1042 			ipv6only = true;
1043 			break;
1044 
1045 		case '?':
1046 		case 'h':
1047 			if (isc_commandline_option != '?') {
1048 				fprintf(stderr, "%s: invalid argument -%c\n",
1049 					argv[0], isc_commandline_option);
1050 			}
1051 			fprintf(stderr, "usage: nsupdate [-CdDi] [-L level] "
1052 					"[-l] [-g | -o | -y keyname:secret "
1053 					"| -k keyfile] [-p port] "
1054 					"[ -S [-K tlskeyfile] [-E tlscertfile] "
1055 					"[-A tlscafile] [-H tlshostname] "
1056 					"[-O] ] [-v] [-V] [-P] [-T] [-4 | -6] "
1057 					"[filename]\n");
1058 			exit(EXIT_FAILURE);
1059 
1060 		case 'P':
1061 			for (t = 0xff00; t <= 0xfffe; t++) {
1062 				if (dns_rdatatype_ismeta(t)) {
1063 					continue;
1064 				}
1065 				dns_rdatatype_format(t, buf, sizeof(buf));
1066 				if (strncmp(buf, "TYPE", 4) != 0) {
1067 					fprintf(stdout, "%s\n", buf);
1068 				}
1069 			}
1070 			doexit = true;
1071 			break;
1072 
1073 		case 'T':
1074 			for (t = 1; t <= 0xfeff; t++) {
1075 				if (dns_rdatatype_ismeta(t)) {
1076 					continue;
1077 				}
1078 				dns_rdatatype_format(t, buf, sizeof(buf));
1079 				if (strncmp(buf, "TYPE", 4) != 0) {
1080 					fprintf(stdout, "%s\n", buf);
1081 				}
1082 			}
1083 			doexit = true;
1084 			break;
1085 
1086 		case 'V':
1087 			printf("nsupdate %s\n", PACKAGE_VERSION);
1088 			doexit = true;
1089 			break;
1090 
1091 		default:
1092 			break;
1093 		}
1094 	}
1095 	if (doexit) {
1096 		exit(EXIT_SUCCESS);
1097 	}
1098 	isc_commandline_reset = true;
1099 	isc_commandline_index = 1;
1100 }
1101 
1102 static void
1103 parse_args(int argc, char **argv) {
1104 	int ch;
1105 	uint32_t i;
1106 	isc_result_t result;
1107 	bool force_interactive = false;
1108 
1109 	debug("parse_args");
1110 	while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
1111 		switch (ch) {
1112 		case '4':
1113 			if (have_ipv4) {
1114 				isc_net_disableipv6();
1115 				have_ipv6 = false;
1116 			} else {
1117 				fatal("can't find IPv4 networking");
1118 			}
1119 			break;
1120 		case '6':
1121 			if (have_ipv6) {
1122 				isc_net_disableipv4();
1123 				have_ipv4 = false;
1124 			} else {
1125 				fatal("can't find IPv6 networking");
1126 			}
1127 			break;
1128 		case 'A':
1129 			use_tls = true;
1130 			tls_ca_file = isc_commandline_argument;
1131 			break;
1132 		case 'C':
1133 			resolvconf = isc_commandline_argument;
1134 			break;
1135 		case 'd':
1136 			debugging = true;
1137 			break;
1138 		case 'D': /* was -dd */
1139 			debugging = true;
1140 			ddebugging = true;
1141 			break;
1142 		case 'E':
1143 			use_tls = true;
1144 			tls_client_cert_file = isc_commandline_argument;
1145 			break;
1146 		case 'H':
1147 			use_tls = true;
1148 			tls_hostname = isc_commandline_argument;
1149 			break;
1150 		case 'M':
1151 			break;
1152 		case 'i':
1153 			force_interactive = true;
1154 			interactive = true;
1155 			break;
1156 		case 'K':
1157 			use_tls = true;
1158 			tls_client_key_file = isc_commandline_argument;
1159 			break;
1160 		case 'l':
1161 			local_only = true;
1162 			break;
1163 		case 'L':
1164 			result = isc_parse_uint32(&i, isc_commandline_argument,
1165 						  10);
1166 			if (result != ISC_R_SUCCESS) {
1167 				fprintf(stderr,
1168 					"bad library debug value "
1169 					"'%s'\n",
1170 					isc_commandline_argument);
1171 				exit(EXIT_FAILURE);
1172 			}
1173 			logdebuglevel = i;
1174 			break;
1175 		case 'y':
1176 			keystr = isc_commandline_argument;
1177 			break;
1178 		case 'v':
1179 			usevc = true;
1180 			break;
1181 		case 'k':
1182 			keyfile = isc_commandline_argument;
1183 			break;
1184 		case 'g':
1185 			usegsstsig = true;
1186 			break;
1187 		case 'o':
1188 			usegsstsig = true;
1189 			break;
1190 		case 'O':
1191 			use_tls = true;
1192 			tls_always_verify_remote = false;
1193 			break;
1194 		case 'p':
1195 			result = isc_parse_uint16(&dnsport,
1196 						  isc_commandline_argument, 10);
1197 			if (result != ISC_R_SUCCESS) {
1198 				fprintf(stderr,
1199 					"bad port number "
1200 					"'%s'\n",
1201 					isc_commandline_argument);
1202 				exit(EXIT_FAILURE);
1203 			}
1204 			break;
1205 		case 'S':
1206 			use_tls = true;
1207 			break;
1208 		case 't':
1209 			result = isc_parse_uint32(&timeout,
1210 						  isc_commandline_argument, 10);
1211 			if (result != ISC_R_SUCCESS) {
1212 				fprintf(stderr, "bad timeout '%s'\n",
1213 					isc_commandline_argument);
1214 				exit(EXIT_FAILURE);
1215 			}
1216 			if (timeout == 0) {
1217 				timeout = UINT_MAX;
1218 			}
1219 			break;
1220 		case 'u':
1221 			result = isc_parse_uint32(&udp_timeout,
1222 						  isc_commandline_argument, 10);
1223 			if (result != ISC_R_SUCCESS) {
1224 				fprintf(stderr, "bad udp timeout '%s'\n",
1225 					isc_commandline_argument);
1226 				exit(EXIT_FAILURE);
1227 			}
1228 			break;
1229 		case 'r':
1230 			result = isc_parse_uint32(&udp_retries,
1231 						  isc_commandline_argument, 10);
1232 			if (result != ISC_R_SUCCESS) {
1233 				fprintf(stderr, "bad udp retries '%s'\n",
1234 					isc_commandline_argument);
1235 				exit(EXIT_FAILURE);
1236 			}
1237 			break;
1238 
1239 		case 'R':
1240 			fatal("The -R option has been deprecated.");
1241 			break;
1242 
1243 		default:
1244 			fprintf(stderr, "%s: unhandled option: %c\n", argv[0],
1245 				isc_commandline_option);
1246 			exit(EXIT_FAILURE);
1247 		}
1248 	}
1249 	if (keyfile != NULL && keystr != NULL) {
1250 		fprintf(stderr, "%s: cannot specify both -k and -y\n", argv[0]);
1251 		exit(EXIT_FAILURE);
1252 	}
1253 
1254 #if HAVE_GSSAPI
1255 	if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
1256 		fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
1257 			argv[0]);
1258 		exit(EXIT_FAILURE);
1259 	}
1260 #else  /* HAVE_GSSAPI */
1261 	if (usegsstsig) {
1262 		fprintf(stderr,
1263 			"%s: cannot specify -g	or -o, "
1264 			"program not linked with GSS API Library\n",
1265 			argv[0]);
1266 		exit(EXIT_FAILURE);
1267 	}
1268 #endif /* HAVE_GSSAPI */
1269 
1270 	if (use_tls) {
1271 		usevc = true;
1272 		if ((tls_client_key_file == NULL) !=
1273 		    (tls_client_cert_file == NULL))
1274 		{
1275 			fprintf(stderr,
1276 				"%s: cannot specify the -K option without"
1277 				"the -E option, and vice versa.\n",
1278 				argv[0]);
1279 			exit(EXIT_FAILURE);
1280 		}
1281 		if (tls_ca_file != NULL && tls_always_verify_remote == false) {
1282 			fprintf(stderr,
1283 				"%s: cannot specify the -A option in "
1284 				"conjuction with the -O option.\n",
1285 				argv[0]);
1286 			exit(EXIT_FAILURE);
1287 		}
1288 	}
1289 
1290 	if (argv[isc_commandline_index] != NULL) {
1291 		if (strcmp(argv[isc_commandline_index], "-") == 0) {
1292 			input = stdin;
1293 		} else {
1294 			result = isc_stdio_open(argv[isc_commandline_index],
1295 						"r", &input);
1296 			if (result != ISC_R_SUCCESS) {
1297 				fprintf(stderr, "could not open '%s': %s\n",
1298 					argv[isc_commandline_index],
1299 					isc_result_totext(result));
1300 				exit(EXIT_FAILURE);
1301 			}
1302 		}
1303 		if (!force_interactive) {
1304 			interactive = false;
1305 		}
1306 	}
1307 }
1308 
1309 static uint16_t
1310 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1311 	isc_result_t result;
1312 	char *word;
1313 	isc_buffer_t source;
1314 
1315 	word = nsu_strsep(cmdlinep, " \t\r\n");
1316 	if (word == NULL || *word == 0) {
1317 		fprintf(stderr, "could not read owner name\n");
1318 		return STATUS_SYNTAX;
1319 	}
1320 
1321 	dns_message_gettempname(msg, namep);
1322 	isc_buffer_init(&source, word, strlen(word));
1323 	isc_buffer_add(&source, strlen(word));
1324 	result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
1325 	if (result != ISC_R_SUCCESS) {
1326 		error("invalid owner name: %s", isc_result_totext(result));
1327 		isc_buffer_invalidate(&source);
1328 		dns_message_puttempname(msg, namep);
1329 		return STATUS_SYNTAX;
1330 	}
1331 	isc_buffer_invalidate(&source);
1332 	return STATUS_MORE;
1333 }
1334 
1335 static uint16_t
1336 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1337 	    dns_rdatatype_t rdatatype, dns_message_t *msg, dns_rdata_t *rdata) {
1338 	char *cmdline = *cmdlinep;
1339 	isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1340 	isc_region_t r;
1341 	isc_lex_t *lex = NULL;
1342 	dns_rdatacallbacks_t callbacks;
1343 	isc_result_t result;
1344 
1345 	if (cmdline == NULL) {
1346 		rdata->flags = DNS_RDATA_UPDATE;
1347 		return STATUS_MORE;
1348 	}
1349 
1350 	while (*cmdline != 0 && isspace((unsigned char)*cmdline)) {
1351 		cmdline++;
1352 	}
1353 
1354 	if (*cmdline != 0) {
1355 		dns_rdatacallbacks_init(&callbacks);
1356 		isc_lex_create(gmctx, strlen(cmdline), &lex);
1357 		isc_buffer_init(&source, cmdline, strlen(cmdline));
1358 		isc_buffer_add(&source, strlen(cmdline));
1359 		result = isc_lex_openbuffer(lex, &source);
1360 		check_result(result, "isc_lex_openbuffer");
1361 		isc_buffer_allocate(gmctx, &buf, MAXWIRE);
1362 		result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1363 					    dns_rootname, 0, gmctx, buf,
1364 					    &callbacks);
1365 		isc_lex_destroy(&lex);
1366 		if (result == ISC_R_SUCCESS) {
1367 			isc_buffer_usedregion(buf, &r);
1368 			isc_buffer_allocate(gmctx, &newbuf, r.length);
1369 			isc_buffer_putmem(newbuf, r.base, r.length);
1370 			isc_buffer_usedregion(newbuf, &r);
1371 			dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1372 			isc_buffer_free(&buf);
1373 			dns_message_takebuffer(msg, &newbuf);
1374 		} else {
1375 			fprintf(stderr, "invalid rdata format: %s\n",
1376 				isc_result_totext(result));
1377 			isc_buffer_free(&buf);
1378 			return STATUS_SYNTAX;
1379 		}
1380 	} else {
1381 		rdata->flags = DNS_RDATA_UPDATE;
1382 	}
1383 	*cmdlinep = cmdline;
1384 	return STATUS_MORE;
1385 }
1386 
1387 static uint16_t
1388 make_prereq(char *cmdline, bool ispositive, bool isrrset) {
1389 	isc_result_t result;
1390 	char *word;
1391 	dns_name_t *name = NULL;
1392 	isc_textregion_t region;
1393 	dns_rdataset_t *rdataset = NULL;
1394 	dns_rdatalist_t *rdatalist = NULL;
1395 	dns_rdataclass_t rdataclass;
1396 	dns_rdatatype_t rdatatype;
1397 	dns_rdata_t *rdata = NULL;
1398 	uint16_t retval;
1399 
1400 	ddebug("make_prereq()");
1401 
1402 	/*
1403 	 * Read the owner name
1404 	 */
1405 	retval = parse_name(&cmdline, updatemsg, &name);
1406 	if (retval != STATUS_MORE) {
1407 		return retval;
1408 	}
1409 
1410 	/*
1411 	 * If this is an rrset prereq, read the class or type.
1412 	 */
1413 	if (isrrset) {
1414 		word = nsu_strsep(&cmdline, " \t\r\n");
1415 		if (word == NULL || *word == 0) {
1416 			fprintf(stderr, "could not read class or type\n");
1417 			goto failure;
1418 		}
1419 		region.base = word;
1420 		region.length = strlen(word);
1421 		result = dns_rdataclass_fromtext(&rdataclass, &region);
1422 		if (result == ISC_R_SUCCESS) {
1423 			if (!setzoneclass(rdataclass)) {
1424 				fprintf(stderr, "class mismatch: %s\n", word);
1425 				goto failure;
1426 			}
1427 			/*
1428 			 * Now read the type.
1429 			 */
1430 			word = nsu_strsep(&cmdline, " \t\r\n");
1431 			if (word == NULL || *word == 0) {
1432 				fprintf(stderr, "could not read type\n");
1433 				goto failure;
1434 			}
1435 			region.base = word;
1436 			region.length = strlen(word);
1437 			result = dns_rdatatype_fromtext(&rdatatype, &region);
1438 			if (result != ISC_R_SUCCESS) {
1439 				fprintf(stderr, "invalid type: %s\n", word);
1440 				goto failure;
1441 			}
1442 		} else {
1443 			rdataclass = getzoneclass();
1444 			result = dns_rdatatype_fromtext(&rdatatype, &region);
1445 			if (result != ISC_R_SUCCESS) {
1446 				fprintf(stderr, "invalid type: %s\n", word);
1447 				goto failure;
1448 			}
1449 		}
1450 	} else {
1451 		rdatatype = dns_rdatatype_any;
1452 	}
1453 
1454 	dns_message_gettemprdata(updatemsg, &rdata);
1455 
1456 	dns_rdata_init(rdata);
1457 
1458 	if (isrrset && ispositive) {
1459 		retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1460 				     rdata);
1461 		if (retval != STATUS_MORE) {
1462 			goto failure;
1463 		}
1464 	} else {
1465 		rdata->flags = DNS_RDATA_UPDATE;
1466 	}
1467 
1468 	dns_message_gettemprdatalist(updatemsg, &rdatalist);
1469 	dns_message_gettemprdataset(updatemsg, &rdataset);
1470 	rdatalist->type = rdatatype;
1471 	if (ispositive) {
1472 		if (isrrset && rdata->data != NULL) {
1473 			rdatalist->rdclass = rdataclass;
1474 		} else {
1475 			rdatalist->rdclass = dns_rdataclass_any;
1476 		}
1477 	} else {
1478 		rdatalist->rdclass = dns_rdataclass_none;
1479 	}
1480 	rdata->rdclass = rdatalist->rdclass;
1481 	rdata->type = rdatatype;
1482 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1483 	dns_rdatalist_tordataset(rdatalist, rdataset);
1484 	ISC_LIST_INIT(name->list);
1485 	ISC_LIST_APPEND(name->list, rdataset, link);
1486 	dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1487 	return STATUS_MORE;
1488 
1489 failure:
1490 	if (name != NULL) {
1491 		dns_message_puttempname(updatemsg, &name);
1492 	}
1493 	return STATUS_SYNTAX;
1494 }
1495 
1496 static uint16_t
1497 evaluate_prereq(char *cmdline) {
1498 	char *word;
1499 	bool ispositive, isrrset;
1500 
1501 	ddebug("evaluate_prereq()");
1502 	word = nsu_strsep(&cmdline, " \t\r\n");
1503 	if (word == NULL || *word == 0) {
1504 		fprintf(stderr, "could not read operation code\n");
1505 		return STATUS_SYNTAX;
1506 	}
1507 	if (strcasecmp(word, "nxdomain") == 0) {
1508 		ispositive = false;
1509 		isrrset = false;
1510 	} else if (strcasecmp(word, "yxdomain") == 0) {
1511 		ispositive = true;
1512 		isrrset = false;
1513 	} else if (strcasecmp(word, "nxrrset") == 0) {
1514 		ispositive = false;
1515 		isrrset = true;
1516 	} else if (strcasecmp(word, "yxrrset") == 0) {
1517 		ispositive = true;
1518 		isrrset = true;
1519 	} else {
1520 		fprintf(stderr, "incorrect operation code: %s\n", word);
1521 		return STATUS_SYNTAX;
1522 	}
1523 	return make_prereq(cmdline, ispositive, isrrset);
1524 }
1525 
1526 static void
1527 updateopt(void) {
1528 	isc_result_t result;
1529 	dns_ednsopt_t ednsopts[1];
1530 	unsigned char ul[8];
1531 	unsigned int count = 0;
1532 
1533 	if (lease_set) {
1534 		isc_buffer_t b;
1535 		INSIST(count < ARRAY_SIZE(ednsopts));
1536 		ednsopts[count++] = (dns_ednsopt_t){ .code = DNS_OPT_UL,
1537 						     .length = keylease_set ? 8
1538 									    : 4,
1539 						     .value = ul };
1540 
1541 		isc_buffer_init(&b, ul, sizeof(ul));
1542 		isc_buffer_putuint32(&b, lease);
1543 		isc_buffer_putuint32(&b, keylease);
1544 	}
1545 
1546 	if (count != 0) {
1547 		dns_rdataset_t *opt = NULL;
1548 		result = dns_message_buildopt(updatemsg, &opt, 0,
1549 					      DEFAULT_EDNS_BUFSIZE, 0, ednsopts,
1550 					      count);
1551 		check_result(result, "dns_message_buildopt");
1552 		result = dns_message_setopt(updatemsg, opt);
1553 		check_result(result, "dns_message_setopt");
1554 	} else {
1555 		result = dns_message_setopt(updatemsg, NULL);
1556 		check_result(result, "dns_message_setopt");
1557 	}
1558 }
1559 
1560 static uint16_t
1561 evaluate_lease(char *cmdline) {
1562 	char *word;
1563 	isc_result_t result;
1564 	uint32_t value1, value2;
1565 
1566 	word = nsu_strsep(&cmdline, " \t\r\n");
1567 	if (word == NULL || *word == 0) {
1568 		fprintf(stderr, "could not read ttl\n");
1569 		return STATUS_SYNTAX;
1570 	}
1571 
1572 	if (!strcasecmp(word, "none")) {
1573 		lease = 0;
1574 		lease_set = false;
1575 		keylease = 0;
1576 		keylease_set = false;
1577 		updateopt();
1578 		return STATUS_MORE;
1579 	}
1580 
1581 	result = isc_parse_uint32(&value1, word, 10);
1582 	if (result != ISC_R_SUCCESS) {
1583 		return STATUS_SYNTAX;
1584 	}
1585 
1586 	word = nsu_strsep(&cmdline, " \t\r\n");
1587 	if (word == NULL || *word == 0) {
1588 		lease = value1;
1589 		lease_set = true;
1590 		keylease = 0;
1591 		keylease_set = false;
1592 		updateopt();
1593 		return STATUS_MORE;
1594 	}
1595 
1596 	result = isc_parse_uint32(&value2, word, 10);
1597 	if (result != ISC_R_SUCCESS) {
1598 		return STATUS_SYNTAX;
1599 	}
1600 
1601 	lease = value1;
1602 	lease_set = true;
1603 	keylease = value2;
1604 	keylease_set = true;
1605 	updateopt();
1606 
1607 	return STATUS_MORE;
1608 }
1609 
1610 static uint16_t
1611 evaluate_server(char *cmdline) {
1612 	char *word, *server;
1613 	long port;
1614 
1615 	if (local_only) {
1616 		fprintf(stderr, "cannot reset server in localhost-only mode\n");
1617 		return STATUS_SYNTAX;
1618 	}
1619 
1620 	word = nsu_strsep(&cmdline, " \t\r\n");
1621 	if (word == NULL || *word == 0) {
1622 		fprintf(stderr, "could not read server name\n");
1623 		return STATUS_SYNTAX;
1624 	}
1625 	server = word;
1626 
1627 	word = nsu_strsep(&cmdline, " \t\r\n");
1628 	if (word == NULL || *word == 0) {
1629 		port = dnsport;
1630 	} else {
1631 		char *endp;
1632 		port = strtol(word, &endp, 10);
1633 		if (*endp != 0) {
1634 			fprintf(stderr, "port '%s' is not numeric\n", word);
1635 			return STATUS_SYNTAX;
1636 		} else if (port < 1 || port > 65535) {
1637 			fprintf(stderr,
1638 				"port '%s' is out of range "
1639 				"(1 to 65535)\n",
1640 				word);
1641 			return STATUS_SYNTAX;
1642 		}
1643 	}
1644 
1645 	if (servers != NULL) {
1646 		if (primary_servers == servers) {
1647 			primary_servers = NULL;
1648 		}
1649 		isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t));
1650 	}
1651 
1652 	default_servers = false;
1653 
1654 	ns_alloc = MAX_SERVERADDRS;
1655 	ns_inuse = 0;
1656 	servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t));
1657 	ns_total = get_addresses(server, (in_port_t)port, servers, ns_alloc);
1658 	if (ns_total == 0) {
1659 		return STATUS_SYNTAX;
1660 	}
1661 
1662 	return STATUS_MORE;
1663 }
1664 
1665 static uint16_t
1666 evaluate_local(char *cmdline) {
1667 	char *word, *local;
1668 	long port;
1669 	struct in_addr in4;
1670 	struct in6_addr in6;
1671 
1672 	word = nsu_strsep(&cmdline, " \t\r\n");
1673 	if (word == NULL || *word == 0) {
1674 		fprintf(stderr, "could not read server name\n");
1675 		return STATUS_SYNTAX;
1676 	}
1677 	local = word;
1678 
1679 	word = nsu_strsep(&cmdline, " \t\r\n");
1680 	if (word == NULL || *word == 0) {
1681 		port = 0;
1682 	} else {
1683 		char *endp;
1684 		port = strtol(word, &endp, 10);
1685 		if (*endp != 0) {
1686 			fprintf(stderr, "port '%s' is not numeric\n", word);
1687 			return STATUS_SYNTAX;
1688 		} else if (port < 1 || port > 65535) {
1689 			fprintf(stderr,
1690 				"port '%s' is out of range "
1691 				"(1 to 65535)\n",
1692 				word);
1693 			return STATUS_SYNTAX;
1694 		}
1695 	}
1696 
1697 	if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) {
1698 		if (localaddr6 == NULL) {
1699 			localaddr6 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
1700 		}
1701 		isc_sockaddr_fromin6(localaddr6, &in6, (in_port_t)port);
1702 	} else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) {
1703 		if (localaddr4 == NULL) {
1704 			localaddr4 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
1705 		}
1706 		isc_sockaddr_fromin(localaddr4, &in4, (in_port_t)port);
1707 	} else {
1708 		fprintf(stderr, "invalid address %s", local);
1709 		return STATUS_SYNTAX;
1710 	}
1711 
1712 	return STATUS_MORE;
1713 }
1714 
1715 static uint16_t
1716 evaluate_key(char *cmdline) {
1717 	char *namestr;
1718 	char *secretstr;
1719 	isc_buffer_t b;
1720 	isc_result_t result;
1721 	dns_fixedname_t fkeyname;
1722 	dns_name_t *mykeyname;
1723 	int secretlen;
1724 	unsigned char *secret = NULL;
1725 	isc_buffer_t secretbuf;
1726 	dst_algorithm_t hmac_alg = DST_ALG_UNKNOWN;
1727 	uint16_t digestbits = 0;
1728 	char *n;
1729 
1730 	namestr = nsu_strsep(&cmdline, " \t\r\n");
1731 	if (namestr == NULL || *namestr == 0) {
1732 		fprintf(stderr, "could not read key name\n");
1733 		return STATUS_SYNTAX;
1734 	}
1735 
1736 	mykeyname = dns_fixedname_initname(&fkeyname);
1737 
1738 	n = strchr(namestr, ':');
1739 	if (n != NULL) {
1740 		if (!parse_hmac(namestr, n - namestr, &hmac_alg, &digestbits)) {
1741 			return STATUS_SYNTAX;
1742 		}
1743 		namestr = n + 1;
1744 	} else {
1745 		hmac_alg = DST_ALG_HMACMD5;
1746 	}
1747 
1748 	isc_buffer_init(&b, namestr, strlen(namestr));
1749 	isc_buffer_add(&b, strlen(namestr));
1750 	result = dns_name_fromtext(mykeyname, &b, dns_rootname, 0, NULL);
1751 	if (result != ISC_R_SUCCESS) {
1752 		fprintf(stderr, "could not parse key name\n");
1753 		return STATUS_SYNTAX;
1754 	}
1755 
1756 	secretstr = nsu_strsep(&cmdline, "\r\n");
1757 	if (secretstr == NULL || *secretstr == 0) {
1758 		fprintf(stderr, "could not read key secret\n");
1759 		return STATUS_SYNTAX;
1760 	}
1761 	secretlen = strlen(secretstr) * 3 / 4;
1762 	secret = isc_mem_allocate(gmctx, secretlen);
1763 
1764 	isc_buffer_init(&secretbuf, secret, secretlen);
1765 	result = isc_base64_decodestring(secretstr, &secretbuf);
1766 	if (result != ISC_R_SUCCESS) {
1767 		fprintf(stderr, "could not create key from %s: %s\n", secretstr,
1768 			isc_result_totext(result));
1769 		isc_mem_free(gmctx, secret);
1770 		return STATUS_SYNTAX;
1771 	}
1772 	secretlen = isc_buffer_usedlength(&secretbuf);
1773 
1774 	if (tsigkey != NULL) {
1775 		dns_tsigkey_detach(&tsigkey);
1776 	}
1777 	result = dns_tsigkey_create(mykeyname, hmac_alg, secret, secretlen,
1778 				    gmctx, &tsigkey);
1779 	isc_mem_free(gmctx, secret);
1780 	if (result != ISC_R_SUCCESS) {
1781 		fprintf(stderr, "could not create key from %s %s: %s\n",
1782 			namestr, secretstr, isc_result_totext(result));
1783 		return STATUS_SYNTAX;
1784 	}
1785 	dst_key_setbits(tsigkey->key, digestbits);
1786 	return STATUS_MORE;
1787 }
1788 
1789 static uint16_t
1790 evaluate_zone(char *cmdline) {
1791 	char *word;
1792 	isc_buffer_t b;
1793 	isc_result_t result;
1794 
1795 	word = nsu_strsep(&cmdline, " \t\r\n");
1796 	if (word == NULL || *word == 0) {
1797 		fprintf(stderr, "could not read zone name\n");
1798 		return STATUS_SYNTAX;
1799 	}
1800 
1801 	userzone = dns_fixedname_initname(&fuserzone);
1802 	isc_buffer_init(&b, word, strlen(word));
1803 	isc_buffer_add(&b, strlen(word));
1804 	result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
1805 	if (result != ISC_R_SUCCESS) {
1806 		userzone = NULL; /* Lest it point to an invalid name */
1807 		fprintf(stderr, "could not parse zone name\n");
1808 		return STATUS_SYNTAX;
1809 	}
1810 
1811 	return STATUS_MORE;
1812 }
1813 
1814 static uint16_t
1815 evaluate_realm(char *cmdline) {
1816 #if HAVE_GSSAPI
1817 	char *word;
1818 	char buf[1024];
1819 	int n;
1820 
1821 	if (realm != NULL) {
1822 		isc_mem_free(gmctx, realm);
1823 		realm = NULL;
1824 	}
1825 
1826 	word = nsu_strsep(&cmdline, " \t\r\n");
1827 	if (word == NULL || *word == 0) {
1828 		return STATUS_MORE;
1829 	}
1830 
1831 	n = snprintf(buf, sizeof(buf), "@%s", word);
1832 	if (n < 0 || (size_t)n >= sizeof(buf)) {
1833 		error("realm is too long");
1834 		return STATUS_SYNTAX;
1835 	}
1836 	realm = isc_mem_strdup(gmctx, buf);
1837 	return STATUS_MORE;
1838 #else  /* HAVE_GSSAPI */
1839 	UNUSED(cmdline);
1840 	return STATUS_SYNTAX;
1841 #endif /* HAVE_GSSAPI */
1842 }
1843 
1844 static uint16_t
1845 evaluate_ttl(char *cmdline) {
1846 	char *word;
1847 	isc_result_t result;
1848 	uint32_t ttl;
1849 
1850 	word = nsu_strsep(&cmdline, " \t\r\n");
1851 	if (word == NULL || *word == 0) {
1852 		fprintf(stderr, "could not read ttl\n");
1853 		return STATUS_SYNTAX;
1854 	}
1855 
1856 	if (!strcasecmp(word, "none")) {
1857 		default_ttl = 0;
1858 		default_ttl_set = false;
1859 		return STATUS_MORE;
1860 	}
1861 
1862 	result = isc_parse_uint32(&ttl, word, 10);
1863 	if (result != ISC_R_SUCCESS) {
1864 		return STATUS_SYNTAX;
1865 	}
1866 
1867 	if (ttl > TTL_MAX) {
1868 		fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word,
1869 			TTL_MAX);
1870 		return STATUS_SYNTAX;
1871 	}
1872 	default_ttl = ttl;
1873 	default_ttl_set = true;
1874 
1875 	return STATUS_MORE;
1876 }
1877 
1878 static uint16_t
1879 evaluate_class(char *cmdline) {
1880 	char *word;
1881 	isc_textregion_t r;
1882 	isc_result_t result;
1883 	dns_rdataclass_t rdclass;
1884 
1885 	word = nsu_strsep(&cmdline, " \t\r\n");
1886 	if (word == NULL || *word == 0) {
1887 		fprintf(stderr, "could not read class name\n");
1888 		return STATUS_SYNTAX;
1889 	}
1890 
1891 	r.base = word;
1892 	r.length = strlen(word);
1893 	result = dns_rdataclass_fromtext(&rdclass, &r);
1894 	if (result != ISC_R_SUCCESS) {
1895 		fprintf(stderr, "could not parse class name: %s\n", word);
1896 		return STATUS_SYNTAX;
1897 	}
1898 	switch (rdclass) {
1899 	case dns_rdataclass_none:
1900 	case dns_rdataclass_any:
1901 	case dns_rdataclass_reserved0:
1902 		fprintf(stderr, "bad default class: %s\n", word);
1903 		return STATUS_SYNTAX;
1904 	default:
1905 		defaultclass = rdclass;
1906 	}
1907 
1908 	return STATUS_MORE;
1909 }
1910 
1911 static uint16_t
1912 update_addordelete(char *cmdline, bool isdelete) {
1913 	isc_result_t result;
1914 	dns_name_t *name = NULL;
1915 	uint32_t ttl;
1916 	char *word;
1917 	dns_rdataclass_t rdataclass;
1918 	dns_rdatatype_t rdatatype;
1919 	dns_rdata_t *rdata = NULL;
1920 	dns_rdatalist_t *rdatalist = NULL;
1921 	dns_rdataset_t *rdataset = NULL;
1922 	isc_textregion_t region;
1923 	uint16_t retval;
1924 
1925 	ddebug("update_addordelete()");
1926 
1927 	/*
1928 	 * Read the owner name.
1929 	 */
1930 	retval = parse_name(&cmdline, updatemsg, &name);
1931 	if (retval != STATUS_MORE) {
1932 		return retval;
1933 	}
1934 
1935 	dns_message_gettemprdata(updatemsg, &rdata);
1936 
1937 	dns_rdata_init(rdata);
1938 
1939 	/*
1940 	 * If this is an add, read the TTL and verify that it's in range.
1941 	 * If it's a delete, ignore a TTL if present (for compatibility).
1942 	 */
1943 	word = nsu_strsep(&cmdline, " \t\r\n");
1944 	if (word == NULL || *word == 0) {
1945 		if (!isdelete) {
1946 			fprintf(stderr, "could not read owner ttl\n");
1947 			goto failure;
1948 		} else {
1949 			ttl = 0;
1950 			rdataclass = dns_rdataclass_any;
1951 			rdatatype = dns_rdatatype_any;
1952 			rdata->flags = DNS_RDATA_UPDATE;
1953 			goto doneparsing;
1954 		}
1955 	}
1956 	result = isc_parse_uint32(&ttl, word, 10);
1957 	if (result != ISC_R_SUCCESS) {
1958 		if (isdelete) {
1959 			ttl = 0;
1960 			goto parseclass;
1961 		} else if (default_ttl_set) {
1962 			ttl = default_ttl;
1963 			goto parseclass;
1964 		} else {
1965 			fprintf(stderr, "ttl '%s': %s\n", word,
1966 				isc_result_totext(result));
1967 			goto failure;
1968 		}
1969 	}
1970 
1971 	if (isdelete) {
1972 		ttl = 0;
1973 	} else if (ttl > TTL_MAX) {
1974 		fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word,
1975 			TTL_MAX);
1976 		goto failure;
1977 	}
1978 
1979 	/*
1980 	 * Read the class or type.
1981 	 */
1982 	word = nsu_strsep(&cmdline, " \t\r\n");
1983 parseclass:
1984 	if (word == NULL || *word == 0) {
1985 		if (isdelete) {
1986 			rdataclass = dns_rdataclass_any;
1987 			rdatatype = dns_rdatatype_any;
1988 			rdata->flags = DNS_RDATA_UPDATE;
1989 			goto doneparsing;
1990 		} else {
1991 			fprintf(stderr, "could not read class or type\n");
1992 			goto failure;
1993 		}
1994 	}
1995 	region.base = word;
1996 	region.length = strlen(word);
1997 	rdataclass = dns_rdataclass_any;
1998 	result = dns_rdataclass_fromtext(&rdataclass, &region);
1999 	if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
2000 		if (!setzoneclass(rdataclass)) {
2001 			fprintf(stderr, "class mismatch: %s\n", word);
2002 			goto failure;
2003 		}
2004 		/*
2005 		 * Now read the type.
2006 		 */
2007 		word = nsu_strsep(&cmdline, " \t\r\n");
2008 		if (word == NULL || *word == 0) {
2009 			if (isdelete) {
2010 				rdataclass = dns_rdataclass_any;
2011 				rdatatype = dns_rdatatype_any;
2012 				rdata->flags = DNS_RDATA_UPDATE;
2013 				goto doneparsing;
2014 			} else {
2015 				fprintf(stderr, "could not read type\n");
2016 				goto failure;
2017 			}
2018 		}
2019 		region.base = word;
2020 		region.length = strlen(word);
2021 		result = dns_rdatatype_fromtext(&rdatatype, &region);
2022 		if (result != ISC_R_SUCCESS) {
2023 			fprintf(stderr, "'%s' is not a valid type: %s\n", word,
2024 				isc_result_totext(result));
2025 			goto failure;
2026 		}
2027 	} else {
2028 		rdataclass = getzoneclass();
2029 		result = dns_rdatatype_fromtext(&rdatatype, &region);
2030 		if (result != ISC_R_SUCCESS) {
2031 			fprintf(stderr,
2032 				"'%s' is not a valid class or type: "
2033 				"%s\n",
2034 				word, isc_result_totext(result));
2035 			goto failure;
2036 		}
2037 	}
2038 
2039 	retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, rdata);
2040 	if (retval != STATUS_MORE) {
2041 		goto failure;
2042 	}
2043 
2044 	if (isdelete) {
2045 		if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
2046 			rdataclass = dns_rdataclass_any;
2047 		} else {
2048 			rdataclass = dns_rdataclass_none;
2049 		}
2050 	} else {
2051 		if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
2052 			fprintf(stderr, "could not read rdata\n");
2053 			goto failure;
2054 		}
2055 	}
2056 
2057 	if (!isdelete && checknames) {
2058 		dns_fixedname_t fixed;
2059 		dns_name_t *bad;
2060 
2061 		if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type,
2062 					  true))
2063 		{
2064 			char namebuf[DNS_NAME_FORMATSIZE];
2065 
2066 			dns_name_format(name, namebuf, sizeof(namebuf));
2067 			fprintf(stderr, "check-names failed: bad owner '%s'\n",
2068 				namebuf);
2069 			goto failure;
2070 		}
2071 
2072 		bad = dns_fixedname_initname(&fixed);
2073 		if (!dns_rdata_checknames(rdata, name, bad)) {
2074 			char namebuf[DNS_NAME_FORMATSIZE];
2075 
2076 			dns_name_format(bad, namebuf, sizeof(namebuf));
2077 			fprintf(stderr, "check-names failed: bad name '%s'\n",
2078 				namebuf);
2079 			goto failure;
2080 		}
2081 	}
2082 
2083 	if (!isdelete && checksvcb && rdata->type == dns_rdatatype_svcb) {
2084 		result = dns_rdata_checksvcb(name, rdata);
2085 		if (result != ISC_R_SUCCESS) {
2086 			fprintf(stderr, "check-svcb failed: %s\n",
2087 				isc_result_totext(result));
2088 			goto failure;
2089 		}
2090 	}
2091 
2092 	if (!isdelete && rdata->type == dns_rdatatype_nsec3param) {
2093 		dns_rdata_nsec3param_t nsec3param;
2094 
2095 		result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
2096 		check_result(result, "dns_rdata_tostruct");
2097 		if (nsec3param.iterations > dns_nsec3_maxiterations()) {
2098 			fprintf(stderr,
2099 				"NSEC3PARAM has excessive iterations (> %u)\n",
2100 				dns_nsec3_maxiterations());
2101 			goto failure;
2102 		}
2103 	}
2104 
2105 doneparsing:
2106 
2107 	dns_message_gettemprdatalist(updatemsg, &rdatalist);
2108 	dns_message_gettemprdataset(updatemsg, &rdataset);
2109 	rdatalist->type = rdatatype;
2110 	rdatalist->rdclass = rdataclass;
2111 	rdatalist->covers = rdatatype;
2112 	rdatalist->ttl = (dns_ttl_t)ttl;
2113 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2114 	dns_rdatalist_tordataset(rdatalist, rdataset);
2115 	ISC_LIST_INIT(name->list);
2116 	ISC_LIST_APPEND(name->list, rdataset, link);
2117 	dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
2118 	return STATUS_MORE;
2119 
2120 failure:
2121 	if (name != NULL) {
2122 		dns_message_puttempname(updatemsg, &name);
2123 	}
2124 	dns_message_puttemprdata(updatemsg, &rdata);
2125 	return STATUS_SYNTAX;
2126 }
2127 
2128 static uint16_t
2129 evaluate_update(char *cmdline) {
2130 	char *word;
2131 	bool isdelete;
2132 
2133 	ddebug("evaluate_update()");
2134 	word = nsu_strsep(&cmdline, " \t\r\n");
2135 	if (word == NULL || *word == 0) {
2136 		fprintf(stderr, "could not read operation code\n");
2137 		return STATUS_SYNTAX;
2138 	}
2139 	if (strcasecmp(word, "delete") == 0) {
2140 		isdelete = true;
2141 	} else if (strcasecmp(word, "del") == 0) {
2142 		isdelete = true;
2143 	} else if (strcasecmp(word, "add") == 0) {
2144 		isdelete = false;
2145 	} else {
2146 		fprintf(stderr, "incorrect operation code: %s\n", word);
2147 		return STATUS_SYNTAX;
2148 	}
2149 	return update_addordelete(cmdline, isdelete);
2150 }
2151 
2152 static uint16_t
2153 evaluate_checknames(char *cmdline) {
2154 	char *word;
2155 
2156 	ddebug("evaluate_checknames()");
2157 	word = nsu_strsep(&cmdline, " \t\r\n");
2158 	if (word == NULL || *word == 0) {
2159 		fprintf(stderr, "could not read check-names directive\n");
2160 		return STATUS_SYNTAX;
2161 	}
2162 	if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 ||
2163 	    strcasecmp(word, "on") == 0)
2164 	{
2165 		checknames = true;
2166 	} else if (strcasecmp(word, "no") == 0 ||
2167 		   strcasecmp(word, "false") == 0 ||
2168 		   strcasecmp(word, "off") == 0)
2169 	{
2170 		checknames = false;
2171 	} else {
2172 		fprintf(stderr, "incorrect check-names directive: %s\n", word);
2173 		return STATUS_SYNTAX;
2174 	}
2175 	return STATUS_MORE;
2176 }
2177 
2178 static uint16_t
2179 evaluate_checksvcb(char *cmdline) {
2180 	char *word;
2181 
2182 	ddebug("evaluate_checksvcb()");
2183 	word = nsu_strsep(&cmdline, " \t\r\n");
2184 	if (word == NULL || *word == 0) {
2185 		fprintf(stderr, "could not read check-svcb directive\n");
2186 		return STATUS_SYNTAX;
2187 	}
2188 	if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 ||
2189 	    strcasecmp(word, "on") == 0)
2190 	{
2191 		checksvcb = true;
2192 	} else if (strcasecmp(word, "no") == 0 ||
2193 		   strcasecmp(word, "false") == 0 ||
2194 		   strcasecmp(word, "off") == 0)
2195 	{
2196 		checksvcb = false;
2197 	} else {
2198 		fprintf(stderr, "incorrect check-svcb directive: %s\n", word);
2199 		return STATUS_SYNTAX;
2200 	}
2201 	return STATUS_MORE;
2202 }
2203 
2204 static void
2205 setzone(dns_name_t *zonename) {
2206 	isc_result_t result;
2207 	dns_name_t *name = NULL;
2208 	dns_rdataset_t *rdataset = NULL;
2209 
2210 	result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
2211 	if (result == ISC_R_SUCCESS) {
2212 		dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
2213 		dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
2214 		for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
2215 		     rdataset = ISC_LIST_HEAD(name->list))
2216 		{
2217 			ISC_LIST_UNLINK(name->list, rdataset, link);
2218 			dns_rdataset_disassociate(rdataset);
2219 			dns_message_puttemprdataset(updatemsg, &rdataset);
2220 		}
2221 		dns_message_puttempname(updatemsg, &name);
2222 	}
2223 
2224 	if (zonename != NULL) {
2225 		dns_message_gettempname(updatemsg, &name);
2226 		dns_name_clone(zonename, name);
2227 		dns_message_gettemprdataset(updatemsg, &rdataset);
2228 		dns_rdataset_makequestion(rdataset, getzoneclass(),
2229 					  dns_rdatatype_soa);
2230 		ISC_LIST_INIT(name->list);
2231 		ISC_LIST_APPEND(name->list, rdataset, link);
2232 		dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
2233 	}
2234 }
2235 
2236 static void
2237 show_message(FILE *stream, dns_message_t *msg, const char *description) {
2238 	isc_result_t result;
2239 	isc_buffer_t *buf = NULL;
2240 	int bufsz;
2241 
2242 	ddebug("show_message()");
2243 
2244 	setzone(userzone);
2245 
2246 	bufsz = INITTEXT;
2247 	do {
2248 		if (bufsz > MAXTEXT) {
2249 			fprintf(stderr, "could not allocate large enough "
2250 					"buffer to display message\n");
2251 			exit(EXIT_FAILURE);
2252 		}
2253 		if (buf != NULL) {
2254 			isc_buffer_free(&buf);
2255 		}
2256 		isc_buffer_allocate(gmctx, &buf, bufsz);
2257 		result = dns_message_totext(msg, style, 0, buf);
2258 		bufsz *= 2;
2259 	} while (result == ISC_R_NOSPACE);
2260 	if (result != ISC_R_SUCCESS) {
2261 		fprintf(stderr, "could not convert message to text format.\n");
2262 		isc_buffer_free(&buf);
2263 		return;
2264 	}
2265 	fprintf(stream, "%s\n%.*s", description,
2266 		(int)isc_buffer_usedlength(buf), (char *)isc_buffer_base(buf));
2267 	fflush(stream);
2268 	isc_buffer_free(&buf);
2269 }
2270 
2271 static uint16_t
2272 do_next_command(char *cmdline) {
2273 	char *word;
2274 
2275 	ddebug("do_next_command()");
2276 	word = nsu_strsep(&cmdline, " \t\r\n");
2277 
2278 	if (word == NULL || *word == 0) {
2279 		return STATUS_SEND;
2280 	}
2281 	if (word[0] == ';') {
2282 		return STATUS_MORE;
2283 	}
2284 	if (strcasecmp(word, "quit") == 0) {
2285 		return STATUS_QUIT;
2286 	}
2287 	if (strcasecmp(word, "prereq") == 0) {
2288 		return evaluate_prereq(cmdline);
2289 	}
2290 	if (strcasecmp(word, "nxdomain") == 0) {
2291 		return make_prereq(cmdline, false, false);
2292 	}
2293 	if (strcasecmp(word, "yxdomain") == 0) {
2294 		return make_prereq(cmdline, true, false);
2295 	}
2296 	if (strcasecmp(word, "nxrrset") == 0) {
2297 		return make_prereq(cmdline, false, true);
2298 	}
2299 	if (strcasecmp(word, "yxrrset") == 0) {
2300 		return make_prereq(cmdline, true, true);
2301 	}
2302 	if (strcasecmp(word, "update") == 0) {
2303 		return evaluate_update(cmdline);
2304 	}
2305 	if (strcasecmp(word, "delete") == 0) {
2306 		return update_addordelete(cmdline, true);
2307 	}
2308 	if (strcasecmp(word, "del") == 0) {
2309 		return update_addordelete(cmdline, true);
2310 	}
2311 	if (strcasecmp(word, "add") == 0) {
2312 		return update_addordelete(cmdline, false);
2313 	}
2314 	if (strcasecmp(word, "lease") == 0) {
2315 		return evaluate_lease(cmdline);
2316 	}
2317 	if (strcasecmp(word, "server") == 0) {
2318 		return evaluate_server(cmdline);
2319 	}
2320 	if (strcasecmp(word, "local") == 0) {
2321 		return evaluate_local(cmdline);
2322 	}
2323 	if (strcasecmp(word, "zone") == 0) {
2324 		return evaluate_zone(cmdline);
2325 	}
2326 	if (strcasecmp(word, "class") == 0) {
2327 		return evaluate_class(cmdline);
2328 	}
2329 	if (strcasecmp(word, "send") == 0) {
2330 		return STATUS_SEND;
2331 	}
2332 	if (strcasecmp(word, "debug") == 0) {
2333 		if (debugging) {
2334 			ddebugging = true;
2335 		} else {
2336 			debugging = true;
2337 		}
2338 		return STATUS_MORE;
2339 	}
2340 	if (strcasecmp(word, "ttl") == 0) {
2341 		return evaluate_ttl(cmdline);
2342 	}
2343 	if (strcasecmp(word, "show") == 0) {
2344 		show_message(stdout, updatemsg, "Outgoing update query:");
2345 		return STATUS_MORE;
2346 	}
2347 	if (strcasecmp(word, "answer") == 0) {
2348 		LOCK(&answer_lock);
2349 		if (answer != NULL) {
2350 			show_message(stdout, answer, "Answer:");
2351 		}
2352 		UNLOCK(&answer_lock);
2353 		return STATUS_MORE;
2354 	}
2355 	if (strcasecmp(word, "key") == 0) {
2356 		usegsstsig = false;
2357 		return evaluate_key(cmdline);
2358 	}
2359 	if (strcasecmp(word, "realm") == 0) {
2360 		return evaluate_realm(cmdline);
2361 	}
2362 	if (strcasecmp(word, "check-names") == 0 ||
2363 	    strcasecmp(word, "checknames") == 0)
2364 	{
2365 		return evaluate_checknames(cmdline);
2366 	}
2367 	if (strcasecmp(word, "check-svcb") == 0 ||
2368 	    strcasecmp(word, "checksvcb") == 0)
2369 	{
2370 		return evaluate_checksvcb(cmdline);
2371 	}
2372 	if (strcasecmp(word, "gsstsig") == 0) {
2373 #if HAVE_GSSAPI
2374 		usegsstsig = true;
2375 #else  /* HAVE_GSSAPI */
2376 		fprintf(stderr, "gsstsig not supported\n");
2377 #endif /* HAVE_GSSAPI */
2378 		return STATUS_MORE;
2379 	}
2380 	if (strcasecmp(word, "oldgsstsig") == 0) {
2381 #if HAVE_GSSAPI
2382 		usegsstsig = true;
2383 #else  /* HAVE_GSSAPI */
2384 		fprintf(stderr, "gsstsig not supported\n");
2385 #endif /* HAVE_GSSAPI */
2386 		return STATUS_MORE;
2387 	}
2388 	if (strcasecmp(word, "help") == 0) {
2389 		fprintf(stdout, "nsupdate " PACKAGE_VERSION ":\n"
2390 				"local address [port]      (set local "
2391 				"resolver)\n"
2392 				"server address [port]     (set primary server "
2393 				"for zone)\n"
2394 				"send                      (send the update "
2395 				"request)\n"
2396 				"show                      (show the update "
2397 				"request)\n"
2398 				"answer                    (show the answer to "
2399 				"the last request)\n"
2400 				"quit                      (quit, any pending "
2401 				"update is not sent)\n"
2402 				"help                      (display this "
2403 				"message)\n"
2404 				"key [hmac:]keyname secret (use TSIG to sign "
2405 				"the request)\n"
2406 				"gsstsig                   (use GSS_TSIG to "
2407 				"sign the request)\n"
2408 				"zone name                 (set the zone to be "
2409 				"updated)\n"
2410 				"class CLASS               (set the zone's DNS "
2411 				"class, e.g. IN (default), CH)\n"
2412 				"check-names { on | off }  (enable / disable "
2413 				"check-names)\n"
2414 				"[prereq] nxdomain name    (require that this "
2415 				"name does not exist)\n"
2416 				"[prereq] yxdomain name    (require that this "
2417 				"name exists)\n"
2418 				"[prereq] nxrrset ....     (require that this "
2419 				"RRset does not exist)\n"
2420 				"[prereq] yxrrset ....     (require that this "
2421 				"RRset exists)\n"
2422 				"[update] add ....         (add the given "
2423 				"record to the zone)\n"
2424 				"[update] del[ete] ....    (remove the given "
2425 				"record(s) from the zone)\n");
2426 		return STATUS_MORE;
2427 	}
2428 	if (strcasecmp(word, "version") == 0) {
2429 		fprintf(stdout, "nsupdate " PACKAGE_VERSION "\n");
2430 		return STATUS_MORE;
2431 	}
2432 	fprintf(stderr, "incorrect section name: %s\n", word);
2433 	return STATUS_SYNTAX;
2434 }
2435 
2436 static uint16_t
2437 get_next_command(void) {
2438 	uint16_t result = STATUS_QUIT;
2439 	char cmdlinebuf[MAXCMD];
2440 	char *cmdline = NULL, *ptr = NULL;
2441 
2442 	if (interactive) {
2443 		cmdline = ptr = readline("> ");
2444 		if (ptr != NULL && *ptr != 0) {
2445 			add_history(ptr);
2446 		}
2447 	} else {
2448 		cmdline = fgets(cmdlinebuf, MAXCMD, input);
2449 	}
2450 
2451 	if (cmdline != NULL) {
2452 		char *tmp = cmdline;
2453 
2454 		/*
2455 		 * Normalize input by removing any eol as readline()
2456 		 * removes eol but fgets doesn't.
2457 		 */
2458 		(void)nsu_strsep(&tmp, "\r\n");
2459 		result = do_next_command(cmdline);
2460 	}
2461 	if (ptr != NULL) {
2462 		free(ptr);
2463 	}
2464 
2465 	return result;
2466 }
2467 
2468 static bool
2469 user_interaction(void) {
2470 	uint16_t result = STATUS_MORE;
2471 
2472 	ddebug("user_interaction()");
2473 	while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
2474 		result = get_next_command();
2475 		if (!interactive && result == STATUS_SYNTAX) {
2476 			fatal("syntax error");
2477 		}
2478 	}
2479 	if (result == STATUS_SEND) {
2480 		return true;
2481 	}
2482 	return false;
2483 }
2484 
2485 static void
2486 done_update(void) {
2487 	ddebug("done_update()");
2488 
2489 	isc_async_current(getinput, NULL);
2490 }
2491 
2492 static void
2493 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
2494 	isc_result_t result;
2495 	dns_rdata_t rdata = DNS_RDATA_INIT;
2496 	dns_rdata_any_tsig_t tsig;
2497 
2498 	result = dns_rdataset_first(rdataset);
2499 	check_result(result, "dns_rdataset_first");
2500 	dns_rdataset_current(rdataset, &rdata);
2501 	result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2502 	check_result(result, "dns_rdata_tostruct");
2503 	if (tsig.error != 0) {
2504 		if (isc_buffer_remaininglength(b) < 1) {
2505 			check_result(ISC_R_NOSPACE, "isc_buffer_"
2506 						    "remaininglength");
2507 		}
2508 		isc_buffer_putstr(b, "(" /*)*/);
2509 		result = dns_tsigrcode_totext(tsig.error, b);
2510 		check_result(result, "dns_tsigrcode_totext");
2511 		if (isc_buffer_remaininglength(b) < 1) {
2512 			check_result(ISC_R_NOSPACE, "isc_buffer_"
2513 						    "remaininglength");
2514 		}
2515 		isc_buffer_putstr(b, /*(*/ ")");
2516 	}
2517 }
2518 
2519 static bool
2520 next_primary(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
2521 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2522 
2523 	isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2524 	fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf,
2525 		isc_result_totext(eresult));
2526 	if (++primary_inuse >= primary_total) {
2527 		return false;
2528 	}
2529 	ddebug("%s: trying next server", caller);
2530 	return true;
2531 }
2532 
2533 static void
2534 update_completed(void *arg) {
2535 	dns_request_t *request = (dns_request_t *)arg;
2536 	isc_result_t result;
2537 
2538 	ddebug("update_completed()");
2539 
2540 	requests--;
2541 
2542 	if (shuttingdown) {
2543 		dns_request_destroy(&request);
2544 		maybeshutdown();
2545 		return;
2546 	}
2547 
2548 	result = dns_request_getresult(request);
2549 	if (result != ISC_R_SUCCESS) {
2550 		if (!next_primary("update_completed",
2551 				  &primary_servers[primary_inuse], result))
2552 		{
2553 			seenerror = true;
2554 			goto done;
2555 		}
2556 
2557 		ddebug("Destroying request [%p]", request);
2558 		dns_request_destroy(&request);
2559 		dns_message_renderreset(updatemsg);
2560 		dns_message_settsigkey(updatemsg, NULL);
2561 		send_update(zname, &primary_servers[primary_inuse]);
2562 		return;
2563 	}
2564 
2565 	LOCK(&answer_lock);
2566 	dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &answer);
2567 	result = dns_request_getresponse(request, answer,
2568 					 DNS_MESSAGEPARSE_PRESERVEORDER);
2569 	switch (result) {
2570 	case ISC_R_SUCCESS:
2571 		if (answer->verify_attempted) {
2572 			ddebug("tsig verification successful");
2573 		}
2574 		break;
2575 	case DNS_R_CLOCKSKEW:
2576 	case DNS_R_EXPECTEDTSIG:
2577 	case DNS_R_TSIGERRORSET:
2578 	case DNS_R_TSIGVERIFYFAILURE:
2579 	case DNS_R_UNEXPECTEDTSIG:
2580 	case ISC_R_FAILURE:
2581 #if 0
2582 		if (usegsstsig && answer->rcode == dns_rcode_noerror) {
2583 			/*
2584 			 * For MS DNS that violates RFC 2845, section 4.2
2585 			 */
2586 			break;
2587 		}
2588 #endif /* if 0 */
2589 		fprintf(stderr, "; TSIG error with server: %s\n",
2590 			isc_result_totext(result));
2591 		seenerror = true;
2592 		break;
2593 	default:
2594 		check_result(result, "dns_request_getresponse");
2595 	}
2596 
2597 	if (answer->opcode != dns_opcode_update) {
2598 		fatal("invalid OPCODE in response to UPDATE request");
2599 	}
2600 
2601 	if (answer->rcode != dns_rcode_noerror) {
2602 		seenerror = true;
2603 		if (!debugging) {
2604 			char buf[64];
2605 			isc_buffer_t b;
2606 			dns_rdataset_t *rds;
2607 
2608 			isc_buffer_init(&b, buf, sizeof(buf) - 1);
2609 			result = dns_rcode_totext(answer->rcode, &b);
2610 			check_result(result, "dns_rcode_totext");
2611 			rds = dns_message_gettsig(answer, NULL);
2612 			if (rds != NULL) {
2613 				check_tsig_error(rds, &b);
2614 			}
2615 			fprintf(stderr, "update failed: %.*s\n",
2616 				(int)isc_buffer_usedlength(&b), buf);
2617 		}
2618 	}
2619 	if (debugging) {
2620 		show_message(stderr, answer, "\nReply from update query:");
2621 	}
2622 	UNLOCK(&answer_lock);
2623 
2624 done:
2625 	dns_request_destroy(&request);
2626 	if (usegsstsig) {
2627 		dns_name_free(&tmpzonename, gmctx);
2628 		dns_name_free(&restart_primary, gmctx);
2629 		dns_name_init(&tmpzonename, 0);
2630 		dns_name_init(&restart_primary, 0);
2631 	}
2632 	done_update();
2633 }
2634 
2635 static void
2636 send_update(dns_name_t *zone, isc_sockaddr_t *primary) {
2637 	isc_result_t result;
2638 	dns_request_t *request = NULL;
2639 	isc_sockaddr_t *srcaddr;
2640 	unsigned int options = DNS_REQUESTOPT_CASE | DNS_REQUESTOPT_LARGE;
2641 	dns_transport_t *req_transport = NULL;
2642 	isc_tlsctx_cache_t *req_tls_ctx_cache = NULL;
2643 
2644 	ddebug("send_update()");
2645 
2646 	setzone(zone);
2647 
2648 	if (usevc) {
2649 		options |= DNS_REQUESTOPT_TCP;
2650 		if (use_tls) {
2651 			req_transport = transport;
2652 			req_tls_ctx_cache = tls_ctx_cache;
2653 		}
2654 	}
2655 
2656 	if (tsigkey == NULL && sig0key != NULL) {
2657 		result = dns_message_setsig0key(updatemsg, sig0key);
2658 		check_result(result, "dns_message_setsig0key");
2659 	}
2660 	if (debugging) {
2661 		char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2662 
2663 		isc_sockaddr_format(primary, addrbuf, sizeof(addrbuf));
2664 		fprintf(stderr, "Sending update to %s\n", addrbuf);
2665 	}
2666 
2667 	if (isc_sockaddr_pf(primary) == AF_INET6) {
2668 		srcaddr = localaddr6;
2669 	} else {
2670 		srcaddr = localaddr4;
2671 	}
2672 
2673 	/* Windows doesn't like the tsig name to be compressed. */
2674 	if (updatemsg->tsigname) {
2675 		updatemsg->tsigname->attributes.nocompress = true;
2676 	}
2677 
2678 	result = dns_request_create(requestmgr, updatemsg, srcaddr, primary,
2679 				    req_transport, req_tls_ctx_cache, options,
2680 				    tsigkey, timeout, udp_timeout, udp_retries,
2681 				    isc_loop_main(loopmgr), update_completed,
2682 				    NULL, &request);
2683 	check_result(result, "dns_request_create");
2684 
2685 	if (debugging) {
2686 		show_message(stdout, updatemsg, "Outgoing update query:");
2687 	}
2688 
2689 	requests++;
2690 }
2691 
2692 static void
2693 next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
2694 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2695 
2696 	isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2697 	fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf,
2698 		isc_result_totext(eresult));
2699 	if (++ns_inuse >= ns_total) {
2700 		fatal("could not reach any name server");
2701 	} else {
2702 		ddebug("%s: trying next server", caller);
2703 	}
2704 }
2705 
2706 static void
2707 recvsoa(void *arg) {
2708 	dns_request_t *request = (dns_request_t *)arg;
2709 	isc_result_t result, eresult = dns_request_getresult(request);
2710 	nsu_requestinfo_t *reqinfo = dns_request_getarg(request);
2711 	dns_message_t *soaquery = reqinfo->msg;
2712 	dns_message_t *rcvmsg = NULL;
2713 	dns_section_t section;
2714 	dns_name_t *name = NULL;
2715 	dns_rdataset_t *soaset = NULL;
2716 	dns_rdata_soa_t soa;
2717 	dns_rdata_t soarr = DNS_RDATA_INIT;
2718 	int pass = 0;
2719 	dns_name_t primary;
2720 	isc_sockaddr_t *addr = reqinfo->addr;
2721 	isc_sockaddr_t *srcaddr = NULL;
2722 	bool seencname = false;
2723 	dns_name_t tname;
2724 	unsigned int nlabels;
2725 
2726 	ddebug("recvsoa()");
2727 
2728 	requests--;
2729 
2730 	if (shuttingdown) {
2731 		dns_request_destroy(&request);
2732 		dns_message_detach(&soaquery);
2733 		isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2734 		maybeshutdown();
2735 		return;
2736 	}
2737 
2738 	if (eresult != ISC_R_SUCCESS) {
2739 		next_server("recvsoa", addr, eresult);
2740 		ddebug("Destroying request [%p]", request);
2741 		dns_request_destroy(&request);
2742 		dns_message_renderreset(soaquery);
2743 		dns_message_settsigkey(soaquery, NULL);
2744 		sendrequest(&servers[ns_inuse], soaquery, &request);
2745 		isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2746 		setzoneclass(dns_rdataclass_none);
2747 		return;
2748 	}
2749 
2750 	isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2751 	reqinfo = NULL;
2752 
2753 	ddebug("About to create rcvmsg");
2754 	dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2755 	result = dns_request_getresponse(request, rcvmsg,
2756 					 DNS_MESSAGEPARSE_PRESERVEORDER);
2757 	if (result == DNS_R_TSIGERRORSET && servers != NULL) {
2758 		unsigned int options = DNS_REQUESTOPT_CASE;
2759 		dns_transport_t *req_transport = NULL;
2760 		isc_tlsctx_cache_t *req_tls_ctx_cache = NULL;
2761 
2762 		dns_message_detach(&rcvmsg);
2763 		ddebug("Destroying request [%p]", request);
2764 		dns_request_destroy(&request);
2765 		reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
2766 		reqinfo->msg = soaquery;
2767 		reqinfo->addr = addr;
2768 		dns_message_renderreset(soaquery);
2769 		ddebug("retrying soa request without TSIG");
2770 
2771 		if (!default_servers && usevc) {
2772 			options |= DNS_REQUESTOPT_TCP;
2773 			if (use_tls) {
2774 				req_transport = transport;
2775 				req_tls_ctx_cache = tls_ctx_cache;
2776 			}
2777 		}
2778 
2779 		if (isc_sockaddr_pf(addr) == AF_INET6) {
2780 			srcaddr = localaddr6;
2781 		} else {
2782 			srcaddr = localaddr4;
2783 		}
2784 
2785 		result = dns_request_create(requestmgr, soaquery, srcaddr, addr,
2786 					    req_transport, req_tls_ctx_cache,
2787 					    options, NULL, timeout, udp_timeout,
2788 					    udp_retries, isc_loop_main(loopmgr),
2789 					    recvsoa, reqinfo, &request);
2790 		check_result(result, "dns_request_create");
2791 		requests++;
2792 		return;
2793 	}
2794 	check_result(result, "dns_request_getresponse");
2795 
2796 	if (rcvmsg->rcode == dns_rcode_refused) {
2797 		next_server("recvsoa", addr, DNS_R_REFUSED);
2798 		dns_message_detach(&rcvmsg);
2799 		dns_request_destroy(&request);
2800 		dns_message_renderreset(soaquery);
2801 		dns_message_settsigkey(soaquery, NULL);
2802 		sendrequest(&servers[ns_inuse], soaquery, &request);
2803 		return;
2804 	}
2805 
2806 	section = DNS_SECTION_ANSWER;
2807 	POST(section);
2808 	if (debugging) {
2809 		show_message(stderr, rcvmsg, "Reply from SOA query:");
2810 	}
2811 
2812 	if (rcvmsg->opcode != dns_opcode_query) {
2813 		fatal("invalid OPCODE in response to SOA query");
2814 	}
2815 
2816 	if (rcvmsg->rcode != dns_rcode_noerror &&
2817 	    rcvmsg->rcode != dns_rcode_nxdomain)
2818 	{
2819 		fatal("response to SOA query was unsuccessful");
2820 	}
2821 
2822 	if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2823 		char namebuf[DNS_NAME_FORMATSIZE];
2824 		dns_name_format(userzone, namebuf, sizeof(namebuf));
2825 		error("specified zone '%s' does not exist (NXDOMAIN)", namebuf);
2826 		dns_message_detach(&rcvmsg);
2827 		dns_request_destroy(&request);
2828 		dns_message_detach(&soaquery);
2829 		ddebug("Out of recvsoa");
2830 		seenerror = true;
2831 		done_update();
2832 		return;
2833 	}
2834 
2835 lookforsoa:
2836 	if (pass == 0) {
2837 		section = DNS_SECTION_ANSWER;
2838 	} else if (pass == 1) {
2839 		section = DNS_SECTION_AUTHORITY;
2840 	} else {
2841 		goto droplabel;
2842 	}
2843 
2844 	result = dns_message_firstname(rcvmsg, section);
2845 	if (result != ISC_R_SUCCESS) {
2846 		pass++;
2847 		goto lookforsoa;
2848 	}
2849 	while (result == ISC_R_SUCCESS) {
2850 		name = NULL;
2851 		dns_message_currentname(rcvmsg, section, &name);
2852 		soaset = NULL;
2853 		result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2854 					      &soaset);
2855 		if (result == ISC_R_SUCCESS) {
2856 			break;
2857 		}
2858 		if (section == DNS_SECTION_ANSWER) {
2859 			dns_rdataset_t *tset = NULL;
2860 			if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2861 						 &tset) == ISC_R_SUCCESS ||
2862 			    dns_message_findtype(name, dns_rdatatype_dname, 0,
2863 						 &tset) == ISC_R_SUCCESS)
2864 			{
2865 				seencname = true;
2866 				break;
2867 			}
2868 		}
2869 
2870 		result = dns_message_nextname(rcvmsg, section);
2871 	}
2872 
2873 	if (soaset == NULL && !seencname) {
2874 		pass++;
2875 		goto lookforsoa;
2876 	}
2877 
2878 	if (seencname) {
2879 		goto droplabel;
2880 	}
2881 
2882 	if (debugging) {
2883 		char namestr[DNS_NAME_FORMATSIZE];
2884 		dns_name_format(name, namestr, sizeof(namestr));
2885 		fprintf(stderr, "Found zone name: %s\n", namestr);
2886 	}
2887 
2888 	result = dns_rdataset_first(soaset);
2889 	check_result(result, "dns_rdataset_first");
2890 
2891 	dns_rdata_init(&soarr);
2892 	dns_rdataset_current(soaset, &soarr);
2893 	result = dns_rdata_tostruct(&soarr, &soa, NULL);
2894 	check_result(result, "dns_rdata_tostruct");
2895 
2896 	dns_name_init(&primary, NULL);
2897 	dns_name_clone(&soa.origin, &primary);
2898 
2899 	if (userzone != NULL) {
2900 		zname = userzone;
2901 	} else {
2902 		/*
2903 		 * Save the zone name in case we need to try a second
2904 		 * address.
2905 		 */
2906 		zname = dns_fixedname_initname(&fzname);
2907 		dns_name_copy(name, zname);
2908 	}
2909 
2910 	if (debugging) {
2911 		char namestr[DNS_NAME_FORMATSIZE];
2912 		dns_name_format(&primary, namestr, sizeof(namestr));
2913 		fprintf(stderr, "The primary is: %s\n", namestr);
2914 	}
2915 
2916 	if (default_servers) {
2917 		char serverstr[DNS_NAME_MAXTEXT + 1];
2918 		isc_buffer_t buf;
2919 
2920 		isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2921 		result = dns_name_totext(&primary, DNS_NAME_OMITFINALDOT, &buf);
2922 		check_result(result, "dns_name_totext");
2923 		serverstr[isc_buffer_usedlength(&buf)] = 0;
2924 
2925 		if (primary_servers != NULL && primary_servers != servers) {
2926 			isc_mem_cput(gmctx, primary_servers, primary_alloc,
2927 				     sizeof(isc_sockaddr_t));
2928 		}
2929 		primary_alloc = MAX_SERVERADDRS;
2930 		primary_servers = isc_mem_cget(gmctx, primary_alloc,
2931 					       sizeof(isc_sockaddr_t));
2932 		primary_total = get_addresses(serverstr, dnsport,
2933 					      primary_servers, primary_alloc);
2934 		if (primary_total == 0) {
2935 			seenerror = true;
2936 			dns_rdata_freestruct(&soa);
2937 			dns_message_detach(&soaquery);
2938 			dns_request_destroy(&request);
2939 			dns_message_detach(&rcvmsg);
2940 			ddebug("Out of recvsoa");
2941 			done_update();
2942 			return;
2943 		}
2944 		primary_inuse = 0;
2945 	} else {
2946 		primary_from_servers();
2947 	}
2948 	dns_rdata_freestruct(&soa);
2949 
2950 #if HAVE_GSSAPI
2951 	if (usegsstsig) {
2952 		dns_name_init(&tmpzonename, NULL);
2953 		dns_name_dup(zname, gmctx, &tmpzonename);
2954 		dns_name_init(&restart_primary, NULL);
2955 		dns_name_dup(&primary, gmctx, &restart_primary);
2956 		start_gssrequest(&primary);
2957 	} else {
2958 		send_update(zname, &primary_servers[primary_inuse]);
2959 		setzoneclass(dns_rdataclass_none);
2960 	}
2961 #else  /* HAVE_GSSAPI */
2962 	send_update(zname, &primary_servers[primary_inuse]);
2963 	setzoneclass(dns_rdataclass_none);
2964 #endif /* HAVE_GSSAPI */
2965 
2966 	dns_message_detach(&soaquery);
2967 	dns_request_destroy(&request);
2968 
2969 out:
2970 	dns_message_detach(&rcvmsg);
2971 	ddebug("Out of recvsoa");
2972 	return;
2973 
2974 droplabel:
2975 	result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2976 	INSIST(result == ISC_R_SUCCESS);
2977 	name = NULL;
2978 	dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2979 	nlabels = dns_name_countlabels(name);
2980 	if (nlabels == 1) {
2981 		fatal("could not find enclosing zone");
2982 	}
2983 	dns_name_init(&tname, NULL);
2984 	dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2985 	dns_name_clone(&tname, name);
2986 	dns_request_destroy(&request);
2987 	dns_message_renderreset(soaquery);
2988 	dns_message_settsigkey(soaquery, NULL);
2989 	sendrequest(&servers[ns_inuse], soaquery, &request);
2990 	goto out;
2991 }
2992 
2993 static void
2994 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
2995 	    dns_request_t **request) {
2996 	isc_result_t result;
2997 	nsu_requestinfo_t *reqinfo;
2998 	isc_sockaddr_t *srcaddr;
2999 	unsigned int options = DNS_REQUESTOPT_CASE;
3000 	dns_transport_t *req_transport = NULL;
3001 	isc_tlsctx_cache_t *req_tls_ctx_cache = NULL;
3002 
3003 	if (!default_servers && usevc) {
3004 		options |= DNS_REQUESTOPT_TCP;
3005 		if (use_tls) {
3006 			req_transport = transport;
3007 			req_tls_ctx_cache = tls_ctx_cache;
3008 		}
3009 	}
3010 
3011 	reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
3012 	reqinfo->msg = msg;
3013 	reqinfo->addr = destaddr;
3014 
3015 	if (isc_sockaddr_pf(destaddr) == AF_INET6) {
3016 		srcaddr = localaddr6;
3017 	} else {
3018 		srcaddr = localaddr4;
3019 	}
3020 
3021 	result = dns_request_create(
3022 		requestmgr, msg, srcaddr, destaddr, req_transport,
3023 		req_tls_ctx_cache, options, default_servers ? NULL : tsigkey,
3024 		timeout, udp_timeout, udp_retries, isc_loop_main(loopmgr),
3025 		recvsoa, reqinfo, request);
3026 	check_result(result, "dns_request_create");
3027 	requests++;
3028 }
3029 
3030 #if HAVE_GSSAPI
3031 
3032 /*
3033  * Get the realm from the users kerberos ticket if possible
3034  */
3035 static void
3036 get_ticket_realm(isc_mem_t *mctx) {
3037 	krb5_context ctx;
3038 	krb5_error_code rc;
3039 	krb5_ccache ccache;
3040 	krb5_principal princ;
3041 	char *name;
3042 	const char *ticket_realm;
3043 
3044 	rc = krb5_init_context(&ctx);
3045 	if (rc != 0) {
3046 		return;
3047 	}
3048 
3049 	rc = krb5_cc_default(ctx, &ccache);
3050 	if (rc != 0) {
3051 		krb5_free_context(ctx);
3052 		return;
3053 	}
3054 
3055 	rc = krb5_cc_get_principal(ctx, ccache, &princ);
3056 	if (rc != 0) {
3057 		krb5_cc_close(ctx, ccache);
3058 		krb5_free_context(ctx);
3059 		return;
3060 	}
3061 
3062 	rc = krb5_unparse_name(ctx, princ, &name);
3063 	if (rc != 0) {
3064 		krb5_free_principal(ctx, princ);
3065 		krb5_cc_close(ctx, ccache);
3066 		krb5_free_context(ctx);
3067 		return;
3068 	}
3069 
3070 	ticket_realm = strrchr(name, '@');
3071 	if (ticket_realm != NULL) {
3072 		realm = isc_mem_strdup(mctx, ticket_realm);
3073 	}
3074 
3075 	free(name);
3076 	krb5_free_principal(ctx, princ);
3077 	krb5_cc_close(ctx, ccache);
3078 	krb5_free_context(ctx);
3079 	if (realm != NULL && debugging) {
3080 		fprintf(stderr, "Found realm from ticket: %s\n", realm + 1);
3081 	}
3082 }
3083 
3084 static void
3085 failed_gssrequest(void) {
3086 	seenerror = true;
3087 
3088 	dns_name_free(&tmpzonename, gmctx);
3089 	dns_name_free(&restart_primary, gmctx);
3090 	dns_name_init(&tmpzonename, NULL);
3091 	dns_name_init(&restart_primary, NULL);
3092 
3093 	done_update();
3094 }
3095 
3096 static void
3097 start_gssrequest(dns_name_t *primary) {
3098 	dns_gss_ctx_id_t context;
3099 	isc_buffer_t buf;
3100 	isc_result_t result;
3101 	uint32_t val = 0;
3102 	dns_message_t *rmsg = NULL;
3103 	dns_request_t *request = NULL;
3104 	dns_name_t *servname;
3105 	dns_fixedname_t fname;
3106 	char namestr[DNS_NAME_FORMATSIZE];
3107 	char mykeystr[DNS_NAME_FORMATSIZE];
3108 	char *err_message = NULL;
3109 
3110 	debug("start_gssrequest");
3111 	usevc = true;
3112 
3113 	if (gssring != NULL) {
3114 		dns_tsigkeyring_detach(&gssring);
3115 	}
3116 
3117 	dns_tsigkeyring_create(gmctx, &gssring);
3118 
3119 	dns_name_format(primary, namestr, sizeof(namestr));
3120 	if (kserver == NULL) {
3121 		kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
3122 	}
3123 
3124 	memmove(kserver, &primary_servers[primary_inuse],
3125 		sizeof(isc_sockaddr_t));
3126 
3127 	servname = dns_fixedname_initname(&fname);
3128 
3129 	if (realm == NULL) {
3130 		get_ticket_realm(gmctx);
3131 	}
3132 
3133 	result = snprintf(servicename, sizeof(servicename), "DNS/%s%s", namestr,
3134 			  realm ? realm : "");
3135 	RUNTIME_CHECK(result < sizeof(servicename));
3136 	isc_buffer_init(&buf, servicename, strlen(servicename));
3137 	isc_buffer_add(&buf, strlen(servicename));
3138 	result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
3139 	if (result != ISC_R_SUCCESS) {
3140 		fatal("dns_name_fromtext(servname) failed: %s",
3141 		      isc_result_totext(result));
3142 	}
3143 
3144 	keyname = dns_fixedname_initname(&fkname);
3145 
3146 	isc_nonce_buf(&val, sizeof(val));
3147 
3148 	result = snprintf(mykeystr, sizeof(mykeystr), "%u.sig-%s", val,
3149 			  namestr);
3150 	RUNTIME_CHECK(result <= sizeof(mykeystr));
3151 
3152 	isc_buffer_init(&buf, mykeystr, strlen(mykeystr));
3153 	isc_buffer_add(&buf, strlen(mykeystr));
3154 
3155 	result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
3156 	if (result != ISC_R_SUCCESS) {
3157 		fatal("dns_name_fromtext(keyname) failed: %s",
3158 		      isc_result_totext(result));
3159 	}
3160 
3161 	/* Windows doesn't recognize name compression in the key name. */
3162 	keyname->attributes.nocompress = true;
3163 
3164 	rmsg = NULL;
3165 	dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, &rmsg);
3166 
3167 	/* Build first request. */
3168 	context = GSS_C_NO_CONTEXT;
3169 	result = dns_tkey_buildgssquery(rmsg, keyname, servname, 0, &context,
3170 					gmctx, &err_message);
3171 	if (result == ISC_R_FAILURE) {
3172 		fprintf(stderr, "tkey query failed: %s\n",
3173 			err_message != NULL ? err_message : "unknown error");
3174 		goto failure;
3175 	}
3176 	if (result != ISC_R_SUCCESS) {
3177 		fatal("dns_tkey_buildgssquery failed: %s",
3178 		      isc_result_totext(result));
3179 	}
3180 
3181 	send_gssrequest(kserver, rmsg, &request, context);
3182 	return;
3183 
3184 failure:
3185 	if (rmsg != NULL) {
3186 		dns_message_detach(&rmsg);
3187 	}
3188 	if (err_message != NULL) {
3189 		isc_mem_free(gmctx, err_message);
3190 	}
3191 	failed_gssrequest();
3192 }
3193 
3194 static void
3195 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
3196 		dns_request_t **request, gss_ctx_id_t context) {
3197 	isc_result_t result;
3198 	nsu_gssinfo_t *reqinfo = NULL;
3199 	isc_sockaddr_t *srcaddr = NULL;
3200 	unsigned int options = DNS_REQUESTOPT_CASE | DNS_REQUESTOPT_TCP;
3201 	dns_transport_t *req_transport = NULL;
3202 	isc_tlsctx_cache_t *req_tls_ctx_cache = NULL;
3203 
3204 	if (!default_servers && use_tls) {
3205 		req_transport = transport;
3206 		req_tls_ctx_cache = tls_ctx_cache;
3207 	}
3208 
3209 	debug("send_gssrequest");
3210 	REQUIRE(destaddr != NULL);
3211 
3212 	reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t));
3213 	*reqinfo = (nsu_gssinfo_t){
3214 		.msg = msg,
3215 		.addr = destaddr,
3216 		.context = context,
3217 	};
3218 
3219 	if (isc_sockaddr_pf(destaddr) == AF_INET6) {
3220 		srcaddr = localaddr6;
3221 	} else {
3222 		srcaddr = localaddr4;
3223 	}
3224 
3225 	result = dns_request_create(
3226 		requestmgr, msg, srcaddr, destaddr, req_transport,
3227 		req_tls_ctx_cache, options, tsigkey, timeout, udp_timeout,
3228 		udp_retries, isc_loop_main(loopmgr), recvgss, reqinfo, request);
3229 	check_result(result, "dns_request_create");
3230 	if (debugging) {
3231 		show_message(stdout, msg, "Outgoing update query:");
3232 	}
3233 	requests++;
3234 }
3235 
3236 static void
3237 recvgss(void *arg) {
3238 	dns_request_t *request = (dns_request_t *)arg;
3239 	nsu_gssinfo_t *reqinfo = dns_request_getarg(request);
3240 	isc_result_t result, eresult = dns_request_getresult(request);
3241 	dns_message_t *rcvmsg = NULL;
3242 	dns_message_t *tsigquery = reqinfo->msg;
3243 	dns_gss_ctx_id_t context = reqinfo->context;
3244 	isc_sockaddr_t *addr = reqinfo->addr;
3245 	isc_buffer_t buf;
3246 	dns_name_t *servname = NULL;
3247 	dns_fixedname_t fname;
3248 	char *err_message = NULL;
3249 
3250 	ddebug("recvgss()");
3251 
3252 	requests--;
3253 
3254 	if (shuttingdown) {
3255 		dns_request_destroy(&request);
3256 		dns_message_detach(&tsigquery);
3257 		isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
3258 		maybeshutdown();
3259 		return;
3260 	}
3261 
3262 	if (eresult != ISC_R_SUCCESS) {
3263 		ddebug("Destroying request [%p]", request);
3264 		dns_request_destroy(&request);
3265 		if (!next_primary("recvgss", addr, eresult)) {
3266 			dns_message_detach(&tsigquery);
3267 			failed_gssrequest();
3268 		} else {
3269 			dns_message_renderreset(tsigquery);
3270 			memmove(kserver, &primary_servers[primary_inuse],
3271 				sizeof(isc_sockaddr_t));
3272 			send_gssrequest(kserver, tsigquery, &request, context);
3273 		}
3274 		isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
3275 		return;
3276 	}
3277 	isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
3278 
3279 	ddebug("recvgss creating rcvmsg");
3280 	dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
3281 
3282 	result = dns_request_getresponse(request, rcvmsg,
3283 					 DNS_MESSAGEPARSE_PRESERVEORDER);
3284 	check_result(result, "dns_request_getresponse");
3285 
3286 	if (debugging) {
3287 		show_message(stderr, rcvmsg,
3288 			     "recvmsg reply from GSS-TSIG query");
3289 	}
3290 
3291 	if (rcvmsg->opcode != dns_opcode_query) {
3292 		fatal("invalid OPCODE in response to GSS-TSIG query");
3293 	}
3294 
3295 	if (rcvmsg->rcode != dns_rcode_noerror &&
3296 	    rcvmsg->rcode != dns_rcode_nxdomain)
3297 	{
3298 		char rcode[64];
3299 		isc_buffer_t b;
3300 
3301 		isc_buffer_init(&b, rcode, sizeof(rcode) - 1);
3302 		result = dns_rcode_totext(rcvmsg->rcode, &b);
3303 		check_result(result, "dns_rcode_totext");
3304 		rcode[isc_buffer_usedlength(&b)] = 0;
3305 
3306 		fatal("response to GSS-TSIG query was unsuccessful (%s)",
3307 		      rcode);
3308 	}
3309 
3310 	servname = dns_fixedname_initname(&fname);
3311 	isc_buffer_init(&buf, servicename, strlen(servicename));
3312 	isc_buffer_add(&buf, strlen(servicename));
3313 	result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
3314 	check_result(result, "dns_name_fromtext");
3315 
3316 	result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context,
3317 				       &tsigkey, gssring, &err_message);
3318 	switch (result) {
3319 	case DNS_R_CONTINUE:
3320 		dns_message_detach(&rcvmsg);
3321 		dns_request_destroy(&request);
3322 		send_gssrequest(kserver, tsigquery, &request, context);
3323 		ddebug("Out of recvgss");
3324 		return;
3325 
3326 	case ISC_R_SUCCESS:
3327 		/*
3328 		 * XXXSRA Waaay too much fun here.  There's no good
3329 		 * reason why we need a TSIG here (the people who put
3330 		 * it into the spec admitted at the time that it was
3331 		 * not a security issue), and Windows clients don't
3332 		 * seem to work if named complies with the spec and
3333 		 * includes the gratuitous TSIG.  So we're in the
3334 		 * bizarre situation of having to choose between
3335 		 * complying with a useless requirement in the spec
3336 		 * and interoperating.  This is nuts.  If we can
3337 		 * confirm this behavior, we should ask the WG to
3338 		 * consider removing the requirement for the
3339 		 * gratuitous TSIG here.  For the moment, we ignore
3340 		 * the TSIG -- this too is a spec violation, but it's
3341 		 * the least insane thing to do.
3342 		 */
3343 
3344 		send_update(&tmpzonename, &primary_servers[primary_inuse]);
3345 		setzoneclass(dns_rdataclass_none);
3346 		break;
3347 
3348 	default:
3349 		fatal("dns_tkey_gssnegotiate: %s %s", isc_result_totext(result),
3350 		      err_message != NULL ? err_message : "");
3351 	}
3352 
3353 	dns_request_destroy(&request);
3354 	dns_message_detach(&tsigquery);
3355 
3356 	dns_message_detach(&rcvmsg);
3357 	ddebug("Out of recvgss");
3358 }
3359 #endif /* HAVE_GSSAPI */
3360 
3361 static void
3362 start_update(void) {
3363 	isc_result_t result;
3364 	dns_rdataset_t *rdataset = NULL;
3365 	dns_name_t *name = NULL;
3366 	dns_request_t *request = NULL;
3367 	dns_message_t *soaquery = NULL;
3368 	dns_name_t *firstname;
3369 	dns_section_t section = DNS_SECTION_UPDATE;
3370 
3371 	ddebug("start_update()");
3372 
3373 	LOCK(&answer_lock);
3374 	if (answer != NULL) {
3375 		dns_message_detach(&answer);
3376 	}
3377 	UNLOCK(&answer_lock);
3378 
3379 	/*
3380 	 * If we have both the zone and the servers we have enough information
3381 	 * to send the update straight away otherwise we need to discover
3382 	 * the zone and / or the primary server.
3383 	 */
3384 	if (userzone != NULL && !default_servers && !usegsstsig) {
3385 		primary_from_servers();
3386 		send_update(userzone, &primary_servers[primary_inuse]);
3387 		setzoneclass(dns_rdataclass_none);
3388 		return;
3389 	}
3390 
3391 	dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
3392 			   &soaquery);
3393 
3394 	if (default_servers) {
3395 		soaquery->flags |= DNS_MESSAGEFLAG_RD;
3396 	}
3397 
3398 	dns_message_gettempname(soaquery, &name);
3399 
3400 	dns_message_gettemprdataset(soaquery, &rdataset);
3401 
3402 	dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
3403 
3404 	if (userzone != NULL) {
3405 		dns_name_clone(userzone, name);
3406 	} else {
3407 		dns_rdataset_t *tmprdataset;
3408 		result = dns_message_firstname(updatemsg, section);
3409 		if (result == ISC_R_NOMORE) {
3410 			section = DNS_SECTION_PREREQUISITE;
3411 			result = dns_message_firstname(updatemsg, section);
3412 		}
3413 		if (result != ISC_R_SUCCESS) {
3414 			dns_message_puttempname(soaquery, &name);
3415 			dns_rdataset_disassociate(rdataset);
3416 			dns_message_puttemprdataset(soaquery, &rdataset);
3417 			dns_message_detach(&soaquery);
3418 			done_update();
3419 			return;
3420 		}
3421 		firstname = NULL;
3422 		dns_message_currentname(updatemsg, section, &firstname);
3423 		dns_name_clone(firstname, name);
3424 		/*
3425 		 * Looks to see if the first name references a DS record
3426 		 * and if that name is not the root remove a label as DS
3427 		 * records live in the parent zone so we need to start our
3428 		 * search one label up.
3429 		 */
3430 		tmprdataset = ISC_LIST_HEAD(firstname->list);
3431 		if (section == DNS_SECTION_UPDATE &&
3432 		    !dns_name_equal(firstname, dns_rootname) &&
3433 		    tmprdataset->type == dns_rdatatype_ds)
3434 		{
3435 			unsigned int labels = dns_name_countlabels(name);
3436 			dns_name_getlabelsequence(name, 1, labels - 1, name);
3437 		}
3438 	}
3439 
3440 	ISC_LIST_INIT(name->list);
3441 	ISC_LIST_APPEND(name->list, rdataset, link);
3442 	dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
3443 
3444 	ns_inuse = 0;
3445 	sendrequest(&servers[ns_inuse], soaquery, &request);
3446 }
3447 
3448 static void
3449 cleanup(void) {
3450 	ddebug("cleanup()");
3451 
3452 	if (tls_ctx_cache != NULL) {
3453 		isc_tlsctx_cache_detach(&tls_ctx_cache);
3454 	}
3455 
3456 	if (transport_list != NULL) {
3457 		dns_transport_list_detach(&transport_list);
3458 	}
3459 
3460 	LOCK(&answer_lock);
3461 	if (answer != NULL) {
3462 		dns_message_detach(&answer);
3463 	}
3464 	UNLOCK(&answer_lock);
3465 
3466 #if HAVE_GSSAPI
3467 	if (tsigkey != NULL) {
3468 		ddebug("detach tsigkey x%p", tsigkey);
3469 		dns_tsigkey_detach(&tsigkey);
3470 	}
3471 	if (gssring != NULL) {
3472 		ddebug("Detaching GSS-TSIG keyring");
3473 		dns_tsigkeyring_detach(&gssring);
3474 	}
3475 #endif /* ifdef HAVE_GSSAPI */
3476 
3477 	if (sig0key != NULL) {
3478 		dst_key_free(&sig0key);
3479 	}
3480 
3481 #ifdef HAVE_GSSAPI
3482 	if (kserver != NULL) {
3483 		isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t));
3484 		kserver = NULL;
3485 	}
3486 	if (realm != NULL) {
3487 		isc_mem_free(gmctx, realm);
3488 		realm = NULL;
3489 	}
3490 	if (dns_name_dynamic(&tmpzonename)) {
3491 		dns_name_free(&tmpzonename, gmctx);
3492 	}
3493 	if (dns_name_dynamic(&restart_primary)) {
3494 		dns_name_free(&restart_primary, gmctx);
3495 	}
3496 #endif /* ifdef HAVE_GSSAPI */
3497 
3498 	ddebug("Removing log context");
3499 	isc_log_destroy(&glctx);
3500 
3501 	ddebug("Destroying memory context");
3502 	if (memdebugging) {
3503 		isc_mem_stats(gmctx, stderr);
3504 	}
3505 
3506 	isc_mutex_destroy(&answer_lock);
3507 
3508 	if (is_dst_up) {
3509 		ddebug("Destroy DST lib");
3510 		dst_lib_destroy();
3511 		is_dst_up = false;
3512 	}
3513 
3514 	ddebug("Shutting down managers");
3515 	isc_managers_destroy(&gmctx, &loopmgr, &netmgr);
3516 }
3517 
3518 static void
3519 getinput(void *arg) {
3520 	bool more;
3521 
3522 	UNUSED(arg);
3523 
3524 	if (shuttingdown) {
3525 		maybeshutdown();
3526 		return;
3527 	}
3528 
3529 	reset_system();
3530 	isc_loopmgr_blocking(loopmgr);
3531 	more = user_interaction();
3532 	isc_loopmgr_nonblocking(loopmgr);
3533 	if (!more) {
3534 		isc_loopmgr_shutdown(loopmgr);
3535 		return;
3536 	}
3537 
3538 	done = false;
3539 	start_update();
3540 }
3541 
3542 int
3543 main(int argc, char **argv) {
3544 	uint32_t timeoutms;
3545 
3546 	style = &dns_master_style_debug;
3547 
3548 	input = stdin;
3549 
3550 	interactive = isatty(0);
3551 
3552 	if (isc_net_probeipv4() == ISC_R_SUCCESS) {
3553 		have_ipv4 = true;
3554 	}
3555 	if (isc_net_probeipv6() == ISC_R_SUCCESS) {
3556 		have_ipv6 = true;
3557 	}
3558 	if (!have_ipv4 && !have_ipv6) {
3559 		fatal("could not find either IPv4 or IPv6");
3560 	}
3561 
3562 	pre_parse_args(argc, argv);
3563 
3564 	isc_managers_create(&gmctx, 1, &loopmgr, &netmgr);
3565 
3566 	parse_args(argc, argv);
3567 
3568 	/* Set the network manager timeouts in milliseconds. */
3569 	timeoutms = timeout * 1000;
3570 	isc_nm_settimeouts(netmgr, timeoutms, timeoutms, timeoutms, timeoutms);
3571 
3572 	isc_loopmgr_setup(loopmgr, setup_system, NULL);
3573 	isc_loopmgr_setup(loopmgr, getinput, NULL);
3574 	isc_loopmgr_teardown(loopmgr, shutdown_program, NULL);
3575 	isc_loopmgr_run(loopmgr);
3576 
3577 	cleanup();
3578 
3579 	if (seenerror) {
3580 		return 2;
3581 	}
3582 
3583 	return 0;
3584 }
3585