1*00b67f09SDavid van Moolenbroek /*	$NetBSD: sample-update.c,v 1.1.1.5 2015/07/08 15:38:07 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2009, 2010, 2012-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek  *
10*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek  */
18*00b67f09SDavid van Moolenbroek 
19*00b67f09SDavid van Moolenbroek /* Id: sample-update.c,v 1.10 2010/12/09 00:54:34 marka Exp  */
20*00b67f09SDavid van Moolenbroek 
21*00b67f09SDavid van Moolenbroek #include <config.h>
22*00b67f09SDavid van Moolenbroek 
23*00b67f09SDavid van Moolenbroek #ifndef WIN32
24*00b67f09SDavid van Moolenbroek #include <sys/types.h>
25*00b67f09SDavid van Moolenbroek #include <sys/socket.h>
26*00b67f09SDavid van Moolenbroek 
27*00b67f09SDavid van Moolenbroek #include <netinet/in.h>
28*00b67f09SDavid van Moolenbroek 
29*00b67f09SDavid van Moolenbroek #include <arpa/inet.h>
30*00b67f09SDavid van Moolenbroek 
31*00b67f09SDavid van Moolenbroek #include <netdb.h>
32*00b67f09SDavid van Moolenbroek #include <unistd.h>
33*00b67f09SDavid van Moolenbroek #endif
34*00b67f09SDavid van Moolenbroek 
35*00b67f09SDavid van Moolenbroek #include <ctype.h>
36*00b67f09SDavid van Moolenbroek #include <stdio.h>
37*00b67f09SDavid van Moolenbroek #include <stdlib.h>
38*00b67f09SDavid van Moolenbroek #include <string.h>
39*00b67f09SDavid van Moolenbroek 
40*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
41*00b67f09SDavid van Moolenbroek #include <isc/commandline.h>
42*00b67f09SDavid van Moolenbroek #include <isc/lex.h>
43*00b67f09SDavid van Moolenbroek #include <isc/lib.h>
44*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
45*00b67f09SDavid van Moolenbroek #include <isc/parseint.h>
46*00b67f09SDavid van Moolenbroek #include <isc/sockaddr.h>
47*00b67f09SDavid van Moolenbroek #include <isc/string.h>
48*00b67f09SDavid van Moolenbroek #include <isc/util.h>
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek #include <dns/callbacks.h>
51*00b67f09SDavid van Moolenbroek #include <dns/client.h>
52*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
53*00b67f09SDavid van Moolenbroek #include <dns/lib.h>
54*00b67f09SDavid van Moolenbroek #include <dns/name.h>
55*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
56*00b67f09SDavid van Moolenbroek #include <dns/rdataclass.h>
57*00b67f09SDavid van Moolenbroek #include <dns/rdatalist.h>
58*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
59*00b67f09SDavid van Moolenbroek #include <dns/rdatastruct.h>
60*00b67f09SDavid van Moolenbroek #include <dns/rdatatype.h>
61*00b67f09SDavid van Moolenbroek #include <dns/result.h>
62*00b67f09SDavid van Moolenbroek #include <dns/secalg.h>
63*00b67f09SDavid van Moolenbroek #include <dns/tsec.h>
64*00b67f09SDavid van Moolenbroek 
65*00b67f09SDavid van Moolenbroek #include <dst/dst.h>
66*00b67f09SDavid van Moolenbroek 
67*00b67f09SDavid van Moolenbroek static dns_tsec_t *tsec = NULL;
68*00b67f09SDavid van Moolenbroek static const dns_rdataclass_t default_rdataclass = dns_rdataclass_in;
69*00b67f09SDavid van Moolenbroek static isc_bufferlist_t usedbuffers;
70*00b67f09SDavid van Moolenbroek static ISC_LIST(dns_rdatalist_t) usedrdatalists;
71*00b67f09SDavid van Moolenbroek 
72*00b67f09SDavid van Moolenbroek static void setup_tsec(char *keyfile, isc_mem_t *mctx);
73*00b67f09SDavid van Moolenbroek static void update_addordelete(isc_mem_t *mctx, char *cmdline,
74*00b67f09SDavid van Moolenbroek 			       isc_boolean_t isdelete, dns_name_t *name);
75*00b67f09SDavid van Moolenbroek static void evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name);
76*00b67f09SDavid van Moolenbroek 
77*00b67f09SDavid van Moolenbroek ISC_PLATFORM_NORETURN_PRE static void
78*00b67f09SDavid van Moolenbroek usage(void) ISC_PLATFORM_NORETURN_POST;
79*00b67f09SDavid van Moolenbroek 
80*00b67f09SDavid van Moolenbroek static void
usage(void)81*00b67f09SDavid van Moolenbroek usage(void) {
82*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "sample-update "
83*00b67f09SDavid van Moolenbroek 		"[-a auth_server] "
84*00b67f09SDavid van Moolenbroek 		"[-k keyfile] "
85*00b67f09SDavid van Moolenbroek 		"[-p prerequisite] "
86*00b67f09SDavid van Moolenbroek 		"[-r recursive_server] "
87*00b67f09SDavid van Moolenbroek 		"[-z zonename] "
88*00b67f09SDavid van Moolenbroek 		"(add|delete) \"name TTL RRtype RDATA\"\n");
89*00b67f09SDavid van Moolenbroek 	exit(1);
90*00b67f09SDavid van Moolenbroek }
91*00b67f09SDavid van Moolenbroek 
92*00b67f09SDavid van Moolenbroek int
main(int argc,char * argv[])93*00b67f09SDavid van Moolenbroek main(int argc, char *argv[]) {
94*00b67f09SDavid van Moolenbroek 	int ch;
95*00b67f09SDavid van Moolenbroek 	struct addrinfo hints, *res;
96*00b67f09SDavid van Moolenbroek 	int gai_error;
97*00b67f09SDavid van Moolenbroek 	dns_client_t *client = NULL;
98*00b67f09SDavid van Moolenbroek 	char *zonenamestr = NULL;
99*00b67f09SDavid van Moolenbroek 	char *keyfilename = NULL;
100*00b67f09SDavid van Moolenbroek 	char *prereqstr = NULL;
101*00b67f09SDavid van Moolenbroek 	isc_sockaddrlist_t auth_servers;
102*00b67f09SDavid van Moolenbroek 	char *auth_server = NULL;
103*00b67f09SDavid van Moolenbroek 	char *recursive_server = NULL;
104*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t sa_auth, sa_recursive;
105*00b67f09SDavid van Moolenbroek 	isc_sockaddrlist_t rec_servers;
106*00b67f09SDavid van Moolenbroek 	isc_result_t result;
107*00b67f09SDavid van Moolenbroek 	isc_boolean_t isdelete;
108*00b67f09SDavid van Moolenbroek 	isc_buffer_t b, *buf;
109*00b67f09SDavid van Moolenbroek 	dns_fixedname_t zname0, pname0, uname0;
110*00b67f09SDavid van Moolenbroek 	unsigned int namelen;
111*00b67f09SDavid van Moolenbroek 	dns_name_t *zname = NULL, *uname, *pname;
112*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset;
113*00b67f09SDavid van Moolenbroek 	dns_rdatalist_t *rdatalist;
114*00b67f09SDavid van Moolenbroek 	dns_rdata_t *rdata;
115*00b67f09SDavid van Moolenbroek 	dns_namelist_t updatelist, prereqlist, *prereqlistp = NULL;
116*00b67f09SDavid van Moolenbroek 	isc_mem_t *umctx = NULL;
117*00b67f09SDavid van Moolenbroek 
118*00b67f09SDavid van Moolenbroek 	while ((ch = isc_commandline_parse(argc, argv, "a:k:p:r:z:")) != EOF) {
119*00b67f09SDavid van Moolenbroek 		switch (ch) {
120*00b67f09SDavid van Moolenbroek 		case 'k':
121*00b67f09SDavid van Moolenbroek 			keyfilename = isc_commandline_argument;
122*00b67f09SDavid van Moolenbroek 			break;
123*00b67f09SDavid van Moolenbroek 		case 'a':
124*00b67f09SDavid van Moolenbroek 			auth_server = isc_commandline_argument;
125*00b67f09SDavid van Moolenbroek 			break;
126*00b67f09SDavid van Moolenbroek 		case 'p':
127*00b67f09SDavid van Moolenbroek 			prereqstr = isc_commandline_argument;
128*00b67f09SDavid van Moolenbroek 			break;
129*00b67f09SDavid van Moolenbroek 		case 'r':
130*00b67f09SDavid van Moolenbroek 			recursive_server = isc_commandline_argument;
131*00b67f09SDavid van Moolenbroek 			break;
132*00b67f09SDavid van Moolenbroek 		case 'z':
133*00b67f09SDavid van Moolenbroek 			zonenamestr = isc_commandline_argument;
134*00b67f09SDavid van Moolenbroek 			break;
135*00b67f09SDavid van Moolenbroek 		default:
136*00b67f09SDavid van Moolenbroek 			usage();
137*00b67f09SDavid van Moolenbroek 		}
138*00b67f09SDavid van Moolenbroek 	}
139*00b67f09SDavid van Moolenbroek 
140*00b67f09SDavid van Moolenbroek 	argc -= isc_commandline_index;
141*00b67f09SDavid van Moolenbroek 	argv += isc_commandline_index;
142*00b67f09SDavid van Moolenbroek 	if (argc < 2)
143*00b67f09SDavid van Moolenbroek 		usage();
144*00b67f09SDavid van Moolenbroek 
145*00b67f09SDavid van Moolenbroek 	/* command line argument validation */
146*00b67f09SDavid van Moolenbroek 	if (strcmp(argv[0], "delete") == 0)
147*00b67f09SDavid van Moolenbroek 		isdelete = ISC_TRUE;
148*00b67f09SDavid van Moolenbroek 	else if (strcmp(argv[0], "add") == 0)
149*00b67f09SDavid van Moolenbroek 		isdelete = ISC_FALSE;
150*00b67f09SDavid van Moolenbroek 	else {
151*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "invalid update command: %s\n", argv[0]);
152*00b67f09SDavid van Moolenbroek 		exit(1);
153*00b67f09SDavid van Moolenbroek 	}
154*00b67f09SDavid van Moolenbroek 
155*00b67f09SDavid van Moolenbroek 	if (auth_server == NULL && recursive_server == NULL) {
156*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "authoritative or recursive server "
157*00b67f09SDavid van Moolenbroek 			"must be specified\n");
158*00b67f09SDavid van Moolenbroek 		usage();
159*00b67f09SDavid van Moolenbroek 	}
160*00b67f09SDavid van Moolenbroek 
161*00b67f09SDavid van Moolenbroek 	/* Initialization */
162*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(usedbuffers);
163*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(usedrdatalists);
164*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(prereqlist);
165*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(auth_servers);
166*00b67f09SDavid van Moolenbroek 	isc_lib_register();
167*00b67f09SDavid van Moolenbroek 	result = dns_lib_init();
168*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
169*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "dns_lib_init failed: %d\n", result);
170*00b67f09SDavid van Moolenbroek 		exit(1);
171*00b67f09SDavid van Moolenbroek 	}
172*00b67f09SDavid van Moolenbroek 	result = isc_mem_create(0, 0, &umctx);
173*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
174*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "failed to crate mctx\n");
175*00b67f09SDavid van Moolenbroek 		exit(1);
176*00b67f09SDavid van Moolenbroek 	}
177*00b67f09SDavid van Moolenbroek 
178*00b67f09SDavid van Moolenbroek 	result = dns_client_create(&client, 0);
179*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
180*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "dns_client_create failed: %d\n", result);
181*00b67f09SDavid van Moolenbroek 		exit(1);
182*00b67f09SDavid van Moolenbroek 	}
183*00b67f09SDavid van Moolenbroek 
184*00b67f09SDavid van Moolenbroek 	/* Set the authoritative server */
185*00b67f09SDavid van Moolenbroek 	if (auth_server != NULL) {
186*00b67f09SDavid van Moolenbroek 		memset(&hints, 0, sizeof(hints));
187*00b67f09SDavid van Moolenbroek 		hints.ai_family = AF_UNSPEC;
188*00b67f09SDavid van Moolenbroek 		hints.ai_socktype = SOCK_DGRAM;
189*00b67f09SDavid van Moolenbroek 		hints.ai_protocol = IPPROTO_UDP;
190*00b67f09SDavid van Moolenbroek #ifdef AI_NUMERICHOST
191*00b67f09SDavid van Moolenbroek 		hints.ai_flags = AI_NUMERICHOST;
192*00b67f09SDavid van Moolenbroek #endif
193*00b67f09SDavid van Moolenbroek 		gai_error = getaddrinfo(auth_server, "53", &hints, &res);
194*00b67f09SDavid van Moolenbroek 		if (gai_error != 0) {
195*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "getaddrinfo failed: %s\n",
196*00b67f09SDavid van Moolenbroek 				gai_strerror(gai_error));
197*00b67f09SDavid van Moolenbroek 			exit(1);
198*00b67f09SDavid van Moolenbroek 		}
199*00b67f09SDavid van Moolenbroek 		INSIST(res->ai_addrlen <= sizeof(sa_auth.type));
200*00b67f09SDavid van Moolenbroek 		memmove(&sa_auth.type, res->ai_addr, res->ai_addrlen);
201*00b67f09SDavid van Moolenbroek 		freeaddrinfo(res);
202*00b67f09SDavid van Moolenbroek 		sa_auth.length = (unsigned int)res->ai_addrlen;
203*00b67f09SDavid van Moolenbroek 		ISC_LINK_INIT(&sa_auth, link);
204*00b67f09SDavid van Moolenbroek 
205*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(auth_servers, &sa_auth, link);
206*00b67f09SDavid van Moolenbroek 	}
207*00b67f09SDavid van Moolenbroek 
208*00b67f09SDavid van Moolenbroek 	/* Set the recursive server */
209*00b67f09SDavid van Moolenbroek 	if (recursive_server != NULL) {
210*00b67f09SDavid van Moolenbroek 		memset(&hints, 0, sizeof(hints));
211*00b67f09SDavid van Moolenbroek 		hints.ai_family = AF_UNSPEC;
212*00b67f09SDavid van Moolenbroek 		hints.ai_socktype = SOCK_DGRAM;
213*00b67f09SDavid van Moolenbroek 		hints.ai_protocol = IPPROTO_UDP;
214*00b67f09SDavid van Moolenbroek #ifdef AI_NUMERICHOST
215*00b67f09SDavid van Moolenbroek 		hints.ai_flags = AI_NUMERICHOST;
216*00b67f09SDavid van Moolenbroek #endif
217*00b67f09SDavid van Moolenbroek 		gai_error = getaddrinfo(recursive_server, "53", &hints, &res);
218*00b67f09SDavid van Moolenbroek 		if (gai_error != 0) {
219*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "getaddrinfo failed: %s\n",
220*00b67f09SDavid van Moolenbroek 				gai_strerror(gai_error));
221*00b67f09SDavid van Moolenbroek 			exit(1);
222*00b67f09SDavid van Moolenbroek 		}
223*00b67f09SDavid van Moolenbroek 		INSIST(res->ai_addrlen <= sizeof(sa_recursive.type));
224*00b67f09SDavid van Moolenbroek 		memmove(&sa_recursive.type, res->ai_addr, res->ai_addrlen);
225*00b67f09SDavid van Moolenbroek 		freeaddrinfo(res);
226*00b67f09SDavid van Moolenbroek 		sa_recursive.length = (unsigned int)res->ai_addrlen;
227*00b67f09SDavid van Moolenbroek 		ISC_LINK_INIT(&sa_recursive, link);
228*00b67f09SDavid van Moolenbroek 		ISC_LIST_INIT(rec_servers);
229*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(rec_servers, &sa_recursive, link);
230*00b67f09SDavid van Moolenbroek 		result = dns_client_setservers(client, dns_rdataclass_in,
231*00b67f09SDavid van Moolenbroek 					       NULL, &rec_servers);
232*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
233*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "set server failed: %d\n", result);
234*00b67f09SDavid van Moolenbroek 			exit(1);
235*00b67f09SDavid van Moolenbroek 		}
236*00b67f09SDavid van Moolenbroek 	}
237*00b67f09SDavid van Moolenbroek 
238*00b67f09SDavid van Moolenbroek 	/* Construct zone name */
239*00b67f09SDavid van Moolenbroek 	zname = NULL;
240*00b67f09SDavid van Moolenbroek 	if (zonenamestr != NULL) {
241*00b67f09SDavid van Moolenbroek 		namelen = strlen(zonenamestr);
242*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&b, zonenamestr, namelen);
243*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&b, namelen);
244*00b67f09SDavid van Moolenbroek 		dns_fixedname_init(&zname0);
245*00b67f09SDavid van Moolenbroek 		zname = dns_fixedname_name(&zname0);
246*00b67f09SDavid van Moolenbroek 		result = dns_name_fromtext(zname, &b, dns_rootname, 0, NULL);
247*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
248*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "failed to convert zone name: %d\n",
249*00b67f09SDavid van Moolenbroek 				result);
250*00b67f09SDavid van Moolenbroek 	}
251*00b67f09SDavid van Moolenbroek 
252*00b67f09SDavid van Moolenbroek 	/* Construct prerequisite name (if given) */
253*00b67f09SDavid van Moolenbroek 	if (prereqstr != NULL) {
254*00b67f09SDavid van Moolenbroek 		dns_fixedname_init(&pname0);
255*00b67f09SDavid van Moolenbroek 		pname = dns_fixedname_name(&pname0);
256*00b67f09SDavid van Moolenbroek 		evaluate_prereq(umctx, prereqstr, pname);
257*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(prereqlist, pname, link);
258*00b67f09SDavid van Moolenbroek 		prereqlistp = &prereqlist;
259*00b67f09SDavid van Moolenbroek 	}
260*00b67f09SDavid van Moolenbroek 
261*00b67f09SDavid van Moolenbroek 	/* Construct update name */
262*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(updatelist);
263*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&uname0);
264*00b67f09SDavid van Moolenbroek 	uname = dns_fixedname_name(&uname0);
265*00b67f09SDavid van Moolenbroek 	update_addordelete(umctx, argv[1], isdelete, uname);
266*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(updatelist, uname, link);
267*00b67f09SDavid van Moolenbroek 
268*00b67f09SDavid van Moolenbroek 	/* Set up TSIG/SIG(0) key (if given) */
269*00b67f09SDavid van Moolenbroek 	if (keyfilename != NULL)
270*00b67f09SDavid van Moolenbroek 		setup_tsec(keyfilename, umctx);
271*00b67f09SDavid van Moolenbroek 
272*00b67f09SDavid van Moolenbroek 	/* Perform update */
273*00b67f09SDavid van Moolenbroek 	result = dns_client_update(client,
274*00b67f09SDavid van Moolenbroek 				   default_rdataclass, /* XXX: fixed */
275*00b67f09SDavid van Moolenbroek 				   zname, prereqlistp, &updatelist,
276*00b67f09SDavid van Moolenbroek 				   (auth_server == NULL) ? NULL :
277*00b67f09SDavid van Moolenbroek 				   &auth_servers, tsec, 0);
278*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
279*00b67f09SDavid van Moolenbroek 		fprintf(stderr,
280*00b67f09SDavid van Moolenbroek 			"update failed: %s\n", dns_result_totext(result));
281*00b67f09SDavid van Moolenbroek 	} else
282*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "update succeeded\n");
283*00b67f09SDavid van Moolenbroek 
284*00b67f09SDavid van Moolenbroek 	/* Cleanup */
285*00b67f09SDavid van Moolenbroek 	while ((pname = ISC_LIST_HEAD(prereqlist)) != NULL) {
286*00b67f09SDavid van Moolenbroek 		while ((rdataset = ISC_LIST_HEAD(pname->list)) != NULL) {
287*00b67f09SDavid van Moolenbroek 			ISC_LIST_UNLINK(pname->list, rdataset, link);
288*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
289*00b67f09SDavid van Moolenbroek 			isc_mem_put(umctx, rdataset, sizeof(*rdataset));
290*00b67f09SDavid van Moolenbroek 		}
291*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(prereqlist, pname, link);
292*00b67f09SDavid van Moolenbroek 	}
293*00b67f09SDavid van Moolenbroek 	while ((uname = ISC_LIST_HEAD(updatelist)) != NULL) {
294*00b67f09SDavid van Moolenbroek 		while ((rdataset = ISC_LIST_HEAD(uname->list)) != NULL) {
295*00b67f09SDavid van Moolenbroek 			ISC_LIST_UNLINK(uname->list, rdataset, link);
296*00b67f09SDavid van Moolenbroek 			dns_rdataset_disassociate(rdataset);
297*00b67f09SDavid van Moolenbroek 			isc_mem_put(umctx, rdataset, sizeof(*rdataset));
298*00b67f09SDavid van Moolenbroek 		}
299*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(updatelist, uname, link);
300*00b67f09SDavid van Moolenbroek 	}
301*00b67f09SDavid van Moolenbroek 	while ((rdatalist = ISC_LIST_HEAD(usedrdatalists)) != NULL) {
302*00b67f09SDavid van Moolenbroek 		while ((rdata = ISC_LIST_HEAD(rdatalist->rdata)) != NULL) {
303*00b67f09SDavid van Moolenbroek 			ISC_LIST_UNLINK(rdatalist->rdata, rdata, link);
304*00b67f09SDavid van Moolenbroek 			isc_mem_put(umctx, rdata, sizeof(*rdata));
305*00b67f09SDavid van Moolenbroek 		}
306*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(usedrdatalists, rdatalist, link);
307*00b67f09SDavid van Moolenbroek 		isc_mem_put(umctx, rdatalist, sizeof(*rdatalist));
308*00b67f09SDavid van Moolenbroek 	}
309*00b67f09SDavid van Moolenbroek 	while ((buf = ISC_LIST_HEAD(usedbuffers)) != NULL) {
310*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(usedbuffers, buf, link);
311*00b67f09SDavid van Moolenbroek 		isc_buffer_free(&buf);
312*00b67f09SDavid van Moolenbroek 	}
313*00b67f09SDavid van Moolenbroek 	if (tsec != NULL)
314*00b67f09SDavid van Moolenbroek 		dns_tsec_destroy(&tsec);
315*00b67f09SDavid van Moolenbroek 	isc_mem_destroy(&umctx);
316*00b67f09SDavid van Moolenbroek 	dns_client_destroy(&client);
317*00b67f09SDavid van Moolenbroek 	dns_lib_shutdown();
318*00b67f09SDavid van Moolenbroek 
319*00b67f09SDavid van Moolenbroek 	return (0);
320*00b67f09SDavid van Moolenbroek }
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek /*
323*00b67f09SDavid van Moolenbroek  *  Subroutines borrowed from nsupdate.c
324*00b67f09SDavid van Moolenbroek  */
325*00b67f09SDavid van Moolenbroek #define MAXWIRE (64 * 1024)
326*00b67f09SDavid van Moolenbroek #define TTL_MAX 2147483647U	/* Maximum signed 32 bit integer. */
327*00b67f09SDavid van Moolenbroek 
328*00b67f09SDavid van Moolenbroek static char *
nsu_strsep(char ** stringp,const char * delim)329*00b67f09SDavid van Moolenbroek nsu_strsep(char **stringp, const char *delim) {
330*00b67f09SDavid van Moolenbroek 	char *string = *stringp;
331*00b67f09SDavid van Moolenbroek 	char *s;
332*00b67f09SDavid van Moolenbroek 	const char *d;
333*00b67f09SDavid van Moolenbroek 	char sc, dc;
334*00b67f09SDavid van Moolenbroek 
335*00b67f09SDavid van Moolenbroek 	if (string == NULL)
336*00b67f09SDavid van Moolenbroek 		return (NULL);
337*00b67f09SDavid van Moolenbroek 
338*00b67f09SDavid van Moolenbroek 	for (; *string != '\0'; string++) {
339*00b67f09SDavid van Moolenbroek 		sc = *string;
340*00b67f09SDavid van Moolenbroek 		for (d = delim; (dc = *d) != '\0'; d++) {
341*00b67f09SDavid van Moolenbroek 			if (sc == dc)
342*00b67f09SDavid van Moolenbroek 				break;
343*00b67f09SDavid van Moolenbroek 		}
344*00b67f09SDavid van Moolenbroek 		if (dc == 0)
345*00b67f09SDavid van Moolenbroek 			break;
346*00b67f09SDavid van Moolenbroek 	}
347*00b67f09SDavid van Moolenbroek 
348*00b67f09SDavid van Moolenbroek 	for (s = string; *s != '\0'; s++) {
349*00b67f09SDavid van Moolenbroek 		sc = *s;
350*00b67f09SDavid van Moolenbroek 		for (d = delim; (dc = *d) != '\0'; d++) {
351*00b67f09SDavid van Moolenbroek 			if (sc == dc) {
352*00b67f09SDavid van Moolenbroek 				*s++ = '\0';
353*00b67f09SDavid van Moolenbroek 				*stringp = s;
354*00b67f09SDavid van Moolenbroek 				return (string);
355*00b67f09SDavid van Moolenbroek 			}
356*00b67f09SDavid van Moolenbroek 		}
357*00b67f09SDavid van Moolenbroek 	}
358*00b67f09SDavid van Moolenbroek 	*stringp = NULL;
359*00b67f09SDavid van Moolenbroek 	return (string);
360*00b67f09SDavid van Moolenbroek }
361*00b67f09SDavid van Moolenbroek 
362*00b67f09SDavid van Moolenbroek static void
fatal(const char * format,...)363*00b67f09SDavid van Moolenbroek fatal(const char *format, ...) {
364*00b67f09SDavid van Moolenbroek 	va_list args;
365*00b67f09SDavid van Moolenbroek 
366*00b67f09SDavid van Moolenbroek 	va_start(args, format);
367*00b67f09SDavid van Moolenbroek 	vfprintf(stderr, format, args);
368*00b67f09SDavid van Moolenbroek 	va_end(args);
369*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "\n");
370*00b67f09SDavid van Moolenbroek 	exit(1);
371*00b67f09SDavid van Moolenbroek }
372*00b67f09SDavid van Moolenbroek 
373*00b67f09SDavid van Moolenbroek static inline void
check_result(isc_result_t result,const char * msg)374*00b67f09SDavid van Moolenbroek check_result(isc_result_t result, const char *msg) {
375*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
376*00b67f09SDavid van Moolenbroek 		fatal("%s: %s", msg, isc_result_totext(result));
377*00b67f09SDavid van Moolenbroek }
378*00b67f09SDavid van Moolenbroek 
379*00b67f09SDavid van Moolenbroek static void
parse_name(char ** cmdlinep,dns_name_t * name)380*00b67f09SDavid van Moolenbroek parse_name(char **cmdlinep, dns_name_t *name) {
381*00b67f09SDavid van Moolenbroek 	isc_result_t result;
382*00b67f09SDavid van Moolenbroek 	char *word;
383*00b67f09SDavid van Moolenbroek 	isc_buffer_t source;
384*00b67f09SDavid van Moolenbroek 
385*00b67f09SDavid van Moolenbroek 	word = nsu_strsep(cmdlinep, " \t\r\n");
386*00b67f09SDavid van Moolenbroek 	if (word == NULL || *word == 0) {
387*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "could not read owner name\n");
388*00b67f09SDavid van Moolenbroek 		exit(1);
389*00b67f09SDavid van Moolenbroek 	}
390*00b67f09SDavid van Moolenbroek 
391*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&source, word, strlen(word));
392*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&source, strlen(word));
393*00b67f09SDavid van Moolenbroek 	result = dns_name_fromtext(name, &source, dns_rootname, 0, NULL);
394*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_name_fromtext");
395*00b67f09SDavid van Moolenbroek 	isc_buffer_invalidate(&source);
396*00b67f09SDavid van Moolenbroek }
397*00b67f09SDavid van Moolenbroek 
398*00b67f09SDavid van Moolenbroek static void
parse_rdata(isc_mem_t * mctx,char ** cmdlinep,dns_rdataclass_t rdataclass,dns_rdatatype_t rdatatype,dns_rdata_t * rdata)399*00b67f09SDavid van Moolenbroek parse_rdata(isc_mem_t *mctx, char **cmdlinep, dns_rdataclass_t rdataclass,
400*00b67f09SDavid van Moolenbroek 	    dns_rdatatype_t rdatatype, dns_rdata_t *rdata)
401*00b67f09SDavid van Moolenbroek {
402*00b67f09SDavid van Moolenbroek 	char *cmdline = *cmdlinep;
403*00b67f09SDavid van Moolenbroek 	isc_buffer_t source, *buf = NULL, *newbuf = NULL;
404*00b67f09SDavid van Moolenbroek 	isc_region_t r;
405*00b67f09SDavid van Moolenbroek 	isc_lex_t *lex = NULL;
406*00b67f09SDavid van Moolenbroek 	dns_rdatacallbacks_t callbacks;
407*00b67f09SDavid van Moolenbroek 	isc_result_t result;
408*00b67f09SDavid van Moolenbroek 
409*00b67f09SDavid van Moolenbroek 	while (cmdline != NULL && *cmdline != 0 &&
410*00b67f09SDavid van Moolenbroek 	       isspace((unsigned char)*cmdline))
411*00b67f09SDavid van Moolenbroek 		cmdline++;
412*00b67f09SDavid van Moolenbroek 
413*00b67f09SDavid van Moolenbroek 	if (cmdline != NULL && *cmdline != 0) {
414*00b67f09SDavid van Moolenbroek 		dns_rdatacallbacks_init(&callbacks);
415*00b67f09SDavid van Moolenbroek 		result = isc_lex_create(mctx, strlen(cmdline), &lex);
416*00b67f09SDavid van Moolenbroek 		check_result(result, "isc_lex_create");
417*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&source, cmdline, strlen(cmdline));
418*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&source, strlen(cmdline));
419*00b67f09SDavid van Moolenbroek 		result = isc_lex_openbuffer(lex, &source);
420*00b67f09SDavid van Moolenbroek 		check_result(result, "isc_lex_openbuffer");
421*00b67f09SDavid van Moolenbroek 		result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
422*00b67f09SDavid van Moolenbroek 		check_result(result, "isc_buffer_allocate");
423*00b67f09SDavid van Moolenbroek 		result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex,
424*00b67f09SDavid van Moolenbroek 					    dns_rootname, 0, mctx, buf,
425*00b67f09SDavid van Moolenbroek 					    &callbacks);
426*00b67f09SDavid van Moolenbroek 		isc_lex_destroy(&lex);
427*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
428*00b67f09SDavid van Moolenbroek 			isc_buffer_usedregion(buf, &r);
429*00b67f09SDavid van Moolenbroek 			result = isc_buffer_allocate(mctx, &newbuf, r.length);
430*00b67f09SDavid van Moolenbroek 			check_result(result, "isc_buffer_allocate");
431*00b67f09SDavid van Moolenbroek 			isc_buffer_putmem(newbuf, r.base, r.length);
432*00b67f09SDavid van Moolenbroek 			isc_buffer_usedregion(newbuf, &r);
433*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(rdata);
434*00b67f09SDavid van Moolenbroek 			dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
435*00b67f09SDavid van Moolenbroek 			isc_buffer_free(&buf);
436*00b67f09SDavid van Moolenbroek 			ISC_LIST_APPEND(usedbuffers, newbuf, link);
437*00b67f09SDavid van Moolenbroek 		} else {
438*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "invalid rdata format: %s\n",
439*00b67f09SDavid van Moolenbroek 				isc_result_totext(result));
440*00b67f09SDavid van Moolenbroek 			isc_buffer_free(&buf);
441*00b67f09SDavid van Moolenbroek 			exit(1);
442*00b67f09SDavid van Moolenbroek 		}
443*00b67f09SDavid van Moolenbroek 	} else {
444*00b67f09SDavid van Moolenbroek 		rdata->flags = DNS_RDATA_UPDATE;
445*00b67f09SDavid van Moolenbroek 	}
446*00b67f09SDavid van Moolenbroek 	*cmdlinep = cmdline;
447*00b67f09SDavid van Moolenbroek }
448*00b67f09SDavid van Moolenbroek 
449*00b67f09SDavid van Moolenbroek static void
update_addordelete(isc_mem_t * mctx,char * cmdline,isc_boolean_t isdelete,dns_name_t * name)450*00b67f09SDavid van Moolenbroek update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete,
451*00b67f09SDavid van Moolenbroek 		   dns_name_t *name)
452*00b67f09SDavid van Moolenbroek {
453*00b67f09SDavid van Moolenbroek 	isc_result_t result;
454*00b67f09SDavid van Moolenbroek 	isc_uint32_t ttl;
455*00b67f09SDavid van Moolenbroek 	char *word;
456*00b67f09SDavid van Moolenbroek 	dns_rdataclass_t rdataclass;
457*00b67f09SDavid van Moolenbroek 	dns_rdatatype_t rdatatype;
458*00b67f09SDavid van Moolenbroek 	dns_rdata_t *rdata = NULL;
459*00b67f09SDavid van Moolenbroek 	dns_rdatalist_t *rdatalist = NULL;
460*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset = NULL;
461*00b67f09SDavid van Moolenbroek 	isc_textregion_t region;
462*00b67f09SDavid van Moolenbroek 
463*00b67f09SDavid van Moolenbroek 	/*
464*00b67f09SDavid van Moolenbroek 	 * Read the owner name.
465*00b67f09SDavid van Moolenbroek 	 */
466*00b67f09SDavid van Moolenbroek 	parse_name(&cmdline, name);
467*00b67f09SDavid van Moolenbroek 
468*00b67f09SDavid van Moolenbroek 	rdata = isc_mem_get(mctx, sizeof(*rdata));
469*00b67f09SDavid van Moolenbroek 	if (rdata == NULL) {
470*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "memory allocation for rdata failed\n");
471*00b67f09SDavid van Moolenbroek 		exit(1);
472*00b67f09SDavid van Moolenbroek 	}
473*00b67f09SDavid van Moolenbroek 	dns_rdata_init(rdata);
474*00b67f09SDavid van Moolenbroek 
475*00b67f09SDavid van Moolenbroek 	/*
476*00b67f09SDavid van Moolenbroek 	 * If this is an add, read the TTL and verify that it's in range.
477*00b67f09SDavid van Moolenbroek 	 * If it's a delete, ignore a TTL if present (for compatibility).
478*00b67f09SDavid van Moolenbroek 	 */
479*00b67f09SDavid van Moolenbroek 	word = nsu_strsep(&cmdline, " \t\r\n");
480*00b67f09SDavid van Moolenbroek 	if (word == NULL || *word == 0) {
481*00b67f09SDavid van Moolenbroek 		if (!isdelete) {
482*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "could not read owner ttl\n");
483*00b67f09SDavid van Moolenbroek 			exit(1);
484*00b67f09SDavid van Moolenbroek 		}
485*00b67f09SDavid van Moolenbroek 		else {
486*00b67f09SDavid van Moolenbroek 			ttl = 0;
487*00b67f09SDavid van Moolenbroek 			rdataclass = dns_rdataclass_any;
488*00b67f09SDavid van Moolenbroek 			rdatatype = dns_rdatatype_any;
489*00b67f09SDavid van Moolenbroek 			rdata->flags = DNS_RDATA_UPDATE;
490*00b67f09SDavid van Moolenbroek 			goto doneparsing;
491*00b67f09SDavid van Moolenbroek 		}
492*00b67f09SDavid van Moolenbroek 	}
493*00b67f09SDavid van Moolenbroek 	result = isc_parse_uint32(&ttl, word, 10);
494*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
495*00b67f09SDavid van Moolenbroek 		if (isdelete) {
496*00b67f09SDavid van Moolenbroek 			ttl = 0;
497*00b67f09SDavid van Moolenbroek 			goto parseclass;
498*00b67f09SDavid van Moolenbroek 		} else {
499*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "ttl '%s': %s\n", word,
500*00b67f09SDavid van Moolenbroek 				isc_result_totext(result));
501*00b67f09SDavid van Moolenbroek 			exit(1);
502*00b67f09SDavid van Moolenbroek 		}
503*00b67f09SDavid van Moolenbroek 	}
504*00b67f09SDavid van Moolenbroek 
505*00b67f09SDavid van Moolenbroek 	if (isdelete)
506*00b67f09SDavid van Moolenbroek 		ttl = 0;
507*00b67f09SDavid van Moolenbroek 	else if (ttl > TTL_MAX) {
508*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
509*00b67f09SDavid van Moolenbroek 			word, TTL_MAX);
510*00b67f09SDavid van Moolenbroek 		exit(1);
511*00b67f09SDavid van Moolenbroek 	}
512*00b67f09SDavid van Moolenbroek 
513*00b67f09SDavid van Moolenbroek 	/*
514*00b67f09SDavid van Moolenbroek 	 * Read the class or type.
515*00b67f09SDavid van Moolenbroek 	 */
516*00b67f09SDavid van Moolenbroek 	word = nsu_strsep(&cmdline, " \t\r\n");
517*00b67f09SDavid van Moolenbroek  parseclass:
518*00b67f09SDavid van Moolenbroek 	if (word == NULL || *word == 0) {
519*00b67f09SDavid van Moolenbroek 		if (isdelete) {
520*00b67f09SDavid van Moolenbroek 			rdataclass = dns_rdataclass_any;
521*00b67f09SDavid van Moolenbroek 			rdatatype = dns_rdatatype_any;
522*00b67f09SDavid van Moolenbroek 			rdata->flags = DNS_RDATA_UPDATE;
523*00b67f09SDavid van Moolenbroek 		goto doneparsing;
524*00b67f09SDavid van Moolenbroek 		} else {
525*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "could not read class or type\n");
526*00b67f09SDavid van Moolenbroek 			exit(1);
527*00b67f09SDavid van Moolenbroek 		}
528*00b67f09SDavid van Moolenbroek 	}
529*00b67f09SDavid van Moolenbroek 	region.base = word;
530*00b67f09SDavid van Moolenbroek 	region.length = strlen(word);
531*00b67f09SDavid van Moolenbroek 	result = dns_rdataclass_fromtext(&rdataclass, &region);
532*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
533*00b67f09SDavid van Moolenbroek 		/*
534*00b67f09SDavid van Moolenbroek 		 * Now read the type.
535*00b67f09SDavid van Moolenbroek 		 */
536*00b67f09SDavid van Moolenbroek 		word = nsu_strsep(&cmdline, " \t\r\n");
537*00b67f09SDavid van Moolenbroek 		if (word == NULL || *word == 0) {
538*00b67f09SDavid van Moolenbroek 			if (isdelete) {
539*00b67f09SDavid van Moolenbroek 				rdataclass = dns_rdataclass_any;
540*00b67f09SDavid van Moolenbroek 				rdatatype = dns_rdatatype_any;
541*00b67f09SDavid van Moolenbroek 				rdata->flags = DNS_RDATA_UPDATE;
542*00b67f09SDavid van Moolenbroek 				goto doneparsing;
543*00b67f09SDavid van Moolenbroek 			} else {
544*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "could not read type\n");
545*00b67f09SDavid van Moolenbroek 				exit(1);
546*00b67f09SDavid van Moolenbroek 			}
547*00b67f09SDavid van Moolenbroek 		}
548*00b67f09SDavid van Moolenbroek 		region.base = word;
549*00b67f09SDavid van Moolenbroek 		region.length = strlen(word);
550*00b67f09SDavid van Moolenbroek 		result = dns_rdatatype_fromtext(&rdatatype, &region);
551*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
552*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "'%s' is not a valid type: %s\n",
553*00b67f09SDavid van Moolenbroek 				word, isc_result_totext(result));
554*00b67f09SDavid van Moolenbroek 			exit(1);
555*00b67f09SDavid van Moolenbroek 		}
556*00b67f09SDavid van Moolenbroek 	} else {
557*00b67f09SDavid van Moolenbroek 		rdataclass = default_rdataclass;
558*00b67f09SDavid van Moolenbroek 		result = dns_rdatatype_fromtext(&rdatatype, &region);
559*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
560*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "'%s' is not a valid class or type: "
561*00b67f09SDavid van Moolenbroek 				"%s\n", word, isc_result_totext(result));
562*00b67f09SDavid van Moolenbroek 			exit(1);
563*00b67f09SDavid van Moolenbroek 		}
564*00b67f09SDavid van Moolenbroek 	}
565*00b67f09SDavid van Moolenbroek 
566*00b67f09SDavid van Moolenbroek 	parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);
567*00b67f09SDavid van Moolenbroek 
568*00b67f09SDavid van Moolenbroek 	if (isdelete) {
569*00b67f09SDavid van Moolenbroek 		if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
570*00b67f09SDavid van Moolenbroek 			rdataclass = dns_rdataclass_any;
571*00b67f09SDavid van Moolenbroek 		else
572*00b67f09SDavid van Moolenbroek 			rdataclass = dns_rdataclass_none;
573*00b67f09SDavid van Moolenbroek 	} else {
574*00b67f09SDavid van Moolenbroek 		if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
575*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "could not read rdata\n");
576*00b67f09SDavid van Moolenbroek 			exit(1);
577*00b67f09SDavid van Moolenbroek 		}
578*00b67f09SDavid van Moolenbroek 	}
579*00b67f09SDavid van Moolenbroek 
580*00b67f09SDavid van Moolenbroek  doneparsing:
581*00b67f09SDavid van Moolenbroek 
582*00b67f09SDavid van Moolenbroek 	rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
583*00b67f09SDavid van Moolenbroek 	if (rdatalist == NULL) {
584*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "memory allocation for rdatalist failed\n");
585*00b67f09SDavid van Moolenbroek 		exit(1);
586*00b67f09SDavid van Moolenbroek 	}
587*00b67f09SDavid van Moolenbroek 	dns_rdatalist_init(rdatalist);
588*00b67f09SDavid van Moolenbroek 	rdatalist->type = rdatatype;
589*00b67f09SDavid van Moolenbroek 	rdatalist->rdclass = rdataclass;
590*00b67f09SDavid van Moolenbroek 	rdatalist->covers = rdatatype;
591*00b67f09SDavid van Moolenbroek 	rdatalist->ttl = (dns_ttl_t)ttl;
592*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(rdatalist->rdata);
593*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
594*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(usedrdatalists, rdatalist, link);
595*00b67f09SDavid van Moolenbroek 
596*00b67f09SDavid van Moolenbroek 	rdataset = isc_mem_get(mctx, sizeof(*rdataset));
597*00b67f09SDavid van Moolenbroek 	if (rdataset == NULL) {
598*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "memory allocation for rdataset failed\n");
599*00b67f09SDavid van Moolenbroek 		exit(1);
600*00b67f09SDavid van Moolenbroek 	}
601*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(rdataset);
602*00b67f09SDavid van Moolenbroek 	dns_rdatalist_tordataset(rdatalist, rdataset);
603*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(name->list);
604*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(name->list, rdataset, link);
605*00b67f09SDavid van Moolenbroek }
606*00b67f09SDavid van Moolenbroek 
607*00b67f09SDavid van Moolenbroek static void
make_prereq(isc_mem_t * mctx,char * cmdline,isc_boolean_t ispositive,isc_boolean_t isrrset,dns_name_t * name)608*00b67f09SDavid van Moolenbroek make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive,
609*00b67f09SDavid van Moolenbroek 	    isc_boolean_t isrrset, dns_name_t *name)
610*00b67f09SDavid van Moolenbroek {
611*00b67f09SDavid van Moolenbroek 	isc_result_t result;
612*00b67f09SDavid van Moolenbroek 	char *word;
613*00b67f09SDavid van Moolenbroek 	isc_textregion_t region;
614*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset = NULL;
615*00b67f09SDavid van Moolenbroek 	dns_rdatalist_t *rdatalist = NULL;
616*00b67f09SDavid van Moolenbroek 	dns_rdataclass_t rdataclass;
617*00b67f09SDavid van Moolenbroek 	dns_rdatatype_t rdatatype;
618*00b67f09SDavid van Moolenbroek 	dns_rdata_t *rdata = NULL;
619*00b67f09SDavid van Moolenbroek 
620*00b67f09SDavid van Moolenbroek 	/*
621*00b67f09SDavid van Moolenbroek 	 * Read the owner name
622*00b67f09SDavid van Moolenbroek 	 */
623*00b67f09SDavid van Moolenbroek 	parse_name(&cmdline, name);
624*00b67f09SDavid van Moolenbroek 
625*00b67f09SDavid van Moolenbroek 	/*
626*00b67f09SDavid van Moolenbroek 	 * If this is an rrset prereq, read the class or type.
627*00b67f09SDavid van Moolenbroek 	 */
628*00b67f09SDavid van Moolenbroek 	if (isrrset) {
629*00b67f09SDavid van Moolenbroek 		word = nsu_strsep(&cmdline, " \t\r\n");
630*00b67f09SDavid van Moolenbroek 		if (word == NULL || *word == 0) {
631*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "could not read class or type\n");
632*00b67f09SDavid van Moolenbroek 			exit(1);
633*00b67f09SDavid van Moolenbroek 		}
634*00b67f09SDavid van Moolenbroek 		region.base = word;
635*00b67f09SDavid van Moolenbroek 		region.length = strlen(word);
636*00b67f09SDavid van Moolenbroek 		result = dns_rdataclass_fromtext(&rdataclass, &region);
637*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
638*00b67f09SDavid van Moolenbroek 			/*
639*00b67f09SDavid van Moolenbroek 			 * Now read the type.
640*00b67f09SDavid van Moolenbroek 			 */
641*00b67f09SDavid van Moolenbroek 			word = nsu_strsep(&cmdline, " \t\r\n");
642*00b67f09SDavid van Moolenbroek 			if (word == NULL || *word == 0) {
643*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "could not read type\n");
644*00b67f09SDavid van Moolenbroek 				exit(1);
645*00b67f09SDavid van Moolenbroek 			}
646*00b67f09SDavid van Moolenbroek 			region.base = word;
647*00b67f09SDavid van Moolenbroek 			region.length = strlen(word);
648*00b67f09SDavid van Moolenbroek 			result = dns_rdatatype_fromtext(&rdatatype, &region);
649*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS) {
650*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid type: %s\n", word);
651*00b67f09SDavid van Moolenbroek 				exit(1);
652*00b67f09SDavid van Moolenbroek 			}
653*00b67f09SDavid van Moolenbroek 		} else {
654*00b67f09SDavid van Moolenbroek 			rdataclass = default_rdataclass;
655*00b67f09SDavid van Moolenbroek 			result = dns_rdatatype_fromtext(&rdatatype, &region);
656*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS) {
657*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid type: %s\n", word);
658*00b67f09SDavid van Moolenbroek 				exit(1);
659*00b67f09SDavid van Moolenbroek 			}
660*00b67f09SDavid van Moolenbroek 		}
661*00b67f09SDavid van Moolenbroek 	} else
662*00b67f09SDavid van Moolenbroek 		rdatatype = dns_rdatatype_any;
663*00b67f09SDavid van Moolenbroek 
664*00b67f09SDavid van Moolenbroek 	rdata = isc_mem_get(mctx, sizeof(*rdata));
665*00b67f09SDavid van Moolenbroek 	if (rdata == NULL) {
666*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "memory allocation for rdata failed\n");
667*00b67f09SDavid van Moolenbroek 		exit(1);
668*00b67f09SDavid van Moolenbroek 	}
669*00b67f09SDavid van Moolenbroek 	dns_rdata_init(rdata);
670*00b67f09SDavid van Moolenbroek 
671*00b67f09SDavid van Moolenbroek 	if (isrrset && ispositive)
672*00b67f09SDavid van Moolenbroek 		parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);
673*00b67f09SDavid van Moolenbroek 	else
674*00b67f09SDavid van Moolenbroek 		rdata->flags = DNS_RDATA_UPDATE;
675*00b67f09SDavid van Moolenbroek 
676*00b67f09SDavid van Moolenbroek 	rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
677*00b67f09SDavid van Moolenbroek 	if (rdatalist == NULL) {
678*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "memory allocation for rdatalist failed\n");
679*00b67f09SDavid van Moolenbroek 		exit(1);
680*00b67f09SDavid van Moolenbroek 	}
681*00b67f09SDavid van Moolenbroek 	dns_rdatalist_init(rdatalist);
682*00b67f09SDavid van Moolenbroek 	rdatalist->type = rdatatype;
683*00b67f09SDavid van Moolenbroek 	if (ispositive) {
684*00b67f09SDavid van Moolenbroek 		if (isrrset && rdata->data != NULL)
685*00b67f09SDavid van Moolenbroek 			rdatalist->rdclass = rdataclass;
686*00b67f09SDavid van Moolenbroek 		else
687*00b67f09SDavid van Moolenbroek 			rdatalist->rdclass = dns_rdataclass_any;
688*00b67f09SDavid van Moolenbroek 	} else
689*00b67f09SDavid van Moolenbroek 		rdatalist->rdclass = dns_rdataclass_none;
690*00b67f09SDavid van Moolenbroek 	rdatalist->covers = 0;
691*00b67f09SDavid van Moolenbroek 	rdatalist->ttl = 0;
692*00b67f09SDavid van Moolenbroek 	rdata->rdclass = rdatalist->rdclass;
693*00b67f09SDavid van Moolenbroek 	rdata->type = rdatatype;
694*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(rdatalist->rdata);
695*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
696*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(usedrdatalists, rdatalist, link);
697*00b67f09SDavid van Moolenbroek 
698*00b67f09SDavid van Moolenbroek 	rdataset = isc_mem_get(mctx, sizeof(*rdataset));
699*00b67f09SDavid van Moolenbroek 	if (rdataset == NULL) {
700*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "memory allocation for rdataset failed\n");
701*00b67f09SDavid van Moolenbroek 		exit(1);
702*00b67f09SDavid van Moolenbroek 	}
703*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(rdataset);
704*00b67f09SDavid van Moolenbroek 	dns_rdatalist_tordataset(rdatalist, rdataset);
705*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(name->list);
706*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(name->list, rdataset, link);
707*00b67f09SDavid van Moolenbroek }
708*00b67f09SDavid van Moolenbroek 
709*00b67f09SDavid van Moolenbroek static void
evaluate_prereq(isc_mem_t * mctx,char * cmdline,dns_name_t * name)710*00b67f09SDavid van Moolenbroek evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name) {
711*00b67f09SDavid van Moolenbroek 	char *word;
712*00b67f09SDavid van Moolenbroek 	isc_boolean_t ispositive, isrrset;
713*00b67f09SDavid van Moolenbroek 
714*00b67f09SDavid van Moolenbroek 	word = nsu_strsep(&cmdline, " \t\r\n");
715*00b67f09SDavid van Moolenbroek 	if (word == NULL || *word == 0) {
716*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "could not read operation code\n");
717*00b67f09SDavid van Moolenbroek 		exit(1);
718*00b67f09SDavid van Moolenbroek 	}
719*00b67f09SDavid van Moolenbroek 	if (strcasecmp(word, "nxdomain") == 0) {
720*00b67f09SDavid van Moolenbroek 		ispositive = ISC_FALSE;
721*00b67f09SDavid van Moolenbroek 		isrrset = ISC_FALSE;
722*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(word, "yxdomain") == 0) {
723*00b67f09SDavid van Moolenbroek 		ispositive = ISC_TRUE;
724*00b67f09SDavid van Moolenbroek 		isrrset = ISC_FALSE;
725*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(word, "nxrrset") == 0) {
726*00b67f09SDavid van Moolenbroek 		ispositive = ISC_FALSE;
727*00b67f09SDavid van Moolenbroek 		isrrset = ISC_TRUE;
728*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(word, "yxrrset") == 0) {
729*00b67f09SDavid van Moolenbroek 		ispositive = ISC_TRUE;
730*00b67f09SDavid van Moolenbroek 		isrrset = ISC_TRUE;
731*00b67f09SDavid van Moolenbroek 	} else {
732*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "incorrect operation code: %s\n", word);
733*00b67f09SDavid van Moolenbroek 		exit(1);
734*00b67f09SDavid van Moolenbroek 	}
735*00b67f09SDavid van Moolenbroek 
736*00b67f09SDavid van Moolenbroek 	make_prereq(mctx, cmdline, ispositive, isrrset, name);
737*00b67f09SDavid van Moolenbroek }
738*00b67f09SDavid van Moolenbroek 
739*00b67f09SDavid van Moolenbroek static void
setup_tsec(char * keyfile,isc_mem_t * mctx)740*00b67f09SDavid van Moolenbroek setup_tsec(char *keyfile, isc_mem_t *mctx) {
741*00b67f09SDavid van Moolenbroek 	dst_key_t *dstkey = NULL;
742*00b67f09SDavid van Moolenbroek 	isc_result_t result;
743*00b67f09SDavid van Moolenbroek 	dns_tsectype_t tsectype;
744*00b67f09SDavid van Moolenbroek 
745*00b67f09SDavid van Moolenbroek 	result = dst_key_fromnamedfile(keyfile, NULL,
746*00b67f09SDavid van Moolenbroek 				       DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
747*00b67f09SDavid van Moolenbroek 				       &dstkey);
748*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
749*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "could not read key from %s: %s\n",
750*00b67f09SDavid van Moolenbroek 			keyfile, isc_result_totext(result));
751*00b67f09SDavid van Moolenbroek 		exit(1);
752*00b67f09SDavid van Moolenbroek 	}
753*00b67f09SDavid van Moolenbroek 
754*00b67f09SDavid van Moolenbroek 	if (dst_key_alg(dstkey) == DST_ALG_HMACMD5)
755*00b67f09SDavid van Moolenbroek 		tsectype = dns_tsectype_tsig;
756*00b67f09SDavid van Moolenbroek 	else
757*00b67f09SDavid van Moolenbroek 		tsectype = dns_tsectype_sig0;
758*00b67f09SDavid van Moolenbroek 
759*00b67f09SDavid van Moolenbroek 	result = dns_tsec_create(mctx, tsectype, dstkey, &tsec);
760*00b67f09SDavid van Moolenbroek 	dst_key_free(&dstkey);
761*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
762*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "could not create tsec: %s\n",
763*00b67f09SDavid van Moolenbroek 			isc_result_totext(result));
764*00b67f09SDavid van Moolenbroek 		exit(1);
765*00b67f09SDavid van Moolenbroek 	}
766*00b67f09SDavid van Moolenbroek }
767