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