xref: /minix/external/bsd/bind/dist/bin/dig/dighost.c (revision 00b67f09)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: dighost.c,v 1.15 2015/07/08 17:28:54 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 2000-2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: dighost.c,v 1.345 2011/12/07 17:23:28 each Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file
23*00b67f09SDavid van Moolenbroek  *  \note
24*00b67f09SDavid van Moolenbroek  * Notice to programmers:  Do not use this code as an example of how to
25*00b67f09SDavid van Moolenbroek  * use the ISC library to perform DNS lookups.  Dig and Host both operate
26*00b67f09SDavid van Moolenbroek  * on the request level, since they allow fine-tuning of output and are
27*00b67f09SDavid van Moolenbroek  * intended as debugging tools.  As a result, they perform many of the
28*00b67f09SDavid van Moolenbroek  * functions which could be better handled using the dns_resolver
29*00b67f09SDavid van Moolenbroek  * functions in most applications.
30*00b67f09SDavid van Moolenbroek  */
31*00b67f09SDavid van Moolenbroek 
32*00b67f09SDavid van Moolenbroek #include <config.h>
33*00b67f09SDavid van Moolenbroek #include <stdlib.h>
34*00b67f09SDavid van Moolenbroek #include <unistd.h>
35*00b67f09SDavid van Moolenbroek #include <string.h>
36*00b67f09SDavid van Moolenbroek #include <limits.h>
37*00b67f09SDavid van Moolenbroek 
38*00b67f09SDavid van Moolenbroek #ifdef HAVE_LOCALE_H
39*00b67f09SDavid van Moolenbroek #include <locale.h>
40*00b67f09SDavid van Moolenbroek #endif
41*00b67f09SDavid van Moolenbroek 
42*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
43*00b67f09SDavid van Moolenbroek #include <idn/result.h>
44*00b67f09SDavid van Moolenbroek #include <idn/log.h>
45*00b67f09SDavid van Moolenbroek #include <idn/resconf.h>
46*00b67f09SDavid van Moolenbroek #include <idn/api.h>
47*00b67f09SDavid van Moolenbroek #endif
48*00b67f09SDavid van Moolenbroek 
49*00b67f09SDavid van Moolenbroek #include <dns/byaddr.h>
50*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
51*00b67f09SDavid van Moolenbroek #include <dns/callbacks.h>
52*00b67f09SDavid van Moolenbroek #include <dns/dnssec.h>
53*00b67f09SDavid van Moolenbroek #include <dns/ds.h>
54*00b67f09SDavid van Moolenbroek #include <dns/master.h>
55*00b67f09SDavid van Moolenbroek #include <dns/nsec.h>
56*00b67f09SDavid van Moolenbroek #include <isc/random.h>
57*00b67f09SDavid van Moolenbroek #include <ctype.h>
58*00b67f09SDavid van Moolenbroek #endif
59*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
60*00b67f09SDavid van Moolenbroek #include <dns/log.h>
61*00b67f09SDavid van Moolenbroek #include <dns/message.h>
62*00b67f09SDavid van Moolenbroek #include <dns/name.h>
63*00b67f09SDavid van Moolenbroek #include <dns/rcode.h>
64*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
65*00b67f09SDavid van Moolenbroek #include <dns/rdataclass.h>
66*00b67f09SDavid van Moolenbroek #include <dns/rdatalist.h>
67*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
68*00b67f09SDavid van Moolenbroek #include <dns/rdatastruct.h>
69*00b67f09SDavid van Moolenbroek #include <dns/rdatatype.h>
70*00b67f09SDavid van Moolenbroek #include <dns/result.h>
71*00b67f09SDavid van Moolenbroek #include <dns/tsig.h>
72*00b67f09SDavid van Moolenbroek 
73*00b67f09SDavid van Moolenbroek #include <dst/dst.h>
74*00b67f09SDavid van Moolenbroek #include <dst/result.h>
75*00b67f09SDavid van Moolenbroek 
76*00b67f09SDavid van Moolenbroek #include <isc/app.h>
77*00b67f09SDavid van Moolenbroek #include <isc/base64.h>
78*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
79*00b67f09SDavid van Moolenbroek #include <isc/file.h>
80*00b67f09SDavid van Moolenbroek #include <isc/hex.h>
81*00b67f09SDavid van Moolenbroek #include <isc/lang.h>
82*00b67f09SDavid van Moolenbroek #include <isc/log.h>
83*00b67f09SDavid van Moolenbroek #include <isc/netaddr.h>
84*00b67f09SDavid van Moolenbroek #include <isc/netdb.h>
85*00b67f09SDavid van Moolenbroek #include <isc/parseint.h>
86*00b67f09SDavid van Moolenbroek #include <isc/print.h>
87*00b67f09SDavid van Moolenbroek #include <isc/random.h>
88*00b67f09SDavid van Moolenbroek #include <isc/result.h>
89*00b67f09SDavid van Moolenbroek #include <isc/serial.h>
90*00b67f09SDavid van Moolenbroek #include <isc/sockaddr.h>
91*00b67f09SDavid van Moolenbroek #include <isc/string.h>
92*00b67f09SDavid van Moolenbroek #include <isc/task.h>
93*00b67f09SDavid van Moolenbroek #include <isc/timer.h>
94*00b67f09SDavid van Moolenbroek #include <isc/types.h>
95*00b67f09SDavid van Moolenbroek #include <isc/util.h>
96*00b67f09SDavid van Moolenbroek 
97*00b67f09SDavid van Moolenbroek #include <isccfg/namedconf.h>
98*00b67f09SDavid van Moolenbroek 
99*00b67f09SDavid van Moolenbroek #include <lwres/lwres.h>
100*00b67f09SDavid van Moolenbroek #include <lwres/net.h>
101*00b67f09SDavid van Moolenbroek 
102*00b67f09SDavid van Moolenbroek #include <bind9/getaddresses.h>
103*00b67f09SDavid van Moolenbroek 
104*00b67f09SDavid van Moolenbroek #include <dig/dig.h>
105*00b67f09SDavid van Moolenbroek 
106*00b67f09SDavid van Moolenbroek #ifdef PKCS11CRYPTO
107*00b67f09SDavid van Moolenbroek #include <pk11/result.h>
108*00b67f09SDavid van Moolenbroek #endif
109*00b67f09SDavid van Moolenbroek 
110*00b67f09SDavid van Moolenbroek #if ! defined(NS_INADDRSZ)
111*00b67f09SDavid van Moolenbroek #define NS_INADDRSZ	 4
112*00b67f09SDavid van Moolenbroek #endif
113*00b67f09SDavid van Moolenbroek 
114*00b67f09SDavid van Moolenbroek #if ! defined(NS_IN6ADDRSZ)
115*00b67f09SDavid van Moolenbroek #define NS_IN6ADDRSZ	16
116*00b67f09SDavid van Moolenbroek #endif
117*00b67f09SDavid van Moolenbroek 
118*00b67f09SDavid van Moolenbroek static lwres_context_t *lwctx = NULL;
119*00b67f09SDavid van Moolenbroek static lwres_conf_t *lwconf;
120*00b67f09SDavid van Moolenbroek 
121*00b67f09SDavid van Moolenbroek dig_lookuplist_t lookup_list;
122*00b67f09SDavid van Moolenbroek dig_serverlist_t server_list;
123*00b67f09SDavid van Moolenbroek dig_searchlistlist_t search_list;
124*00b67f09SDavid van Moolenbroek 
125*00b67f09SDavid van Moolenbroek isc_boolean_t
126*00b67f09SDavid van Moolenbroek 	check_ra = ISC_FALSE,
127*00b67f09SDavid van Moolenbroek 	have_ipv4 = ISC_FALSE,
128*00b67f09SDavid van Moolenbroek 	have_ipv6 = ISC_FALSE,
129*00b67f09SDavid van Moolenbroek 	specified_source = ISC_FALSE,
130*00b67f09SDavid van Moolenbroek 	free_now = ISC_FALSE,
131*00b67f09SDavid van Moolenbroek 	cancel_now = ISC_FALSE,
132*00b67f09SDavid van Moolenbroek 	usesearch = ISC_FALSE,
133*00b67f09SDavid van Moolenbroek 	showsearch = ISC_FALSE,
134*00b67f09SDavid van Moolenbroek 	qr = ISC_FALSE,
135*00b67f09SDavid van Moolenbroek 	is_dst_up = ISC_FALSE,
136*00b67f09SDavid van Moolenbroek 	keep_open = ISC_FALSE;
137*00b67f09SDavid van Moolenbroek in_port_t port = 53;
138*00b67f09SDavid van Moolenbroek unsigned int timeout = 0;
139*00b67f09SDavid van Moolenbroek unsigned int extrabytes;
140*00b67f09SDavid van Moolenbroek isc_mem_t *mctx = NULL;
141*00b67f09SDavid van Moolenbroek isc_log_t *lctx = NULL;
142*00b67f09SDavid van Moolenbroek isc_taskmgr_t *taskmgr = NULL;
143*00b67f09SDavid van Moolenbroek isc_task_t *global_task = NULL;
144*00b67f09SDavid van Moolenbroek isc_timermgr_t *timermgr = NULL;
145*00b67f09SDavid van Moolenbroek isc_socketmgr_t *socketmgr = NULL;
146*00b67f09SDavid van Moolenbroek isc_sockaddr_t bind_address;
147*00b67f09SDavid van Moolenbroek isc_sockaddr_t bind_any;
148*00b67f09SDavid van Moolenbroek int sendcount = 0;
149*00b67f09SDavid van Moolenbroek int recvcount = 0;
150*00b67f09SDavid van Moolenbroek int sockcount = 0;
151*00b67f09SDavid van Moolenbroek int ndots = -1;
152*00b67f09SDavid van Moolenbroek int tries = 3;
153*00b67f09SDavid van Moolenbroek int lookup_counter = 0;
154*00b67f09SDavid van Moolenbroek 
155*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
156*00b67f09SDavid van Moolenbroek static void		initialize_idn(void);
157*00b67f09SDavid van Moolenbroek static isc_result_t	output_filter(isc_buffer_t *buffer,
158*00b67f09SDavid van Moolenbroek 				      unsigned int used_org,
159*00b67f09SDavid van Moolenbroek 				      isc_boolean_t absolute);
160*00b67f09SDavid van Moolenbroek static idn_result_t	append_textname(char *name, const char *origin,
161*00b67f09SDavid van Moolenbroek 					size_t namesize);
162*00b67f09SDavid van Moolenbroek static void		idn_check_result(idn_result_t r, const char *msg);
163*00b67f09SDavid van Moolenbroek 
164*00b67f09SDavid van Moolenbroek #define MAXDLEN		256
165*00b67f09SDavid van Moolenbroek int  idnoptions	= 0;
166*00b67f09SDavid van Moolenbroek #endif
167*00b67f09SDavid van Moolenbroek 
168*00b67f09SDavid van Moolenbroek isc_socket_t *keep = NULL;
169*00b67f09SDavid van Moolenbroek isc_sockaddr_t keepaddr;
170*00b67f09SDavid van Moolenbroek 
171*00b67f09SDavid van Moolenbroek /*%
172*00b67f09SDavid van Moolenbroek  * Exit Codes:
173*00b67f09SDavid van Moolenbroek  *
174*00b67f09SDavid van Moolenbroek  *\li	0   Everything went well, including things like NXDOMAIN
175*00b67f09SDavid van Moolenbroek  *\li	1   Usage error
176*00b67f09SDavid van Moolenbroek  *\li	7   Got too many RR's or Names
177*00b67f09SDavid van Moolenbroek  *\li	8   Couldn't open batch file
178*00b67f09SDavid van Moolenbroek  *\li	9   No reply from server
179*00b67f09SDavid van Moolenbroek  *\li	10  Internal error
180*00b67f09SDavid van Moolenbroek  */
181*00b67f09SDavid van Moolenbroek int exitcode = 0;
182*00b67f09SDavid van Moolenbroek int fatalexit = 0;
183*00b67f09SDavid van Moolenbroek char keynametext[MXNAME];
184*00b67f09SDavid van Moolenbroek char keyfile[MXNAME] = "";
185*00b67f09SDavid van Moolenbroek char keysecret[MXNAME] = "";
186*00b67f09SDavid van Moolenbroek unsigned char cookie_secret[33];
187*00b67f09SDavid van Moolenbroek unsigned char cookie[8];
188*00b67f09SDavid van Moolenbroek dns_name_t *hmacname = NULL;
189*00b67f09SDavid van Moolenbroek unsigned int digestbits = 0;
190*00b67f09SDavid van Moolenbroek isc_buffer_t *namebuf = NULL;
191*00b67f09SDavid van Moolenbroek dns_tsigkey_t *key = NULL;
192*00b67f09SDavid van Moolenbroek isc_boolean_t validated = ISC_TRUE;
193*00b67f09SDavid van Moolenbroek isc_entropy_t *entp = NULL;
194*00b67f09SDavid van Moolenbroek isc_mempool_t *commctx = NULL;
195*00b67f09SDavid van Moolenbroek isc_boolean_t debugging = ISC_FALSE;
196*00b67f09SDavid van Moolenbroek isc_boolean_t debugtiming = ISC_FALSE;
197*00b67f09SDavid van Moolenbroek isc_boolean_t memdebugging = ISC_FALSE;
198*00b67f09SDavid van Moolenbroek const char *progname = NULL;
199*00b67f09SDavid van Moolenbroek isc_mutex_t lookup_lock;
200*00b67f09SDavid van Moolenbroek dig_lookup_t *current_lookup = NULL;
201*00b67f09SDavid van Moolenbroek 
202*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
203*00b67f09SDavid van Moolenbroek 
204*00b67f09SDavid van Moolenbroek isc_result_t	  get_trusted_key(isc_mem_t *mctx);
205*00b67f09SDavid van Moolenbroek dns_rdataset_t *  sigchase_scanname(dns_rdatatype_t type,
206*00b67f09SDavid van Moolenbroek 				    dns_rdatatype_t covers,
207*00b67f09SDavid van Moolenbroek 				    isc_boolean_t *lookedup,
208*00b67f09SDavid van Moolenbroek 				    dns_name_t *rdata_name);
209*00b67f09SDavid van Moolenbroek dns_rdataset_t *  chase_scanname_section(dns_message_t *msg,
210*00b67f09SDavid van Moolenbroek 					 dns_name_t *name,
211*00b67f09SDavid van Moolenbroek 					 dns_rdatatype_t type,
212*00b67f09SDavid van Moolenbroek 					 dns_rdatatype_t covers,
213*00b67f09SDavid van Moolenbroek 					 int section);
214*00b67f09SDavid van Moolenbroek isc_result_t	  advanced_rrsearch(dns_rdataset_t **rdataset,
215*00b67f09SDavid van Moolenbroek 				    dns_name_t *name,
216*00b67f09SDavid van Moolenbroek 				    dns_rdatatype_t type,
217*00b67f09SDavid van Moolenbroek 				    dns_rdatatype_t covers,
218*00b67f09SDavid van Moolenbroek 				    isc_boolean_t *lookedup);
219*00b67f09SDavid van Moolenbroek isc_result_t	  sigchase_verify_sig_key(dns_name_t *name,
220*00b67f09SDavid van Moolenbroek 					  dns_rdataset_t *rdataset,
221*00b67f09SDavid van Moolenbroek 					  dst_key_t* dnsseckey,
222*00b67f09SDavid van Moolenbroek 					  dns_rdataset_t *sigrdataset,
223*00b67f09SDavid van Moolenbroek 					  isc_mem_t *mctx);
224*00b67f09SDavid van Moolenbroek isc_result_t	  sigchase_verify_sig(dns_name_t *name,
225*00b67f09SDavid van Moolenbroek 				      dns_rdataset_t *rdataset,
226*00b67f09SDavid van Moolenbroek 				      dns_rdataset_t *keyrdataset,
227*00b67f09SDavid van Moolenbroek 				      dns_rdataset_t *sigrdataset,
228*00b67f09SDavid van Moolenbroek 				      isc_mem_t *mctx);
229*00b67f09SDavid van Moolenbroek isc_result_t	  sigchase_verify_ds(dns_name_t *name,
230*00b67f09SDavid van Moolenbroek 				     dns_rdataset_t *keyrdataset,
231*00b67f09SDavid van Moolenbroek 				     dns_rdataset_t *dsrdataset,
232*00b67f09SDavid van Moolenbroek 				     isc_mem_t *mctx);
233*00b67f09SDavid van Moolenbroek void		  sigchase(dns_message_t *msg);
234*00b67f09SDavid van Moolenbroek void		  print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
235*00b67f09SDavid van Moolenbroek void		  print_rdataset(dns_name_t *name,
236*00b67f09SDavid van Moolenbroek 				 dns_rdataset_t *rdataset, isc_mem_t *mctx);
237*00b67f09SDavid van Moolenbroek void		  dup_name(dns_name_t *source, dns_name_t* target,
238*00b67f09SDavid van Moolenbroek 			   isc_mem_t *mctx);
239*00b67f09SDavid van Moolenbroek void		  free_name(dns_name_t *name, isc_mem_t *mctx);
240*00b67f09SDavid van Moolenbroek void		  dump_database(void);
241*00b67f09SDavid van Moolenbroek void		  dump_database_section(dns_message_t *msg, int section);
242*00b67f09SDavid van Moolenbroek dns_rdataset_t *  search_type(dns_name_t *name, dns_rdatatype_t type,
243*00b67f09SDavid van Moolenbroek 			      dns_rdatatype_t covers);
244*00b67f09SDavid van Moolenbroek isc_result_t	  contains_trusted_key(dns_name_t *name,
245*00b67f09SDavid van Moolenbroek 				       dns_rdataset_t *rdataset,
246*00b67f09SDavid van Moolenbroek 				       dns_rdataset_t *sigrdataset,
247*00b67f09SDavid van Moolenbroek 				       isc_mem_t *mctx);
248*00b67f09SDavid van Moolenbroek void		  print_type(dns_rdatatype_t type);
249*00b67f09SDavid van Moolenbroek isc_result_t	  prove_nx_domain(dns_message_t * msg,
250*00b67f09SDavid van Moolenbroek 				  dns_name_t * name,
251*00b67f09SDavid van Moolenbroek 				  dns_name_t * rdata_name,
252*00b67f09SDavid van Moolenbroek 				  dns_rdataset_t ** rdataset,
253*00b67f09SDavid van Moolenbroek 				  dns_rdataset_t ** sigrdataset);
254*00b67f09SDavid van Moolenbroek isc_result_t	  prove_nx_type(dns_message_t * msg, dns_name_t *name,
255*00b67f09SDavid van Moolenbroek 				dns_rdataset_t *nsec,
256*00b67f09SDavid van Moolenbroek 				dns_rdataclass_t class,
257*00b67f09SDavid van Moolenbroek 				dns_rdatatype_t type,
258*00b67f09SDavid van Moolenbroek 				dns_name_t * rdata_name,
259*00b67f09SDavid van Moolenbroek 				dns_rdataset_t ** rdataset,
260*00b67f09SDavid van Moolenbroek 				dns_rdataset_t ** sigrdataset);
261*00b67f09SDavid van Moolenbroek isc_result_t	  prove_nx(dns_message_t * msg, dns_name_t * name,
262*00b67f09SDavid van Moolenbroek 			   dns_rdataclass_t class,
263*00b67f09SDavid van Moolenbroek 			   dns_rdatatype_t type,
264*00b67f09SDavid van Moolenbroek 			   dns_name_t * rdata_name,
265*00b67f09SDavid van Moolenbroek 			   dns_rdataset_t ** rdataset,
266*00b67f09SDavid van Moolenbroek 			   dns_rdataset_t ** sigrdataset);
267*00b67f09SDavid van Moolenbroek static void	  nameFromString(const char *str, dns_name_t *p_ret);
268*00b67f09SDavid van Moolenbroek int		  inf_name(dns_name_t * name1, dns_name_t * name2);
269*00b67f09SDavid van Moolenbroek isc_result_t	  removetmpkey(isc_mem_t *mctx, const char *file);
270*00b67f09SDavid van Moolenbroek void		  clean_trustedkey(void);
271*00b67f09SDavid van Moolenbroek isc_result_t 	  insert_trustedkey(void *arg, dns_name_t *name,
272*00b67f09SDavid van Moolenbroek 				    dns_rdataset_t *rdataset);
273*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_BU
274*00b67f09SDavid van Moolenbroek isc_result_t	  getneededrr(dns_message_t *msg);
275*00b67f09SDavid van Moolenbroek void		  sigchase_bottom_up(dns_message_t *msg);
276*00b67f09SDavid van Moolenbroek void		  sigchase_bu(dns_message_t *msg);
277*00b67f09SDavid van Moolenbroek #endif
278*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
279*00b67f09SDavid van Moolenbroek isc_result_t	  initialization(dns_name_t *name);
280*00b67f09SDavid van Moolenbroek isc_result_t	  prepare_lookup(dns_name_t *name);
281*00b67f09SDavid van Moolenbroek isc_result_t	  grandfather_pb_test(dns_name_t * zone_name,
282*00b67f09SDavid van Moolenbroek 				      dns_rdataset_t *sigrdataset);
283*00b67f09SDavid van Moolenbroek isc_result_t	  child_of_zone(dns_name_t *name,
284*00b67f09SDavid van Moolenbroek 				dns_name_t *zone_name,
285*00b67f09SDavid van Moolenbroek 				dns_name_t *child_name);
286*00b67f09SDavid van Moolenbroek void		  sigchase_td(dns_message_t *msg);
287*00b67f09SDavid van Moolenbroek #endif
288*00b67f09SDavid van Moolenbroek char trustedkey[MXNAME] = "";
289*00b67f09SDavid van Moolenbroek 
290*00b67f09SDavid van Moolenbroek dns_rdataset_t *chase_rdataset = NULL;
291*00b67f09SDavid van Moolenbroek dns_rdataset_t *chase_sigrdataset = NULL;
292*00b67f09SDavid van Moolenbroek dns_rdataset_t *chase_dsrdataset = NULL;
293*00b67f09SDavid van Moolenbroek dns_rdataset_t *chase_sigdsrdataset = NULL;
294*00b67f09SDavid van Moolenbroek dns_rdataset_t *chase_keyrdataset = NULL;
295*00b67f09SDavid van Moolenbroek dns_rdataset_t *chase_sigkeyrdataset = NULL;
296*00b67f09SDavid van Moolenbroek dns_rdataset_t *chase_nsrdataset = NULL;
297*00b67f09SDavid van Moolenbroek 
298*00b67f09SDavid van Moolenbroek dns_name_t chase_name; /* the query name */
299*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
300*00b67f09SDavid van Moolenbroek /*
301*00b67f09SDavid van Moolenbroek  * the current name is the parent name when we follow delegation
302*00b67f09SDavid van Moolenbroek  */
303*00b67f09SDavid van Moolenbroek dns_name_t chase_current_name;
304*00b67f09SDavid van Moolenbroek /*
305*00b67f09SDavid van Moolenbroek  * the child name is used for delegation (NS DS responses in AUTHORITY section)
306*00b67f09SDavid van Moolenbroek  */
307*00b67f09SDavid van Moolenbroek dns_name_t chase_authority_name;
308*00b67f09SDavid van Moolenbroek #endif
309*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_BU
310*00b67f09SDavid van Moolenbroek dns_name_t chase_signame;
311*00b67f09SDavid van Moolenbroek #endif
312*00b67f09SDavid van Moolenbroek 
313*00b67f09SDavid van Moolenbroek 
314*00b67f09SDavid van Moolenbroek isc_boolean_t chase_siglookedup = ISC_FALSE;
315*00b67f09SDavid van Moolenbroek isc_boolean_t chase_keylookedup = ISC_FALSE;
316*00b67f09SDavid van Moolenbroek isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
317*00b67f09SDavid van Moolenbroek isc_boolean_t chase_dslookedup = ISC_FALSE;
318*00b67f09SDavid van Moolenbroek isc_boolean_t chase_sigdslookedup = ISC_FALSE;
319*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
320*00b67f09SDavid van Moolenbroek isc_boolean_t chase_nslookedup = ISC_FALSE;
321*00b67f09SDavid van Moolenbroek isc_boolean_t chase_lookedup = ISC_FALSE;
322*00b67f09SDavid van Moolenbroek 
323*00b67f09SDavid van Moolenbroek 
324*00b67f09SDavid van Moolenbroek isc_boolean_t delegation_follow = ISC_FALSE;
325*00b67f09SDavid van Moolenbroek isc_boolean_t grandfather_pb = ISC_FALSE;
326*00b67f09SDavid van Moolenbroek isc_boolean_t have_response = ISC_FALSE;
327*00b67f09SDavid van Moolenbroek isc_boolean_t have_delegation_ns = ISC_FALSE;
328*00b67f09SDavid van Moolenbroek dns_message_t * error_message = NULL;
329*00b67f09SDavid van Moolenbroek #endif
330*00b67f09SDavid van Moolenbroek 
331*00b67f09SDavid van Moolenbroek isc_boolean_t dsvalidating = ISC_FALSE;
332*00b67f09SDavid van Moolenbroek isc_boolean_t chase_name_dup = ISC_FALSE;
333*00b67f09SDavid van Moolenbroek 
334*00b67f09SDavid van Moolenbroek ISC_LIST(dig_message_t) chase_message_list;
335*00b67f09SDavid van Moolenbroek ISC_LIST(dig_message_t) chase_message_list2;
336*00b67f09SDavid van Moolenbroek 
337*00b67f09SDavid van Moolenbroek 
338*00b67f09SDavid van Moolenbroek #define MAX_TRUSTED_KEY 5
339*00b67f09SDavid van Moolenbroek typedef struct struct_trusted_key_list {
340*00b67f09SDavid van Moolenbroek 	dst_key_t * key[MAX_TRUSTED_KEY];
341*00b67f09SDavid van Moolenbroek 	int nb_tk;
342*00b67f09SDavid van Moolenbroek } struct_tk_list;
343*00b67f09SDavid van Moolenbroek 
344*00b67f09SDavid van Moolenbroek struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
345*00b67f09SDavid van Moolenbroek 
346*00b67f09SDavid van Moolenbroek #endif
347*00b67f09SDavid van Moolenbroek 
348*00b67f09SDavid van Moolenbroek #define DIG_MAX_ADDRESSES 20
349*00b67f09SDavid van Moolenbroek 
350*00b67f09SDavid van Moolenbroek /*%
351*00b67f09SDavid van Moolenbroek  * Apply and clear locks at the event level in global task.
352*00b67f09SDavid van Moolenbroek  * Can I get rid of these using shutdown events?  XXX
353*00b67f09SDavid van Moolenbroek  */
354*00b67f09SDavid van Moolenbroek #define LOCK_LOOKUP {\
355*00b67f09SDavid van Moolenbroek 	debug("lock_lookup %s:%d", __FILE__, __LINE__);\
356*00b67f09SDavid van Moolenbroek 	check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
357*00b67f09SDavid van Moolenbroek 	debug("success");\
358*00b67f09SDavid van Moolenbroek }
359*00b67f09SDavid van Moolenbroek #define UNLOCK_LOOKUP {\
360*00b67f09SDavid van Moolenbroek 	debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
361*00b67f09SDavid van Moolenbroek 	check_result(isc_mutex_unlock((&lookup_lock)),\
362*00b67f09SDavid van Moolenbroek 		     "isc_mutex_unlock");\
363*00b67f09SDavid van Moolenbroek }
364*00b67f09SDavid van Moolenbroek 
365*00b67f09SDavid van Moolenbroek static void
366*00b67f09SDavid van Moolenbroek cancel_lookup(dig_lookup_t *lookup);
367*00b67f09SDavid van Moolenbroek 
368*00b67f09SDavid van Moolenbroek static void
369*00b67f09SDavid van Moolenbroek recv_done(isc_task_t *task, isc_event_t *event);
370*00b67f09SDavid van Moolenbroek 
371*00b67f09SDavid van Moolenbroek static void
372*00b67f09SDavid van Moolenbroek send_udp(dig_query_t *query);
373*00b67f09SDavid van Moolenbroek 
374*00b67f09SDavid van Moolenbroek static void
375*00b67f09SDavid van Moolenbroek connect_timeout(isc_task_t *task, isc_event_t *event);
376*00b67f09SDavid van Moolenbroek 
377*00b67f09SDavid van Moolenbroek static void
378*00b67f09SDavid van Moolenbroek launch_next_query(dig_query_t *query, isc_boolean_t include_question);
379*00b67f09SDavid van Moolenbroek 
380*00b67f09SDavid van Moolenbroek static void
381*00b67f09SDavid van Moolenbroek check_next_lookup(dig_lookup_t *lookup);
382*00b67f09SDavid van Moolenbroek 
383*00b67f09SDavid van Moolenbroek static isc_boolean_t
384*00b67f09SDavid van Moolenbroek next_origin(dig_lookup_t *oldlookup);
385*00b67f09SDavid van Moolenbroek 
386*00b67f09SDavid van Moolenbroek static void *
mem_alloc(void * arg,size_t size)387*00b67f09SDavid van Moolenbroek mem_alloc(void *arg, size_t size) {
388*00b67f09SDavid van Moolenbroek 	return (isc_mem_get(arg, size));
389*00b67f09SDavid van Moolenbroek }
390*00b67f09SDavid van Moolenbroek 
391*00b67f09SDavid van Moolenbroek static void
mem_free(void * arg,void * mem,size_t size)392*00b67f09SDavid van Moolenbroek mem_free(void *arg, void *mem, size_t size) {
393*00b67f09SDavid van Moolenbroek 	isc_mem_put(arg, mem, size);
394*00b67f09SDavid van Moolenbroek }
395*00b67f09SDavid van Moolenbroek 
396*00b67f09SDavid van Moolenbroek char *
next_token(char ** stringp,const char * delim)397*00b67f09SDavid van Moolenbroek next_token(char **stringp, const char *delim) {
398*00b67f09SDavid van Moolenbroek 	char *res;
399*00b67f09SDavid van Moolenbroek 
400*00b67f09SDavid van Moolenbroek 	do {
401*00b67f09SDavid van Moolenbroek 		res = strsep(stringp, delim);
402*00b67f09SDavid van Moolenbroek 		if (res == NULL)
403*00b67f09SDavid van Moolenbroek 			break;
404*00b67f09SDavid van Moolenbroek 	} while (*res == '\0');
405*00b67f09SDavid van Moolenbroek 	return (res);
406*00b67f09SDavid van Moolenbroek }
407*00b67f09SDavid van Moolenbroek 
408*00b67f09SDavid van Moolenbroek static int
count_dots(char * string)409*00b67f09SDavid van Moolenbroek count_dots(char *string) {
410*00b67f09SDavid van Moolenbroek 	char *s;
411*00b67f09SDavid van Moolenbroek 	int i = 0;
412*00b67f09SDavid van Moolenbroek 
413*00b67f09SDavid van Moolenbroek 	s = string;
414*00b67f09SDavid van Moolenbroek 	while (*s != '\0') {
415*00b67f09SDavid van Moolenbroek 		if (*s == '.')
416*00b67f09SDavid van Moolenbroek 			i++;
417*00b67f09SDavid van Moolenbroek 		s++;
418*00b67f09SDavid van Moolenbroek 	}
419*00b67f09SDavid van Moolenbroek 	return (i);
420*00b67f09SDavid van Moolenbroek }
421*00b67f09SDavid van Moolenbroek 
422*00b67f09SDavid van Moolenbroek static void
hex_dump(isc_buffer_t * b)423*00b67f09SDavid van Moolenbroek hex_dump(isc_buffer_t *b) {
424*00b67f09SDavid van Moolenbroek 	unsigned int len, i;
425*00b67f09SDavid van Moolenbroek 	isc_region_t r;
426*00b67f09SDavid van Moolenbroek 
427*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(b, &r);
428*00b67f09SDavid van Moolenbroek 
429*00b67f09SDavid van Moolenbroek 	printf("%d bytes\n", r.length);
430*00b67f09SDavid van Moolenbroek 	for (len = 0; len < r.length; len++) {
431*00b67f09SDavid van Moolenbroek 		printf("%02x ", r.base[len]);
432*00b67f09SDavid van Moolenbroek 		if (len % 16 == 15) {
433*00b67f09SDavid van Moolenbroek 			fputs("         ", stdout);
434*00b67f09SDavid van Moolenbroek 			for (i = len - 15; i <= len; i++) {
435*00b67f09SDavid van Moolenbroek 				if (r.base[i] >= '!' && r.base[i] <= '}')
436*00b67f09SDavid van Moolenbroek 					putchar(r.base[i]);
437*00b67f09SDavid van Moolenbroek 				else
438*00b67f09SDavid van Moolenbroek 					putchar('.');
439*00b67f09SDavid van Moolenbroek 			}
440*00b67f09SDavid van Moolenbroek 			printf("\n");
441*00b67f09SDavid van Moolenbroek 		}
442*00b67f09SDavid van Moolenbroek 	}
443*00b67f09SDavid van Moolenbroek 	if (len % 16 != 0) {
444*00b67f09SDavid van Moolenbroek 		for (i = len; (i % 16) != 0; i++)
445*00b67f09SDavid van Moolenbroek 			fputs("   ", stdout);
446*00b67f09SDavid van Moolenbroek 		fputs("         ", stdout);
447*00b67f09SDavid van Moolenbroek 		for (i = ((len>>4)<<4); i < len; i++) {
448*00b67f09SDavid van Moolenbroek 			if (r.base[i] >= '!' && r.base[i] <= '}')
449*00b67f09SDavid van Moolenbroek 				putchar(r.base[i]);
450*00b67f09SDavid van Moolenbroek 			else
451*00b67f09SDavid van Moolenbroek 				putchar('.');
452*00b67f09SDavid van Moolenbroek 		}
453*00b67f09SDavid van Moolenbroek 		printf("\n");
454*00b67f09SDavid van Moolenbroek 	}
455*00b67f09SDavid van Moolenbroek }
456*00b67f09SDavid van Moolenbroek 
457*00b67f09SDavid van Moolenbroek /*%
458*00b67f09SDavid van Moolenbroek  * Append 'len' bytes of 'text' at '*p', failing with
459*00b67f09SDavid van Moolenbroek  * ISC_R_NOSPACE if that would advance p past 'end'.
460*00b67f09SDavid van Moolenbroek  */
461*00b67f09SDavid van Moolenbroek static isc_result_t
append(const char * text,int len,char ** p,char * end)462*00b67f09SDavid van Moolenbroek append(const char *text, int len, char **p, char *end) {
463*00b67f09SDavid van Moolenbroek 	if (len > end - *p)
464*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
465*00b67f09SDavid van Moolenbroek 	memmove(*p, text, len);
466*00b67f09SDavid van Moolenbroek 	*p += len;
467*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
468*00b67f09SDavid van Moolenbroek }
469*00b67f09SDavid van Moolenbroek 
470*00b67f09SDavid van Moolenbroek static isc_result_t
reverse_octets(const char * in,char ** p,char * end)471*00b67f09SDavid van Moolenbroek reverse_octets(const char *in, char **p, char *end) {
472*00b67f09SDavid van Moolenbroek 	char *dot = strchr(in, '.');
473*00b67f09SDavid van Moolenbroek 	int len;
474*00b67f09SDavid van Moolenbroek 	if (dot != NULL) {
475*00b67f09SDavid van Moolenbroek 		isc_result_t result;
476*00b67f09SDavid van Moolenbroek 		result = reverse_octets(dot + 1, p, end);
477*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
478*00b67f09SDavid van Moolenbroek 			return (result);
479*00b67f09SDavid van Moolenbroek 		result = append(".", 1, p, end);
480*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
481*00b67f09SDavid van Moolenbroek 			return (result);
482*00b67f09SDavid van Moolenbroek 		len = (int)(dot - in);
483*00b67f09SDavid van Moolenbroek 	} else {
484*00b67f09SDavid van Moolenbroek 		len = strlen(in);
485*00b67f09SDavid van Moolenbroek 	}
486*00b67f09SDavid van Moolenbroek 	return (append(in, len, p, end));
487*00b67f09SDavid van Moolenbroek }
488*00b67f09SDavid van Moolenbroek 
489*00b67f09SDavid van Moolenbroek isc_result_t
get_reverse(char * reverse,size_t len,char * value,isc_boolean_t ip6_int,isc_boolean_t strict)490*00b67f09SDavid van Moolenbroek get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
491*00b67f09SDavid van Moolenbroek 	    isc_boolean_t strict)
492*00b67f09SDavid van Moolenbroek {
493*00b67f09SDavid van Moolenbroek 	int r;
494*00b67f09SDavid van Moolenbroek 	isc_result_t result;
495*00b67f09SDavid van Moolenbroek 	isc_netaddr_t addr;
496*00b67f09SDavid van Moolenbroek 
497*00b67f09SDavid van Moolenbroek 	addr.family = AF_INET6;
498*00b67f09SDavid van Moolenbroek 	r = inet_pton(AF_INET6, value, &addr.type.in6);
499*00b67f09SDavid van Moolenbroek 	if (r > 0) {
500*00b67f09SDavid van Moolenbroek 		/* This is a valid IPv6 address. */
501*00b67f09SDavid van Moolenbroek 		dns_fixedname_t fname;
502*00b67f09SDavid van Moolenbroek 		dns_name_t *name;
503*00b67f09SDavid van Moolenbroek 		unsigned int options = 0;
504*00b67f09SDavid van Moolenbroek 
505*00b67f09SDavid van Moolenbroek 		if (ip6_int)
506*00b67f09SDavid van Moolenbroek 			options |= DNS_BYADDROPT_IPV6INT;
507*00b67f09SDavid van Moolenbroek 		dns_fixedname_init(&fname);
508*00b67f09SDavid van Moolenbroek 		name = dns_fixedname_name(&fname);
509*00b67f09SDavid van Moolenbroek 		result = dns_byaddr_createptrname2(&addr, options, name);
510*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
511*00b67f09SDavid van Moolenbroek 			return (result);
512*00b67f09SDavid van Moolenbroek 		dns_name_format(name, reverse, (unsigned int)len);
513*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
514*00b67f09SDavid van Moolenbroek 	} else {
515*00b67f09SDavid van Moolenbroek 		/*
516*00b67f09SDavid van Moolenbroek 		 * Not a valid IPv6 address.  Assume IPv4.
517*00b67f09SDavid van Moolenbroek 		 * If 'strict' is not set, construct the
518*00b67f09SDavid van Moolenbroek 		 * in-addr.arpa name by blindly reversing
519*00b67f09SDavid van Moolenbroek 		 * octets whether or not they look like integers,
520*00b67f09SDavid van Moolenbroek 		 * so that this can be used for RFC2317 names
521*00b67f09SDavid van Moolenbroek 		 * and such.
522*00b67f09SDavid van Moolenbroek 		 */
523*00b67f09SDavid van Moolenbroek 		char *p = reverse;
524*00b67f09SDavid van Moolenbroek 		char *end = reverse + len;
525*00b67f09SDavid van Moolenbroek 		if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
526*00b67f09SDavid van Moolenbroek 			return (DNS_R_BADDOTTEDQUAD);
527*00b67f09SDavid van Moolenbroek 		result = reverse_octets(value, &p, end);
528*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
529*00b67f09SDavid van Moolenbroek 			return (result);
530*00b67f09SDavid van Moolenbroek 		/* Append .in-addr.arpa. and a terminating NUL. */
531*00b67f09SDavid van Moolenbroek 		result = append(".in-addr.arpa.", 15, &p, end);
532*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
533*00b67f09SDavid van Moolenbroek 			return (result);
534*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
535*00b67f09SDavid van Moolenbroek 	}
536*00b67f09SDavid van Moolenbroek }
537*00b67f09SDavid van Moolenbroek 
538*00b67f09SDavid van Moolenbroek void
fatal(const char * format,...)539*00b67f09SDavid van Moolenbroek fatal(const char *format, ...) {
540*00b67f09SDavid van Moolenbroek 	va_list args;
541*00b67f09SDavid van Moolenbroek 
542*00b67f09SDavid van Moolenbroek 	fflush(stdout);
543*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "%s: ", progname);
544*00b67f09SDavid van Moolenbroek 	va_start(args, format);
545*00b67f09SDavid van Moolenbroek 	vfprintf(stderr, format, args);
546*00b67f09SDavid van Moolenbroek 	va_end(args);
547*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "\n");
548*00b67f09SDavid van Moolenbroek 	if (exitcode < 10)
549*00b67f09SDavid van Moolenbroek 		exitcode = 10;
550*00b67f09SDavid van Moolenbroek 	if (fatalexit != 0)
551*00b67f09SDavid van Moolenbroek 		exitcode = fatalexit;
552*00b67f09SDavid van Moolenbroek 	exit(exitcode);
553*00b67f09SDavid van Moolenbroek }
554*00b67f09SDavid van Moolenbroek 
555*00b67f09SDavid van Moolenbroek void
debug(const char * format,...)556*00b67f09SDavid van Moolenbroek debug(const char *format, ...) {
557*00b67f09SDavid van Moolenbroek 	va_list args;
558*00b67f09SDavid van Moolenbroek 	isc_time_t t;
559*00b67f09SDavid van Moolenbroek 
560*00b67f09SDavid van Moolenbroek 	if (debugging) {
561*00b67f09SDavid van Moolenbroek 		fflush(stdout);
562*00b67f09SDavid van Moolenbroek 		if (debugtiming) {
563*00b67f09SDavid van Moolenbroek 			TIME_NOW(&t);
564*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t),
565*00b67f09SDavid van Moolenbroek 				isc_time_nanoseconds(&t) / 1000);
566*00b67f09SDavid van Moolenbroek 		}
567*00b67f09SDavid van Moolenbroek 		va_start(args, format);
568*00b67f09SDavid van Moolenbroek 		vfprintf(stderr, format, args);
569*00b67f09SDavid van Moolenbroek 		va_end(args);
570*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "\n");
571*00b67f09SDavid van Moolenbroek 	}
572*00b67f09SDavid van Moolenbroek }
573*00b67f09SDavid van Moolenbroek 
574*00b67f09SDavid van Moolenbroek void
check_result(isc_result_t result,const char * msg)575*00b67f09SDavid van Moolenbroek check_result(isc_result_t result, const char *msg) {
576*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
577*00b67f09SDavid van Moolenbroek 		fatal("%s: %s", msg, isc_result_totext(result));
578*00b67f09SDavid van Moolenbroek 	}
579*00b67f09SDavid van Moolenbroek }
580*00b67f09SDavid van Moolenbroek 
581*00b67f09SDavid van Moolenbroek /*%
582*00b67f09SDavid van Moolenbroek  * Create a server structure, which is part of the lookup structure.
583*00b67f09SDavid van Moolenbroek  * This is little more than a linked list of servers to query in hopes
584*00b67f09SDavid van Moolenbroek  * of finding the answer the user is looking for
585*00b67f09SDavid van Moolenbroek  */
586*00b67f09SDavid van Moolenbroek dig_server_t *
make_server(const char * servname,const char * userarg)587*00b67f09SDavid van Moolenbroek make_server(const char *servname, const char *userarg) {
588*00b67f09SDavid van Moolenbroek 	dig_server_t *srv;
589*00b67f09SDavid van Moolenbroek 
590*00b67f09SDavid van Moolenbroek 	REQUIRE(servname != NULL);
591*00b67f09SDavid van Moolenbroek 
592*00b67f09SDavid van Moolenbroek 	debug("make_server(%s)", servname);
593*00b67f09SDavid van Moolenbroek 	srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
594*00b67f09SDavid van Moolenbroek 	if (srv == NULL)
595*00b67f09SDavid van Moolenbroek 		fatal("memory allocation failure in %s:%d",
596*00b67f09SDavid van Moolenbroek 		      __FILE__, __LINE__);
597*00b67f09SDavid van Moolenbroek 	strlcpy(srv->servername, servname, MXNAME);
598*00b67f09SDavid van Moolenbroek 	strlcpy(srv->userarg, userarg, MXNAME);
599*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(srv, link);
600*00b67f09SDavid van Moolenbroek 	return (srv);
601*00b67f09SDavid van Moolenbroek }
602*00b67f09SDavid van Moolenbroek 
603*00b67f09SDavid van Moolenbroek static int
addr2af(int lwresaddrtype)604*00b67f09SDavid van Moolenbroek addr2af(int lwresaddrtype)
605*00b67f09SDavid van Moolenbroek {
606*00b67f09SDavid van Moolenbroek 	int af = 0;
607*00b67f09SDavid van Moolenbroek 
608*00b67f09SDavid van Moolenbroek 	switch (lwresaddrtype) {
609*00b67f09SDavid van Moolenbroek 	case LWRES_ADDRTYPE_V4:
610*00b67f09SDavid van Moolenbroek 		af = AF_INET;
611*00b67f09SDavid van Moolenbroek 		break;
612*00b67f09SDavid van Moolenbroek 
613*00b67f09SDavid van Moolenbroek 	case LWRES_ADDRTYPE_V6:
614*00b67f09SDavid van Moolenbroek 		af = AF_INET6;
615*00b67f09SDavid van Moolenbroek 		break;
616*00b67f09SDavid van Moolenbroek 	}
617*00b67f09SDavid van Moolenbroek 
618*00b67f09SDavid van Moolenbroek 	return (af);
619*00b67f09SDavid van Moolenbroek }
620*00b67f09SDavid van Moolenbroek 
621*00b67f09SDavid van Moolenbroek /*%
622*00b67f09SDavid van Moolenbroek  * Create a copy of the server list from the lwres configuration structure.
623*00b67f09SDavid van Moolenbroek  * The dest list must have already had ISC_LIST_INIT applied.
624*00b67f09SDavid van Moolenbroek  */
625*00b67f09SDavid van Moolenbroek static void
copy_server_list(lwres_conf_t * confdata,dig_serverlist_t * dest)626*00b67f09SDavid van Moolenbroek copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
627*00b67f09SDavid van Moolenbroek 	dig_server_t *newsrv;
628*00b67f09SDavid van Moolenbroek 	char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
629*00b67f09SDavid van Moolenbroek 		 sizeof("%4000000000")];
630*00b67f09SDavid van Moolenbroek 	int af;
631*00b67f09SDavid van Moolenbroek 	int i;
632*00b67f09SDavid van Moolenbroek 
633*00b67f09SDavid van Moolenbroek 	debug("copy_server_list()");
634*00b67f09SDavid van Moolenbroek 	for (i = 0; i < confdata->nsnext; i++) {
635*00b67f09SDavid van Moolenbroek 		af = addr2af(confdata->nameservers[i].family);
636*00b67f09SDavid van Moolenbroek 
637*00b67f09SDavid van Moolenbroek 		if (af == AF_INET && !have_ipv4)
638*00b67f09SDavid van Moolenbroek 			continue;
639*00b67f09SDavid van Moolenbroek 		if (af == AF_INET6 && !have_ipv6)
640*00b67f09SDavid van Moolenbroek 			continue;
641*00b67f09SDavid van Moolenbroek 
642*00b67f09SDavid van Moolenbroek 		lwres_net_ntop(af, confdata->nameservers[i].address,
643*00b67f09SDavid van Moolenbroek 				   tmp, sizeof(tmp));
644*00b67f09SDavid van Moolenbroek 		if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
645*00b67f09SDavid van Moolenbroek 			char buf[sizeof("%4000000000")];
646*00b67f09SDavid van Moolenbroek 			snprintf(buf, sizeof(buf), "%%%u",
647*00b67f09SDavid van Moolenbroek 				 confdata->nameservers[i].zone);
648*00b67f09SDavid van Moolenbroek 			strlcat(tmp, buf, sizeof(tmp));
649*00b67f09SDavid van Moolenbroek 		}
650*00b67f09SDavid van Moolenbroek 		newsrv = make_server(tmp, tmp);
651*00b67f09SDavid van Moolenbroek 		ISC_LINK_INIT(newsrv, link);
652*00b67f09SDavid van Moolenbroek 		ISC_LIST_ENQUEUE(*dest, newsrv, link);
653*00b67f09SDavid van Moolenbroek 	}
654*00b67f09SDavid van Moolenbroek }
655*00b67f09SDavid van Moolenbroek 
656*00b67f09SDavid van Moolenbroek void
flush_server_list(void)657*00b67f09SDavid van Moolenbroek flush_server_list(void) {
658*00b67f09SDavid van Moolenbroek 	dig_server_t *s, *ps;
659*00b67f09SDavid van Moolenbroek 
660*00b67f09SDavid van Moolenbroek 	debug("flush_server_list()");
661*00b67f09SDavid van Moolenbroek 	s = ISC_LIST_HEAD(server_list);
662*00b67f09SDavid van Moolenbroek 	while (s != NULL) {
663*00b67f09SDavid van Moolenbroek 		ps = s;
664*00b67f09SDavid van Moolenbroek 		s = ISC_LIST_NEXT(s, link);
665*00b67f09SDavid van Moolenbroek 		ISC_LIST_DEQUEUE(server_list, ps, link);
666*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, ps);
667*00b67f09SDavid van Moolenbroek 	}
668*00b67f09SDavid van Moolenbroek }
669*00b67f09SDavid van Moolenbroek 
670*00b67f09SDavid van Moolenbroek void
set_nameserver(char * opt)671*00b67f09SDavid van Moolenbroek set_nameserver(char *opt) {
672*00b67f09SDavid van Moolenbroek 	isc_result_t result;
673*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
674*00b67f09SDavid van Moolenbroek 	isc_netaddr_t netaddr;
675*00b67f09SDavid van Moolenbroek 	int count, i;
676*00b67f09SDavid van Moolenbroek 	dig_server_t *srv;
677*00b67f09SDavid van Moolenbroek 	char tmp[ISC_NETADDR_FORMATSIZE];
678*00b67f09SDavid van Moolenbroek 
679*00b67f09SDavid van Moolenbroek 	if (opt == NULL)
680*00b67f09SDavid van Moolenbroek 		return;
681*00b67f09SDavid van Moolenbroek 
682*00b67f09SDavid van Moolenbroek 	result = bind9_getaddresses(opt, 0, sockaddrs,
683*00b67f09SDavid van Moolenbroek 				    DIG_MAX_ADDRESSES, &count);
684*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
685*00b67f09SDavid van Moolenbroek 		fatal("couldn't get address for '%s': %s",
686*00b67f09SDavid van Moolenbroek 		      opt, isc_result_totext(result));
687*00b67f09SDavid van Moolenbroek 
688*00b67f09SDavid van Moolenbroek 	flush_server_list();
689*00b67f09SDavid van Moolenbroek 
690*00b67f09SDavid van Moolenbroek 	for (i = 0; i < count; i++) {
691*00b67f09SDavid van Moolenbroek 		isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
692*00b67f09SDavid van Moolenbroek 		isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
693*00b67f09SDavid van Moolenbroek 		srv = make_server(tmp, opt);
694*00b67f09SDavid van Moolenbroek 		if (srv == NULL)
695*00b67f09SDavid van Moolenbroek 			fatal("memory allocation failure");
696*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(server_list, srv, link);
697*00b67f09SDavid van Moolenbroek 	}
698*00b67f09SDavid van Moolenbroek }
699*00b67f09SDavid van Moolenbroek 
700*00b67f09SDavid van Moolenbroek static isc_result_t
add_nameserver(lwres_conf_t * confdata,const char * addr,int af)701*00b67f09SDavid van Moolenbroek add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
702*00b67f09SDavid van Moolenbroek 
703*00b67f09SDavid van Moolenbroek 	int i = confdata->nsnext;
704*00b67f09SDavid van Moolenbroek 
705*00b67f09SDavid van Moolenbroek 	if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
706*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
707*00b67f09SDavid van Moolenbroek 
708*00b67f09SDavid van Moolenbroek 	switch (af) {
709*00b67f09SDavid van Moolenbroek 	case AF_INET:
710*00b67f09SDavid van Moolenbroek 		confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
711*00b67f09SDavid van Moolenbroek 		confdata->nameservers[i].length = NS_INADDRSZ;
712*00b67f09SDavid van Moolenbroek 		break;
713*00b67f09SDavid van Moolenbroek 	case AF_INET6:
714*00b67f09SDavid van Moolenbroek 		confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
715*00b67f09SDavid van Moolenbroek 		confdata->nameservers[i].length = NS_IN6ADDRSZ;
716*00b67f09SDavid van Moolenbroek 		break;
717*00b67f09SDavid van Moolenbroek 	default:
718*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
719*00b67f09SDavid van Moolenbroek 	}
720*00b67f09SDavid van Moolenbroek 
721*00b67f09SDavid van Moolenbroek 	if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
722*00b67f09SDavid van Moolenbroek 		confdata->nsnext++;
723*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
724*00b67f09SDavid van Moolenbroek 	}
725*00b67f09SDavid van Moolenbroek 	return (ISC_R_FAILURE);
726*00b67f09SDavid van Moolenbroek }
727*00b67f09SDavid van Moolenbroek 
728*00b67f09SDavid van Moolenbroek /*%
729*00b67f09SDavid van Moolenbroek  * Produce a cloned server list.  The dest list must have already had
730*00b67f09SDavid van Moolenbroek  * ISC_LIST_INIT applied.
731*00b67f09SDavid van Moolenbroek  */
732*00b67f09SDavid van Moolenbroek void
clone_server_list(dig_serverlist_t src,dig_serverlist_t * dest)733*00b67f09SDavid van Moolenbroek clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
734*00b67f09SDavid van Moolenbroek 	dig_server_t *srv, *newsrv;
735*00b67f09SDavid van Moolenbroek 
736*00b67f09SDavid van Moolenbroek 	debug("clone_server_list()");
737*00b67f09SDavid van Moolenbroek 	srv = ISC_LIST_HEAD(src);
738*00b67f09SDavid van Moolenbroek 	while (srv != NULL) {
739*00b67f09SDavid van Moolenbroek 		newsrv = make_server(srv->servername, srv->userarg);
740*00b67f09SDavid van Moolenbroek 		ISC_LINK_INIT(newsrv, link);
741*00b67f09SDavid van Moolenbroek 		ISC_LIST_ENQUEUE(*dest, newsrv, link);
742*00b67f09SDavid van Moolenbroek 		srv = ISC_LIST_NEXT(srv, link);
743*00b67f09SDavid van Moolenbroek 	}
744*00b67f09SDavid van Moolenbroek }
745*00b67f09SDavid van Moolenbroek 
746*00b67f09SDavid van Moolenbroek /*%
747*00b67f09SDavid van Moolenbroek  * Create an empty lookup structure, which holds all the information needed
748*00b67f09SDavid van Moolenbroek  * to get an answer to a user's question.  This structure contains two
749*00b67f09SDavid van Moolenbroek  * linked lists: the server list (servers to query) and the query list
750*00b67f09SDavid van Moolenbroek  * (outstanding queries which have been made to the listed servers).
751*00b67f09SDavid van Moolenbroek  */
752*00b67f09SDavid van Moolenbroek dig_lookup_t *
make_empty_lookup(void)753*00b67f09SDavid van Moolenbroek make_empty_lookup(void) {
754*00b67f09SDavid van Moolenbroek 	dig_lookup_t *looknew;
755*00b67f09SDavid van Moolenbroek 
756*00b67f09SDavid van Moolenbroek 	debug("make_empty_lookup()");
757*00b67f09SDavid van Moolenbroek 
758*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
759*00b67f09SDavid van Moolenbroek 
760*00b67f09SDavid van Moolenbroek 	looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
761*00b67f09SDavid van Moolenbroek 	if (looknew == NULL)
762*00b67f09SDavid van Moolenbroek 		fatal("memory allocation failure in %s:%d",
763*00b67f09SDavid van Moolenbroek 		       __FILE__, __LINE__);
764*00b67f09SDavid van Moolenbroek 	looknew->pending = ISC_TRUE;
765*00b67f09SDavid van Moolenbroek 	looknew->textname[0] = 0;
766*00b67f09SDavid van Moolenbroek 	looknew->cmdline[0] = 0;
767*00b67f09SDavid van Moolenbroek 	looknew->rdtype = dns_rdatatype_a;
768*00b67f09SDavid van Moolenbroek 	looknew->qrdtype = dns_rdatatype_a;
769*00b67f09SDavid van Moolenbroek 	looknew->rdclass = dns_rdataclass_in;
770*00b67f09SDavid van Moolenbroek 	looknew->rdtypeset = ISC_FALSE;
771*00b67f09SDavid van Moolenbroek 	looknew->rdclassset = ISC_FALSE;
772*00b67f09SDavid van Moolenbroek 	looknew->sendspace = NULL;
773*00b67f09SDavid van Moolenbroek 	looknew->sendmsg = NULL;
774*00b67f09SDavid van Moolenbroek 	looknew->name = NULL;
775*00b67f09SDavid van Moolenbroek 	looknew->oname = NULL;
776*00b67f09SDavid van Moolenbroek 	looknew->timer = NULL;
777*00b67f09SDavid van Moolenbroek 	looknew->xfr_q = NULL;
778*00b67f09SDavid van Moolenbroek 	looknew->current_query = NULL;
779*00b67f09SDavid van Moolenbroek 	looknew->doing_xfr = ISC_FALSE;
780*00b67f09SDavid van Moolenbroek 	looknew->ixfr_serial = 0;
781*00b67f09SDavid van Moolenbroek 	looknew->trace = ISC_FALSE;
782*00b67f09SDavid van Moolenbroek 	looknew->trace_root = ISC_FALSE;
783*00b67f09SDavid van Moolenbroek 	looknew->identify = ISC_FALSE;
784*00b67f09SDavid van Moolenbroek 	looknew->identify_previous_line = ISC_FALSE;
785*00b67f09SDavid van Moolenbroek 	looknew->ignore = ISC_FALSE;
786*00b67f09SDavid van Moolenbroek 	looknew->servfail_stops = ISC_TRUE;
787*00b67f09SDavid van Moolenbroek 	looknew->besteffort = ISC_TRUE;
788*00b67f09SDavid van Moolenbroek 	looknew->dnssec = ISC_FALSE;
789*00b67f09SDavid van Moolenbroek 	looknew->expire = ISC_FALSE;
790*00b67f09SDavid van Moolenbroek 	looknew->nsid = ISC_FALSE;
791*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
792*00b67f09SDavid van Moolenbroek 	looknew->sit = ISC_FALSE;
793*00b67f09SDavid van Moolenbroek #endif
794*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
795*00b67f09SDavid van Moolenbroek 	looknew->sigchase = ISC_FALSE;
796*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
797*00b67f09SDavid van Moolenbroek 	looknew->do_topdown = ISC_FALSE;
798*00b67f09SDavid van Moolenbroek 	looknew->trace_root_sigchase = ISC_FALSE;
799*00b67f09SDavid van Moolenbroek 	looknew->rdtype_sigchaseset = ISC_FALSE;
800*00b67f09SDavid van Moolenbroek 	looknew->rdtype_sigchase = dns_rdatatype_any;
801*00b67f09SDavid van Moolenbroek 	looknew->qrdtype_sigchase = dns_rdatatype_any;
802*00b67f09SDavid van Moolenbroek 	looknew->rdclass_sigchase = dns_rdataclass_in;
803*00b67f09SDavid van Moolenbroek 	looknew->rdclass_sigchaseset = ISC_FALSE;
804*00b67f09SDavid van Moolenbroek #endif
805*00b67f09SDavid van Moolenbroek #endif
806*00b67f09SDavid van Moolenbroek 	looknew->udpsize = 0;
807*00b67f09SDavid van Moolenbroek 	looknew->edns = -1;
808*00b67f09SDavid van Moolenbroek 	looknew->recurse = ISC_TRUE;
809*00b67f09SDavid van Moolenbroek 	looknew->aaonly = ISC_FALSE;
810*00b67f09SDavid van Moolenbroek 	looknew->adflag = ISC_FALSE;
811*00b67f09SDavid van Moolenbroek 	looknew->cdflag = ISC_FALSE;
812*00b67f09SDavid van Moolenbroek 	looknew->ns_search_only = ISC_FALSE;
813*00b67f09SDavid van Moolenbroek 	looknew->origin = NULL;
814*00b67f09SDavid van Moolenbroek 	looknew->tsigctx = NULL;
815*00b67f09SDavid van Moolenbroek 	looknew->querysig = NULL;
816*00b67f09SDavid van Moolenbroek 	looknew->retries = tries;
817*00b67f09SDavid van Moolenbroek 	looknew->nsfound = 0;
818*00b67f09SDavid van Moolenbroek 	looknew->tcp_mode = ISC_FALSE;
819*00b67f09SDavid van Moolenbroek 	looknew->tcp_mode_set = ISC_FALSE;
820*00b67f09SDavid van Moolenbroek 	looknew->ip6_int = ISC_FALSE;
821*00b67f09SDavid van Moolenbroek 	looknew->comments = ISC_TRUE;
822*00b67f09SDavid van Moolenbroek 	looknew->stats = ISC_TRUE;
823*00b67f09SDavid van Moolenbroek 	looknew->section_question = ISC_TRUE;
824*00b67f09SDavid van Moolenbroek 	looknew->section_answer = ISC_TRUE;
825*00b67f09SDavid van Moolenbroek 	looknew->section_authority = ISC_TRUE;
826*00b67f09SDavid van Moolenbroek 	looknew->section_additional = ISC_TRUE;
827*00b67f09SDavid van Moolenbroek 	looknew->new_search = ISC_FALSE;
828*00b67f09SDavid van Moolenbroek 	looknew->done_as_is = ISC_FALSE;
829*00b67f09SDavid van Moolenbroek 	looknew->need_search = ISC_FALSE;
830*00b67f09SDavid van Moolenbroek 	looknew->ecs_addr = NULL;
831*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
832*00b67f09SDavid van Moolenbroek 	looknew->sitvalue = NULL;
833*00b67f09SDavid van Moolenbroek #endif
834*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&looknew->fdomain);
835*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(looknew, link);
836*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(looknew->q);
837*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(looknew->connecting);
838*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(looknew->my_server_list);
839*00b67f09SDavid van Moolenbroek 	return (looknew);
840*00b67f09SDavid van Moolenbroek }
841*00b67f09SDavid van Moolenbroek 
842*00b67f09SDavid van Moolenbroek /*%
843*00b67f09SDavid van Moolenbroek  * Clone a lookup, perhaps copying the server list.  This does not clone
844*00b67f09SDavid van Moolenbroek  * the query list, since it will be regenerated by the setup_lookup()
845*00b67f09SDavid van Moolenbroek  * function, nor does it queue up the new lookup for processing.
846*00b67f09SDavid van Moolenbroek  * Caution: If you don't clone the servers, you MUST clone the server
847*00b67f09SDavid van Moolenbroek  * list separately from somewhere else, or construct it by hand.
848*00b67f09SDavid van Moolenbroek  */
849*00b67f09SDavid van Moolenbroek dig_lookup_t *
clone_lookup(dig_lookup_t * lookold,isc_boolean_t servers)850*00b67f09SDavid van Moolenbroek clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
851*00b67f09SDavid van Moolenbroek 	dig_lookup_t *looknew;
852*00b67f09SDavid van Moolenbroek 
853*00b67f09SDavid van Moolenbroek 	debug("clone_lookup()");
854*00b67f09SDavid van Moolenbroek 
855*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
856*00b67f09SDavid van Moolenbroek 
857*00b67f09SDavid van Moolenbroek 	looknew = make_empty_lookup();
858*00b67f09SDavid van Moolenbroek 	INSIST(looknew != NULL);
859*00b67f09SDavid van Moolenbroek 	strlcpy(looknew->textname, lookold->textname, MXNAME);
860*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
861*00b67f09SDavid van Moolenbroek 	strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
862*00b67f09SDavid van Moolenbroek #endif
863*00b67f09SDavid van Moolenbroek 	strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
864*00b67f09SDavid van Moolenbroek 	looknew->textname[MXNAME-1] = 0;
865*00b67f09SDavid van Moolenbroek 	looknew->rdtype = lookold->rdtype;
866*00b67f09SDavid van Moolenbroek 	looknew->qrdtype = lookold->qrdtype;
867*00b67f09SDavid van Moolenbroek 	looknew->rdclass = lookold->rdclass;
868*00b67f09SDavid van Moolenbroek 	looknew->rdtypeset = lookold->rdtypeset;
869*00b67f09SDavid van Moolenbroek 	looknew->rdclassset = lookold->rdclassset;
870*00b67f09SDavid van Moolenbroek 	looknew->doing_xfr = lookold->doing_xfr;
871*00b67f09SDavid van Moolenbroek 	looknew->ixfr_serial = lookold->ixfr_serial;
872*00b67f09SDavid van Moolenbroek 	looknew->trace = lookold->trace;
873*00b67f09SDavid van Moolenbroek 	looknew->trace_root = lookold->trace_root;
874*00b67f09SDavid van Moolenbroek 	looknew->identify = lookold->identify;
875*00b67f09SDavid van Moolenbroek 	looknew->identify_previous_line = lookold->identify_previous_line;
876*00b67f09SDavid van Moolenbroek 	looknew->ignore = lookold->ignore;
877*00b67f09SDavid van Moolenbroek 	looknew->servfail_stops = lookold->servfail_stops;
878*00b67f09SDavid van Moolenbroek 	looknew->besteffort = lookold->besteffort;
879*00b67f09SDavid van Moolenbroek 	looknew->dnssec = lookold->dnssec;
880*00b67f09SDavid van Moolenbroek 	looknew->expire = lookold->expire;
881*00b67f09SDavid van Moolenbroek 	looknew->nsid = lookold->nsid;
882*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
883*00b67f09SDavid van Moolenbroek 	looknew->sit = lookold->sit;
884*00b67f09SDavid van Moolenbroek 	looknew->sitvalue = lookold->sitvalue;
885*00b67f09SDavid van Moolenbroek #endif
886*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
887*00b67f09SDavid van Moolenbroek 	looknew->sigchase = lookold->sigchase;
888*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
889*00b67f09SDavid van Moolenbroek 	looknew->do_topdown = lookold->do_topdown;
890*00b67f09SDavid van Moolenbroek 	looknew->trace_root_sigchase = lookold->trace_root_sigchase;
891*00b67f09SDavid van Moolenbroek 	looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
892*00b67f09SDavid van Moolenbroek 	looknew->rdtype_sigchase = lookold->rdtype_sigchase;
893*00b67f09SDavid van Moolenbroek 	looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
894*00b67f09SDavid van Moolenbroek 	looknew->rdclass_sigchase = lookold->rdclass_sigchase;
895*00b67f09SDavid van Moolenbroek 	looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
896*00b67f09SDavid van Moolenbroek #endif
897*00b67f09SDavid van Moolenbroek #endif
898*00b67f09SDavid van Moolenbroek 	looknew->udpsize = lookold->udpsize;
899*00b67f09SDavid van Moolenbroek 	looknew->edns = lookold->edns;
900*00b67f09SDavid van Moolenbroek 	looknew->recurse = lookold->recurse;
901*00b67f09SDavid van Moolenbroek 	looknew->aaonly = lookold->aaonly;
902*00b67f09SDavid van Moolenbroek 	looknew->adflag = lookold->adflag;
903*00b67f09SDavid van Moolenbroek 	looknew->cdflag = lookold->cdflag;
904*00b67f09SDavid van Moolenbroek 	looknew->ns_search_only = lookold->ns_search_only;
905*00b67f09SDavid van Moolenbroek 	looknew->tcp_mode = lookold->tcp_mode;
906*00b67f09SDavid van Moolenbroek 	looknew->tcp_mode_set = lookold->tcp_mode_set;
907*00b67f09SDavid van Moolenbroek 	looknew->comments = lookold->comments;
908*00b67f09SDavid van Moolenbroek 	looknew->stats = lookold->stats;
909*00b67f09SDavid van Moolenbroek 	looknew->section_question = lookold->section_question;
910*00b67f09SDavid van Moolenbroek 	looknew->section_answer = lookold->section_answer;
911*00b67f09SDavid van Moolenbroek 	looknew->section_authority = lookold->section_authority;
912*00b67f09SDavid van Moolenbroek 	looknew->section_additional = lookold->section_additional;
913*00b67f09SDavid van Moolenbroek 	looknew->retries = lookold->retries;
914*00b67f09SDavid van Moolenbroek 	looknew->tsigctx = NULL;
915*00b67f09SDavid van Moolenbroek 	looknew->need_search = lookold->need_search;
916*00b67f09SDavid van Moolenbroek 	looknew->done_as_is = lookold->done_as_is;
917*00b67f09SDavid van Moolenbroek 
918*00b67f09SDavid van Moolenbroek 	if (lookold->ecs_addr != NULL) {
919*00b67f09SDavid van Moolenbroek 		size_t len = sizeof(isc_sockaddr_t);
920*00b67f09SDavid van Moolenbroek 		looknew->ecs_addr = isc_mem_allocate(mctx, len);
921*00b67f09SDavid van Moolenbroek 		memmove(looknew->ecs_addr, lookold->ecs_addr, len);
922*00b67f09SDavid van Moolenbroek 	}
923*00b67f09SDavid van Moolenbroek 
924*00b67f09SDavid van Moolenbroek 	dns_name_copy(dns_fixedname_name(&lookold->fdomain),
925*00b67f09SDavid van Moolenbroek 		      dns_fixedname_name(&looknew->fdomain), NULL);
926*00b67f09SDavid van Moolenbroek 
927*00b67f09SDavid van Moolenbroek 	if (servers)
928*00b67f09SDavid van Moolenbroek 		clone_server_list(lookold->my_server_list,
929*00b67f09SDavid van Moolenbroek 				  &looknew->my_server_list);
930*00b67f09SDavid van Moolenbroek 	return (looknew);
931*00b67f09SDavid van Moolenbroek }
932*00b67f09SDavid van Moolenbroek 
933*00b67f09SDavid van Moolenbroek /*%
934*00b67f09SDavid van Moolenbroek  * Requeue a lookup for further processing, perhaps copying the server
935*00b67f09SDavid van Moolenbroek  * list.  The new lookup structure is returned to the caller, and is
936*00b67f09SDavid van Moolenbroek  * queued for processing.  If servers are not cloned in the requeue, they
937*00b67f09SDavid van Moolenbroek  * must be added before allowing the current event to complete, since the
938*00b67f09SDavid van Moolenbroek  * completion of the event may result in the next entry on the lookup
939*00b67f09SDavid van Moolenbroek  * queue getting run.
940*00b67f09SDavid van Moolenbroek  */
941*00b67f09SDavid van Moolenbroek dig_lookup_t *
requeue_lookup(dig_lookup_t * lookold,isc_boolean_t servers)942*00b67f09SDavid van Moolenbroek requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
943*00b67f09SDavid van Moolenbroek 	dig_lookup_t *looknew;
944*00b67f09SDavid van Moolenbroek 
945*00b67f09SDavid van Moolenbroek 	debug("requeue_lookup()");
946*00b67f09SDavid van Moolenbroek 
947*00b67f09SDavid van Moolenbroek 	lookup_counter++;
948*00b67f09SDavid van Moolenbroek 	if (lookup_counter > LOOKUP_LIMIT)
949*00b67f09SDavid van Moolenbroek 		fatal("too many lookups");
950*00b67f09SDavid van Moolenbroek 
951*00b67f09SDavid van Moolenbroek 	looknew = clone_lookup(lookold, servers);
952*00b67f09SDavid van Moolenbroek 	INSIST(looknew != NULL);
953*00b67f09SDavid van Moolenbroek 
954*00b67f09SDavid van Moolenbroek 	debug("before insertion, init@%p -> %p, new@%p -> %p",
955*00b67f09SDavid van Moolenbroek 	      lookold, lookold->link.next, looknew, looknew->link.next);
956*00b67f09SDavid van Moolenbroek 	ISC_LIST_PREPEND(lookup_list, looknew, link);
957*00b67f09SDavid van Moolenbroek 	debug("after insertion, init -> %p, new = %p, new -> %p",
958*00b67f09SDavid van Moolenbroek 	      lookold, looknew, looknew->link.next);
959*00b67f09SDavid van Moolenbroek 	return (looknew);
960*00b67f09SDavid van Moolenbroek }
961*00b67f09SDavid van Moolenbroek 
962*00b67f09SDavid van Moolenbroek 
963*00b67f09SDavid van Moolenbroek static void
setup_text_key(void)964*00b67f09SDavid van Moolenbroek setup_text_key(void) {
965*00b67f09SDavid van Moolenbroek 	isc_result_t result;
966*00b67f09SDavid van Moolenbroek 	dns_name_t keyname;
967*00b67f09SDavid van Moolenbroek 	isc_buffer_t secretbuf;
968*00b67f09SDavid van Moolenbroek 	int secretsize;
969*00b67f09SDavid van Moolenbroek 	unsigned char *secretstore;
970*00b67f09SDavid van Moolenbroek 
971*00b67f09SDavid van Moolenbroek 	debug("setup_text_key()");
972*00b67f09SDavid van Moolenbroek 	result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
973*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_buffer_allocate");
974*00b67f09SDavid van Moolenbroek 	dns_name_init(&keyname, NULL);
975*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_name_init");
976*00b67f09SDavid van Moolenbroek 	isc_buffer_putstr(namebuf, keynametext);
977*00b67f09SDavid van Moolenbroek 	secretsize = strlen(keysecret) * 3 / 4;
978*00b67f09SDavid van Moolenbroek 	secretstore = isc_mem_allocate(mctx, secretsize);
979*00b67f09SDavid van Moolenbroek 	if (secretstore == NULL)
980*00b67f09SDavid van Moolenbroek 		fatal("memory allocation failure in %s:%d",
981*00b67f09SDavid van Moolenbroek 		      __FILE__, __LINE__);
982*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&secretbuf, secretstore, secretsize);
983*00b67f09SDavid van Moolenbroek 	result = isc_base64_decodestring(keysecret, &secretbuf);
984*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
985*00b67f09SDavid van Moolenbroek 		goto failure;
986*00b67f09SDavid van Moolenbroek 
987*00b67f09SDavid van Moolenbroek 	secretsize = isc_buffer_usedlength(&secretbuf);
988*00b67f09SDavid van Moolenbroek 
989*00b67f09SDavid van Moolenbroek 	if (hmacname == NULL) {
990*00b67f09SDavid van Moolenbroek 		result = DST_R_UNSUPPORTEDALG;
991*00b67f09SDavid van Moolenbroek 		goto failure;
992*00b67f09SDavid van Moolenbroek 	}
993*00b67f09SDavid van Moolenbroek 
994*00b67f09SDavid van Moolenbroek 	result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
995*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
996*00b67f09SDavid van Moolenbroek 		goto failure;
997*00b67f09SDavid van Moolenbroek 
998*00b67f09SDavid van Moolenbroek 	result = dns_tsigkey_create(&keyname, hmacname, secretstore,
999*00b67f09SDavid van Moolenbroek 				    secretsize, ISC_FALSE, NULL, 0, 0, mctx,
1000*00b67f09SDavid van Moolenbroek 				    NULL, &key);
1001*00b67f09SDavid van Moolenbroek  failure:
1002*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1003*00b67f09SDavid van Moolenbroek 		printf(";; Couldn't create key %s: %s\n",
1004*00b67f09SDavid van Moolenbroek 		       keynametext, isc_result_totext(result));
1005*00b67f09SDavid van Moolenbroek 	else
1006*00b67f09SDavid van Moolenbroek 		dst_key_setbits(key->key, digestbits);
1007*00b67f09SDavid van Moolenbroek 
1008*00b67f09SDavid van Moolenbroek 	isc_mem_free(mctx, secretstore);
1009*00b67f09SDavid van Moolenbroek 	dns_name_invalidate(&keyname);
1010*00b67f09SDavid van Moolenbroek 	isc_buffer_free(&namebuf);
1011*00b67f09SDavid van Moolenbroek }
1012*00b67f09SDavid van Moolenbroek 
1013*00b67f09SDavid van Moolenbroek isc_result_t
parse_uint(isc_uint32_t * uip,const char * value,isc_uint32_t max,const char * desc)1014*00b67f09SDavid van Moolenbroek parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
1015*00b67f09SDavid van Moolenbroek 	   const char *desc) {
1016*00b67f09SDavid van Moolenbroek 	isc_uint32_t n;
1017*00b67f09SDavid van Moolenbroek 	isc_result_t result = isc_parse_uint32(&n, value, 10);
1018*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS && n > max)
1019*00b67f09SDavid van Moolenbroek 		result = ISC_R_RANGE;
1020*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1021*00b67f09SDavid van Moolenbroek 		printf("invalid %s '%s': %s\n", desc,
1022*00b67f09SDavid van Moolenbroek 		       value, isc_result_totext(result));
1023*00b67f09SDavid van Moolenbroek 		return (result);
1024*00b67f09SDavid van Moolenbroek 	}
1025*00b67f09SDavid van Moolenbroek 	*uip = n;
1026*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1027*00b67f09SDavid van Moolenbroek }
1028*00b67f09SDavid van Moolenbroek 
1029*00b67f09SDavid van Moolenbroek static isc_uint32_t
parse_bits(char * arg,const char * desc,isc_uint32_t max)1030*00b67f09SDavid van Moolenbroek parse_bits(char *arg, const char *desc, isc_uint32_t max) {
1031*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1032*00b67f09SDavid van Moolenbroek 	isc_uint32_t tmp;
1033*00b67f09SDavid van Moolenbroek 
1034*00b67f09SDavid van Moolenbroek 	result = parse_uint(&tmp, arg, max, desc);
1035*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1036*00b67f09SDavid van Moolenbroek 		fatal("couldn't parse digest bits");
1037*00b67f09SDavid van Moolenbroek 	tmp = (tmp + 7) & ~0x7U;
1038*00b67f09SDavid van Moolenbroek 	return (tmp);
1039*00b67f09SDavid van Moolenbroek }
1040*00b67f09SDavid van Moolenbroek 
1041*00b67f09SDavid van Moolenbroek isc_result_t
parse_netprefix(isc_sockaddr_t ** sap,const char * value)1042*00b67f09SDavid van Moolenbroek parse_netprefix(isc_sockaddr_t **sap, const char *value) {
1043*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
1044*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t *sa = NULL;
1045*00b67f09SDavid van Moolenbroek 	struct in_addr in4;
1046*00b67f09SDavid van Moolenbroek 	struct in6_addr in6;
1047*00b67f09SDavid van Moolenbroek 	isc_uint32_t netmask = 0;
1048*00b67f09SDavid van Moolenbroek 	char *slash = NULL;
1049*00b67f09SDavid van Moolenbroek 	isc_boolean_t parsed = ISC_FALSE;
1050*00b67f09SDavid van Moolenbroek 
1051*00b67f09SDavid van Moolenbroek 	if ((slash = strchr(value, '/'))) {
1052*00b67f09SDavid van Moolenbroek 		*slash = '\0';
1053*00b67f09SDavid van Moolenbroek 		result = isc_parse_uint32(&netmask, slash + 1, 10);
1054*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
1055*00b67f09SDavid van Moolenbroek 			*slash = '/';
1056*00b67f09SDavid van Moolenbroek 			fatal("invalid prefix length '%s': %s\n",
1057*00b67f09SDavid van Moolenbroek 			      value, isc_result_totext(result));
1058*00b67f09SDavid van Moolenbroek 		}
1059*00b67f09SDavid van Moolenbroek 	}
1060*00b67f09SDavid van Moolenbroek 
1061*00b67f09SDavid van Moolenbroek 	sa = isc_mem_allocate(mctx, sizeof(*sa));
1062*00b67f09SDavid van Moolenbroek 	if (inet_pton(AF_INET6, value, &in6) == 1) {
1063*00b67f09SDavid van Moolenbroek 		isc_sockaddr_fromin6(sa, &in6, 0);
1064*00b67f09SDavid van Moolenbroek 		parsed = ISC_TRUE;
1065*00b67f09SDavid van Moolenbroek 		if (netmask == 0 || netmask > 128)
1066*00b67f09SDavid van Moolenbroek 			netmask = 128;
1067*00b67f09SDavid van Moolenbroek 	} else if (inet_pton(AF_INET, value, &in4) == 1) {
1068*00b67f09SDavid van Moolenbroek 		parsed = ISC_TRUE;
1069*00b67f09SDavid van Moolenbroek 		isc_sockaddr_fromin(sa, &in4, 0);
1070*00b67f09SDavid van Moolenbroek 		if (netmask == 0 || netmask > 32)
1071*00b67f09SDavid van Moolenbroek 			netmask = 32;
1072*00b67f09SDavid van Moolenbroek 	} else if (netmask != 0) {
1073*00b67f09SDavid van Moolenbroek 		char buf[64];
1074*00b67f09SDavid van Moolenbroek 		int i;
1075*00b67f09SDavid van Moolenbroek 
1076*00b67f09SDavid van Moolenbroek 		strlcpy(buf, value, sizeof(buf));
1077*00b67f09SDavid van Moolenbroek 		for (i = 0; i < 3; i++) {
1078*00b67f09SDavid van Moolenbroek 			strlcat(buf, ".0", sizeof(buf));
1079*00b67f09SDavid van Moolenbroek 			if (inet_pton(AF_INET, buf, &in4) == 1) {
1080*00b67f09SDavid van Moolenbroek 				parsed = ISC_TRUE;
1081*00b67f09SDavid van Moolenbroek 				isc_sockaddr_fromin(sa, &in4, 0);
1082*00b67f09SDavid van Moolenbroek 				break;
1083*00b67f09SDavid van Moolenbroek 			}
1084*00b67f09SDavid van Moolenbroek 		}
1085*00b67f09SDavid van Moolenbroek 
1086*00b67f09SDavid van Moolenbroek 	}
1087*00b67f09SDavid van Moolenbroek 
1088*00b67f09SDavid van Moolenbroek 	if (slash != NULL)
1089*00b67f09SDavid van Moolenbroek 		*slash = '/';
1090*00b67f09SDavid van Moolenbroek 
1091*00b67f09SDavid van Moolenbroek 	if (!parsed)
1092*00b67f09SDavid van Moolenbroek 		fatal("invalid address '%s'", value);
1093*00b67f09SDavid van Moolenbroek 
1094*00b67f09SDavid van Moolenbroek 	sa->length = netmask;
1095*00b67f09SDavid van Moolenbroek 	*sap = sa;
1096*00b67f09SDavid van Moolenbroek 
1097*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1098*00b67f09SDavid van Moolenbroek }
1099*00b67f09SDavid van Moolenbroek 
1100*00b67f09SDavid van Moolenbroek 
1101*00b67f09SDavid van Moolenbroek /*
1102*00b67f09SDavid van Moolenbroek  * Parse HMAC algorithm specification
1103*00b67f09SDavid van Moolenbroek  */
1104*00b67f09SDavid van Moolenbroek void
parse_hmac(const char * hmac)1105*00b67f09SDavid van Moolenbroek parse_hmac(const char *hmac) {
1106*00b67f09SDavid van Moolenbroek 	char buf[20];
1107*00b67f09SDavid van Moolenbroek 	int len;
1108*00b67f09SDavid van Moolenbroek 
1109*00b67f09SDavid van Moolenbroek 	REQUIRE(hmac != NULL);
1110*00b67f09SDavid van Moolenbroek 
1111*00b67f09SDavid van Moolenbroek 	len = strlen(hmac);
1112*00b67f09SDavid van Moolenbroek 	if (len >= (int) sizeof(buf))
1113*00b67f09SDavid van Moolenbroek 		fatal("unknown key type '%.*s'", len, hmac);
1114*00b67f09SDavid van Moolenbroek 	strlcpy(buf, hmac, sizeof(buf));
1115*00b67f09SDavid van Moolenbroek 
1116*00b67f09SDavid van Moolenbroek 	digestbits = 0;
1117*00b67f09SDavid van Moolenbroek 
1118*00b67f09SDavid van Moolenbroek 	if (strcasecmp(buf, "hmac-md5") == 0) {
1119*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACMD5_NAME;
1120*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
1121*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACMD5_NAME;
1122*00b67f09SDavid van Moolenbroek 		digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
1123*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(buf, "hmac-sha1") == 0) {
1124*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA1_NAME;
1125*00b67f09SDavid van Moolenbroek 		digestbits = 0;
1126*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
1127*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA1_NAME;
1128*00b67f09SDavid van Moolenbroek 		digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
1129*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(buf, "hmac-sha224") == 0) {
1130*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA224_NAME;
1131*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
1132*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA224_NAME;
1133*00b67f09SDavid van Moolenbroek 		digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
1134*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(buf, "hmac-sha256") == 0) {
1135*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA256_NAME;
1136*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1137*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA256_NAME;
1138*00b67f09SDavid van Moolenbroek 		digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
1139*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(buf, "hmac-sha384") == 0) {
1140*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA384_NAME;
1141*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1142*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA384_NAME;
1143*00b67f09SDavid van Moolenbroek 		digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
1144*00b67f09SDavid van Moolenbroek 	} else if (strcasecmp(buf, "hmac-sha512") == 0) {
1145*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA512_NAME;
1146*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1147*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA512_NAME;
1148*00b67f09SDavid van Moolenbroek 		digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
1149*00b67f09SDavid van Moolenbroek 	} else {
1150*00b67f09SDavid van Moolenbroek 		fprintf(stderr, ";; Warning, ignoring "
1151*00b67f09SDavid van Moolenbroek 			"invalid TSIG algorithm %s\n", buf);
1152*00b67f09SDavid van Moolenbroek 	}
1153*00b67f09SDavid van Moolenbroek }
1154*00b67f09SDavid van Moolenbroek 
1155*00b67f09SDavid van Moolenbroek /*
1156*00b67f09SDavid van Moolenbroek  * Get a key from a named.conf format keyfile
1157*00b67f09SDavid van Moolenbroek  */
1158*00b67f09SDavid van Moolenbroek static isc_result_t
read_confkey(void)1159*00b67f09SDavid van Moolenbroek read_confkey(void) {
1160*00b67f09SDavid van Moolenbroek 	cfg_parser_t *pctx = NULL;
1161*00b67f09SDavid van Moolenbroek 	cfg_obj_t *file = NULL;
1162*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *keyobj = NULL;
1163*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *secretobj = NULL;
1164*00b67f09SDavid van Moolenbroek 	const cfg_obj_t *algorithmobj = NULL;
1165*00b67f09SDavid van Moolenbroek 	const char *keyname;
1166*00b67f09SDavid van Moolenbroek 	const char *secretstr;
1167*00b67f09SDavid van Moolenbroek 	const char *algorithm;
1168*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1169*00b67f09SDavid van Moolenbroek 
1170*00b67f09SDavid van Moolenbroek 	if (! isc_file_exists(keyfile))
1171*00b67f09SDavid van Moolenbroek 		return (ISC_R_FILENOTFOUND);
1172*00b67f09SDavid van Moolenbroek 
1173*00b67f09SDavid van Moolenbroek 	result = cfg_parser_create(mctx, NULL, &pctx);
1174*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1175*00b67f09SDavid van Moolenbroek 		goto cleanup;
1176*00b67f09SDavid van Moolenbroek 
1177*00b67f09SDavid van Moolenbroek 	result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1178*00b67f09SDavid van Moolenbroek 				&file);
1179*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1180*00b67f09SDavid van Moolenbroek 		goto cleanup;
1181*00b67f09SDavid van Moolenbroek 
1182*00b67f09SDavid van Moolenbroek 	result = cfg_map_get(file, "key", &keyobj);
1183*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1184*00b67f09SDavid van Moolenbroek 		goto cleanup;
1185*00b67f09SDavid van Moolenbroek 
1186*00b67f09SDavid van Moolenbroek 	(void) cfg_map_get(keyobj, "secret", &secretobj);
1187*00b67f09SDavid van Moolenbroek 	(void) cfg_map_get(keyobj, "algorithm", &algorithmobj);
1188*00b67f09SDavid van Moolenbroek 	if (secretobj == NULL || algorithmobj == NULL)
1189*00b67f09SDavid van Moolenbroek 		fatal("key must have algorithm and secret");
1190*00b67f09SDavid van Moolenbroek 
1191*00b67f09SDavid van Moolenbroek 	keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
1192*00b67f09SDavid van Moolenbroek 	secretstr = cfg_obj_asstring(secretobj);
1193*00b67f09SDavid van Moolenbroek 	algorithm = cfg_obj_asstring(algorithmobj);
1194*00b67f09SDavid van Moolenbroek 
1195*00b67f09SDavid van Moolenbroek 	strlcpy(keynametext, keyname, sizeof(keynametext));
1196*00b67f09SDavid van Moolenbroek 	strlcpy(keysecret, secretstr, sizeof(keysecret));
1197*00b67f09SDavid van Moolenbroek 	parse_hmac(algorithm);
1198*00b67f09SDavid van Moolenbroek 	setup_text_key();
1199*00b67f09SDavid van Moolenbroek 
1200*00b67f09SDavid van Moolenbroek  cleanup:
1201*00b67f09SDavid van Moolenbroek 	if (pctx != NULL) {
1202*00b67f09SDavid van Moolenbroek 		if (file != NULL)
1203*00b67f09SDavid van Moolenbroek 			cfg_obj_destroy(pctx, &file);
1204*00b67f09SDavid van Moolenbroek 		cfg_parser_destroy(&pctx);
1205*00b67f09SDavid van Moolenbroek 	}
1206*00b67f09SDavid van Moolenbroek 
1207*00b67f09SDavid van Moolenbroek 	return (result);
1208*00b67f09SDavid van Moolenbroek }
1209*00b67f09SDavid van Moolenbroek 
1210*00b67f09SDavid van Moolenbroek static void
setup_file_key(void)1211*00b67f09SDavid van Moolenbroek setup_file_key(void) {
1212*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1213*00b67f09SDavid van Moolenbroek 	dst_key_t *dstkey = NULL;
1214*00b67f09SDavid van Moolenbroek 
1215*00b67f09SDavid van Moolenbroek 	debug("setup_file_key()");
1216*00b67f09SDavid van Moolenbroek 
1217*00b67f09SDavid van Moolenbroek 	/* Try reading the key from a K* pair */
1218*00b67f09SDavid van Moolenbroek 	result = dst_key_fromnamedfile(keyfile, NULL,
1219*00b67f09SDavid van Moolenbroek 				       DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
1220*00b67f09SDavid van Moolenbroek 				       &dstkey);
1221*00b67f09SDavid van Moolenbroek 
1222*00b67f09SDavid van Moolenbroek 	/* If that didn't work, try reading it as a session.key keyfile */
1223*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1224*00b67f09SDavid van Moolenbroek 		result = read_confkey();
1225*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS)
1226*00b67f09SDavid van Moolenbroek 			return;
1227*00b67f09SDavid van Moolenbroek 	}
1228*00b67f09SDavid van Moolenbroek 
1229*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1230*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "Couldn't read key from %s: %s\n",
1231*00b67f09SDavid van Moolenbroek 			keyfile, isc_result_totext(result));
1232*00b67f09SDavid van Moolenbroek 		goto failure;
1233*00b67f09SDavid van Moolenbroek 	}
1234*00b67f09SDavid van Moolenbroek 
1235*00b67f09SDavid van Moolenbroek 	switch (dst_key_alg(dstkey)) {
1236*00b67f09SDavid van Moolenbroek 	case DST_ALG_HMACMD5:
1237*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACMD5_NAME;
1238*00b67f09SDavid van Moolenbroek 		break;
1239*00b67f09SDavid van Moolenbroek 	case DST_ALG_HMACSHA1:
1240*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA1_NAME;
1241*00b67f09SDavid van Moolenbroek 		break;
1242*00b67f09SDavid van Moolenbroek 	case DST_ALG_HMACSHA224:
1243*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA224_NAME;
1244*00b67f09SDavid van Moolenbroek 		break;
1245*00b67f09SDavid van Moolenbroek 	case DST_ALG_HMACSHA256:
1246*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA256_NAME;
1247*00b67f09SDavid van Moolenbroek 		break;
1248*00b67f09SDavid van Moolenbroek 	case DST_ALG_HMACSHA384:
1249*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA384_NAME;
1250*00b67f09SDavid van Moolenbroek 		break;
1251*00b67f09SDavid van Moolenbroek 	case DST_ALG_HMACSHA512:
1252*00b67f09SDavid van Moolenbroek 		hmacname = DNS_TSIG_HMACSHA512_NAME;
1253*00b67f09SDavid van Moolenbroek 		break;
1254*00b67f09SDavid van Moolenbroek 	default:
1255*00b67f09SDavid van Moolenbroek 		printf(";; Couldn't create key %s: bad algorithm\n",
1256*00b67f09SDavid van Moolenbroek 		       keynametext);
1257*00b67f09SDavid van Moolenbroek 		goto failure;
1258*00b67f09SDavid van Moolenbroek 	}
1259*00b67f09SDavid van Moolenbroek 	result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
1260*00b67f09SDavid van Moolenbroek 					   dstkey, ISC_FALSE, NULL, 0, 0,
1261*00b67f09SDavid van Moolenbroek 					   mctx, NULL, &key);
1262*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1263*00b67f09SDavid van Moolenbroek 		printf(";; Couldn't create key %s: %s\n",
1264*00b67f09SDavid van Moolenbroek 		       keynametext, isc_result_totext(result));
1265*00b67f09SDavid van Moolenbroek 		goto failure;
1266*00b67f09SDavid van Moolenbroek 	}
1267*00b67f09SDavid van Moolenbroek  failure:
1268*00b67f09SDavid van Moolenbroek 	if (dstkey != NULL)
1269*00b67f09SDavid van Moolenbroek 		dst_key_free(&dstkey);
1270*00b67f09SDavid van Moolenbroek }
1271*00b67f09SDavid van Moolenbroek 
1272*00b67f09SDavid van Moolenbroek static dig_searchlist_t *
make_searchlist_entry(char * domain)1273*00b67f09SDavid van Moolenbroek make_searchlist_entry(char *domain) {
1274*00b67f09SDavid van Moolenbroek 	dig_searchlist_t *search;
1275*00b67f09SDavid van Moolenbroek 	search = isc_mem_allocate(mctx, sizeof(*search));
1276*00b67f09SDavid van Moolenbroek 	if (search == NULL)
1277*00b67f09SDavid van Moolenbroek 		fatal("memory allocation failure in %s:%d",
1278*00b67f09SDavid van Moolenbroek 		      __FILE__, __LINE__);
1279*00b67f09SDavid van Moolenbroek 	strlcpy(search->origin, domain, MXNAME);
1280*00b67f09SDavid van Moolenbroek 	search->origin[MXNAME-1] = 0;
1281*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(search, link);
1282*00b67f09SDavid van Moolenbroek 	return (search);
1283*00b67f09SDavid van Moolenbroek }
1284*00b67f09SDavid van Moolenbroek 
1285*00b67f09SDavid van Moolenbroek static void
clear_searchlist(void)1286*00b67f09SDavid van Moolenbroek clear_searchlist(void) {
1287*00b67f09SDavid van Moolenbroek 	dig_searchlist_t *search;
1288*00b67f09SDavid van Moolenbroek 	while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1289*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(search_list, search, link);
1290*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, search);
1291*00b67f09SDavid van Moolenbroek 	}
1292*00b67f09SDavid van Moolenbroek }
1293*00b67f09SDavid van Moolenbroek 
1294*00b67f09SDavid van Moolenbroek static void
create_search_list(lwres_conf_t * confdata)1295*00b67f09SDavid van Moolenbroek create_search_list(lwres_conf_t *confdata) {
1296*00b67f09SDavid van Moolenbroek 	int i;
1297*00b67f09SDavid van Moolenbroek 	dig_searchlist_t *search;
1298*00b67f09SDavid van Moolenbroek 
1299*00b67f09SDavid van Moolenbroek 	debug("create_search_list()");
1300*00b67f09SDavid van Moolenbroek 	clear_searchlist();
1301*00b67f09SDavid van Moolenbroek 
1302*00b67f09SDavid van Moolenbroek 	for (i = 0; i < confdata->searchnxt; i++) {
1303*00b67f09SDavid van Moolenbroek 		search = make_searchlist_entry(confdata->search[i]);
1304*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(search_list, search, link);
1305*00b67f09SDavid van Moolenbroek 	}
1306*00b67f09SDavid van Moolenbroek }
1307*00b67f09SDavid van Moolenbroek 
1308*00b67f09SDavid van Moolenbroek /*%
1309*00b67f09SDavid van Moolenbroek  * Setup the system as a whole, reading key information and resolv.conf
1310*00b67f09SDavid van Moolenbroek  * settings.
1311*00b67f09SDavid van Moolenbroek  */
1312*00b67f09SDavid van Moolenbroek void
setup_system(void)1313*00b67f09SDavid van Moolenbroek setup_system(void) {
1314*00b67f09SDavid van Moolenbroek 	dig_searchlist_t *domain = NULL;
1315*00b67f09SDavid van Moolenbroek 	lwres_result_t lwresult;
1316*00b67f09SDavid van Moolenbroek 	unsigned int lwresflags;
1317*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1318*00b67f09SDavid van Moolenbroek 
1319*00b67f09SDavid van Moolenbroek 	debug("setup_system()");
1320*00b67f09SDavid van Moolenbroek 
1321*00b67f09SDavid van Moolenbroek 	lwresflags = LWRES_CONTEXT_SERVERMODE;
1322*00b67f09SDavid van Moolenbroek 	if (have_ipv4)
1323*00b67f09SDavid van Moolenbroek 		lwresflags |= LWRES_CONTEXT_USEIPV4;
1324*00b67f09SDavid van Moolenbroek 	if (have_ipv6)
1325*00b67f09SDavid van Moolenbroek 		lwresflags |= LWRES_CONTEXT_USEIPV6;
1326*00b67f09SDavid van Moolenbroek 
1327*00b67f09SDavid van Moolenbroek 	lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
1328*00b67f09SDavid van Moolenbroek 					lwresflags);
1329*00b67f09SDavid van Moolenbroek 	if (lwresult != LWRES_R_SUCCESS)
1330*00b67f09SDavid van Moolenbroek 		fatal("lwres_context_create failed");
1331*00b67f09SDavid van Moolenbroek 
1332*00b67f09SDavid van Moolenbroek 	lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
1333*00b67f09SDavid van Moolenbroek 	if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1334*00b67f09SDavid van Moolenbroek 		fatal("parse of %s failed", RESOLV_CONF);
1335*00b67f09SDavid van Moolenbroek 
1336*00b67f09SDavid van Moolenbroek 	lwconf = lwres_conf_get(lwctx);
1337*00b67f09SDavid van Moolenbroek 
1338*00b67f09SDavid van Moolenbroek 	/* Make the search list */
1339*00b67f09SDavid van Moolenbroek 	if (lwconf->searchnxt > 0)
1340*00b67f09SDavid van Moolenbroek 		create_search_list(lwconf);
1341*00b67f09SDavid van Moolenbroek 	else { /* No search list. Use the domain name if any */
1342*00b67f09SDavid van Moolenbroek 		if (lwconf->domainname != NULL) {
1343*00b67f09SDavid van Moolenbroek 			domain = make_searchlist_entry(lwconf->domainname);
1344*00b67f09SDavid van Moolenbroek 			ISC_LIST_APPEND(search_list, domain, link);
1345*00b67f09SDavid van Moolenbroek 			domain  = NULL;
1346*00b67f09SDavid van Moolenbroek 		}
1347*00b67f09SDavid van Moolenbroek 	}
1348*00b67f09SDavid van Moolenbroek 
1349*00b67f09SDavid van Moolenbroek 	if (ndots == -1) {
1350*00b67f09SDavid van Moolenbroek 		ndots = lwconf->ndots;
1351*00b67f09SDavid van Moolenbroek 		debug("ndots is %d.", ndots);
1352*00b67f09SDavid van Moolenbroek 	}
1353*00b67f09SDavid van Moolenbroek 
1354*00b67f09SDavid van Moolenbroek 	/* If user doesn't specify server use nameservers from resolv.conf. */
1355*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_EMPTY(server_list))
1356*00b67f09SDavid van Moolenbroek 		copy_server_list(lwconf, &server_list);
1357*00b67f09SDavid van Moolenbroek 
1358*00b67f09SDavid van Moolenbroek 	/* If we don't find a nameserver fall back to localhost */
1359*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_EMPTY(server_list)) {
1360*00b67f09SDavid van Moolenbroek 		if (have_ipv4) {
1361*00b67f09SDavid van Moolenbroek 			lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1362*00b67f09SDavid van Moolenbroek 			if (lwresult != ISC_R_SUCCESS)
1363*00b67f09SDavid van Moolenbroek 				fatal("add_nameserver failed");
1364*00b67f09SDavid van Moolenbroek 		}
1365*00b67f09SDavid van Moolenbroek 		if (have_ipv6) {
1366*00b67f09SDavid van Moolenbroek 			lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1367*00b67f09SDavid van Moolenbroek 			if (lwresult != ISC_R_SUCCESS)
1368*00b67f09SDavid van Moolenbroek 				fatal("add_nameserver failed");
1369*00b67f09SDavid van Moolenbroek 		}
1370*00b67f09SDavid van Moolenbroek 
1371*00b67f09SDavid van Moolenbroek 		copy_server_list(lwconf, &server_list);
1372*00b67f09SDavid van Moolenbroek 	}
1373*00b67f09SDavid van Moolenbroek 
1374*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
1375*00b67f09SDavid van Moolenbroek 	initialize_idn();
1376*00b67f09SDavid van Moolenbroek #endif
1377*00b67f09SDavid van Moolenbroek 
1378*00b67f09SDavid van Moolenbroek 	if (keyfile[0] != 0)
1379*00b67f09SDavid van Moolenbroek 		setup_file_key();
1380*00b67f09SDavid van Moolenbroek 	else if (keysecret[0] != 0)
1381*00b67f09SDavid van Moolenbroek 		setup_text_key();
1382*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
1383*00b67f09SDavid van Moolenbroek 	/* Setup the list of messages for +sigchase */
1384*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(chase_message_list);
1385*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(chase_message_list2);
1386*00b67f09SDavid van Moolenbroek 	dns_name_init(&chase_name, NULL);
1387*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
1388*00b67f09SDavid van Moolenbroek 	dns_name_init(&chase_current_name, NULL);
1389*00b67f09SDavid van Moolenbroek 	dns_name_init(&chase_authority_name, NULL);
1390*00b67f09SDavid van Moolenbroek #endif
1391*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_BU
1392*00b67f09SDavid van Moolenbroek 	dns_name_init(&chase_signame, NULL);
1393*00b67f09SDavid van Moolenbroek #endif
1394*00b67f09SDavid van Moolenbroek 
1395*00b67f09SDavid van Moolenbroek #endif
1396*00b67f09SDavid van Moolenbroek 	result = isc_entropy_getdata(entp, cookie_secret,
1397*00b67f09SDavid van Moolenbroek 				     sizeof(cookie_secret), NULL, 0);
1398*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1399*00b67f09SDavid van Moolenbroek 		fatal("unable to generate cookie secret");
1400*00b67f09SDavid van Moolenbroek }
1401*00b67f09SDavid van Moolenbroek 
1402*00b67f09SDavid van Moolenbroek /*%
1403*00b67f09SDavid van Moolenbroek  * Override the search list derived from resolv.conf by 'domain'.
1404*00b67f09SDavid van Moolenbroek  */
1405*00b67f09SDavid van Moolenbroek void
set_search_domain(char * domain)1406*00b67f09SDavid van Moolenbroek set_search_domain(char *domain) {
1407*00b67f09SDavid van Moolenbroek 	dig_searchlist_t *search;
1408*00b67f09SDavid van Moolenbroek 
1409*00b67f09SDavid van Moolenbroek 	clear_searchlist();
1410*00b67f09SDavid van Moolenbroek 	search = make_searchlist_entry(domain);
1411*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(search_list, search, link);
1412*00b67f09SDavid van Moolenbroek }
1413*00b67f09SDavid van Moolenbroek 
1414*00b67f09SDavid van Moolenbroek /*%
1415*00b67f09SDavid van Moolenbroek  * Setup the ISC and DNS libraries for use by the system.
1416*00b67f09SDavid van Moolenbroek  */
1417*00b67f09SDavid van Moolenbroek void
setup_libs(void)1418*00b67f09SDavid van Moolenbroek setup_libs(void) {
1419*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1420*00b67f09SDavid van Moolenbroek 	isc_logconfig_t *logconfig = NULL;
1421*00b67f09SDavid van Moolenbroek 
1422*00b67f09SDavid van Moolenbroek 	debug("setup_libs()");
1423*00b67f09SDavid van Moolenbroek 
1424*00b67f09SDavid van Moolenbroek #ifdef PKCS11CRYPTO
1425*00b67f09SDavid van Moolenbroek 	pk11_result_register();
1426*00b67f09SDavid van Moolenbroek #endif
1427*00b67f09SDavid van Moolenbroek 	dns_result_register();
1428*00b67f09SDavid van Moolenbroek 
1429*00b67f09SDavid van Moolenbroek 	result = isc_net_probeipv4();
1430*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
1431*00b67f09SDavid van Moolenbroek 		have_ipv4 = ISC_TRUE;
1432*00b67f09SDavid van Moolenbroek 
1433*00b67f09SDavid van Moolenbroek 	result = isc_net_probeipv6();
1434*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
1435*00b67f09SDavid van Moolenbroek 		have_ipv6 = ISC_TRUE;
1436*00b67f09SDavid van Moolenbroek 	if (!have_ipv6 && !have_ipv4)
1437*00b67f09SDavid van Moolenbroek 		fatal("can't find either v4 or v6 networking");
1438*00b67f09SDavid van Moolenbroek 
1439*00b67f09SDavid van Moolenbroek 	result = isc_mem_create(0, 0, &mctx);
1440*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_mem_create");
1441*00b67f09SDavid van Moolenbroek 	isc_mem_setname(mctx, "dig", NULL);
1442*00b67f09SDavid van Moolenbroek 
1443*00b67f09SDavid van Moolenbroek 	result = isc_log_create(mctx, &lctx, &logconfig);
1444*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_log_create");
1445*00b67f09SDavid van Moolenbroek 
1446*00b67f09SDavid van Moolenbroek 	isc_log_setcontext(lctx);
1447*00b67f09SDavid van Moolenbroek 	dns_log_init(lctx);
1448*00b67f09SDavid van Moolenbroek 	dns_log_setcontext(lctx);
1449*00b67f09SDavid van Moolenbroek 
1450*00b67f09SDavid van Moolenbroek 	result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1451*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_log_usechannel");
1452*00b67f09SDavid van Moolenbroek 
1453*00b67f09SDavid van Moolenbroek 	isc_log_setdebuglevel(lctx, 0);
1454*00b67f09SDavid van Moolenbroek 
1455*00b67f09SDavid van Moolenbroek 	result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
1456*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_taskmgr_create");
1457*00b67f09SDavid van Moolenbroek 
1458*00b67f09SDavid van Moolenbroek 	result = isc_task_create(taskmgr, 0, &global_task);
1459*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_task_create");
1460*00b67f09SDavid van Moolenbroek 	isc_task_setname(global_task, "dig", NULL);
1461*00b67f09SDavid van Moolenbroek 
1462*00b67f09SDavid van Moolenbroek 	result = isc_timermgr_create(mctx, &timermgr);
1463*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_timermgr_create");
1464*00b67f09SDavid van Moolenbroek 
1465*00b67f09SDavid van Moolenbroek 	result = isc_socketmgr_create(mctx, &socketmgr);
1466*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_socketmgr_create");
1467*00b67f09SDavid van Moolenbroek 
1468*00b67f09SDavid van Moolenbroek 	result = isc_entropy_create(mctx, &entp);
1469*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_entropy_create");
1470*00b67f09SDavid van Moolenbroek 
1471*00b67f09SDavid van Moolenbroek 	result = dst_lib_init(mctx, entp, 0);
1472*00b67f09SDavid van Moolenbroek 	check_result(result, "dst_lib_init");
1473*00b67f09SDavid van Moolenbroek 	is_dst_up = ISC_TRUE;
1474*00b67f09SDavid van Moolenbroek 
1475*00b67f09SDavid van Moolenbroek 	result = isc_mempool_create(mctx, COMMSIZE, &commctx);
1476*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_mempool_create");
1477*00b67f09SDavid van Moolenbroek 	isc_mempool_setname(commctx, "COMMPOOL");
1478*00b67f09SDavid van Moolenbroek 	/*
1479*00b67f09SDavid van Moolenbroek 	 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1480*00b67f09SDavid van Moolenbroek 	 * systems.
1481*00b67f09SDavid van Moolenbroek 	 */
1482*00b67f09SDavid van Moolenbroek 	isc_mempool_setfreemax(commctx, 6);
1483*00b67f09SDavid van Moolenbroek 	isc_mempool_setfillcount(commctx, 2);
1484*00b67f09SDavid van Moolenbroek 
1485*00b67f09SDavid van Moolenbroek 	result = isc_mutex_init(&lookup_lock);
1486*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_mutex_init");
1487*00b67f09SDavid van Moolenbroek }
1488*00b67f09SDavid van Moolenbroek 
1489*00b67f09SDavid van Moolenbroek /*%
1490*00b67f09SDavid van Moolenbroek  * Add EDNS0 option record to a message.  Currently, the only supported
1491*00b67f09SDavid van Moolenbroek  * options are UDP buffer size, the DO bit, and EDNS options
1492*00b67f09SDavid van Moolenbroek  * (e.g., NSID, SIT, client-subnet)
1493*00b67f09SDavid van Moolenbroek  */
1494*00b67f09SDavid van Moolenbroek static void
add_opt(dns_message_t * msg,isc_uint16_t udpsize,isc_uint16_t edns,isc_boolean_t dnssec,dns_ednsopt_t * opts,size_t count)1495*00b67f09SDavid van Moolenbroek add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
1496*00b67f09SDavid van Moolenbroek 	isc_boolean_t dnssec, dns_ednsopt_t *opts, size_t count)
1497*00b67f09SDavid van Moolenbroek {
1498*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset = NULL;
1499*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1500*00b67f09SDavid van Moolenbroek 	unsigned int flags = 0;
1501*00b67f09SDavid van Moolenbroek 
1502*00b67f09SDavid van Moolenbroek 	debug("add_opt()");
1503*00b67f09SDavid van Moolenbroek 	if (dnssec)
1504*00b67f09SDavid van Moolenbroek 		flags |= DNS_MESSAGEEXTFLAG_DO;
1505*00b67f09SDavid van Moolenbroek 	result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
1506*00b67f09SDavid van Moolenbroek 				      opts, count);
1507*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_buildopt");
1508*00b67f09SDavid van Moolenbroek 	result = dns_message_setopt(msg, rdataset);
1509*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_setopt");
1510*00b67f09SDavid van Moolenbroek }
1511*00b67f09SDavid van Moolenbroek 
1512*00b67f09SDavid van Moolenbroek /*%
1513*00b67f09SDavid van Moolenbroek  * Add a question section to a message, asking for the specified name,
1514*00b67f09SDavid van Moolenbroek  * type, and class.
1515*00b67f09SDavid van Moolenbroek  */
1516*00b67f09SDavid van Moolenbroek static void
add_question(dns_message_t * message,dns_name_t * name,dns_rdataclass_t rdclass,dns_rdatatype_t rdtype)1517*00b67f09SDavid van Moolenbroek add_question(dns_message_t *message, dns_name_t *name,
1518*00b67f09SDavid van Moolenbroek 	     dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1519*00b67f09SDavid van Moolenbroek {
1520*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset;
1521*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1522*00b67f09SDavid van Moolenbroek 
1523*00b67f09SDavid van Moolenbroek 	debug("add_question()");
1524*00b67f09SDavid van Moolenbroek 	rdataset = NULL;
1525*00b67f09SDavid van Moolenbroek 	result = dns_message_gettemprdataset(message, &rdataset);
1526*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_gettemprdataset()");
1527*00b67f09SDavid van Moolenbroek 	dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1528*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(name->list, rdataset, link);
1529*00b67f09SDavid van Moolenbroek }
1530*00b67f09SDavid van Moolenbroek 
1531*00b67f09SDavid van Moolenbroek /*%
1532*00b67f09SDavid van Moolenbroek  * Check if we're done with all the queued lookups, which is true iff
1533*00b67f09SDavid van Moolenbroek  * all sockets, sends, and recvs are accounted for (counters == 0),
1534*00b67f09SDavid van Moolenbroek  * and the lookup list is empty.
1535*00b67f09SDavid van Moolenbroek  * If we are done, pass control back out to dighost_shutdown() (which is
1536*00b67f09SDavid van Moolenbroek  * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1537*00b67f09SDavid van Moolenbroek  * a whole or reseed the lookup list.
1538*00b67f09SDavid van Moolenbroek  */
1539*00b67f09SDavid van Moolenbroek static void
check_if_done(void)1540*00b67f09SDavid van Moolenbroek check_if_done(void) {
1541*00b67f09SDavid van Moolenbroek 	debug("check_if_done()");
1542*00b67f09SDavid van Moolenbroek 	debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1543*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1544*00b67f09SDavid van Moolenbroek 	    sendcount == 0) {
1545*00b67f09SDavid van Moolenbroek 		INSIST(sockcount == 0);
1546*00b67f09SDavid van Moolenbroek 		INSIST(recvcount == 0);
1547*00b67f09SDavid van Moolenbroek 		debug("shutting down");
1548*00b67f09SDavid van Moolenbroek 		dighost_shutdown();
1549*00b67f09SDavid van Moolenbroek 	}
1550*00b67f09SDavid van Moolenbroek }
1551*00b67f09SDavid van Moolenbroek 
1552*00b67f09SDavid van Moolenbroek /*%
1553*00b67f09SDavid van Moolenbroek  * Clear out a query when we're done with it.  WARNING: This routine
1554*00b67f09SDavid van Moolenbroek  * WILL invalidate the query pointer.
1555*00b67f09SDavid van Moolenbroek  */
1556*00b67f09SDavid van Moolenbroek static void
clear_query(dig_query_t * query)1557*00b67f09SDavid van Moolenbroek clear_query(dig_query_t *query) {
1558*00b67f09SDavid van Moolenbroek 	dig_lookup_t *lookup;
1559*00b67f09SDavid van Moolenbroek 
1560*00b67f09SDavid van Moolenbroek 	REQUIRE(query != NULL);
1561*00b67f09SDavid van Moolenbroek 
1562*00b67f09SDavid van Moolenbroek 	debug("clear_query(%p)", query);
1563*00b67f09SDavid van Moolenbroek 
1564*00b67f09SDavid van Moolenbroek 	lookup = query->lookup;
1565*00b67f09SDavid van Moolenbroek 
1566*00b67f09SDavid van Moolenbroek 	if (lookup->current_query == query)
1567*00b67f09SDavid van Moolenbroek 		lookup->current_query = NULL;
1568*00b67f09SDavid van Moolenbroek 
1569*00b67f09SDavid van Moolenbroek 	if (ISC_LINK_LINKED(query, link))
1570*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(lookup->q, query, link);
1571*00b67f09SDavid van Moolenbroek 	if (ISC_LINK_LINKED(query, clink))
1572*00b67f09SDavid van Moolenbroek 		ISC_LIST_UNLINK(lookup->connecting, query, clink);
1573*00b67f09SDavid van Moolenbroek 	if (ISC_LINK_LINKED(&query->recvbuf, link))
1574*00b67f09SDavid van Moolenbroek 		ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1575*00b67f09SDavid van Moolenbroek 				 link);
1576*00b67f09SDavid van Moolenbroek 	if (ISC_LINK_LINKED(&query->lengthbuf, link))
1577*00b67f09SDavid van Moolenbroek 		ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1578*00b67f09SDavid van Moolenbroek 				 link);
1579*00b67f09SDavid van Moolenbroek 	INSIST(query->recvspace != NULL);
1580*00b67f09SDavid van Moolenbroek 
1581*00b67f09SDavid van Moolenbroek 	if (query->sock != NULL) {
1582*00b67f09SDavid van Moolenbroek 		isc_socket_detach(&query->sock);
1583*00b67f09SDavid van Moolenbroek 		sockcount--;
1584*00b67f09SDavid van Moolenbroek 		debug("sockcount=%d", sockcount);
1585*00b67f09SDavid van Moolenbroek 	}
1586*00b67f09SDavid van Moolenbroek 	isc_mempool_put(commctx, query->recvspace);
1587*00b67f09SDavid van Moolenbroek 	isc_buffer_invalidate(&query->recvbuf);
1588*00b67f09SDavid van Moolenbroek 	isc_buffer_invalidate(&query->lengthbuf);
1589*00b67f09SDavid van Moolenbroek 	if (query->waiting_senddone)
1590*00b67f09SDavid van Moolenbroek 		query->pending_free = ISC_TRUE;
1591*00b67f09SDavid van Moolenbroek 	else
1592*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, query);
1593*00b67f09SDavid van Moolenbroek }
1594*00b67f09SDavid van Moolenbroek 
1595*00b67f09SDavid van Moolenbroek /*%
1596*00b67f09SDavid van Moolenbroek  * Try and clear out a lookup if we're done with it.  Return ISC_TRUE if
1597*00b67f09SDavid van Moolenbroek  * the lookup was successfully cleared.  If ISC_TRUE is returned, the
1598*00b67f09SDavid van Moolenbroek  * lookup pointer has been invalidated.
1599*00b67f09SDavid van Moolenbroek  */
1600*00b67f09SDavid van Moolenbroek static isc_boolean_t
try_clear_lookup(dig_lookup_t * lookup)1601*00b67f09SDavid van Moolenbroek try_clear_lookup(dig_lookup_t *lookup) {
1602*00b67f09SDavid van Moolenbroek 	dig_query_t *q;
1603*00b67f09SDavid van Moolenbroek 
1604*00b67f09SDavid van Moolenbroek 	REQUIRE(lookup != NULL);
1605*00b67f09SDavid van Moolenbroek 
1606*00b67f09SDavid van Moolenbroek 	debug("try_clear_lookup(%p)", lookup);
1607*00b67f09SDavid van Moolenbroek 
1608*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_HEAD(lookup->q) != NULL ||
1609*00b67f09SDavid van Moolenbroek 	    ISC_LIST_HEAD(lookup->connecting) != NULL)
1610*00b67f09SDavid van Moolenbroek 	{
1611*00b67f09SDavid van Moolenbroek 		if (debugging) {
1612*00b67f09SDavid van Moolenbroek 			q = ISC_LIST_HEAD(lookup->q);
1613*00b67f09SDavid van Moolenbroek 			while (q != NULL) {
1614*00b67f09SDavid van Moolenbroek 				debug("query to %s still pending", q->servname);
1615*00b67f09SDavid van Moolenbroek 				q = ISC_LIST_NEXT(q, link);
1616*00b67f09SDavid van Moolenbroek 			}
1617*00b67f09SDavid van Moolenbroek 
1618*00b67f09SDavid van Moolenbroek 			q = ISC_LIST_HEAD(lookup->connecting);
1619*00b67f09SDavid van Moolenbroek 			while (q != NULL) {
1620*00b67f09SDavid van Moolenbroek 				debug("query to %s still connecting",
1621*00b67f09SDavid van Moolenbroek 				      q->servname);
1622*00b67f09SDavid van Moolenbroek 				q = ISC_LIST_NEXT(q, clink);
1623*00b67f09SDavid van Moolenbroek 			}
1624*00b67f09SDavid van Moolenbroek 		}
1625*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
1626*00b67f09SDavid van Moolenbroek 	}
1627*00b67f09SDavid van Moolenbroek 
1628*00b67f09SDavid van Moolenbroek 	/*
1629*00b67f09SDavid van Moolenbroek 	 * At this point, we know there are no queries on the lookup,
1630*00b67f09SDavid van Moolenbroek 	 * so can make it go away also.
1631*00b67f09SDavid van Moolenbroek 	 */
1632*00b67f09SDavid van Moolenbroek 	destroy_lookup(lookup);
1633*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
1634*00b67f09SDavid van Moolenbroek }
1635*00b67f09SDavid van Moolenbroek 
1636*00b67f09SDavid van Moolenbroek void
destroy_lookup(dig_lookup_t * lookup)1637*00b67f09SDavid van Moolenbroek destroy_lookup(dig_lookup_t *lookup) {
1638*00b67f09SDavid van Moolenbroek 	dig_server_t *s;
1639*00b67f09SDavid van Moolenbroek 	void *ptr;
1640*00b67f09SDavid van Moolenbroek 
1641*00b67f09SDavid van Moolenbroek 	debug("destroy");
1642*00b67f09SDavid van Moolenbroek 	s = ISC_LIST_HEAD(lookup->my_server_list);
1643*00b67f09SDavid van Moolenbroek 	while (s != NULL) {
1644*00b67f09SDavid van Moolenbroek 		debug("freeing server %p belonging to %p", s, lookup);
1645*00b67f09SDavid van Moolenbroek 		ptr = s;
1646*00b67f09SDavid van Moolenbroek 		s = ISC_LIST_NEXT(s, link);
1647*00b67f09SDavid van Moolenbroek 		ISC_LIST_DEQUEUE(lookup->my_server_list,
1648*00b67f09SDavid van Moolenbroek 				 (dig_server_t *)ptr, link);
1649*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, ptr);
1650*00b67f09SDavid van Moolenbroek 	}
1651*00b67f09SDavid van Moolenbroek 	if (lookup->sendmsg != NULL)
1652*00b67f09SDavid van Moolenbroek 		dns_message_destroy(&lookup->sendmsg);
1653*00b67f09SDavid van Moolenbroek 	if (lookup->querysig != NULL) {
1654*00b67f09SDavid van Moolenbroek 		debug("freeing buffer %p", lookup->querysig);
1655*00b67f09SDavid van Moolenbroek 		isc_buffer_free(&lookup->querysig);
1656*00b67f09SDavid van Moolenbroek 	}
1657*00b67f09SDavid van Moolenbroek 	if (lookup->timer != NULL)
1658*00b67f09SDavid van Moolenbroek 		isc_timer_detach(&lookup->timer);
1659*00b67f09SDavid van Moolenbroek 	if (lookup->sendspace != NULL)
1660*00b67f09SDavid van Moolenbroek 		isc_mempool_put(commctx, lookup->sendspace);
1661*00b67f09SDavid van Moolenbroek 
1662*00b67f09SDavid van Moolenbroek 	if (lookup->tsigctx != NULL)
1663*00b67f09SDavid van Moolenbroek 		dst_context_destroy(&lookup->tsigctx);
1664*00b67f09SDavid van Moolenbroek 
1665*00b67f09SDavid van Moolenbroek 	if (lookup->ecs_addr != NULL)
1666*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, lookup->ecs_addr);
1667*00b67f09SDavid van Moolenbroek 
1668*00b67f09SDavid van Moolenbroek 	isc_mem_free(mctx, lookup);
1669*00b67f09SDavid van Moolenbroek }
1670*00b67f09SDavid van Moolenbroek 
1671*00b67f09SDavid van Moolenbroek /*%
1672*00b67f09SDavid van Moolenbroek  * If we can, start the next lookup in the queue running.
1673*00b67f09SDavid van Moolenbroek  * This assumes that the lookup on the head of the queue hasn't been
1674*00b67f09SDavid van Moolenbroek  * started yet.  It also removes the lookup from the head of the queue,
1675*00b67f09SDavid van Moolenbroek  * setting the current_lookup pointer pointing to it.
1676*00b67f09SDavid van Moolenbroek  */
1677*00b67f09SDavid van Moolenbroek void
start_lookup(void)1678*00b67f09SDavid van Moolenbroek start_lookup(void) {
1679*00b67f09SDavid van Moolenbroek 	debug("start_lookup()");
1680*00b67f09SDavid van Moolenbroek 	if (cancel_now)
1681*00b67f09SDavid van Moolenbroek 		return;
1682*00b67f09SDavid van Moolenbroek 
1683*00b67f09SDavid van Moolenbroek 	/*
1684*00b67f09SDavid van Moolenbroek 	 * If there's a current lookup running, we really shouldn't get
1685*00b67f09SDavid van Moolenbroek 	 * here.
1686*00b67f09SDavid van Moolenbroek 	 */
1687*00b67f09SDavid van Moolenbroek 	INSIST(current_lookup == NULL);
1688*00b67f09SDavid van Moolenbroek 
1689*00b67f09SDavid van Moolenbroek 	current_lookup = ISC_LIST_HEAD(lookup_list);
1690*00b67f09SDavid van Moolenbroek 	/*
1691*00b67f09SDavid van Moolenbroek 	 * Put the current lookup somewhere so cancel_all can find it
1692*00b67f09SDavid van Moolenbroek 	 */
1693*00b67f09SDavid van Moolenbroek 	if (current_lookup != NULL) {
1694*00b67f09SDavid van Moolenbroek 		ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1695*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
1696*00b67f09SDavid van Moolenbroek 		if (current_lookup->do_topdown &&
1697*00b67f09SDavid van Moolenbroek 		    !current_lookup->rdtype_sigchaseset) {
1698*00b67f09SDavid van Moolenbroek 			dst_key_t *trustedkey = NULL;
1699*00b67f09SDavid van Moolenbroek 			isc_buffer_t *b = NULL;
1700*00b67f09SDavid van Moolenbroek 			isc_region_t r;
1701*00b67f09SDavid van Moolenbroek 			isc_result_t result;
1702*00b67f09SDavid van Moolenbroek 			dns_name_t query_name;
1703*00b67f09SDavid van Moolenbroek 			dns_name_t *key_name;
1704*00b67f09SDavid van Moolenbroek 			int i;
1705*00b67f09SDavid van Moolenbroek 
1706*00b67f09SDavid van Moolenbroek 			result = get_trusted_key(mctx);
1707*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS) {
1708*00b67f09SDavid van Moolenbroek 				printf("\n;; No trusted key, "
1709*00b67f09SDavid van Moolenbroek 				       "+sigchase option is disabled\n");
1710*00b67f09SDavid van Moolenbroek 				current_lookup->sigchase = ISC_FALSE;
1711*00b67f09SDavid van Moolenbroek 				goto novalidation;
1712*00b67f09SDavid van Moolenbroek 			}
1713*00b67f09SDavid van Moolenbroek 			dns_name_init(&query_name, NULL);
1714*00b67f09SDavid van Moolenbroek 			nameFromString(current_lookup->textname, &query_name);
1715*00b67f09SDavid van Moolenbroek 
1716*00b67f09SDavid van Moolenbroek 			for (i = 0; i < tk_list.nb_tk; i++) {
1717*00b67f09SDavid van Moolenbroek 				key_name = dst_key_name(tk_list.key[i]);
1718*00b67f09SDavid van Moolenbroek 
1719*00b67f09SDavid van Moolenbroek 				if (dns_name_issubdomain(&query_name,
1720*00b67f09SDavid van Moolenbroek 							 key_name) == ISC_TRUE)
1721*00b67f09SDavid van Moolenbroek 					trustedkey = tk_list.key[i];
1722*00b67f09SDavid van Moolenbroek 				/*
1723*00b67f09SDavid van Moolenbroek 				 * Verify temp is really the lowest
1724*00b67f09SDavid van Moolenbroek 				 * WARNING
1725*00b67f09SDavid van Moolenbroek 				 */
1726*00b67f09SDavid van Moolenbroek 			}
1727*00b67f09SDavid van Moolenbroek 			if (trustedkey == NULL) {
1728*00b67f09SDavid van Moolenbroek 				printf("\n;; The queried zone: ");
1729*00b67f09SDavid van Moolenbroek 				dns_name_print(&query_name, stdout);
1730*00b67f09SDavid van Moolenbroek 				printf(" isn't a subdomain of any Trusted Keys"
1731*00b67f09SDavid van Moolenbroek 				       ": +sigchase option is disable\n");
1732*00b67f09SDavid van Moolenbroek 				current_lookup->sigchase = ISC_FALSE;
1733*00b67f09SDavid van Moolenbroek 				free_name(&query_name, mctx);
1734*00b67f09SDavid van Moolenbroek 				goto novalidation;
1735*00b67f09SDavid van Moolenbroek 			}
1736*00b67f09SDavid van Moolenbroek 			free_name(&query_name, mctx);
1737*00b67f09SDavid van Moolenbroek 
1738*00b67f09SDavid van Moolenbroek 			current_lookup->rdtype_sigchase
1739*00b67f09SDavid van Moolenbroek 				= current_lookup->rdtype;
1740*00b67f09SDavid van Moolenbroek 			current_lookup->rdtype_sigchaseset
1741*00b67f09SDavid van Moolenbroek 				= current_lookup->rdtypeset;
1742*00b67f09SDavid van Moolenbroek 			current_lookup->rdtype = dns_rdatatype_ns;
1743*00b67f09SDavid van Moolenbroek 
1744*00b67f09SDavid van Moolenbroek 			current_lookup->qrdtype_sigchase
1745*00b67f09SDavid van Moolenbroek 				= current_lookup->qrdtype;
1746*00b67f09SDavid van Moolenbroek 			current_lookup->qrdtype = dns_rdatatype_ns;
1747*00b67f09SDavid van Moolenbroek 
1748*00b67f09SDavid van Moolenbroek 			current_lookup->rdclass_sigchase
1749*00b67f09SDavid van Moolenbroek 				= current_lookup->rdclass;
1750*00b67f09SDavid van Moolenbroek 			current_lookup->rdclass_sigchaseset
1751*00b67f09SDavid van Moolenbroek 				= current_lookup->rdclassset;
1752*00b67f09SDavid van Moolenbroek 			current_lookup->rdclass = dns_rdataclass_in;
1753*00b67f09SDavid van Moolenbroek 
1754*00b67f09SDavid van Moolenbroek 			strlcpy(current_lookup->textnamesigchase,
1755*00b67f09SDavid van Moolenbroek 				current_lookup->textname, MXNAME);
1756*00b67f09SDavid van Moolenbroek 
1757*00b67f09SDavid van Moolenbroek 			current_lookup->trace_root_sigchase = ISC_TRUE;
1758*00b67f09SDavid van Moolenbroek 
1759*00b67f09SDavid van Moolenbroek 			result = isc_buffer_allocate(mctx, &b, BUFSIZE);
1760*00b67f09SDavid van Moolenbroek 			check_result(result, "isc_buffer_allocate");
1761*00b67f09SDavid van Moolenbroek 			result = dns_name_totext(dst_key_name(trustedkey),
1762*00b67f09SDavid van Moolenbroek 						 ISC_FALSE, b);
1763*00b67f09SDavid van Moolenbroek 			check_result(result, "dns_name_totext");
1764*00b67f09SDavid van Moolenbroek 			isc_buffer_usedregion(b, &r);
1765*00b67f09SDavid van Moolenbroek 			r.base[r.length] = '\0';
1766*00b67f09SDavid van Moolenbroek 			strlcpy(current_lookup->textname, (char*)r.base,
1767*00b67f09SDavid van Moolenbroek 				MXNAME);
1768*00b67f09SDavid van Moolenbroek 			isc_buffer_free(&b);
1769*00b67f09SDavid van Moolenbroek 
1770*00b67f09SDavid van Moolenbroek 			nameFromString(current_lookup->textnamesigchase,
1771*00b67f09SDavid van Moolenbroek 				       &chase_name);
1772*00b67f09SDavid van Moolenbroek 
1773*00b67f09SDavid van Moolenbroek 			dns_name_init(&chase_authority_name, NULL);
1774*00b67f09SDavid van Moolenbroek 		}
1775*00b67f09SDavid van Moolenbroek 	novalidation:
1776*00b67f09SDavid van Moolenbroek #endif
1777*00b67f09SDavid van Moolenbroek 		if (setup_lookup(current_lookup))
1778*00b67f09SDavid van Moolenbroek 			do_lookup(current_lookup);
1779*00b67f09SDavid van Moolenbroek 		else if (next_origin(current_lookup))
1780*00b67f09SDavid van Moolenbroek 			check_next_lookup(current_lookup);
1781*00b67f09SDavid van Moolenbroek 	} else {
1782*00b67f09SDavid van Moolenbroek 		check_if_done();
1783*00b67f09SDavid van Moolenbroek 	}
1784*00b67f09SDavid van Moolenbroek }
1785*00b67f09SDavid van Moolenbroek 
1786*00b67f09SDavid van Moolenbroek /*%
1787*00b67f09SDavid van Moolenbroek  * If we can, clear the current lookup and start the next one running.
1788*00b67f09SDavid van Moolenbroek  * This calls try_clear_lookup, so may invalidate the lookup pointer.
1789*00b67f09SDavid van Moolenbroek  */
1790*00b67f09SDavid van Moolenbroek static void
check_next_lookup(dig_lookup_t * lookup)1791*00b67f09SDavid van Moolenbroek check_next_lookup(dig_lookup_t *lookup) {
1792*00b67f09SDavid van Moolenbroek 
1793*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
1794*00b67f09SDavid van Moolenbroek 
1795*00b67f09SDavid van Moolenbroek 	debug("check_next_lookup(%p)", lookup);
1796*00b67f09SDavid van Moolenbroek 
1797*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_HEAD(lookup->q) != NULL) {
1798*00b67f09SDavid van Moolenbroek 		debug("still have a worker");
1799*00b67f09SDavid van Moolenbroek 		return;
1800*00b67f09SDavid van Moolenbroek 	}
1801*00b67f09SDavid van Moolenbroek 	if (try_clear_lookup(lookup)) {
1802*00b67f09SDavid van Moolenbroek 		current_lookup = NULL;
1803*00b67f09SDavid van Moolenbroek 		start_lookup();
1804*00b67f09SDavid van Moolenbroek 	}
1805*00b67f09SDavid van Moolenbroek }
1806*00b67f09SDavid van Moolenbroek 
1807*00b67f09SDavid van Moolenbroek /*%
1808*00b67f09SDavid van Moolenbroek  * Create and queue a new lookup as a followup to the current lookup,
1809*00b67f09SDavid van Moolenbroek  * based on the supplied message and section.  This is used in trace and
1810*00b67f09SDavid van Moolenbroek  * name server search modes to start a new lookup using servers from
1811*00b67f09SDavid van Moolenbroek  * NS records in a reply. Returns the number of followup lookups made.
1812*00b67f09SDavid van Moolenbroek  */
1813*00b67f09SDavid van Moolenbroek static int
followup_lookup(dns_message_t * msg,dig_query_t * query,dns_section_t section)1814*00b67f09SDavid van Moolenbroek followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1815*00b67f09SDavid van Moolenbroek {
1816*00b67f09SDavid van Moolenbroek 	dig_lookup_t *lookup = NULL;
1817*00b67f09SDavid van Moolenbroek 	dig_server_t *srv = NULL;
1818*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset = NULL;
1819*00b67f09SDavid van Moolenbroek 	dns_rdata_t rdata = DNS_RDATA_INIT;
1820*00b67f09SDavid van Moolenbroek 	dns_name_t *name = NULL;
1821*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1822*00b67f09SDavid van Moolenbroek 	isc_boolean_t success = ISC_FALSE;
1823*00b67f09SDavid van Moolenbroek 	int numLookups = 0;
1824*00b67f09SDavid van Moolenbroek 	int num;
1825*00b67f09SDavid van Moolenbroek 	isc_result_t lresult, addresses_result;
1826*00b67f09SDavid van Moolenbroek 	char bad_namestr[DNS_NAME_FORMATSIZE];
1827*00b67f09SDavid van Moolenbroek 	dns_name_t *domain;
1828*00b67f09SDavid van Moolenbroek 	isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
1829*00b67f09SDavid van Moolenbroek 
1830*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
1831*00b67f09SDavid van Moolenbroek 
1832*00b67f09SDavid van Moolenbroek 	debug("following up %s", query->lookup->textname);
1833*00b67f09SDavid van Moolenbroek 
1834*00b67f09SDavid van Moolenbroek 	addresses_result = ISC_R_SUCCESS;
1835*00b67f09SDavid van Moolenbroek 	bad_namestr[0] = '\0';
1836*00b67f09SDavid van Moolenbroek 	for (result = dns_message_firstname(msg, section);
1837*00b67f09SDavid van Moolenbroek 	     result == ISC_R_SUCCESS;
1838*00b67f09SDavid van Moolenbroek 	     result = dns_message_nextname(msg, section)) {
1839*00b67f09SDavid van Moolenbroek 		name = NULL;
1840*00b67f09SDavid van Moolenbroek 		dns_message_currentname(msg, section, &name);
1841*00b67f09SDavid van Moolenbroek 
1842*00b67f09SDavid van Moolenbroek 		if (section == DNS_SECTION_AUTHORITY) {
1843*00b67f09SDavid van Moolenbroek 			rdataset = NULL;
1844*00b67f09SDavid van Moolenbroek 			result = dns_message_findtype(name, dns_rdatatype_soa,
1845*00b67f09SDavid van Moolenbroek 						      0, &rdataset);
1846*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS)
1847*00b67f09SDavid van Moolenbroek 				return (0);
1848*00b67f09SDavid van Moolenbroek 		}
1849*00b67f09SDavid van Moolenbroek 		rdataset = NULL;
1850*00b67f09SDavid van Moolenbroek 		result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1851*00b67f09SDavid van Moolenbroek 					      &rdataset);
1852*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1853*00b67f09SDavid van Moolenbroek 			continue;
1854*00b67f09SDavid van Moolenbroek 
1855*00b67f09SDavid van Moolenbroek 		debug("found NS set");
1856*00b67f09SDavid van Moolenbroek 
1857*00b67f09SDavid van Moolenbroek 		if (query->lookup->trace && !query->lookup->trace_root) {
1858*00b67f09SDavid van Moolenbroek 			dns_namereln_t namereln;
1859*00b67f09SDavid van Moolenbroek 			unsigned int nlabels;
1860*00b67f09SDavid van Moolenbroek 			int order;
1861*00b67f09SDavid van Moolenbroek 
1862*00b67f09SDavid van Moolenbroek 			domain = dns_fixedname_name(&query->lookup->fdomain);
1863*00b67f09SDavid van Moolenbroek 			namereln = dns_name_fullcompare(name, domain,
1864*00b67f09SDavid van Moolenbroek 							&order, &nlabels);
1865*00b67f09SDavid van Moolenbroek 			if (namereln == dns_namereln_equal) {
1866*00b67f09SDavid van Moolenbroek 				if (!horizontal)
1867*00b67f09SDavid van Moolenbroek 					printf(";; BAD (HORIZONTAL) REFERRAL\n");
1868*00b67f09SDavid van Moolenbroek 				horizontal = ISC_TRUE;
1869*00b67f09SDavid van Moolenbroek 			} else if (namereln != dns_namereln_subdomain) {
1870*00b67f09SDavid van Moolenbroek 				if (!bad)
1871*00b67f09SDavid van Moolenbroek 					printf(";; BAD REFERRAL\n");
1872*00b67f09SDavid van Moolenbroek 				bad = ISC_TRUE;
1873*00b67f09SDavid van Moolenbroek 				continue;
1874*00b67f09SDavid van Moolenbroek 			}
1875*00b67f09SDavid van Moolenbroek 		}
1876*00b67f09SDavid van Moolenbroek 
1877*00b67f09SDavid van Moolenbroek 		for (result = dns_rdataset_first(rdataset);
1878*00b67f09SDavid van Moolenbroek 		     result == ISC_R_SUCCESS;
1879*00b67f09SDavid van Moolenbroek 		     result = dns_rdataset_next(rdataset)) {
1880*00b67f09SDavid van Moolenbroek 			char namestr[DNS_NAME_FORMATSIZE];
1881*00b67f09SDavid van Moolenbroek 			dns_rdata_ns_t ns;
1882*00b67f09SDavid van Moolenbroek 
1883*00b67f09SDavid van Moolenbroek 			if (query->lookup->trace_root &&
1884*00b67f09SDavid van Moolenbroek 			    query->lookup->nsfound >= MXSERV)
1885*00b67f09SDavid van Moolenbroek 				break;
1886*00b67f09SDavid van Moolenbroek 
1887*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(rdataset, &rdata);
1888*00b67f09SDavid van Moolenbroek 
1889*00b67f09SDavid van Moolenbroek 			query->lookup->nsfound++;
1890*00b67f09SDavid van Moolenbroek 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
1891*00b67f09SDavid van Moolenbroek 			check_result(result, "dns_rdata_tostruct");
1892*00b67f09SDavid van Moolenbroek 			dns_name_format(&ns.name, namestr, sizeof(namestr));
1893*00b67f09SDavid van Moolenbroek 			dns_rdata_freestruct(&ns);
1894*00b67f09SDavid van Moolenbroek 
1895*00b67f09SDavid van Moolenbroek 			/* Initialize lookup if we've not yet */
1896*00b67f09SDavid van Moolenbroek 			debug("found NS %s", namestr);
1897*00b67f09SDavid van Moolenbroek 			if (!success) {
1898*00b67f09SDavid van Moolenbroek 				success = ISC_TRUE;
1899*00b67f09SDavid van Moolenbroek 				lookup_counter++;
1900*00b67f09SDavid van Moolenbroek 				lookup = requeue_lookup(query->lookup,
1901*00b67f09SDavid van Moolenbroek 							ISC_FALSE);
1902*00b67f09SDavid van Moolenbroek 				cancel_lookup(query->lookup);
1903*00b67f09SDavid van Moolenbroek 				lookup->doing_xfr = ISC_FALSE;
1904*00b67f09SDavid van Moolenbroek 				if (!lookup->trace_root &&
1905*00b67f09SDavid van Moolenbroek 				    section == DNS_SECTION_ANSWER)
1906*00b67f09SDavid van Moolenbroek 					lookup->trace = ISC_FALSE;
1907*00b67f09SDavid van Moolenbroek 				else
1908*00b67f09SDavid van Moolenbroek 					lookup->trace = query->lookup->trace;
1909*00b67f09SDavid van Moolenbroek 				lookup->ns_search_only =
1910*00b67f09SDavid van Moolenbroek 					query->lookup->ns_search_only;
1911*00b67f09SDavid van Moolenbroek 				lookup->trace_root = ISC_FALSE;
1912*00b67f09SDavid van Moolenbroek 				if (lookup->ns_search_only)
1913*00b67f09SDavid van Moolenbroek 					lookup->recurse = ISC_FALSE;
1914*00b67f09SDavid van Moolenbroek 				domain = dns_fixedname_name(&lookup->fdomain);
1915*00b67f09SDavid van Moolenbroek 				dns_name_copy(name, domain, NULL);
1916*00b67f09SDavid van Moolenbroek 			}
1917*00b67f09SDavid van Moolenbroek 			debug("adding server %s", namestr);
1918*00b67f09SDavid van Moolenbroek 			num = getaddresses(lookup, namestr, &lresult);
1919*00b67f09SDavid van Moolenbroek 			if (lresult != ISC_R_SUCCESS) {
1920*00b67f09SDavid van Moolenbroek 				printf("couldn't get address for '%s': %s\n",
1921*00b67f09SDavid van Moolenbroek 				       namestr, isc_result_totext(lresult));
1922*00b67f09SDavid van Moolenbroek 				if (addresses_result == ISC_R_SUCCESS) {
1923*00b67f09SDavid van Moolenbroek 					addresses_result = lresult;
1924*00b67f09SDavid van Moolenbroek 					strcpy(bad_namestr, namestr);
1925*00b67f09SDavid van Moolenbroek 				}
1926*00b67f09SDavid van Moolenbroek 			}
1927*00b67f09SDavid van Moolenbroek 			numLookups += num;
1928*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&rdata);
1929*00b67f09SDavid van Moolenbroek 		}
1930*00b67f09SDavid van Moolenbroek 	}
1931*00b67f09SDavid van Moolenbroek 	if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1932*00b67f09SDavid van Moolenbroek 		fatal("couldn't get address for '%s': %s",
1933*00b67f09SDavid van Moolenbroek 		      bad_namestr, isc_result_totext(result));
1934*00b67f09SDavid van Moolenbroek 	}
1935*00b67f09SDavid van Moolenbroek 
1936*00b67f09SDavid van Moolenbroek 	if (lookup == NULL &&
1937*00b67f09SDavid van Moolenbroek 	    section == DNS_SECTION_ANSWER &&
1938*00b67f09SDavid van Moolenbroek 	    (query->lookup->trace || query->lookup->ns_search_only))
1939*00b67f09SDavid van Moolenbroek 		return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1940*00b67f09SDavid van Moolenbroek 
1941*00b67f09SDavid van Moolenbroek 	/*
1942*00b67f09SDavid van Moolenbroek 	 * Randomize the order the nameserver will be tried.
1943*00b67f09SDavid van Moolenbroek 	 */
1944*00b67f09SDavid van Moolenbroek 	if (numLookups > 1) {
1945*00b67f09SDavid van Moolenbroek 		isc_uint32_t i, j;
1946*00b67f09SDavid van Moolenbroek 		dig_serverlist_t my_server_list;
1947*00b67f09SDavid van Moolenbroek 		dig_server_t *next;
1948*00b67f09SDavid van Moolenbroek 
1949*00b67f09SDavid van Moolenbroek 		ISC_LIST_INIT(my_server_list);
1950*00b67f09SDavid van Moolenbroek 
1951*00b67f09SDavid van Moolenbroek 		i = numLookups;
1952*00b67f09SDavid van Moolenbroek 		for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1953*00b67f09SDavid van Moolenbroek 		     srv != NULL;
1954*00b67f09SDavid van Moolenbroek 		     srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1955*00b67f09SDavid van Moolenbroek 			INSIST(i > 0);
1956*00b67f09SDavid van Moolenbroek 			isc_random_get(&j);
1957*00b67f09SDavid van Moolenbroek 			j %= i;
1958*00b67f09SDavid van Moolenbroek 			next = ISC_LIST_NEXT(srv, link);
1959*00b67f09SDavid van Moolenbroek 			while (j-- > 0 && next != NULL) {
1960*00b67f09SDavid van Moolenbroek 				srv = next;
1961*00b67f09SDavid van Moolenbroek 				next = ISC_LIST_NEXT(srv, link);
1962*00b67f09SDavid van Moolenbroek 			}
1963*00b67f09SDavid van Moolenbroek 			ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1964*00b67f09SDavid van Moolenbroek 			ISC_LIST_APPEND(my_server_list, srv, link);
1965*00b67f09SDavid van Moolenbroek 			i--;
1966*00b67f09SDavid van Moolenbroek 		}
1967*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPENDLIST(lookup->my_server_list,
1968*00b67f09SDavid van Moolenbroek 				    my_server_list, link);
1969*00b67f09SDavid van Moolenbroek 	}
1970*00b67f09SDavid van Moolenbroek 
1971*00b67f09SDavid van Moolenbroek 	return (numLookups);
1972*00b67f09SDavid van Moolenbroek }
1973*00b67f09SDavid van Moolenbroek 
1974*00b67f09SDavid van Moolenbroek /*%
1975*00b67f09SDavid van Moolenbroek  * Create and queue a new lookup using the next origin from the search
1976*00b67f09SDavid van Moolenbroek  * list, read in setup_system().
1977*00b67f09SDavid van Moolenbroek  *
1978*00b67f09SDavid van Moolenbroek  * Return ISC_TRUE iff there was another searchlist entry.
1979*00b67f09SDavid van Moolenbroek  */
1980*00b67f09SDavid van Moolenbroek static isc_boolean_t
next_origin(dig_lookup_t * oldlookup)1981*00b67f09SDavid van Moolenbroek next_origin(dig_lookup_t *oldlookup) {
1982*00b67f09SDavid van Moolenbroek 	dig_lookup_t *newlookup;
1983*00b67f09SDavid van Moolenbroek 	dig_searchlist_t *search;
1984*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixed;
1985*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
1986*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1987*00b67f09SDavid van Moolenbroek 
1988*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
1989*00b67f09SDavid van Moolenbroek 
1990*00b67f09SDavid van Moolenbroek 	debug("next_origin()");
1991*00b67f09SDavid van Moolenbroek 	debug("following up %s", oldlookup->textname);
1992*00b67f09SDavid van Moolenbroek 
1993*00b67f09SDavid van Moolenbroek 	if (!usesearch)
1994*00b67f09SDavid van Moolenbroek 		/*
1995*00b67f09SDavid van Moolenbroek 		 * We're not using a search list, so don't even think
1996*00b67f09SDavid van Moolenbroek 		 * about finding the next entry.
1997*00b67f09SDavid van Moolenbroek 		 */
1998*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
1999*00b67f09SDavid van Moolenbroek 
2000*00b67f09SDavid van Moolenbroek 	/*
2001*00b67f09SDavid van Moolenbroek 	 * Check for a absolute name or ndots being met.
2002*00b67f09SDavid van Moolenbroek 	 */
2003*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixed);
2004*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fixed);
2005*00b67f09SDavid van Moolenbroek 	result = dns_name_fromstring2(name, oldlookup->textname, NULL,
2006*00b67f09SDavid van Moolenbroek 				      0, NULL);
2007*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS &&
2008*00b67f09SDavid van Moolenbroek 	    (dns_name_isabsolute(name) ||
2009*00b67f09SDavid van Moolenbroek 	     (int)dns_name_countlabels(name) > ndots))
2010*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
2011*00b67f09SDavid van Moolenbroek 
2012*00b67f09SDavid van Moolenbroek 	if (oldlookup->origin == NULL && !oldlookup->need_search)
2013*00b67f09SDavid van Moolenbroek 		/*
2014*00b67f09SDavid van Moolenbroek 		 * Then we just did rootorg; there's nothing left.
2015*00b67f09SDavid van Moolenbroek 		 */
2016*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
2017*00b67f09SDavid van Moolenbroek 	if (oldlookup->origin == NULL && oldlookup->need_search) {
2018*00b67f09SDavid van Moolenbroek 		newlookup = requeue_lookup(oldlookup, ISC_TRUE);
2019*00b67f09SDavid van Moolenbroek 		newlookup->origin = ISC_LIST_HEAD(search_list);
2020*00b67f09SDavid van Moolenbroek 		newlookup->need_search = ISC_FALSE;
2021*00b67f09SDavid van Moolenbroek 	} else {
2022*00b67f09SDavid van Moolenbroek 		search = ISC_LIST_NEXT(oldlookup->origin, link);
2023*00b67f09SDavid van Moolenbroek 		if (search == NULL && oldlookup->done_as_is)
2024*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
2025*00b67f09SDavid van Moolenbroek 		newlookup = requeue_lookup(oldlookup, ISC_TRUE);
2026*00b67f09SDavid van Moolenbroek 		newlookup->origin = search;
2027*00b67f09SDavid van Moolenbroek 	}
2028*00b67f09SDavid van Moolenbroek 	cancel_lookup(oldlookup);
2029*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
2030*00b67f09SDavid van Moolenbroek }
2031*00b67f09SDavid van Moolenbroek 
2032*00b67f09SDavid van Moolenbroek /*%
2033*00b67f09SDavid van Moolenbroek  * Insert an SOA record into the sendmessage in a lookup.  Used for
2034*00b67f09SDavid van Moolenbroek  * creating IXFR queries.
2035*00b67f09SDavid van Moolenbroek  */
2036*00b67f09SDavid van Moolenbroek static void
insert_soa(dig_lookup_t * lookup)2037*00b67f09SDavid van Moolenbroek insert_soa(dig_lookup_t *lookup) {
2038*00b67f09SDavid van Moolenbroek 	isc_result_t result;
2039*00b67f09SDavid van Moolenbroek 	dns_rdata_soa_t soa;
2040*00b67f09SDavid van Moolenbroek 	dns_rdata_t *rdata = NULL;
2041*00b67f09SDavid van Moolenbroek 	dns_rdatalist_t *rdatalist = NULL;
2042*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset = NULL;
2043*00b67f09SDavid van Moolenbroek 	dns_name_t *soaname = NULL;
2044*00b67f09SDavid van Moolenbroek 
2045*00b67f09SDavid van Moolenbroek 	debug("insert_soa()");
2046*00b67f09SDavid van Moolenbroek 	soa.mctx = mctx;
2047*00b67f09SDavid van Moolenbroek 	soa.serial = lookup->ixfr_serial;
2048*00b67f09SDavid van Moolenbroek 	soa.refresh = 0;
2049*00b67f09SDavid van Moolenbroek 	soa.retry = 0;
2050*00b67f09SDavid van Moolenbroek 	soa.expire = 0;
2051*00b67f09SDavid van Moolenbroek 	soa.minimum = 0;
2052*00b67f09SDavid van Moolenbroek 	soa.common.rdclass = lookup->rdclass;
2053*00b67f09SDavid van Moolenbroek 	soa.common.rdtype = dns_rdatatype_soa;
2054*00b67f09SDavid van Moolenbroek 
2055*00b67f09SDavid van Moolenbroek 	dns_name_init(&soa.origin, NULL);
2056*00b67f09SDavid van Moolenbroek 	dns_name_init(&soa.contact, NULL);
2057*00b67f09SDavid van Moolenbroek 
2058*00b67f09SDavid van Moolenbroek 	dns_name_clone(dns_rootname, &soa.origin);
2059*00b67f09SDavid van Moolenbroek 	dns_name_clone(dns_rootname, &soa.contact);
2060*00b67f09SDavid van Moolenbroek 
2061*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
2062*00b67f09SDavid van Moolenbroek 			sizeof(lookup->rdatastore));
2063*00b67f09SDavid van Moolenbroek 
2064*00b67f09SDavid van Moolenbroek 	result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
2065*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_gettemprdata");
2066*00b67f09SDavid van Moolenbroek 
2067*00b67f09SDavid van Moolenbroek 	result = dns_rdata_fromstruct(rdata, lookup->rdclass,
2068*00b67f09SDavid van Moolenbroek 				      dns_rdatatype_soa, &soa,
2069*00b67f09SDavid van Moolenbroek 				      &lookup->rdatabuf);
2070*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_rdata_fromstruct");
2071*00b67f09SDavid van Moolenbroek 
2072*00b67f09SDavid van Moolenbroek 	result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
2073*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_gettemprdatalist");
2074*00b67f09SDavid van Moolenbroek 
2075*00b67f09SDavid van Moolenbroek 	result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
2076*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_gettemprdataset");
2077*00b67f09SDavid van Moolenbroek 
2078*00b67f09SDavid van Moolenbroek 	dns_rdatalist_init(rdatalist);
2079*00b67f09SDavid van Moolenbroek 	rdatalist->type = dns_rdatatype_soa;
2080*00b67f09SDavid van Moolenbroek 	rdatalist->rdclass = lookup->rdclass;
2081*00b67f09SDavid van Moolenbroek 	rdatalist->covers = 0;
2082*00b67f09SDavid van Moolenbroek 	rdatalist->ttl = 0;
2083*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(rdatalist->rdata);
2084*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2085*00b67f09SDavid van Moolenbroek 
2086*00b67f09SDavid van Moolenbroek 	dns_rdatalist_tordataset(rdatalist, rdataset);
2087*00b67f09SDavid van Moolenbroek 
2088*00b67f09SDavid van Moolenbroek 	result = dns_message_gettempname(lookup->sendmsg, &soaname);
2089*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_gettempname");
2090*00b67f09SDavid van Moolenbroek 	dns_name_init(soaname, NULL);
2091*00b67f09SDavid van Moolenbroek 	dns_name_clone(lookup->name, soaname);
2092*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(soaname->list);
2093*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(soaname->list, rdataset, link);
2094*00b67f09SDavid van Moolenbroek 	dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
2095*00b67f09SDavid van Moolenbroek }
2096*00b67f09SDavid van Moolenbroek 
2097*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
2098*00b67f09SDavid van Moolenbroek static void
compute_cookie(unsigned char * clientcookie,size_t len)2099*00b67f09SDavid van Moolenbroek compute_cookie(unsigned char *clientcookie, size_t len) {
2100*00b67f09SDavid van Moolenbroek 	/* XXXMPA need to fix, should be per server. */
2101*00b67f09SDavid van Moolenbroek 	INSIST(len >= 8U);
2102*00b67f09SDavid van Moolenbroek 	memmove(clientcookie, cookie_secret, 8);
2103*00b67f09SDavid van Moolenbroek }
2104*00b67f09SDavid van Moolenbroek #endif
2105*00b67f09SDavid van Moolenbroek 
2106*00b67f09SDavid van Moolenbroek /*%
2107*00b67f09SDavid van Moolenbroek  * Setup the supplied lookup structure, making it ready to start sending
2108*00b67f09SDavid van Moolenbroek  * queries to servers.  Create and initialize the message to be sent as
2109*00b67f09SDavid van Moolenbroek  * well as the query structures and buffer space for the replies.  If the
2110*00b67f09SDavid van Moolenbroek  * server list is empty, clone it from the system default list.
2111*00b67f09SDavid van Moolenbroek  */
2112*00b67f09SDavid van Moolenbroek isc_boolean_t
setup_lookup(dig_lookup_t * lookup)2113*00b67f09SDavid van Moolenbroek setup_lookup(dig_lookup_t *lookup) {
2114*00b67f09SDavid van Moolenbroek 	isc_result_t result;
2115*00b67f09SDavid van Moolenbroek 	isc_uint32_t id;
2116*00b67f09SDavid van Moolenbroek 	int len;
2117*00b67f09SDavid van Moolenbroek 	dig_server_t *serv;
2118*00b67f09SDavid van Moolenbroek 	dig_query_t *query;
2119*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
2120*00b67f09SDavid van Moolenbroek 	dns_compress_t cctx;
2121*00b67f09SDavid van Moolenbroek 	char store[MXNAME];
2122*00b67f09SDavid van Moolenbroek 	char ecsbuf[20];
2123*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
2124*00b67f09SDavid van Moolenbroek 	char sitbuf[256];
2125*00b67f09SDavid van Moolenbroek #endif
2126*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
2127*00b67f09SDavid van Moolenbroek 	idn_result_t mr;
2128*00b67f09SDavid van Moolenbroek 	char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
2129*00b67f09SDavid van Moolenbroek #endif
2130*00b67f09SDavid van Moolenbroek 
2131*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
2132*00b67f09SDavid van Moolenbroek 	result = dns_name_settotextfilter(output_filter);
2133*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_name_settotextfilter");
2134*00b67f09SDavid van Moolenbroek #endif
2135*00b67f09SDavid van Moolenbroek 
2136*00b67f09SDavid van Moolenbroek 	REQUIRE(lookup != NULL);
2137*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
2138*00b67f09SDavid van Moolenbroek 
2139*00b67f09SDavid van Moolenbroek 	debug("setup_lookup(%p)", lookup);
2140*00b67f09SDavid van Moolenbroek 
2141*00b67f09SDavid van Moolenbroek 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2142*00b67f09SDavid van Moolenbroek 				    &lookup->sendmsg);
2143*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_create");
2144*00b67f09SDavid van Moolenbroek 
2145*00b67f09SDavid van Moolenbroek 	if (lookup->new_search) {
2146*00b67f09SDavid van Moolenbroek 		debug("resetting lookup counter.");
2147*00b67f09SDavid van Moolenbroek 		lookup_counter = 0;
2148*00b67f09SDavid van Moolenbroek 	}
2149*00b67f09SDavid van Moolenbroek 
2150*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_EMPTY(lookup->my_server_list)) {
2151*00b67f09SDavid van Moolenbroek 		debug("cloning server list");
2152*00b67f09SDavid van Moolenbroek 		clone_server_list(server_list, &lookup->my_server_list);
2153*00b67f09SDavid van Moolenbroek 	}
2154*00b67f09SDavid van Moolenbroek 	result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
2155*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_gettempname");
2156*00b67f09SDavid van Moolenbroek 	dns_name_init(lookup->name, NULL);
2157*00b67f09SDavid van Moolenbroek 
2158*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&lookup->namebuf, lookup->namespace,
2159*00b67f09SDavid van Moolenbroek 			sizeof(lookup->namespace));
2160*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
2161*00b67f09SDavid van Moolenbroek 			sizeof(lookup->onamespace));
2162*00b67f09SDavid van Moolenbroek 
2163*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
2164*00b67f09SDavid van Moolenbroek 	/*
2165*00b67f09SDavid van Moolenbroek 	 * We cannot convert `textname' and `origin' separately.
2166*00b67f09SDavid van Moolenbroek 	 * `textname' doesn't contain TLD, but local mapping needs
2167*00b67f09SDavid van Moolenbroek 	 * TLD.
2168*00b67f09SDavid van Moolenbroek 	 */
2169*00b67f09SDavid van Moolenbroek 	mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
2170*00b67f09SDavid van Moolenbroek 			    utf8_textname, sizeof(utf8_textname));
2171*00b67f09SDavid van Moolenbroek 	idn_check_result(mr, "convert textname to UTF-8");
2172*00b67f09SDavid van Moolenbroek #endif
2173*00b67f09SDavid van Moolenbroek 
2174*00b67f09SDavid van Moolenbroek 	/*
2175*00b67f09SDavid van Moolenbroek 	 * If the name has too many dots, force the origin to be NULL
2176*00b67f09SDavid van Moolenbroek 	 * (which produces an absolute lookup).  Otherwise, take the origin
2177*00b67f09SDavid van Moolenbroek 	 * we have if there's one in the struct already.  If it's NULL,
2178*00b67f09SDavid van Moolenbroek 	 * take the first entry in the searchlist iff either usesearch
2179*00b67f09SDavid van Moolenbroek 	 * is TRUE or we got a domain line in the resolv.conf file.
2180*00b67f09SDavid van Moolenbroek 	 */
2181*00b67f09SDavid van Moolenbroek 	if (lookup->new_search) {
2182*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
2183*00b67f09SDavid van Moolenbroek 		if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
2184*00b67f09SDavid van Moolenbroek 			lookup->origin = NULL; /* Force abs lookup */
2185*00b67f09SDavid van Moolenbroek 			lookup->done_as_is = ISC_TRUE;
2186*00b67f09SDavid van Moolenbroek 			lookup->need_search = usesearch;
2187*00b67f09SDavid van Moolenbroek 		} else if (lookup->origin == NULL && usesearch) {
2188*00b67f09SDavid van Moolenbroek 			lookup->origin = ISC_LIST_HEAD(search_list);
2189*00b67f09SDavid van Moolenbroek 			lookup->need_search = ISC_FALSE;
2190*00b67f09SDavid van Moolenbroek 		}
2191*00b67f09SDavid van Moolenbroek #else
2192*00b67f09SDavid van Moolenbroek 		if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
2193*00b67f09SDavid van Moolenbroek 			lookup->origin = NULL; /* Force abs lookup */
2194*00b67f09SDavid van Moolenbroek 			lookup->done_as_is = ISC_TRUE;
2195*00b67f09SDavid van Moolenbroek 			lookup->need_search = usesearch;
2196*00b67f09SDavid van Moolenbroek 		} else if (lookup->origin == NULL && usesearch) {
2197*00b67f09SDavid van Moolenbroek 			lookup->origin = ISC_LIST_HEAD(search_list);
2198*00b67f09SDavid van Moolenbroek 			lookup->need_search = ISC_FALSE;
2199*00b67f09SDavid van Moolenbroek 		}
2200*00b67f09SDavid van Moolenbroek #endif
2201*00b67f09SDavid van Moolenbroek 	}
2202*00b67f09SDavid van Moolenbroek 
2203*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
2204*00b67f09SDavid van Moolenbroek 	if (lookup->origin != NULL) {
2205*00b67f09SDavid van Moolenbroek 		mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
2206*00b67f09SDavid van Moolenbroek 				    lookup->origin->origin, utf8_origin,
2207*00b67f09SDavid van Moolenbroek 				    sizeof(utf8_origin));
2208*00b67f09SDavid van Moolenbroek 		idn_check_result(mr, "convert origin to UTF-8");
2209*00b67f09SDavid van Moolenbroek 		mr = append_textname(utf8_textname, utf8_origin,
2210*00b67f09SDavid van Moolenbroek 				     sizeof(utf8_textname));
2211*00b67f09SDavid van Moolenbroek 		idn_check_result(mr, "append origin to textname");
2212*00b67f09SDavid van Moolenbroek 	}
2213*00b67f09SDavid van Moolenbroek 	mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
2214*00b67f09SDavid van Moolenbroek 			    IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
2215*00b67f09SDavid van Moolenbroek 			    idn_textname, sizeof(idn_textname));
2216*00b67f09SDavid van Moolenbroek 	idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
2217*00b67f09SDavid van Moolenbroek #else
2218*00b67f09SDavid van Moolenbroek 	if (lookup->origin != NULL) {
2219*00b67f09SDavid van Moolenbroek 		debug("trying origin %s", lookup->origin->origin);
2220*00b67f09SDavid van Moolenbroek 		result = dns_message_gettempname(lookup->sendmsg,
2221*00b67f09SDavid van Moolenbroek 						 &lookup->oname);
2222*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_message_gettempname");
2223*00b67f09SDavid van Moolenbroek 		dns_name_init(lookup->oname, NULL);
2224*00b67f09SDavid van Moolenbroek 		/* XXX Helper funct to conv char* to name? */
2225*00b67f09SDavid van Moolenbroek 		len = strlen(lookup->origin->origin);
2226*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&b, lookup->origin->origin, len);
2227*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&b, len);
2228*00b67f09SDavid van Moolenbroek 		result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
2229*00b67f09SDavid van Moolenbroek 					   0, &lookup->onamebuf);
2230*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
2231*00b67f09SDavid van Moolenbroek 			dns_message_puttempname(lookup->sendmsg,
2232*00b67f09SDavid van Moolenbroek 						&lookup->name);
2233*00b67f09SDavid van Moolenbroek 			dns_message_puttempname(lookup->sendmsg,
2234*00b67f09SDavid van Moolenbroek 						&lookup->oname);
2235*00b67f09SDavid van Moolenbroek 			fatal("'%s' is not in legal name syntax (%s)",
2236*00b67f09SDavid van Moolenbroek 			      lookup->origin->origin,
2237*00b67f09SDavid van Moolenbroek 			      isc_result_totext(result));
2238*00b67f09SDavid van Moolenbroek 		}
2239*00b67f09SDavid van Moolenbroek 		if (lookup->trace && lookup->trace_root) {
2240*00b67f09SDavid van Moolenbroek 			dns_name_clone(dns_rootname, lookup->name);
2241*00b67f09SDavid van Moolenbroek 		} else {
2242*00b67f09SDavid van Moolenbroek 			dns_fixedname_t fixed;
2243*00b67f09SDavid van Moolenbroek 			dns_name_t *name;
2244*00b67f09SDavid van Moolenbroek 
2245*00b67f09SDavid van Moolenbroek 			dns_fixedname_init(&fixed);
2246*00b67f09SDavid van Moolenbroek 			name = dns_fixedname_name(&fixed);
2247*00b67f09SDavid van Moolenbroek 			len = strlen(lookup->textname);
2248*00b67f09SDavid van Moolenbroek 			isc_buffer_init(&b, lookup->textname, len);
2249*00b67f09SDavid van Moolenbroek 			isc_buffer_add(&b, len);
2250*00b67f09SDavid van Moolenbroek 			result = dns_name_fromtext(name, &b, NULL, 0, NULL);
2251*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS &&
2252*00b67f09SDavid van Moolenbroek 			    !dns_name_isabsolute(name))
2253*00b67f09SDavid van Moolenbroek 				result = dns_name_concatenate(name,
2254*00b67f09SDavid van Moolenbroek 							      lookup->oname,
2255*00b67f09SDavid van Moolenbroek 							      lookup->name,
2256*00b67f09SDavid van Moolenbroek 							      &lookup->namebuf);
2257*00b67f09SDavid van Moolenbroek 			else if (result == ISC_R_SUCCESS)
2258*00b67f09SDavid van Moolenbroek 				result = dns_name_copy(name, lookup->name,
2259*00b67f09SDavid van Moolenbroek 						       &lookup->namebuf);
2260*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS) {
2261*00b67f09SDavid van Moolenbroek 				dns_message_puttempname(lookup->sendmsg,
2262*00b67f09SDavid van Moolenbroek 							&lookup->name);
2263*00b67f09SDavid van Moolenbroek 				dns_message_puttempname(lookup->sendmsg,
2264*00b67f09SDavid van Moolenbroek 							&lookup->oname);
2265*00b67f09SDavid van Moolenbroek 				if (result == DNS_R_NAMETOOLONG)
2266*00b67f09SDavid van Moolenbroek 					return (ISC_FALSE);
2267*00b67f09SDavid van Moolenbroek 				fatal("'%s' is not in legal name syntax (%s)",
2268*00b67f09SDavid van Moolenbroek 				      lookup->textname,
2269*00b67f09SDavid van Moolenbroek 				      isc_result_totext(result));
2270*00b67f09SDavid van Moolenbroek 			}
2271*00b67f09SDavid van Moolenbroek 		}
2272*00b67f09SDavid van Moolenbroek 		dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2273*00b67f09SDavid van Moolenbroek 	} else
2274*00b67f09SDavid van Moolenbroek #endif
2275*00b67f09SDavid van Moolenbroek 	{
2276*00b67f09SDavid van Moolenbroek 		debug("using root origin");
2277*00b67f09SDavid van Moolenbroek 		if (lookup->trace && lookup->trace_root)
2278*00b67f09SDavid van Moolenbroek 			dns_name_clone(dns_rootname, lookup->name);
2279*00b67f09SDavid van Moolenbroek 		else {
2280*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
2281*00b67f09SDavid van Moolenbroek 			len = strlen(idn_textname);
2282*00b67f09SDavid van Moolenbroek 			isc_buffer_init(&b, idn_textname, len);
2283*00b67f09SDavid van Moolenbroek 			isc_buffer_add(&b, len);
2284*00b67f09SDavid van Moolenbroek 			result = dns_name_fromtext(lookup->name, &b,
2285*00b67f09SDavid van Moolenbroek 						   dns_rootname, 0,
2286*00b67f09SDavid van Moolenbroek 						   &lookup->namebuf);
2287*00b67f09SDavid van Moolenbroek #else
2288*00b67f09SDavid van Moolenbroek 			len = strlen(lookup->textname);
2289*00b67f09SDavid van Moolenbroek 			isc_buffer_init(&b, lookup->textname, len);
2290*00b67f09SDavid van Moolenbroek 			isc_buffer_add(&b, len);
2291*00b67f09SDavid van Moolenbroek 			result = dns_name_fromtext(lookup->name, &b,
2292*00b67f09SDavid van Moolenbroek 						   dns_rootname, 0,
2293*00b67f09SDavid van Moolenbroek 						   &lookup->namebuf);
2294*00b67f09SDavid van Moolenbroek #endif
2295*00b67f09SDavid van Moolenbroek 		}
2296*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
2297*00b67f09SDavid van Moolenbroek 			dns_message_puttempname(lookup->sendmsg,
2298*00b67f09SDavid van Moolenbroek 						&lookup->name);
2299*00b67f09SDavid van Moolenbroek 			fatal("'%s' is not a legal name "
2300*00b67f09SDavid van Moolenbroek 			      "(%s)", lookup->textname,
2301*00b67f09SDavid van Moolenbroek 			      isc_result_totext(result));
2302*00b67f09SDavid van Moolenbroek 		}
2303*00b67f09SDavid van Moolenbroek 	}
2304*00b67f09SDavid van Moolenbroek 	dns_name_format(lookup->name, store, sizeof(store));
2305*00b67f09SDavid van Moolenbroek 	trying(store, lookup);
2306*00b67f09SDavid van Moolenbroek 	INSIST(dns_name_isabsolute(lookup->name));
2307*00b67f09SDavid van Moolenbroek 
2308*00b67f09SDavid van Moolenbroek 	isc_random_get(&id);
2309*00b67f09SDavid van Moolenbroek 	lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2310*00b67f09SDavid van Moolenbroek 	lookup->sendmsg->opcode = dns_opcode_query;
2311*00b67f09SDavid van Moolenbroek 	lookup->msgcounter = 0;
2312*00b67f09SDavid van Moolenbroek 	/*
2313*00b67f09SDavid van Moolenbroek 	 * If this is a trace request, completely disallow recursion, since
2314*00b67f09SDavid van Moolenbroek 	 * it's meaningless for traces.
2315*00b67f09SDavid van Moolenbroek 	 */
2316*00b67f09SDavid van Moolenbroek 	if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2317*00b67f09SDavid van Moolenbroek 		lookup->recurse = ISC_FALSE;
2318*00b67f09SDavid van Moolenbroek 
2319*00b67f09SDavid van Moolenbroek 	if (lookup->recurse &&
2320*00b67f09SDavid van Moolenbroek 	    lookup->rdtype != dns_rdatatype_axfr &&
2321*00b67f09SDavid van Moolenbroek 	    lookup->rdtype != dns_rdatatype_ixfr) {
2322*00b67f09SDavid van Moolenbroek 		debug("recursive query");
2323*00b67f09SDavid van Moolenbroek 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2324*00b67f09SDavid van Moolenbroek 	}
2325*00b67f09SDavid van Moolenbroek 
2326*00b67f09SDavid van Moolenbroek 	/* XXX aaflag */
2327*00b67f09SDavid van Moolenbroek 	if (lookup->aaonly) {
2328*00b67f09SDavid van Moolenbroek 		debug("AA query");
2329*00b67f09SDavid van Moolenbroek 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2330*00b67f09SDavid van Moolenbroek 	}
2331*00b67f09SDavid van Moolenbroek 
2332*00b67f09SDavid van Moolenbroek 	if (lookup->adflag) {
2333*00b67f09SDavid van Moolenbroek 		debug("AD query");
2334*00b67f09SDavid van Moolenbroek 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2335*00b67f09SDavid van Moolenbroek 	}
2336*00b67f09SDavid van Moolenbroek 
2337*00b67f09SDavid van Moolenbroek 	if (lookup->cdflag) {
2338*00b67f09SDavid van Moolenbroek 		debug("CD query");
2339*00b67f09SDavid van Moolenbroek 		lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2340*00b67f09SDavid van Moolenbroek 	}
2341*00b67f09SDavid van Moolenbroek 
2342*00b67f09SDavid van Moolenbroek 	dns_message_addname(lookup->sendmsg, lookup->name,
2343*00b67f09SDavid van Moolenbroek 			    DNS_SECTION_QUESTION);
2344*00b67f09SDavid van Moolenbroek 
2345*00b67f09SDavid van Moolenbroek 	if (lookup->trace && lookup->trace_root) {
2346*00b67f09SDavid van Moolenbroek 		lookup->qrdtype = lookup->rdtype;
2347*00b67f09SDavid van Moolenbroek 		lookup->rdtype = dns_rdatatype_ns;
2348*00b67f09SDavid van Moolenbroek 	}
2349*00b67f09SDavid van Moolenbroek 
2350*00b67f09SDavid van Moolenbroek 	if ((lookup->rdtype == dns_rdatatype_axfr) ||
2351*00b67f09SDavid van Moolenbroek 	    (lookup->rdtype == dns_rdatatype_ixfr)) {
2352*00b67f09SDavid van Moolenbroek 		/*
2353*00b67f09SDavid van Moolenbroek 		 * Force TCP mode if we're doing an axfr.
2354*00b67f09SDavid van Moolenbroek 		 */
2355*00b67f09SDavid van Moolenbroek 		if (lookup->rdtype == dns_rdatatype_axfr) {
2356*00b67f09SDavid van Moolenbroek 			lookup->doing_xfr = ISC_TRUE;
2357*00b67f09SDavid van Moolenbroek 			lookup->tcp_mode = ISC_TRUE;
2358*00b67f09SDavid van Moolenbroek 		} else if (lookup->tcp_mode) {
2359*00b67f09SDavid van Moolenbroek 			lookup->doing_xfr = ISC_TRUE;
2360*00b67f09SDavid van Moolenbroek 		}
2361*00b67f09SDavid van Moolenbroek 	}
2362*00b67f09SDavid van Moolenbroek 
2363*00b67f09SDavid van Moolenbroek 	add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2364*00b67f09SDavid van Moolenbroek 		     lookup->rdtype);
2365*00b67f09SDavid van Moolenbroek 
2366*00b67f09SDavid van Moolenbroek 	/* add_soa */
2367*00b67f09SDavid van Moolenbroek 	if (lookup->rdtype == dns_rdatatype_ixfr)
2368*00b67f09SDavid van Moolenbroek 		insert_soa(lookup);
2369*00b67f09SDavid van Moolenbroek 
2370*00b67f09SDavid van Moolenbroek 	/* XXX Insist this? */
2371*00b67f09SDavid van Moolenbroek 	lookup->tsigctx = NULL;
2372*00b67f09SDavid van Moolenbroek 	lookup->querysig = NULL;
2373*00b67f09SDavid van Moolenbroek 	if (key != NULL) {
2374*00b67f09SDavid van Moolenbroek 		debug("initializing keys");
2375*00b67f09SDavid van Moolenbroek 		result = dns_message_settsigkey(lookup->sendmsg, key);
2376*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_message_settsigkey");
2377*00b67f09SDavid van Moolenbroek 	}
2378*00b67f09SDavid van Moolenbroek 
2379*00b67f09SDavid van Moolenbroek 	lookup->sendspace = isc_mempool_get(commctx);
2380*00b67f09SDavid van Moolenbroek 	if (lookup->sendspace == NULL)
2381*00b67f09SDavid van Moolenbroek 		fatal("memory allocation failure");
2382*00b67f09SDavid van Moolenbroek 
2383*00b67f09SDavid van Moolenbroek 	result = dns_compress_init(&cctx, -1, mctx);
2384*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_compress_init");
2385*00b67f09SDavid van Moolenbroek 
2386*00b67f09SDavid van Moolenbroek 	debug("starting to render the message");
2387*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2388*00b67f09SDavid van Moolenbroek 	result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2389*00b67f09SDavid van Moolenbroek 					 &lookup->renderbuf);
2390*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_renderbegin");
2391*00b67f09SDavid van Moolenbroek 	if (lookup->udpsize > 0 || lookup->dnssec ||
2392*00b67f09SDavid van Moolenbroek 	    lookup->edns > -1 || lookup->ecs_addr != NULL)
2393*00b67f09SDavid van Moolenbroek 	{
2394*00b67f09SDavid van Moolenbroek 		dns_ednsopt_t opts[DNS_EDNSOPTIONS];
2395*00b67f09SDavid van Moolenbroek 		int i = 0;
2396*00b67f09SDavid van Moolenbroek 
2397*00b67f09SDavid van Moolenbroek 		if (lookup->udpsize == 0)
2398*00b67f09SDavid van Moolenbroek 			lookup->udpsize = 4096;
2399*00b67f09SDavid van Moolenbroek 		if (lookup->edns < 0)
2400*00b67f09SDavid van Moolenbroek 			lookup->edns = 0;
2401*00b67f09SDavid van Moolenbroek 
2402*00b67f09SDavid van Moolenbroek 		if (lookup->nsid) {
2403*00b67f09SDavid van Moolenbroek 			INSIST(i < DNS_EDNSOPTIONS);
2404*00b67f09SDavid van Moolenbroek 			opts[i].code = DNS_OPT_NSID;
2405*00b67f09SDavid van Moolenbroek 			opts[i].length = 0;
2406*00b67f09SDavid van Moolenbroek 			opts[i].value = NULL;
2407*00b67f09SDavid van Moolenbroek 			i++;
2408*00b67f09SDavid van Moolenbroek 		}
2409*00b67f09SDavid van Moolenbroek 
2410*00b67f09SDavid van Moolenbroek 		if (lookup->ecs_addr != NULL) {
2411*00b67f09SDavid van Moolenbroek 			isc_uint32_t prefixlen;
2412*00b67f09SDavid van Moolenbroek 			struct sockaddr *sa;
2413*00b67f09SDavid van Moolenbroek 			struct sockaddr_in *sin;
2414*00b67f09SDavid van Moolenbroek 			struct sockaddr_in6 *sin6;
2415*00b67f09SDavid van Moolenbroek 			size_t addrl;
2416*00b67f09SDavid van Moolenbroek 
2417*00b67f09SDavid van Moolenbroek 			sa = &lookup->ecs_addr->type.sa;
2418*00b67f09SDavid van Moolenbroek 			prefixlen = lookup->ecs_addr->length;
2419*00b67f09SDavid van Moolenbroek 
2420*00b67f09SDavid van Moolenbroek 			/* Round up prefix len to a multiple of 8 */
2421*00b67f09SDavid van Moolenbroek 			addrl = (prefixlen + 7) / 8;
2422*00b67f09SDavid van Moolenbroek 
2423*00b67f09SDavid van Moolenbroek 			INSIST(i < DNS_EDNSOPTIONS);
2424*00b67f09SDavid van Moolenbroek 			opts[i].code = DNS_OPT_CLIENT_SUBNET;
2425*00b67f09SDavid van Moolenbroek 			opts[i].length = (isc_uint16_t) addrl + 4;
2426*00b67f09SDavid van Moolenbroek 			check_result(result, "isc_buffer_allocate");
2427*00b67f09SDavid van Moolenbroek 			isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
2428*00b67f09SDavid van Moolenbroek 			if (sa->sa_family == AF_INET) {
2429*00b67f09SDavid van Moolenbroek 				sin = (struct sockaddr_in *) sa;
2430*00b67f09SDavid van Moolenbroek 				isc_buffer_putuint16(&b, 1);
2431*00b67f09SDavid van Moolenbroek 				isc_buffer_putuint8(&b, prefixlen);
2432*00b67f09SDavid van Moolenbroek 				isc_buffer_putuint8(&b, 0);
2433*00b67f09SDavid van Moolenbroek 				isc_buffer_putmem(&b,
2434*00b67f09SDavid van Moolenbroek 					  (isc_uint8_t *) &sin->sin_addr,
2435*00b67f09SDavid van Moolenbroek 					  (unsigned int) addrl);
2436*00b67f09SDavid van Moolenbroek 			} else {
2437*00b67f09SDavid van Moolenbroek 				sin6 = (struct sockaddr_in6 *) sa;
2438*00b67f09SDavid van Moolenbroek 				isc_buffer_putuint16(&b, 2);
2439*00b67f09SDavid van Moolenbroek 				isc_buffer_putuint8(&b, prefixlen);
2440*00b67f09SDavid van Moolenbroek 				isc_buffer_putuint8(&b, 0);
2441*00b67f09SDavid van Moolenbroek 				isc_buffer_putmem(&b,
2442*00b67f09SDavid van Moolenbroek 					  (isc_uint8_t *) &sin6->sin6_addr,
2443*00b67f09SDavid van Moolenbroek 					  (unsigned int) addrl);
2444*00b67f09SDavid van Moolenbroek 			}
2445*00b67f09SDavid van Moolenbroek 
2446*00b67f09SDavid van Moolenbroek 			opts[i].value = (isc_uint8_t *) ecsbuf;
2447*00b67f09SDavid van Moolenbroek 			i++;
2448*00b67f09SDavid van Moolenbroek 		}
2449*00b67f09SDavid van Moolenbroek 
2450*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
2451*00b67f09SDavid van Moolenbroek 		if (lookup->sit) {
2452*00b67f09SDavid van Moolenbroek 			INSIST(i < DNS_EDNSOPTIONS);
2453*00b67f09SDavid van Moolenbroek 			opts[i].code = DNS_OPT_SIT;
2454*00b67f09SDavid van Moolenbroek 			if (lookup->sitvalue != NULL) {
2455*00b67f09SDavid van Moolenbroek 				isc_buffer_init(&b, sitbuf, sizeof(sitbuf));
2456*00b67f09SDavid van Moolenbroek 				result = isc_hex_decodestring(lookup->sitvalue,
2457*00b67f09SDavid van Moolenbroek 							      &b);
2458*00b67f09SDavid van Moolenbroek 				check_result(result, "isc_hex_decodestring");
2459*00b67f09SDavid van Moolenbroek 				opts[i].value = isc_buffer_base(&b);
2460*00b67f09SDavid van Moolenbroek 				opts[i].length = isc_buffer_usedlength(&b);
2461*00b67f09SDavid van Moolenbroek 			} else {
2462*00b67f09SDavid van Moolenbroek 				compute_cookie(cookie, sizeof(cookie));
2463*00b67f09SDavid van Moolenbroek 				opts[i].length = 8;
2464*00b67f09SDavid van Moolenbroek 				opts[i].value = cookie;
2465*00b67f09SDavid van Moolenbroek 			}
2466*00b67f09SDavid van Moolenbroek 			i++;
2467*00b67f09SDavid van Moolenbroek 		}
2468*00b67f09SDavid van Moolenbroek #endif
2469*00b67f09SDavid van Moolenbroek 
2470*00b67f09SDavid van Moolenbroek 		if (lookup->expire) {
2471*00b67f09SDavid van Moolenbroek 			INSIST(i < DNS_EDNSOPTIONS);
2472*00b67f09SDavid van Moolenbroek 			opts[i].code = DNS_OPT_EXPIRE;
2473*00b67f09SDavid van Moolenbroek 			opts[i].length = 0;
2474*00b67f09SDavid van Moolenbroek 			opts[i].value = NULL;
2475*00b67f09SDavid van Moolenbroek 			i++;
2476*00b67f09SDavid van Moolenbroek 		}
2477*00b67f09SDavid van Moolenbroek 
2478*00b67f09SDavid van Moolenbroek 		add_opt(lookup->sendmsg, lookup->udpsize,
2479*00b67f09SDavid van Moolenbroek 			lookup->edns, lookup->dnssec, opts, i);
2480*00b67f09SDavid van Moolenbroek 	}
2481*00b67f09SDavid van Moolenbroek 
2482*00b67f09SDavid van Moolenbroek 	result = dns_message_rendersection(lookup->sendmsg,
2483*00b67f09SDavid van Moolenbroek 					   DNS_SECTION_QUESTION, 0);
2484*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_rendersection");
2485*00b67f09SDavid van Moolenbroek 	result = dns_message_rendersection(lookup->sendmsg,
2486*00b67f09SDavid van Moolenbroek 					   DNS_SECTION_AUTHORITY, 0);
2487*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_rendersection");
2488*00b67f09SDavid van Moolenbroek 	result = dns_message_renderend(lookup->sendmsg);
2489*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_renderend");
2490*00b67f09SDavid van Moolenbroek 	debug("done rendering");
2491*00b67f09SDavid van Moolenbroek 
2492*00b67f09SDavid van Moolenbroek 	dns_compress_invalidate(&cctx);
2493*00b67f09SDavid van Moolenbroek 
2494*00b67f09SDavid van Moolenbroek 	/*
2495*00b67f09SDavid van Moolenbroek 	 * Force TCP mode if the request is larger than 512 bytes.
2496*00b67f09SDavid van Moolenbroek 	 */
2497*00b67f09SDavid van Moolenbroek 	if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2498*00b67f09SDavid van Moolenbroek 		lookup->tcp_mode = ISC_TRUE;
2499*00b67f09SDavid van Moolenbroek 
2500*00b67f09SDavid van Moolenbroek 	lookup->pending = ISC_FALSE;
2501*00b67f09SDavid van Moolenbroek 
2502*00b67f09SDavid van Moolenbroek 	for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2503*00b67f09SDavid van Moolenbroek 	     serv != NULL;
2504*00b67f09SDavid van Moolenbroek 	     serv = ISC_LIST_NEXT(serv, link)) {
2505*00b67f09SDavid van Moolenbroek 		query = isc_mem_allocate(mctx, sizeof(dig_query_t));
2506*00b67f09SDavid van Moolenbroek 		if (query == NULL)
2507*00b67f09SDavid van Moolenbroek 			fatal("memory allocation failure in %s:%d",
2508*00b67f09SDavid van Moolenbroek 			      __FILE__, __LINE__);
2509*00b67f09SDavid van Moolenbroek 		debug("create query %p linked to lookup %p",
2510*00b67f09SDavid van Moolenbroek 		       query, lookup);
2511*00b67f09SDavid van Moolenbroek 		query->lookup = lookup;
2512*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
2513*00b67f09SDavid van Moolenbroek 		query->waiting_senddone = ISC_FALSE;
2514*00b67f09SDavid van Moolenbroek 		query->pending_free = ISC_FALSE;
2515*00b67f09SDavid van Moolenbroek 		query->recv_made = ISC_FALSE;
2516*00b67f09SDavid van Moolenbroek 		query->first_pass = ISC_TRUE;
2517*00b67f09SDavid van Moolenbroek 		query->first_soa_rcvd = ISC_FALSE;
2518*00b67f09SDavid van Moolenbroek 		query->second_rr_rcvd = ISC_FALSE;
2519*00b67f09SDavid van Moolenbroek 		query->first_repeat_rcvd = ISC_FALSE;
2520*00b67f09SDavid van Moolenbroek 		query->warn_id = ISC_TRUE;
2521*00b67f09SDavid van Moolenbroek 		query->first_rr_serial = 0;
2522*00b67f09SDavid van Moolenbroek 		query->second_rr_serial = 0;
2523*00b67f09SDavid van Moolenbroek 		query->servname = serv->servername;
2524*00b67f09SDavid van Moolenbroek 		query->userarg = serv->userarg;
2525*00b67f09SDavid van Moolenbroek 		query->rr_count = 0;
2526*00b67f09SDavid van Moolenbroek 		query->msg_count = 0;
2527*00b67f09SDavid van Moolenbroek 		query->byte_count = 0;
2528*00b67f09SDavid van Moolenbroek 		query->ixfr_axfr = ISC_FALSE;
2529*00b67f09SDavid van Moolenbroek 		ISC_LIST_INIT(query->recvlist);
2530*00b67f09SDavid van Moolenbroek 		ISC_LIST_INIT(query->lengthlist);
2531*00b67f09SDavid van Moolenbroek 		query->sock = NULL;
2532*00b67f09SDavid van Moolenbroek 		query->recvspace = isc_mempool_get(commctx);
2533*00b67f09SDavid van Moolenbroek 		if (query->recvspace == NULL)
2534*00b67f09SDavid van Moolenbroek 			fatal("memory allocation failure");
2535*00b67f09SDavid van Moolenbroek 
2536*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2537*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2538*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&query->slbuf, query->slspace, 2);
2539*00b67f09SDavid van Moolenbroek 		query->sendbuf = lookup->renderbuf;
2540*00b67f09SDavid van Moolenbroek 
2541*00b67f09SDavid van Moolenbroek 		ISC_LINK_INIT(query, clink);
2542*00b67f09SDavid van Moolenbroek 		ISC_LINK_INIT(query, link);
2543*00b67f09SDavid van Moolenbroek 		ISC_LIST_ENQUEUE(lookup->q, query, link);
2544*00b67f09SDavid van Moolenbroek 	}
2545*00b67f09SDavid van Moolenbroek 
2546*00b67f09SDavid van Moolenbroek 	/* XXX qrflag, print_query, etc... */
2547*00b67f09SDavid van Moolenbroek 	if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2548*00b67f09SDavid van Moolenbroek 		extrabytes = 0;
2549*00b67f09SDavid van Moolenbroek 		printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2550*00b67f09SDavid van Moolenbroek 			     ISC_TRUE);
2551*00b67f09SDavid van Moolenbroek 	}
2552*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
2553*00b67f09SDavid van Moolenbroek }
2554*00b67f09SDavid van Moolenbroek 
2555*00b67f09SDavid van Moolenbroek /*%
2556*00b67f09SDavid van Moolenbroek  * Event handler for send completion.  Track send counter, and clear out
2557*00b67f09SDavid van Moolenbroek  * the query if the send was canceled.
2558*00b67f09SDavid van Moolenbroek  */
2559*00b67f09SDavid van Moolenbroek static void
send_done(isc_task_t * _task,isc_event_t * event)2560*00b67f09SDavid van Moolenbroek send_done(isc_task_t *_task, isc_event_t *event) {
2561*00b67f09SDavid van Moolenbroek 	isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2562*00b67f09SDavid van Moolenbroek 	isc_buffer_t *b = NULL;
2563*00b67f09SDavid van Moolenbroek 	dig_query_t *query, *next;
2564*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l;
2565*00b67f09SDavid van Moolenbroek 
2566*00b67f09SDavid van Moolenbroek 	REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2567*00b67f09SDavid van Moolenbroek 
2568*00b67f09SDavid van Moolenbroek 	UNUSED(_task);
2569*00b67f09SDavid van Moolenbroek 
2570*00b67f09SDavid van Moolenbroek 	LOCK_LOOKUP;
2571*00b67f09SDavid van Moolenbroek 
2572*00b67f09SDavid van Moolenbroek 	debug("send_done()");
2573*00b67f09SDavid van Moolenbroek 	sendcount--;
2574*00b67f09SDavid van Moolenbroek 	debug("sendcount=%d", sendcount);
2575*00b67f09SDavid van Moolenbroek 	INSIST(sendcount >= 0);
2576*00b67f09SDavid van Moolenbroek 
2577*00b67f09SDavid van Moolenbroek 	for  (b = ISC_LIST_HEAD(sevent->bufferlist);
2578*00b67f09SDavid van Moolenbroek 	      b != NULL;
2579*00b67f09SDavid van Moolenbroek 	      b = ISC_LIST_HEAD(sevent->bufferlist)) {
2580*00b67f09SDavid van Moolenbroek 		ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2581*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, b);
2582*00b67f09SDavid van Moolenbroek 	}
2583*00b67f09SDavid van Moolenbroek 
2584*00b67f09SDavid van Moolenbroek 	query = event->ev_arg;
2585*00b67f09SDavid van Moolenbroek 	query->waiting_senddone = ISC_FALSE;
2586*00b67f09SDavid van Moolenbroek 	l = query->lookup;
2587*00b67f09SDavid van Moolenbroek 
2588*00b67f09SDavid van Moolenbroek 	if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
2589*00b67f09SDavid van Moolenbroek 		debug("sending next, since searching");
2590*00b67f09SDavid van Moolenbroek 		next = ISC_LIST_NEXT(query, link);
2591*00b67f09SDavid van Moolenbroek 		if (next != NULL)
2592*00b67f09SDavid van Moolenbroek 			send_udp(next);
2593*00b67f09SDavid van Moolenbroek 	}
2594*00b67f09SDavid van Moolenbroek 
2595*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
2596*00b67f09SDavid van Moolenbroek 
2597*00b67f09SDavid van Moolenbroek 	if (query->pending_free)
2598*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, query);
2599*00b67f09SDavid van Moolenbroek 
2600*00b67f09SDavid van Moolenbroek 	check_if_done();
2601*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
2602*00b67f09SDavid van Moolenbroek }
2603*00b67f09SDavid van Moolenbroek 
2604*00b67f09SDavid van Moolenbroek /*%
2605*00b67f09SDavid van Moolenbroek  * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2606*00b67f09SDavid van Moolenbroek  * IO sockets.  The cancel handlers should take care of cleaning up the
2607*00b67f09SDavid van Moolenbroek  * query and lookup structures
2608*00b67f09SDavid van Moolenbroek  */
2609*00b67f09SDavid van Moolenbroek static void
cancel_lookup(dig_lookup_t * lookup)2610*00b67f09SDavid van Moolenbroek cancel_lookup(dig_lookup_t *lookup) {
2611*00b67f09SDavid van Moolenbroek 	dig_query_t *query, *next;
2612*00b67f09SDavid van Moolenbroek 
2613*00b67f09SDavid van Moolenbroek 	debug("cancel_lookup()");
2614*00b67f09SDavid van Moolenbroek 	query = ISC_LIST_HEAD(lookup->q);
2615*00b67f09SDavid van Moolenbroek 	while (query != NULL) {
2616*00b67f09SDavid van Moolenbroek 		next = ISC_LIST_NEXT(query, link);
2617*00b67f09SDavid van Moolenbroek 		if (query->sock != NULL) {
2618*00b67f09SDavid van Moolenbroek 			isc_socket_cancel(query->sock, global_task,
2619*00b67f09SDavid van Moolenbroek 					  ISC_SOCKCANCEL_ALL);
2620*00b67f09SDavid van Moolenbroek 			check_if_done();
2621*00b67f09SDavid van Moolenbroek 		} else {
2622*00b67f09SDavid van Moolenbroek 			clear_query(query);
2623*00b67f09SDavid van Moolenbroek 		}
2624*00b67f09SDavid van Moolenbroek 		query = next;
2625*00b67f09SDavid van Moolenbroek 	}
2626*00b67f09SDavid van Moolenbroek 	if (lookup->timer != NULL)
2627*00b67f09SDavid van Moolenbroek 		isc_timer_detach(&lookup->timer);
2628*00b67f09SDavid van Moolenbroek 	lookup->pending = ISC_FALSE;
2629*00b67f09SDavid van Moolenbroek 	lookup->retries = 0;
2630*00b67f09SDavid van Moolenbroek }
2631*00b67f09SDavid van Moolenbroek 
2632*00b67f09SDavid van Moolenbroek static void
bringup_timer(dig_query_t * query,unsigned int default_timeout)2633*00b67f09SDavid van Moolenbroek bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2634*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l;
2635*00b67f09SDavid van Moolenbroek 	unsigned int local_timeout;
2636*00b67f09SDavid van Moolenbroek 	isc_result_t result;
2637*00b67f09SDavid van Moolenbroek 
2638*00b67f09SDavid van Moolenbroek 	debug("bringup_timer()");
2639*00b67f09SDavid van Moolenbroek 	/*
2640*00b67f09SDavid van Moolenbroek 	 * If the timer already exists, that means we're calling this
2641*00b67f09SDavid van Moolenbroek 	 * a second time (for a retry).  Don't need to recreate it,
2642*00b67f09SDavid van Moolenbroek 	 * just reset it.
2643*00b67f09SDavid van Moolenbroek 	 */
2644*00b67f09SDavid van Moolenbroek 	l = query->lookup;
2645*00b67f09SDavid van Moolenbroek 	if (ISC_LIST_NEXT(query, link) != NULL)
2646*00b67f09SDavid van Moolenbroek 		local_timeout = SERVER_TIMEOUT;
2647*00b67f09SDavid van Moolenbroek 	else {
2648*00b67f09SDavid van Moolenbroek 		if (timeout == 0)
2649*00b67f09SDavid van Moolenbroek 			local_timeout = default_timeout;
2650*00b67f09SDavid van Moolenbroek 		else
2651*00b67f09SDavid van Moolenbroek 			local_timeout = timeout;
2652*00b67f09SDavid van Moolenbroek 	}
2653*00b67f09SDavid van Moolenbroek 	debug("have local timeout of %d", local_timeout);
2654*00b67f09SDavid van Moolenbroek 	isc_interval_set(&l->interval, local_timeout, 0);
2655*00b67f09SDavid van Moolenbroek 	if (l->timer != NULL)
2656*00b67f09SDavid van Moolenbroek 		isc_timer_detach(&l->timer);
2657*00b67f09SDavid van Moolenbroek 	result = isc_timer_create(timermgr, isc_timertype_once, NULL,
2658*00b67f09SDavid van Moolenbroek 				  &l->interval, global_task, connect_timeout,
2659*00b67f09SDavid van Moolenbroek 				  l, &l->timer);
2660*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_timer_create");
2661*00b67f09SDavid van Moolenbroek }
2662*00b67f09SDavid van Moolenbroek 
2663*00b67f09SDavid van Moolenbroek static void
force_timeout(dig_lookup_t * l,dig_query_t * query)2664*00b67f09SDavid van Moolenbroek force_timeout(dig_lookup_t *l, dig_query_t *query) {
2665*00b67f09SDavid van Moolenbroek 	isc_event_t *event;
2666*00b67f09SDavid van Moolenbroek 
2667*00b67f09SDavid van Moolenbroek 	debug("force_timeout ()");
2668*00b67f09SDavid van Moolenbroek 	event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
2669*00b67f09SDavid van Moolenbroek 				   connect_timeout, l,
2670*00b67f09SDavid van Moolenbroek 				   sizeof(isc_event_t));
2671*00b67f09SDavid van Moolenbroek 	if (event == NULL) {
2672*00b67f09SDavid van Moolenbroek 		fatal("isc_event_allocate: %s",
2673*00b67f09SDavid van Moolenbroek 		      isc_result_totext(ISC_R_NOMEMORY));
2674*00b67f09SDavid van Moolenbroek 	}
2675*00b67f09SDavid van Moolenbroek 	isc_task_send(global_task, &event);
2676*00b67f09SDavid van Moolenbroek 
2677*00b67f09SDavid van Moolenbroek 	/*
2678*00b67f09SDavid van Moolenbroek 	 * The timer may have expired if, for example, get_address() takes
2679*00b67f09SDavid van Moolenbroek 	 * long time and the timer was running on a different thread.
2680*00b67f09SDavid van Moolenbroek 	 * We need to cancel the possible timeout event not to confuse
2681*00b67f09SDavid van Moolenbroek 	 * ourselves due to the duplicate events.
2682*00b67f09SDavid van Moolenbroek 	 */
2683*00b67f09SDavid van Moolenbroek 	if (l->timer != NULL)
2684*00b67f09SDavid van Moolenbroek 		isc_timer_detach(&l->timer);
2685*00b67f09SDavid van Moolenbroek }
2686*00b67f09SDavid van Moolenbroek 
2687*00b67f09SDavid van Moolenbroek 
2688*00b67f09SDavid van Moolenbroek static void
2689*00b67f09SDavid van Moolenbroek connect_done(isc_task_t *task, isc_event_t *event);
2690*00b67f09SDavid van Moolenbroek 
2691*00b67f09SDavid van Moolenbroek /*%
2692*00b67f09SDavid van Moolenbroek  * Unlike send_udp, this can't be called multiple times with the same
2693*00b67f09SDavid van Moolenbroek  * query.  When we retry TCP, we requeue the whole lookup, which should
2694*00b67f09SDavid van Moolenbroek  * start anew.
2695*00b67f09SDavid van Moolenbroek  */
2696*00b67f09SDavid van Moolenbroek static void
send_tcp_connect(dig_query_t * query)2697*00b67f09SDavid van Moolenbroek send_tcp_connect(dig_query_t *query) {
2698*00b67f09SDavid van Moolenbroek 	isc_result_t result;
2699*00b67f09SDavid van Moolenbroek 	dig_query_t *next;
2700*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l;
2701*00b67f09SDavid van Moolenbroek 
2702*00b67f09SDavid van Moolenbroek 	debug("send_tcp_connect(%p)", query);
2703*00b67f09SDavid van Moolenbroek 
2704*00b67f09SDavid van Moolenbroek 	l = query->lookup;
2705*00b67f09SDavid van Moolenbroek 	query->waiting_connect = ISC_TRUE;
2706*00b67f09SDavid van Moolenbroek 	query->lookup->current_query = query;
2707*00b67f09SDavid van Moolenbroek 	result = get_address(query->servname, port, &query->sockaddr);
2708*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
2709*00b67f09SDavid van Moolenbroek 		/*
2710*00b67f09SDavid van Moolenbroek 		 * This servname doesn't have an address.  Try the next server
2711*00b67f09SDavid van Moolenbroek 		 * by triggering an immediate 'timeout' (we lie, but the effect
2712*00b67f09SDavid van Moolenbroek 		 * is the same).
2713*00b67f09SDavid van Moolenbroek 		 */
2714*00b67f09SDavid van Moolenbroek 		force_timeout(l, query);
2715*00b67f09SDavid van Moolenbroek 		return;
2716*00b67f09SDavid van Moolenbroek 	}
2717*00b67f09SDavid van Moolenbroek 
2718*00b67f09SDavid van Moolenbroek 	if (specified_source &&
2719*00b67f09SDavid van Moolenbroek 	    (isc_sockaddr_pf(&query->sockaddr) !=
2720*00b67f09SDavid van Moolenbroek 	     isc_sockaddr_pf(&bind_address))) {
2721*00b67f09SDavid van Moolenbroek 		printf(";; Skipping server %s, incompatible "
2722*00b67f09SDavid van Moolenbroek 		       "address family\n", query->servname);
2723*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
2724*00b67f09SDavid van Moolenbroek 		next = ISC_LIST_NEXT(query, link);
2725*00b67f09SDavid van Moolenbroek 		l = query->lookup;
2726*00b67f09SDavid van Moolenbroek 		clear_query(query);
2727*00b67f09SDavid van Moolenbroek 		if (next == NULL) {
2728*00b67f09SDavid van Moolenbroek 			printf(";; No acceptable nameservers\n");
2729*00b67f09SDavid van Moolenbroek 			check_next_lookup(l);
2730*00b67f09SDavid van Moolenbroek 			return;
2731*00b67f09SDavid van Moolenbroek 		}
2732*00b67f09SDavid van Moolenbroek 		send_tcp_connect(next);
2733*00b67f09SDavid van Moolenbroek 		return;
2734*00b67f09SDavid van Moolenbroek 	}
2735*00b67f09SDavid van Moolenbroek 
2736*00b67f09SDavid van Moolenbroek 	INSIST(query->sock == NULL);
2737*00b67f09SDavid van Moolenbroek 
2738*00b67f09SDavid van Moolenbroek 	if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
2739*00b67f09SDavid van Moolenbroek 		sockcount++;
2740*00b67f09SDavid van Moolenbroek 		isc_socket_attach(keep, &query->sock);
2741*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
2742*00b67f09SDavid van Moolenbroek 		launch_next_query(query, ISC_TRUE);
2743*00b67f09SDavid van Moolenbroek 		goto search;
2744*00b67f09SDavid van Moolenbroek 	}
2745*00b67f09SDavid van Moolenbroek 
2746*00b67f09SDavid van Moolenbroek 	result = isc_socket_create(socketmgr,
2747*00b67f09SDavid van Moolenbroek 				   isc_sockaddr_pf(&query->sockaddr),
2748*00b67f09SDavid van Moolenbroek 				   isc_sockettype_tcp, &query->sock);
2749*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_socket_create");
2750*00b67f09SDavid van Moolenbroek 	sockcount++;
2751*00b67f09SDavid van Moolenbroek 	debug("sockcount=%d", sockcount);
2752*00b67f09SDavid van Moolenbroek 	if (specified_source)
2753*00b67f09SDavid van Moolenbroek 		result = isc_socket_bind(query->sock, &bind_address,
2754*00b67f09SDavid van Moolenbroek 					 ISC_SOCKET_REUSEADDRESS);
2755*00b67f09SDavid van Moolenbroek 	else {
2756*00b67f09SDavid van Moolenbroek 		if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2757*00b67f09SDavid van Moolenbroek 		    have_ipv4)
2758*00b67f09SDavid van Moolenbroek 			isc_sockaddr_any(&bind_any);
2759*00b67f09SDavid van Moolenbroek 		else
2760*00b67f09SDavid van Moolenbroek 			isc_sockaddr_any6(&bind_any);
2761*00b67f09SDavid van Moolenbroek 		result = isc_socket_bind(query->sock, &bind_any, 0);
2762*00b67f09SDavid van Moolenbroek 	}
2763*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_socket_bind");
2764*00b67f09SDavid van Moolenbroek 	bringup_timer(query, TCP_TIMEOUT);
2765*00b67f09SDavid van Moolenbroek 	result = isc_socket_connect(query->sock, &query->sockaddr,
2766*00b67f09SDavid van Moolenbroek 				    global_task, connect_done, query);
2767*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_socket_connect");
2768*00b67f09SDavid van Moolenbroek  search:
2769*00b67f09SDavid van Moolenbroek 	/*
2770*00b67f09SDavid van Moolenbroek 	 * If we're at the endgame of a nameserver search, we need to
2771*00b67f09SDavid van Moolenbroek 	 * immediately bring up all the queries.  Do it here.
2772*00b67f09SDavid van Moolenbroek 	 */
2773*00b67f09SDavid van Moolenbroek 	if (l->ns_search_only && !l->trace_root) {
2774*00b67f09SDavid van Moolenbroek 		debug("sending next, since searching");
2775*00b67f09SDavid van Moolenbroek 		next = ISC_LIST_NEXT(query, link);
2776*00b67f09SDavid van Moolenbroek 		if (ISC_LINK_LINKED(query, link))
2777*00b67f09SDavid van Moolenbroek 			ISC_LIST_DEQUEUE(l->q, query, link);
2778*00b67f09SDavid van Moolenbroek 		ISC_LIST_ENQUEUE(l->connecting, query, clink);
2779*00b67f09SDavid van Moolenbroek 		if (next != NULL)
2780*00b67f09SDavid van Moolenbroek 			send_tcp_connect(next);
2781*00b67f09SDavid van Moolenbroek 	}
2782*00b67f09SDavid van Moolenbroek }
2783*00b67f09SDavid van Moolenbroek 
2784*00b67f09SDavid van Moolenbroek static isc_buffer_t *
clone_buffer(isc_buffer_t * source)2785*00b67f09SDavid van Moolenbroek clone_buffer(isc_buffer_t *source) {
2786*00b67f09SDavid van Moolenbroek 	isc_buffer_t *buffer;
2787*00b67f09SDavid van Moolenbroek 	buffer = isc_mem_allocate(mctx, sizeof(*buffer));
2788*00b67f09SDavid van Moolenbroek 	if (buffer == NULL)
2789*00b67f09SDavid van Moolenbroek 		fatal("memory allocation failure in %s:%d",
2790*00b67f09SDavid van Moolenbroek 		      __FILE__, __LINE__);
2791*00b67f09SDavid van Moolenbroek 	*buffer = *source;
2792*00b67f09SDavid van Moolenbroek 	return (buffer);
2793*00b67f09SDavid van Moolenbroek }
2794*00b67f09SDavid van Moolenbroek 
2795*00b67f09SDavid van Moolenbroek /*%
2796*00b67f09SDavid van Moolenbroek  * Send a UDP packet to the remote nameserver, possible starting the
2797*00b67f09SDavid van Moolenbroek  * recv action as well.  Also make sure that the timer is running and
2798*00b67f09SDavid van Moolenbroek  * is properly reset.
2799*00b67f09SDavid van Moolenbroek  */
2800*00b67f09SDavid van Moolenbroek static void
send_udp(dig_query_t * query)2801*00b67f09SDavid van Moolenbroek send_udp(dig_query_t *query) {
2802*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l = NULL;
2803*00b67f09SDavid van Moolenbroek 	isc_result_t result;
2804*00b67f09SDavid van Moolenbroek 	isc_buffer_t *sendbuf;
2805*00b67f09SDavid van Moolenbroek 
2806*00b67f09SDavid van Moolenbroek 	debug("send_udp(%p)", query);
2807*00b67f09SDavid van Moolenbroek 
2808*00b67f09SDavid van Moolenbroek 	l = query->lookup;
2809*00b67f09SDavid van Moolenbroek 	bringup_timer(query, UDP_TIMEOUT);
2810*00b67f09SDavid van Moolenbroek 	l->current_query = query;
2811*00b67f09SDavid van Moolenbroek 	debug("working on lookup %p, query %p", query->lookup, query);
2812*00b67f09SDavid van Moolenbroek 	if (!query->recv_made) {
2813*00b67f09SDavid van Moolenbroek 		/* XXX Check the sense of this, need assertion? */
2814*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
2815*00b67f09SDavid van Moolenbroek 		result = get_address(query->servname, port, &query->sockaddr);
2816*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
2817*00b67f09SDavid van Moolenbroek 			/* This servname doesn't have an address. */
2818*00b67f09SDavid van Moolenbroek 			force_timeout(l, query);
2819*00b67f09SDavid van Moolenbroek 			return;
2820*00b67f09SDavid van Moolenbroek 		}
2821*00b67f09SDavid van Moolenbroek 
2822*00b67f09SDavid van Moolenbroek 		result = isc_socket_create(socketmgr,
2823*00b67f09SDavid van Moolenbroek 					   isc_sockaddr_pf(&query->sockaddr),
2824*00b67f09SDavid van Moolenbroek 					   isc_sockettype_udp, &query->sock);
2825*00b67f09SDavid van Moolenbroek 		check_result(result, "isc_socket_create");
2826*00b67f09SDavid van Moolenbroek 		sockcount++;
2827*00b67f09SDavid van Moolenbroek 		debug("sockcount=%d", sockcount);
2828*00b67f09SDavid van Moolenbroek 		if (specified_source) {
2829*00b67f09SDavid van Moolenbroek 			result = isc_socket_bind(query->sock, &bind_address,
2830*00b67f09SDavid van Moolenbroek 						 ISC_SOCKET_REUSEADDRESS);
2831*00b67f09SDavid van Moolenbroek 		} else {
2832*00b67f09SDavid van Moolenbroek 			isc_sockaddr_anyofpf(&bind_any,
2833*00b67f09SDavid van Moolenbroek 					isc_sockaddr_pf(&query->sockaddr));
2834*00b67f09SDavid van Moolenbroek 			result = isc_socket_bind(query->sock, &bind_any, 0);
2835*00b67f09SDavid van Moolenbroek 		}
2836*00b67f09SDavid van Moolenbroek 		check_result(result, "isc_socket_bind");
2837*00b67f09SDavid van Moolenbroek 
2838*00b67f09SDavid van Moolenbroek 		query->recv_made = ISC_TRUE;
2839*00b67f09SDavid van Moolenbroek 		ISC_LINK_INIT(&query->recvbuf, link);
2840*00b67f09SDavid van Moolenbroek 		ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2841*00b67f09SDavid van Moolenbroek 				 link);
2842*00b67f09SDavid van Moolenbroek 		debug("recving with lookup=%p, query=%p, sock=%p",
2843*00b67f09SDavid van Moolenbroek 		      query->lookup, query, query->sock);
2844*00b67f09SDavid van Moolenbroek 		result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2845*00b67f09SDavid van Moolenbroek 					  global_task, recv_done, query);
2846*00b67f09SDavid van Moolenbroek 		check_result(result, "isc_socket_recvv");
2847*00b67f09SDavid van Moolenbroek 		recvcount++;
2848*00b67f09SDavid van Moolenbroek 		debug("recvcount=%d", recvcount);
2849*00b67f09SDavid van Moolenbroek 	}
2850*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(query->sendlist);
2851*00b67f09SDavid van Moolenbroek 	sendbuf = clone_buffer(&query->sendbuf);
2852*00b67f09SDavid van Moolenbroek 	ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
2853*00b67f09SDavid van Moolenbroek 	debug("sending a request");
2854*00b67f09SDavid van Moolenbroek 	TIME_NOW(&query->time_sent);
2855*00b67f09SDavid van Moolenbroek 	INSIST(query->sock != NULL);
2856*00b67f09SDavid van Moolenbroek 	query->waiting_senddone = ISC_TRUE;
2857*00b67f09SDavid van Moolenbroek 	result = isc_socket_sendtov2(query->sock, &query->sendlist,
2858*00b67f09SDavid van Moolenbroek 				     global_task, send_done, query,
2859*00b67f09SDavid van Moolenbroek 				     &query->sockaddr, NULL,
2860*00b67f09SDavid van Moolenbroek 				     ISC_SOCKFLAG_NORETRY);
2861*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_socket_sendtov");
2862*00b67f09SDavid van Moolenbroek 	sendcount++;
2863*00b67f09SDavid van Moolenbroek }
2864*00b67f09SDavid van Moolenbroek 
2865*00b67f09SDavid van Moolenbroek /*%
2866*00b67f09SDavid van Moolenbroek  * IO timeout handler, used for both connect and recv timeouts.  If
2867*00b67f09SDavid van Moolenbroek  * retries are still allowed, either resend the UDP packet or queue a
2868*00b67f09SDavid van Moolenbroek  * new TCP lookup.  Otherwise, cancel the lookup.
2869*00b67f09SDavid van Moolenbroek  */
2870*00b67f09SDavid van Moolenbroek static void
connect_timeout(isc_task_t * task,isc_event_t * event)2871*00b67f09SDavid van Moolenbroek connect_timeout(isc_task_t *task, isc_event_t *event) {
2872*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l = NULL;
2873*00b67f09SDavid van Moolenbroek 	dig_query_t *query = NULL, *next, *cq;
2874*00b67f09SDavid van Moolenbroek 
2875*00b67f09SDavid van Moolenbroek 	UNUSED(task);
2876*00b67f09SDavid van Moolenbroek 	REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2877*00b67f09SDavid van Moolenbroek 
2878*00b67f09SDavid van Moolenbroek 	debug("connect_timeout()");
2879*00b67f09SDavid van Moolenbroek 
2880*00b67f09SDavid van Moolenbroek 	LOCK_LOOKUP;
2881*00b67f09SDavid van Moolenbroek 	l = event->ev_arg;
2882*00b67f09SDavid van Moolenbroek 	query = l->current_query;
2883*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
2884*00b67f09SDavid van Moolenbroek 
2885*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
2886*00b67f09SDavid van Moolenbroek 
2887*00b67f09SDavid van Moolenbroek 	if ((query != NULL) && (query->lookup->current_query != NULL) &&
2888*00b67f09SDavid van Moolenbroek 	    (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2889*00b67f09SDavid van Moolenbroek 		debug("trying next server...");
2890*00b67f09SDavid van Moolenbroek 		cq = query->lookup->current_query;
2891*00b67f09SDavid van Moolenbroek 		if (!l->tcp_mode)
2892*00b67f09SDavid van Moolenbroek 			send_udp(ISC_LIST_NEXT(cq, link));
2893*00b67f09SDavid van Moolenbroek 		else {
2894*00b67f09SDavid van Moolenbroek 			if (query->sock != NULL)
2895*00b67f09SDavid van Moolenbroek 				isc_socket_cancel(query->sock, NULL,
2896*00b67f09SDavid van Moolenbroek 						  ISC_SOCKCANCEL_ALL);
2897*00b67f09SDavid van Moolenbroek 			next = ISC_LIST_NEXT(cq, link);
2898*00b67f09SDavid van Moolenbroek 			if (next != NULL)
2899*00b67f09SDavid van Moolenbroek 				send_tcp_connect(next);
2900*00b67f09SDavid van Moolenbroek 		}
2901*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
2902*00b67f09SDavid van Moolenbroek 		return;
2903*00b67f09SDavid van Moolenbroek 	}
2904*00b67f09SDavid van Moolenbroek 
2905*00b67f09SDavid van Moolenbroek 	if (l->retries > 1) {
2906*00b67f09SDavid van Moolenbroek 		if (!l->tcp_mode) {
2907*00b67f09SDavid van Moolenbroek 			l->retries--;
2908*00b67f09SDavid van Moolenbroek 			debug("resending UDP request to first server");
2909*00b67f09SDavid van Moolenbroek 			send_udp(ISC_LIST_HEAD(l->q));
2910*00b67f09SDavid van Moolenbroek 		} else {
2911*00b67f09SDavid van Moolenbroek 			debug("making new TCP request, %d tries left",
2912*00b67f09SDavid van Moolenbroek 			      l->retries);
2913*00b67f09SDavid van Moolenbroek 			l->retries--;
2914*00b67f09SDavid van Moolenbroek 			requeue_lookup(l, ISC_TRUE);
2915*00b67f09SDavid van Moolenbroek 			cancel_lookup(l);
2916*00b67f09SDavid van Moolenbroek 			check_next_lookup(l);
2917*00b67f09SDavid van Moolenbroek 		}
2918*00b67f09SDavid van Moolenbroek 	} else {
2919*00b67f09SDavid van Moolenbroek 		fputs(l->cmdline, stdout);
2920*00b67f09SDavid van Moolenbroek 		printf(";; connection timed out; no servers could be "
2921*00b67f09SDavid van Moolenbroek 		       "reached\n");
2922*00b67f09SDavid van Moolenbroek 		cancel_lookup(l);
2923*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
2924*00b67f09SDavid van Moolenbroek 		if (exitcode < 9)
2925*00b67f09SDavid van Moolenbroek 			exitcode = 9;
2926*00b67f09SDavid van Moolenbroek 	}
2927*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
2928*00b67f09SDavid van Moolenbroek }
2929*00b67f09SDavid van Moolenbroek 
2930*00b67f09SDavid van Moolenbroek /*%
2931*00b67f09SDavid van Moolenbroek  * Event handler for the TCP recv which gets the length header of TCP
2932*00b67f09SDavid van Moolenbroek  * packets.  Start the next recv of length bytes.
2933*00b67f09SDavid van Moolenbroek  */
2934*00b67f09SDavid van Moolenbroek static void
tcp_length_done(isc_task_t * task,isc_event_t * event)2935*00b67f09SDavid van Moolenbroek tcp_length_done(isc_task_t *task, isc_event_t *event) {
2936*00b67f09SDavid van Moolenbroek 	isc_socketevent_t *sevent;
2937*00b67f09SDavid van Moolenbroek 	isc_buffer_t *b = NULL;
2938*00b67f09SDavid van Moolenbroek 	isc_result_t result;
2939*00b67f09SDavid van Moolenbroek 	dig_query_t *query = NULL;
2940*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l;
2941*00b67f09SDavid van Moolenbroek 	isc_uint16_t length;
2942*00b67f09SDavid van Moolenbroek 
2943*00b67f09SDavid van Moolenbroek 	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2944*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
2945*00b67f09SDavid van Moolenbroek 
2946*00b67f09SDavid van Moolenbroek 	UNUSED(task);
2947*00b67f09SDavid van Moolenbroek 
2948*00b67f09SDavid van Moolenbroek 	debug("tcp_length_done()");
2949*00b67f09SDavid van Moolenbroek 
2950*00b67f09SDavid van Moolenbroek 	LOCK_LOOKUP;
2951*00b67f09SDavid van Moolenbroek 	sevent = (isc_socketevent_t *)event;
2952*00b67f09SDavid van Moolenbroek 	query = event->ev_arg;
2953*00b67f09SDavid van Moolenbroek 
2954*00b67f09SDavid van Moolenbroek 	recvcount--;
2955*00b67f09SDavid van Moolenbroek 	INSIST(recvcount >= 0);
2956*00b67f09SDavid van Moolenbroek 
2957*00b67f09SDavid van Moolenbroek 	b = ISC_LIST_HEAD(sevent->bufferlist);
2958*00b67f09SDavid van Moolenbroek 	INSIST(b ==  &query->lengthbuf);
2959*00b67f09SDavid van Moolenbroek 	ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2960*00b67f09SDavid van Moolenbroek 
2961*00b67f09SDavid van Moolenbroek 	if (sevent->result == ISC_R_CANCELED) {
2962*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
2963*00b67f09SDavid van Moolenbroek 		l = query->lookup;
2964*00b67f09SDavid van Moolenbroek 		clear_query(query);
2965*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
2966*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
2967*00b67f09SDavid van Moolenbroek 		return;
2968*00b67f09SDavid van Moolenbroek 	}
2969*00b67f09SDavid van Moolenbroek 	if (sevent->result != ISC_R_SUCCESS) {
2970*00b67f09SDavid van Moolenbroek 		char sockstr[ISC_SOCKADDR_FORMATSIZE];
2971*00b67f09SDavid van Moolenbroek 		isc_sockaddr_format(&query->sockaddr, sockstr,
2972*00b67f09SDavid van Moolenbroek 				    sizeof(sockstr));
2973*00b67f09SDavid van Moolenbroek 		printf(";; communications error to %s: %s\n",
2974*00b67f09SDavid van Moolenbroek 		       sockstr, isc_result_totext(sevent->result));
2975*00b67f09SDavid van Moolenbroek 		l = query->lookup;
2976*00b67f09SDavid van Moolenbroek 		isc_socket_detach(&query->sock);
2977*00b67f09SDavid van Moolenbroek 		sockcount--;
2978*00b67f09SDavid van Moolenbroek 		debug("sockcount=%d", sockcount);
2979*00b67f09SDavid van Moolenbroek 		INSIST(sockcount >= 0);
2980*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
2981*00b67f09SDavid van Moolenbroek 		clear_query(query);
2982*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
2983*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
2984*00b67f09SDavid van Moolenbroek 		return;
2985*00b67f09SDavid van Moolenbroek 	}
2986*00b67f09SDavid van Moolenbroek 	length = isc_buffer_getuint16(b);
2987*00b67f09SDavid van Moolenbroek 	if (length == 0) {
2988*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
2989*00b67f09SDavid van Moolenbroek 		launch_next_query(query, ISC_FALSE);
2990*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
2991*00b67f09SDavid van Moolenbroek 		return;
2992*00b67f09SDavid van Moolenbroek 	}
2993*00b67f09SDavid van Moolenbroek 
2994*00b67f09SDavid van Moolenbroek 	/*
2995*00b67f09SDavid van Moolenbroek 	 * Even though the buffer was already init'ed, we need
2996*00b67f09SDavid van Moolenbroek 	 * to redo it now, to force the length we want.
2997*00b67f09SDavid van Moolenbroek 	 */
2998*00b67f09SDavid van Moolenbroek 	isc_buffer_invalidate(&query->recvbuf);
2999*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&query->recvbuf, query->recvspace, length);
3000*00b67f09SDavid van Moolenbroek 	ENSURE(ISC_LIST_EMPTY(query->recvlist));
3001*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(&query->recvbuf, link);
3002*00b67f09SDavid van Moolenbroek 	ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3003*00b67f09SDavid van Moolenbroek 	debug("recving with lookup=%p, query=%p", query->lookup, query);
3004*00b67f09SDavid van Moolenbroek 	result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
3005*00b67f09SDavid van Moolenbroek 				  recv_done, query);
3006*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_socket_recvv");
3007*00b67f09SDavid van Moolenbroek 	recvcount++;
3008*00b67f09SDavid van Moolenbroek 	debug("resubmitted recv request with length %d, recvcount=%d",
3009*00b67f09SDavid van Moolenbroek 	      length, recvcount);
3010*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
3011*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
3012*00b67f09SDavid van Moolenbroek }
3013*00b67f09SDavid van Moolenbroek 
3014*00b67f09SDavid van Moolenbroek /*%
3015*00b67f09SDavid van Moolenbroek  * For transfers that involve multiple recvs (XFR's in particular),
3016*00b67f09SDavid van Moolenbroek  * launch the next recv.
3017*00b67f09SDavid van Moolenbroek  */
3018*00b67f09SDavid van Moolenbroek static void
launch_next_query(dig_query_t * query,isc_boolean_t include_question)3019*00b67f09SDavid van Moolenbroek launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
3020*00b67f09SDavid van Moolenbroek 	isc_result_t result;
3021*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l;
3022*00b67f09SDavid van Moolenbroek 	isc_buffer_t *buffer;
3023*00b67f09SDavid van Moolenbroek 
3024*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
3025*00b67f09SDavid van Moolenbroek 
3026*00b67f09SDavid van Moolenbroek 	debug("launch_next_query()");
3027*00b67f09SDavid van Moolenbroek 
3028*00b67f09SDavid van Moolenbroek 	if (!query->lookup->pending) {
3029*00b67f09SDavid van Moolenbroek 		debug("ignoring launch_next_query because !pending");
3030*00b67f09SDavid van Moolenbroek 		isc_socket_detach(&query->sock);
3031*00b67f09SDavid van Moolenbroek 		sockcount--;
3032*00b67f09SDavid van Moolenbroek 		debug("sockcount=%d", sockcount);
3033*00b67f09SDavid van Moolenbroek 		INSIST(sockcount >= 0);
3034*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
3035*00b67f09SDavid van Moolenbroek 		l = query->lookup;
3036*00b67f09SDavid van Moolenbroek 		clear_query(query);
3037*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
3038*00b67f09SDavid van Moolenbroek 		return;
3039*00b67f09SDavid van Moolenbroek 	}
3040*00b67f09SDavid van Moolenbroek 
3041*00b67f09SDavid van Moolenbroek 	isc_buffer_clear(&query->slbuf);
3042*00b67f09SDavid van Moolenbroek 	isc_buffer_clear(&query->lengthbuf);
3043*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
3044*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(query->sendlist);
3045*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(&query->slbuf, link);
3046*00b67f09SDavid van Moolenbroek 	if (!query->first_soa_rcvd) {
3047*00b67f09SDavid van Moolenbroek 		buffer = clone_buffer(&query->slbuf);
3048*00b67f09SDavid van Moolenbroek 		ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
3049*00b67f09SDavid van Moolenbroek 		if (include_question) {
3050*00b67f09SDavid van Moolenbroek 			buffer = clone_buffer(&query->sendbuf);
3051*00b67f09SDavid van Moolenbroek 			ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
3052*00b67f09SDavid van Moolenbroek 		}
3053*00b67f09SDavid van Moolenbroek 	}
3054*00b67f09SDavid van Moolenbroek 
3055*00b67f09SDavid van Moolenbroek 	ISC_LINK_INIT(&query->lengthbuf, link);
3056*00b67f09SDavid van Moolenbroek 	ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
3057*00b67f09SDavid van Moolenbroek 
3058*00b67f09SDavid van Moolenbroek 	result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
3059*00b67f09SDavid van Moolenbroek 				  global_task, tcp_length_done, query);
3060*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_socket_recvv");
3061*00b67f09SDavid van Moolenbroek 	recvcount++;
3062*00b67f09SDavid van Moolenbroek 	debug("recvcount=%d", recvcount);
3063*00b67f09SDavid van Moolenbroek 	if (!query->first_soa_rcvd) {
3064*00b67f09SDavid van Moolenbroek 		debug("sending a request in launch_next_query");
3065*00b67f09SDavid van Moolenbroek 		TIME_NOW(&query->time_sent);
3066*00b67f09SDavid van Moolenbroek 		query->waiting_senddone = ISC_TRUE;
3067*00b67f09SDavid van Moolenbroek 		result = isc_socket_sendv(query->sock, &query->sendlist,
3068*00b67f09SDavid van Moolenbroek 					  global_task, send_done, query);
3069*00b67f09SDavid van Moolenbroek 		check_result(result, "isc_socket_sendv");
3070*00b67f09SDavid van Moolenbroek 		sendcount++;
3071*00b67f09SDavid van Moolenbroek 		debug("sendcount=%d", sendcount);
3072*00b67f09SDavid van Moolenbroek 	}
3073*00b67f09SDavid van Moolenbroek 	query->waiting_connect = ISC_FALSE;
3074*00b67f09SDavid van Moolenbroek #if 0
3075*00b67f09SDavid van Moolenbroek 	check_next_lookup(query->lookup);
3076*00b67f09SDavid van Moolenbroek #endif
3077*00b67f09SDavid van Moolenbroek 	return;
3078*00b67f09SDavid van Moolenbroek }
3079*00b67f09SDavid van Moolenbroek 
3080*00b67f09SDavid van Moolenbroek /*%
3081*00b67f09SDavid van Moolenbroek  * Event handler for TCP connect complete.  Make sure the connection was
3082*00b67f09SDavid van Moolenbroek  * successful, then pass into launch_next_query to actually send the
3083*00b67f09SDavid van Moolenbroek  * question.
3084*00b67f09SDavid van Moolenbroek  */
3085*00b67f09SDavid van Moolenbroek static void
connect_done(isc_task_t * task,isc_event_t * event)3086*00b67f09SDavid van Moolenbroek connect_done(isc_task_t *task, isc_event_t *event) {
3087*00b67f09SDavid van Moolenbroek 	isc_socketevent_t *sevent = NULL;
3088*00b67f09SDavid van Moolenbroek 	dig_query_t *query = NULL, *next;
3089*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l;
3090*00b67f09SDavid van Moolenbroek 
3091*00b67f09SDavid van Moolenbroek 	UNUSED(task);
3092*00b67f09SDavid van Moolenbroek 
3093*00b67f09SDavid van Moolenbroek 	REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
3094*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
3095*00b67f09SDavid van Moolenbroek 
3096*00b67f09SDavid van Moolenbroek 	debug("connect_done()");
3097*00b67f09SDavid van Moolenbroek 
3098*00b67f09SDavid van Moolenbroek 	LOCK_LOOKUP;
3099*00b67f09SDavid van Moolenbroek 	sevent = (isc_socketevent_t *)event;
3100*00b67f09SDavid van Moolenbroek 	query = sevent->ev_arg;
3101*00b67f09SDavid van Moolenbroek 
3102*00b67f09SDavid van Moolenbroek 	INSIST(query->waiting_connect);
3103*00b67f09SDavid van Moolenbroek 
3104*00b67f09SDavid van Moolenbroek 	query->waiting_connect = ISC_FALSE;
3105*00b67f09SDavid van Moolenbroek 
3106*00b67f09SDavid van Moolenbroek 	if (sevent->result == ISC_R_CANCELED) {
3107*00b67f09SDavid van Moolenbroek 		debug("in cancel handler");
3108*00b67f09SDavid van Moolenbroek 		isc_socket_detach(&query->sock);
3109*00b67f09SDavid van Moolenbroek 		INSIST(sockcount > 0);
3110*00b67f09SDavid van Moolenbroek 		sockcount--;
3111*00b67f09SDavid van Moolenbroek 		debug("sockcount=%d", sockcount);
3112*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
3113*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
3114*00b67f09SDavid van Moolenbroek 		l = query->lookup;
3115*00b67f09SDavid van Moolenbroek 		clear_query(query);
3116*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
3117*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
3118*00b67f09SDavid van Moolenbroek 		return;
3119*00b67f09SDavid van Moolenbroek 	}
3120*00b67f09SDavid van Moolenbroek 	if (sevent->result != ISC_R_SUCCESS) {
3121*00b67f09SDavid van Moolenbroek 		char sockstr[ISC_SOCKADDR_FORMATSIZE];
3122*00b67f09SDavid van Moolenbroek 
3123*00b67f09SDavid van Moolenbroek 		debug("unsuccessful connection: %s",
3124*00b67f09SDavid van Moolenbroek 		      isc_result_totext(sevent->result));
3125*00b67f09SDavid van Moolenbroek 		isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
3126*00b67f09SDavid van Moolenbroek 		if (sevent->result != ISC_R_CANCELED)
3127*00b67f09SDavid van Moolenbroek 			printf(";; Connection to %s(%s) for %s failed: "
3128*00b67f09SDavid van Moolenbroek 			       "%s.\n", sockstr,
3129*00b67f09SDavid van Moolenbroek 			       query->servname, query->lookup->textname,
3130*00b67f09SDavid van Moolenbroek 			       isc_result_totext(sevent->result));
3131*00b67f09SDavid van Moolenbroek 		isc_socket_detach(&query->sock);
3132*00b67f09SDavid van Moolenbroek 		sockcount--;
3133*00b67f09SDavid van Moolenbroek 		INSIST(sockcount >= 0);
3134*00b67f09SDavid van Moolenbroek 		/* XXX Clean up exitcodes */
3135*00b67f09SDavid van Moolenbroek 		if (exitcode < 9)
3136*00b67f09SDavid van Moolenbroek 			exitcode = 9;
3137*00b67f09SDavid van Moolenbroek 		debug("sockcount=%d", sockcount);
3138*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
3139*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
3140*00b67f09SDavid van Moolenbroek 		l = query->lookup;
3141*00b67f09SDavid van Moolenbroek 		if ((l->current_query != NULL) &&
3142*00b67f09SDavid van Moolenbroek 		    (ISC_LINK_LINKED(l->current_query, link)))
3143*00b67f09SDavid van Moolenbroek 			next = ISC_LIST_NEXT(l->current_query, link);
3144*00b67f09SDavid van Moolenbroek 		else
3145*00b67f09SDavid van Moolenbroek 			next = NULL;
3146*00b67f09SDavid van Moolenbroek 		clear_query(query);
3147*00b67f09SDavid van Moolenbroek 		if (next != NULL) {
3148*00b67f09SDavid van Moolenbroek 			bringup_timer(next, TCP_TIMEOUT);
3149*00b67f09SDavid van Moolenbroek 			send_tcp_connect(next);
3150*00b67f09SDavid van Moolenbroek 		} else
3151*00b67f09SDavid van Moolenbroek 			check_next_lookup(l);
3152*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
3153*00b67f09SDavid van Moolenbroek 		return;
3154*00b67f09SDavid van Moolenbroek 	}
3155*00b67f09SDavid van Moolenbroek 	if (keep_open) {
3156*00b67f09SDavid van Moolenbroek 		if (keep != NULL)
3157*00b67f09SDavid van Moolenbroek 			isc_socket_detach(&keep);
3158*00b67f09SDavid van Moolenbroek 		isc_socket_attach(query->sock, &keep);
3159*00b67f09SDavid van Moolenbroek 		keepaddr = query->sockaddr;
3160*00b67f09SDavid van Moolenbroek 	}
3161*00b67f09SDavid van Moolenbroek 	launch_next_query(query, ISC_TRUE);
3162*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
3163*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
3164*00b67f09SDavid van Moolenbroek }
3165*00b67f09SDavid van Moolenbroek 
3166*00b67f09SDavid van Moolenbroek /*%
3167*00b67f09SDavid van Moolenbroek  * Check if the ongoing XFR needs more data before it's complete, using
3168*00b67f09SDavid van Moolenbroek  * the semantics of IXFR and AXFR protocols.  Much of the complexity of
3169*00b67f09SDavid van Moolenbroek  * this routine comes from determining when an IXFR is complete.
3170*00b67f09SDavid van Moolenbroek  * ISC_FALSE means more data is on the way, and the recv has been issued.
3171*00b67f09SDavid van Moolenbroek  */
3172*00b67f09SDavid van Moolenbroek static isc_boolean_t
check_for_more_data(dig_query_t * query,dns_message_t * msg,isc_socketevent_t * sevent)3173*00b67f09SDavid van Moolenbroek check_for_more_data(dig_query_t *query, dns_message_t *msg,
3174*00b67f09SDavid van Moolenbroek 		    isc_socketevent_t *sevent)
3175*00b67f09SDavid van Moolenbroek {
3176*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset = NULL;
3177*00b67f09SDavid van Moolenbroek 	dns_rdata_t rdata = DNS_RDATA_INIT;
3178*00b67f09SDavid van Moolenbroek 	dns_rdata_soa_t soa;
3179*00b67f09SDavid van Moolenbroek 	isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
3180*00b67f09SDavid van Moolenbroek 	isc_result_t result;
3181*00b67f09SDavid van Moolenbroek 	isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
3182*00b67f09SDavid van Moolenbroek 	isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr;
3183*00b67f09SDavid van Moolenbroek 
3184*00b67f09SDavid van Moolenbroek 	if (ixfr)
3185*00b67f09SDavid van Moolenbroek 		axfr = query->ixfr_axfr;
3186*00b67f09SDavid van Moolenbroek 
3187*00b67f09SDavid van Moolenbroek 	debug("check_for_more_data()");
3188*00b67f09SDavid van Moolenbroek 
3189*00b67f09SDavid van Moolenbroek 	/*
3190*00b67f09SDavid van Moolenbroek 	 * By the time we're in this routine, we know we're doing
3191*00b67f09SDavid van Moolenbroek 	 * either an AXFR or IXFR.  If there's no second_rr_type,
3192*00b67f09SDavid van Moolenbroek 	 * then we don't yet know which kind of answer we got back
3193*00b67f09SDavid van Moolenbroek 	 * from the server.  Here, we're going to walk through the
3194*00b67f09SDavid van Moolenbroek 	 * rr's in the message, acting as necessary whenever we hit
3195*00b67f09SDavid van Moolenbroek 	 * an SOA rr.
3196*00b67f09SDavid van Moolenbroek 	 */
3197*00b67f09SDavid van Moolenbroek 
3198*00b67f09SDavid van Moolenbroek 	query->msg_count++;
3199*00b67f09SDavid van Moolenbroek 	query->byte_count += sevent->n;
3200*00b67f09SDavid van Moolenbroek 	result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
3201*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
3202*00b67f09SDavid van Moolenbroek 		puts("; Transfer failed.");
3203*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
3204*00b67f09SDavid van Moolenbroek 	}
3205*00b67f09SDavid van Moolenbroek 	do {
3206*00b67f09SDavid van Moolenbroek 		dns_name_t *name;
3207*00b67f09SDavid van Moolenbroek 		name = NULL;
3208*00b67f09SDavid van Moolenbroek 		dns_message_currentname(msg, DNS_SECTION_ANSWER,
3209*00b67f09SDavid van Moolenbroek 					&name);
3210*00b67f09SDavid van Moolenbroek 		for (rdataset = ISC_LIST_HEAD(name->list);
3211*00b67f09SDavid van Moolenbroek 		     rdataset != NULL;
3212*00b67f09SDavid van Moolenbroek 		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
3213*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_first(rdataset);
3214*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
3215*00b67f09SDavid van Moolenbroek 				continue;
3216*00b67f09SDavid van Moolenbroek 			do {
3217*00b67f09SDavid van Moolenbroek 				query->rr_count++;
3218*00b67f09SDavid van Moolenbroek 				dns_rdata_reset(&rdata);
3219*00b67f09SDavid van Moolenbroek 				dns_rdataset_current(rdataset, &rdata);
3220*00b67f09SDavid van Moolenbroek 				/*
3221*00b67f09SDavid van Moolenbroek 				 * If this is the first rr, make sure
3222*00b67f09SDavid van Moolenbroek 				 * it's an SOA
3223*00b67f09SDavid van Moolenbroek 				 */
3224*00b67f09SDavid van Moolenbroek 				if ((!query->first_soa_rcvd) &&
3225*00b67f09SDavid van Moolenbroek 				    (rdata.type != dns_rdatatype_soa)) {
3226*00b67f09SDavid van Moolenbroek 					puts("; Transfer failed.  "
3227*00b67f09SDavid van Moolenbroek 					     "Didn't start with SOA answer.");
3228*00b67f09SDavid van Moolenbroek 					return (ISC_TRUE);
3229*00b67f09SDavid van Moolenbroek 				}
3230*00b67f09SDavid van Moolenbroek 				if ((!query->second_rr_rcvd) &&
3231*00b67f09SDavid van Moolenbroek 				    (rdata.type != dns_rdatatype_soa)) {
3232*00b67f09SDavid van Moolenbroek 					query->second_rr_rcvd = ISC_TRUE;
3233*00b67f09SDavid van Moolenbroek 					query->second_rr_serial = 0;
3234*00b67f09SDavid van Moolenbroek 					debug("got the second rr as nonsoa");
3235*00b67f09SDavid van Moolenbroek 					axfr = query->ixfr_axfr = ISC_TRUE;
3236*00b67f09SDavid van Moolenbroek 					goto next_rdata;
3237*00b67f09SDavid van Moolenbroek 				}
3238*00b67f09SDavid van Moolenbroek 
3239*00b67f09SDavid van Moolenbroek 				/*
3240*00b67f09SDavid van Moolenbroek 				 * If the record is anything except an SOA
3241*00b67f09SDavid van Moolenbroek 				 * now, just continue on...
3242*00b67f09SDavid van Moolenbroek 				 */
3243*00b67f09SDavid van Moolenbroek 				if (rdata.type != dns_rdatatype_soa)
3244*00b67f09SDavid van Moolenbroek 					goto next_rdata;
3245*00b67f09SDavid van Moolenbroek 
3246*00b67f09SDavid van Moolenbroek 				/* Now we have an SOA.  Work with it. */
3247*00b67f09SDavid van Moolenbroek 				debug("got an SOA");
3248*00b67f09SDavid van Moolenbroek 				result = dns_rdata_tostruct(&rdata, &soa, NULL);
3249*00b67f09SDavid van Moolenbroek 				check_result(result, "dns_rdata_tostruct");
3250*00b67f09SDavid van Moolenbroek 				serial = soa.serial;
3251*00b67f09SDavid van Moolenbroek 				dns_rdata_freestruct(&soa);
3252*00b67f09SDavid van Moolenbroek 				if (!query->first_soa_rcvd) {
3253*00b67f09SDavid van Moolenbroek 					query->first_soa_rcvd = ISC_TRUE;
3254*00b67f09SDavid van Moolenbroek 					query->first_rr_serial = serial;
3255*00b67f09SDavid van Moolenbroek 					debug("this is the first serial %u",
3256*00b67f09SDavid van Moolenbroek 					      serial);
3257*00b67f09SDavid van Moolenbroek 					if (ixfr && isc_serial_ge(ixfr_serial,
3258*00b67f09SDavid van Moolenbroek 								  serial)) {
3259*00b67f09SDavid van Moolenbroek 						debug("got up to date "
3260*00b67f09SDavid van Moolenbroek 						      "response");
3261*00b67f09SDavid van Moolenbroek 						goto doexit;
3262*00b67f09SDavid van Moolenbroek 					}
3263*00b67f09SDavid van Moolenbroek 					goto next_rdata;
3264*00b67f09SDavid van Moolenbroek 				}
3265*00b67f09SDavid van Moolenbroek 				if (axfr) {
3266*00b67f09SDavid van Moolenbroek 					debug("doing axfr, got second SOA");
3267*00b67f09SDavid van Moolenbroek 					goto doexit;
3268*00b67f09SDavid van Moolenbroek 				}
3269*00b67f09SDavid van Moolenbroek 				if (!query->second_rr_rcvd) {
3270*00b67f09SDavid van Moolenbroek 					if (query->first_rr_serial == serial) {
3271*00b67f09SDavid van Moolenbroek 						debug("doing ixfr, got "
3272*00b67f09SDavid van Moolenbroek 						      "empty zone");
3273*00b67f09SDavid van Moolenbroek 						goto doexit;
3274*00b67f09SDavid van Moolenbroek 					}
3275*00b67f09SDavid van Moolenbroek 					debug("this is the second serial %u",
3276*00b67f09SDavid van Moolenbroek 					      serial);
3277*00b67f09SDavid van Moolenbroek 					query->second_rr_rcvd = ISC_TRUE;
3278*00b67f09SDavid van Moolenbroek 					query->second_rr_serial = serial;
3279*00b67f09SDavid van Moolenbroek 					goto next_rdata;
3280*00b67f09SDavid van Moolenbroek 				}
3281*00b67f09SDavid van Moolenbroek 				/*
3282*00b67f09SDavid van Moolenbroek 				 * If we get to this point, we're doing an
3283*00b67f09SDavid van Moolenbroek 				 * IXFR and have to start really looking
3284*00b67f09SDavid van Moolenbroek 				 * at serial numbers.
3285*00b67f09SDavid van Moolenbroek 				 */
3286*00b67f09SDavid van Moolenbroek 				if (query->first_rr_serial == serial) {
3287*00b67f09SDavid van Moolenbroek 					debug("got a match for ixfr");
3288*00b67f09SDavid van Moolenbroek 					if (!query->first_repeat_rcvd) {
3289*00b67f09SDavid van Moolenbroek 						query->first_repeat_rcvd =
3290*00b67f09SDavid van Moolenbroek 							ISC_TRUE;
3291*00b67f09SDavid van Moolenbroek 						goto next_rdata;
3292*00b67f09SDavid van Moolenbroek 					}
3293*00b67f09SDavid van Moolenbroek 					debug("done with ixfr");
3294*00b67f09SDavid van Moolenbroek 					goto doexit;
3295*00b67f09SDavid van Moolenbroek 				}
3296*00b67f09SDavid van Moolenbroek 				debug("meaningless soa %u", serial);
3297*00b67f09SDavid van Moolenbroek 			next_rdata:
3298*00b67f09SDavid van Moolenbroek 				result = dns_rdataset_next(rdataset);
3299*00b67f09SDavid van Moolenbroek 			} while (result == ISC_R_SUCCESS);
3300*00b67f09SDavid van Moolenbroek 		}
3301*00b67f09SDavid van Moolenbroek 		result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3302*00b67f09SDavid van Moolenbroek 	} while (result == ISC_R_SUCCESS);
3303*00b67f09SDavid van Moolenbroek 	launch_next_query(query, ISC_FALSE);
3304*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
3305*00b67f09SDavid van Moolenbroek  doexit:
3306*00b67f09SDavid van Moolenbroek 	received(sevent->n, &sevent->address, query);
3307*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
3308*00b67f09SDavid van Moolenbroek }
3309*00b67f09SDavid van Moolenbroek 
3310*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
3311*00b67f09SDavid van Moolenbroek static void
process_sit(dig_lookup_t * l,dns_message_t * msg,isc_buffer_t * optbuf,size_t optlen)3312*00b67f09SDavid van Moolenbroek process_sit(dig_lookup_t *l, dns_message_t *msg,
3313*00b67f09SDavid van Moolenbroek 	    isc_buffer_t *optbuf, size_t optlen)
3314*00b67f09SDavid van Moolenbroek {
3315*00b67f09SDavid van Moolenbroek 	char bb[256];
3316*00b67f09SDavid van Moolenbroek 	isc_buffer_t hexbuf;
3317*00b67f09SDavid van Moolenbroek 	size_t len;
3318*00b67f09SDavid van Moolenbroek 	const unsigned char *sit;
3319*00b67f09SDavid van Moolenbroek 	isc_result_t result;
3320*00b67f09SDavid van Moolenbroek 
3321*00b67f09SDavid van Moolenbroek 	if (l->sitvalue != NULL) {
3322*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&hexbuf, bb, sizeof(bb));
3323*00b67f09SDavid van Moolenbroek 		result = isc_hex_decodestring(l->sitvalue, &hexbuf);
3324*00b67f09SDavid van Moolenbroek 		check_result(result, "isc_hex_decodestring");
3325*00b67f09SDavid van Moolenbroek 		sit = isc_buffer_base(&hexbuf);
3326*00b67f09SDavid van Moolenbroek 		len = isc_buffer_usedlength(&hexbuf);
3327*00b67f09SDavid van Moolenbroek 	} else {
3328*00b67f09SDavid van Moolenbroek 		sit = cookie;
3329*00b67f09SDavid van Moolenbroek 		len = sizeof(cookie);
3330*00b67f09SDavid van Moolenbroek 	}
3331*00b67f09SDavid van Moolenbroek 
3332*00b67f09SDavid van Moolenbroek 	INSIST(msg->sitok == 0 && msg->sitbad == 0);
3333*00b67f09SDavid van Moolenbroek 	if (optlen >= len && optlen >= 8U) {
3334*00b67f09SDavid van Moolenbroek 		if (memcmp(isc_buffer_current(optbuf), sit, 8) == 0) {
3335*00b67f09SDavid van Moolenbroek 			msg->sitok = 1;
3336*00b67f09SDavid van Moolenbroek 		} else {
3337*00b67f09SDavid van Moolenbroek 			printf(";; Warning: SIT client cookie mismatch\n");
3338*00b67f09SDavid van Moolenbroek 			msg->sitbad = 1;
3339*00b67f09SDavid van Moolenbroek 		}
3340*00b67f09SDavid van Moolenbroek 	} else {
3341*00b67f09SDavid van Moolenbroek 		printf(";; Warning: SIT bad token (too short)\n");
3342*00b67f09SDavid van Moolenbroek 		msg->sitbad = 1;
3343*00b67f09SDavid van Moolenbroek 	}
3344*00b67f09SDavid van Moolenbroek 	isc_buffer_forward(optbuf, (unsigned int)optlen);
3345*00b67f09SDavid van Moolenbroek }
3346*00b67f09SDavid van Moolenbroek 
3347*00b67f09SDavid van Moolenbroek static void
process_opt(dig_lookup_t * l,dns_message_t * msg)3348*00b67f09SDavid van Moolenbroek process_opt(dig_lookup_t *l, dns_message_t *msg) {
3349*00b67f09SDavid van Moolenbroek 	dns_rdata_t rdata;
3350*00b67f09SDavid van Moolenbroek 	isc_result_t result;
3351*00b67f09SDavid van Moolenbroek 	isc_buffer_t optbuf;
3352*00b67f09SDavid van Moolenbroek 	isc_uint16_t optcode, optlen;
3353*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *opt = msg->opt;
3354*00b67f09SDavid van Moolenbroek 
3355*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(opt);
3356*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
3357*00b67f09SDavid van Moolenbroek 		dns_rdata_init(&rdata);
3358*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(opt, &rdata);
3359*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
3360*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&optbuf, rdata.length);
3361*00b67f09SDavid van Moolenbroek 		while (isc_buffer_remaininglength(&optbuf) >= 4) {
3362*00b67f09SDavid van Moolenbroek 			optcode = isc_buffer_getuint16(&optbuf);
3363*00b67f09SDavid van Moolenbroek 			optlen = isc_buffer_getuint16(&optbuf);
3364*00b67f09SDavid van Moolenbroek 			switch (optcode) {
3365*00b67f09SDavid van Moolenbroek 			case DNS_OPT_SIT:
3366*00b67f09SDavid van Moolenbroek 				process_sit(l, msg, &optbuf, optlen);
3367*00b67f09SDavid van Moolenbroek 				break;
3368*00b67f09SDavid van Moolenbroek 			default:
3369*00b67f09SDavid van Moolenbroek 				isc_buffer_forward(&optbuf, optlen);
3370*00b67f09SDavid van Moolenbroek 				break;
3371*00b67f09SDavid van Moolenbroek 			}
3372*00b67f09SDavid van Moolenbroek 		}
3373*00b67f09SDavid van Moolenbroek 	}
3374*00b67f09SDavid van Moolenbroek }
3375*00b67f09SDavid van Moolenbroek #endif
3376*00b67f09SDavid van Moolenbroek 
3377*00b67f09SDavid van Moolenbroek 
3378*00b67f09SDavid van Moolenbroek /*%
3379*00b67f09SDavid van Moolenbroek  * Event handler for recv complete.  Perform whatever actions are necessary,
3380*00b67f09SDavid van Moolenbroek  * based on the specifics of the user's request.
3381*00b67f09SDavid van Moolenbroek  */
3382*00b67f09SDavid van Moolenbroek static void
recv_done(isc_task_t * task,isc_event_t * event)3383*00b67f09SDavid van Moolenbroek recv_done(isc_task_t *task, isc_event_t *event) {
3384*00b67f09SDavid van Moolenbroek 	isc_socketevent_t *sevent = NULL;
3385*00b67f09SDavid van Moolenbroek 	dig_query_t *query = NULL;
3386*00b67f09SDavid van Moolenbroek 	isc_buffer_t *b = NULL;
3387*00b67f09SDavid van Moolenbroek 	dns_message_t *msg = NULL;
3388*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3389*00b67f09SDavid van Moolenbroek 	dig_message_t *chase_msg = NULL;
3390*00b67f09SDavid van Moolenbroek 	dig_message_t *chase_msg2 = NULL;
3391*00b67f09SDavid van Moolenbroek #endif
3392*00b67f09SDavid van Moolenbroek 	isc_result_t result;
3393*00b67f09SDavid van Moolenbroek 	dig_lookup_t *n, *l;
3394*00b67f09SDavid van Moolenbroek 	isc_boolean_t docancel = ISC_FALSE;
3395*00b67f09SDavid van Moolenbroek 	isc_boolean_t match = ISC_TRUE;
3396*00b67f09SDavid van Moolenbroek 	unsigned int parseflags;
3397*00b67f09SDavid van Moolenbroek 	dns_messageid_t id;
3398*00b67f09SDavid van Moolenbroek 	unsigned int msgflags;
3399*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3400*00b67f09SDavid van Moolenbroek 	isc_result_t do_sigchase = ISC_FALSE;
3401*00b67f09SDavid van Moolenbroek 
3402*00b67f09SDavid van Moolenbroek 	dns_message_t *msg_temp = NULL;
3403*00b67f09SDavid van Moolenbroek 	isc_region_t r;
3404*00b67f09SDavid van Moolenbroek 	isc_buffer_t *buf = NULL;
3405*00b67f09SDavid van Moolenbroek #endif
3406*00b67f09SDavid van Moolenbroek 
3407*00b67f09SDavid van Moolenbroek 	UNUSED(task);
3408*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
3409*00b67f09SDavid van Moolenbroek 
3410*00b67f09SDavid van Moolenbroek 	debug("recv_done()");
3411*00b67f09SDavid van Moolenbroek 
3412*00b67f09SDavid van Moolenbroek 	LOCK_LOOKUP;
3413*00b67f09SDavid van Moolenbroek 	recvcount--;
3414*00b67f09SDavid van Moolenbroek 	debug("recvcount=%d", recvcount);
3415*00b67f09SDavid van Moolenbroek 	INSIST(recvcount >= 0);
3416*00b67f09SDavid van Moolenbroek 
3417*00b67f09SDavid van Moolenbroek 	query = event->ev_arg;
3418*00b67f09SDavid van Moolenbroek 	TIME_NOW(&query->time_recv);
3419*00b67f09SDavid van Moolenbroek 	debug("lookup=%p, query=%p", query->lookup, query);
3420*00b67f09SDavid van Moolenbroek 
3421*00b67f09SDavid van Moolenbroek 	l = query->lookup;
3422*00b67f09SDavid van Moolenbroek 
3423*00b67f09SDavid van Moolenbroek 	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3424*00b67f09SDavid van Moolenbroek 	sevent = (isc_socketevent_t *)event;
3425*00b67f09SDavid van Moolenbroek 
3426*00b67f09SDavid van Moolenbroek 	b = ISC_LIST_HEAD(sevent->bufferlist);
3427*00b67f09SDavid van Moolenbroek 	INSIST(b == &query->recvbuf);
3428*00b67f09SDavid van Moolenbroek 	ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3429*00b67f09SDavid van Moolenbroek 
3430*00b67f09SDavid van Moolenbroek 	if ((l->tcp_mode) && (l->timer != NULL))
3431*00b67f09SDavid van Moolenbroek 		isc_timer_touch(l->timer);
3432*00b67f09SDavid van Moolenbroek 	if ((!l->pending && !l->ns_search_only) || cancel_now) {
3433*00b67f09SDavid van Moolenbroek 		debug("no longer pending.  Got %s",
3434*00b67f09SDavid van Moolenbroek 			isc_result_totext(sevent->result));
3435*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
3436*00b67f09SDavid van Moolenbroek 
3437*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
3438*00b67f09SDavid van Moolenbroek 		clear_query(query);
3439*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
3440*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
3441*00b67f09SDavid van Moolenbroek 		return;
3442*00b67f09SDavid van Moolenbroek 	}
3443*00b67f09SDavid van Moolenbroek 
3444*00b67f09SDavid van Moolenbroek 	if (sevent->result != ISC_R_SUCCESS) {
3445*00b67f09SDavid van Moolenbroek 		if (sevent->result == ISC_R_CANCELED) {
3446*00b67f09SDavid van Moolenbroek 			debug("in recv cancel handler");
3447*00b67f09SDavid van Moolenbroek 			query->waiting_connect = ISC_FALSE;
3448*00b67f09SDavid van Moolenbroek 		} else {
3449*00b67f09SDavid van Moolenbroek 			printf(";; communications error: %s\n",
3450*00b67f09SDavid van Moolenbroek 			       isc_result_totext(sevent->result));
3451*00b67f09SDavid van Moolenbroek 			isc_socket_detach(&query->sock);
3452*00b67f09SDavid van Moolenbroek 			sockcount--;
3453*00b67f09SDavid van Moolenbroek 			debug("sockcount=%d", sockcount);
3454*00b67f09SDavid van Moolenbroek 			INSIST(sockcount >= 0);
3455*00b67f09SDavid van Moolenbroek 		}
3456*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
3457*00b67f09SDavid van Moolenbroek 		clear_query(query);
3458*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
3459*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
3460*00b67f09SDavid van Moolenbroek 		return;
3461*00b67f09SDavid van Moolenbroek 	}
3462*00b67f09SDavid van Moolenbroek 
3463*00b67f09SDavid van Moolenbroek 	if (!l->tcp_mode &&
3464*00b67f09SDavid van Moolenbroek 	    !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3465*00b67f09SDavid van Moolenbroek 				  ISC_SOCKADDR_CMPADDR|
3466*00b67f09SDavid van Moolenbroek 				  ISC_SOCKADDR_CMPPORT|
3467*00b67f09SDavid van Moolenbroek 				  ISC_SOCKADDR_CMPSCOPE|
3468*00b67f09SDavid van Moolenbroek 				  ISC_SOCKADDR_CMPSCOPEZERO)) {
3469*00b67f09SDavid van Moolenbroek 		char buf1[ISC_SOCKADDR_FORMATSIZE];
3470*00b67f09SDavid van Moolenbroek 		char buf2[ISC_SOCKADDR_FORMATSIZE];
3471*00b67f09SDavid van Moolenbroek 		isc_sockaddr_t any;
3472*00b67f09SDavid van Moolenbroek 
3473*00b67f09SDavid van Moolenbroek 		if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3474*00b67f09SDavid van Moolenbroek 			isc_sockaddr_any(&any);
3475*00b67f09SDavid van Moolenbroek 		else
3476*00b67f09SDavid van Moolenbroek 			isc_sockaddr_any6(&any);
3477*00b67f09SDavid van Moolenbroek 
3478*00b67f09SDavid van Moolenbroek 		/*
3479*00b67f09SDavid van Moolenbroek 		* We don't expect a match when the packet is
3480*00b67f09SDavid van Moolenbroek 		* sent to 0.0.0.0, :: or to a multicast addresses.
3481*00b67f09SDavid van Moolenbroek 		* XXXMPA broadcast needs to be handled here as well.
3482*00b67f09SDavid van Moolenbroek 		*/
3483*00b67f09SDavid van Moolenbroek 		if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3484*00b67f09SDavid van Moolenbroek 		     !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3485*00b67f09SDavid van Moolenbroek 		    isc_sockaddr_getport(&query->sockaddr) !=
3486*00b67f09SDavid van Moolenbroek 		    isc_sockaddr_getport(&sevent->address)) {
3487*00b67f09SDavid van Moolenbroek 			isc_sockaddr_format(&sevent->address, buf1,
3488*00b67f09SDavid van Moolenbroek 			sizeof(buf1));
3489*00b67f09SDavid van Moolenbroek 			isc_sockaddr_format(&query->sockaddr, buf2,
3490*00b67f09SDavid van Moolenbroek 			sizeof(buf2));
3491*00b67f09SDavid van Moolenbroek 			printf(";; reply from unexpected source: %s,"
3492*00b67f09SDavid van Moolenbroek 			" expected %s\n", buf1, buf2);
3493*00b67f09SDavid van Moolenbroek 			match = ISC_FALSE;
3494*00b67f09SDavid van Moolenbroek 		}
3495*00b67f09SDavid van Moolenbroek 	}
3496*00b67f09SDavid van Moolenbroek 
3497*00b67f09SDavid van Moolenbroek 	result = dns_message_peekheader(b, &id, &msgflags);
3498*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3499*00b67f09SDavid van Moolenbroek 		match = ISC_FALSE;
3500*00b67f09SDavid van Moolenbroek 		if (l->tcp_mode) {
3501*00b67f09SDavid van Moolenbroek 			isc_boolean_t fail = ISC_TRUE;
3502*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS) {
3503*00b67f09SDavid van Moolenbroek 				if (!query->first_soa_rcvd ||
3504*00b67f09SDavid van Moolenbroek 				     query->warn_id)
3505*00b67f09SDavid van Moolenbroek 					printf(";; %s: ID mismatch: "
3506*00b67f09SDavid van Moolenbroek 					       "expected ID %u, got %u\n",
3507*00b67f09SDavid van Moolenbroek 					       query->first_soa_rcvd ?
3508*00b67f09SDavid van Moolenbroek 					       "WARNING" : "ERROR",
3509*00b67f09SDavid van Moolenbroek 					       l->sendmsg->id, id);
3510*00b67f09SDavid van Moolenbroek 				if (query->first_soa_rcvd)
3511*00b67f09SDavid van Moolenbroek 					fail = ISC_FALSE;
3512*00b67f09SDavid van Moolenbroek 				query->warn_id = ISC_FALSE;
3513*00b67f09SDavid van Moolenbroek 			} else
3514*00b67f09SDavid van Moolenbroek 				printf(";; ERROR: short "
3515*00b67f09SDavid van Moolenbroek 				       "(< header size) message\n");
3516*00b67f09SDavid van Moolenbroek 			if (fail) {
3517*00b67f09SDavid van Moolenbroek 				isc_event_free(&event);
3518*00b67f09SDavid van Moolenbroek 				clear_query(query);
3519*00b67f09SDavid van Moolenbroek 				check_next_lookup(l);
3520*00b67f09SDavid van Moolenbroek 				UNLOCK_LOOKUP;
3521*00b67f09SDavid van Moolenbroek 				return;
3522*00b67f09SDavid van Moolenbroek 			}
3523*00b67f09SDavid van Moolenbroek 			match = ISC_TRUE;
3524*00b67f09SDavid van Moolenbroek 		} else if (result == ISC_R_SUCCESS)
3525*00b67f09SDavid van Moolenbroek 			printf(";; Warning: ID mismatch: "
3526*00b67f09SDavid van Moolenbroek 			       "expected ID %u, got %u\n", l->sendmsg->id, id);
3527*00b67f09SDavid van Moolenbroek 		else
3528*00b67f09SDavid van Moolenbroek 			printf(";; Warning: short "
3529*00b67f09SDavid van Moolenbroek 			       "(< header size) message received\n");
3530*00b67f09SDavid van Moolenbroek 	}
3531*00b67f09SDavid van Moolenbroek 
3532*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3533*00b67f09SDavid van Moolenbroek 		printf(";; Warning: query response not set\n");
3534*00b67f09SDavid van Moolenbroek 
3535*00b67f09SDavid van Moolenbroek 	if (!match)
3536*00b67f09SDavid van Moolenbroek 		goto udp_mismatch;
3537*00b67f09SDavid van Moolenbroek 
3538*00b67f09SDavid van Moolenbroek 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3539*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_message_create");
3540*00b67f09SDavid van Moolenbroek 
3541*00b67f09SDavid van Moolenbroek 	if (key != NULL) {
3542*00b67f09SDavid van Moolenbroek 		if (l->querysig == NULL) {
3543*00b67f09SDavid van Moolenbroek 			debug("getting initial querysig");
3544*00b67f09SDavid van Moolenbroek 			result = dns_message_getquerytsig(l->sendmsg, mctx,
3545*00b67f09SDavid van Moolenbroek 							  &l->querysig);
3546*00b67f09SDavid van Moolenbroek 			check_result(result, "dns_message_getquerytsig");
3547*00b67f09SDavid van Moolenbroek 		}
3548*00b67f09SDavid van Moolenbroek 		result = dns_message_setquerytsig(msg, l->querysig);
3549*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_message_setquerytsig");
3550*00b67f09SDavid van Moolenbroek 		result = dns_message_settsigkey(msg, key);
3551*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_message_settsigkey");
3552*00b67f09SDavid van Moolenbroek 		msg->tsigctx = l->tsigctx;
3553*00b67f09SDavid van Moolenbroek 		l->tsigctx = NULL;
3554*00b67f09SDavid van Moolenbroek 		if (l->msgcounter != 0)
3555*00b67f09SDavid van Moolenbroek 			msg->tcp_continuation = 1;
3556*00b67f09SDavid van Moolenbroek 		l->msgcounter++;
3557*00b67f09SDavid van Moolenbroek 	}
3558*00b67f09SDavid van Moolenbroek 
3559*00b67f09SDavid van Moolenbroek 	debug("before parse starts");
3560*00b67f09SDavid van Moolenbroek 	parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
3561*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3562*00b67f09SDavid van Moolenbroek 	if (!l->sigchase) {
3563*00b67f09SDavid van Moolenbroek 		do_sigchase = ISC_FALSE;
3564*00b67f09SDavid van Moolenbroek 	} else {
3565*00b67f09SDavid van Moolenbroek 		parseflags = 0;
3566*00b67f09SDavid van Moolenbroek 		do_sigchase = ISC_TRUE;
3567*00b67f09SDavid van Moolenbroek 	}
3568*00b67f09SDavid van Moolenbroek #endif
3569*00b67f09SDavid van Moolenbroek 	if (l->besteffort) {
3570*00b67f09SDavid van Moolenbroek 		parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3571*00b67f09SDavid van Moolenbroek 		parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3572*00b67f09SDavid van Moolenbroek 	}
3573*00b67f09SDavid van Moolenbroek 	result = dns_message_parse(msg, b, parseflags);
3574*00b67f09SDavid van Moolenbroek 	if (result == DNS_R_RECOVERABLE) {
3575*00b67f09SDavid van Moolenbroek 		printf(";; Warning: Message parser reports malformed "
3576*00b67f09SDavid van Moolenbroek 		       "message packet.\n");
3577*00b67f09SDavid van Moolenbroek 		result = ISC_R_SUCCESS;
3578*00b67f09SDavid van Moolenbroek 	}
3579*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
3580*00b67f09SDavid van Moolenbroek 		printf(";; Got bad packet: %s\n", isc_result_totext(result));
3581*00b67f09SDavid van Moolenbroek 		hex_dump(b);
3582*00b67f09SDavid van Moolenbroek 		query->waiting_connect = ISC_FALSE;
3583*00b67f09SDavid van Moolenbroek 		dns_message_destroy(&msg);
3584*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
3585*00b67f09SDavid van Moolenbroek 		clear_query(query);
3586*00b67f09SDavid van Moolenbroek 		cancel_lookup(l);
3587*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
3588*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
3589*00b67f09SDavid van Moolenbroek 		return;
3590*00b67f09SDavid van Moolenbroek 	}
3591*00b67f09SDavid van Moolenbroek 	if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3592*00b67f09SDavid van Moolenbroek 		match = ISC_TRUE;
3593*00b67f09SDavid van Moolenbroek 		for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3594*00b67f09SDavid van Moolenbroek 		     result == ISC_R_SUCCESS && match;
3595*00b67f09SDavid van Moolenbroek 		     result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3596*00b67f09SDavid van Moolenbroek 			dns_name_t *name = NULL;
3597*00b67f09SDavid van Moolenbroek 			dns_rdataset_t *rdataset;
3598*00b67f09SDavid van Moolenbroek 
3599*00b67f09SDavid van Moolenbroek 			dns_message_currentname(msg, DNS_SECTION_QUESTION,
3600*00b67f09SDavid van Moolenbroek 						&name);
3601*00b67f09SDavid van Moolenbroek 			for (rdataset = ISC_LIST_HEAD(name->list);
3602*00b67f09SDavid van Moolenbroek 			     rdataset != NULL;
3603*00b67f09SDavid van Moolenbroek 			     rdataset = ISC_LIST_NEXT(rdataset, link)) {
3604*00b67f09SDavid van Moolenbroek 				if (l->rdtype != rdataset->type ||
3605*00b67f09SDavid van Moolenbroek 				    l->rdclass != rdataset->rdclass ||
3606*00b67f09SDavid van Moolenbroek 				    !dns_name_equal(l->name, name)) {
3607*00b67f09SDavid van Moolenbroek 					char namestr[DNS_NAME_FORMATSIZE];
3608*00b67f09SDavid van Moolenbroek 					char typebuf[DNS_RDATATYPE_FORMATSIZE];
3609*00b67f09SDavid van Moolenbroek 					char classbuf[DNS_RDATACLASS_FORMATSIZE];
3610*00b67f09SDavid van Moolenbroek 					dns_name_format(name, namestr,
3611*00b67f09SDavid van Moolenbroek 							sizeof(namestr));
3612*00b67f09SDavid van Moolenbroek 					dns_rdatatype_format(rdataset->type,
3613*00b67f09SDavid van Moolenbroek 							     typebuf,
3614*00b67f09SDavid van Moolenbroek 							     sizeof(typebuf));
3615*00b67f09SDavid van Moolenbroek 					dns_rdataclass_format(rdataset->rdclass,
3616*00b67f09SDavid van Moolenbroek 							      classbuf,
3617*00b67f09SDavid van Moolenbroek 							      sizeof(classbuf));
3618*00b67f09SDavid van Moolenbroek 					printf(";; Question section mismatch: "
3619*00b67f09SDavid van Moolenbroek 					       "got %s/%s/%s\n",
3620*00b67f09SDavid van Moolenbroek 					       namestr, typebuf, classbuf);
3621*00b67f09SDavid van Moolenbroek 					match = ISC_FALSE;
3622*00b67f09SDavid van Moolenbroek 				}
3623*00b67f09SDavid van Moolenbroek 			}
3624*00b67f09SDavid van Moolenbroek 		}
3625*00b67f09SDavid van Moolenbroek 		if (!match) {
3626*00b67f09SDavid van Moolenbroek 			dns_message_destroy(&msg);
3627*00b67f09SDavid van Moolenbroek 			if (l->tcp_mode) {
3628*00b67f09SDavid van Moolenbroek 				isc_event_free(&event);
3629*00b67f09SDavid van Moolenbroek 				clear_query(query);
3630*00b67f09SDavid van Moolenbroek 				check_next_lookup(l);
3631*00b67f09SDavid van Moolenbroek 				UNLOCK_LOOKUP;
3632*00b67f09SDavid van Moolenbroek 				return;
3633*00b67f09SDavid van Moolenbroek 			} else
3634*00b67f09SDavid van Moolenbroek 				goto udp_mismatch;
3635*00b67f09SDavid van Moolenbroek 		}
3636*00b67f09SDavid van Moolenbroek 	}
3637*00b67f09SDavid van Moolenbroek 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3638*00b67f09SDavid van Moolenbroek 	    !l->ignore && !l->tcp_mode) {
3639*00b67f09SDavid van Moolenbroek 		if (l->comments)
3640*00b67f09SDavid van Moolenbroek 			printf(";; Truncated, retrying in TCP mode.\n");
3641*00b67f09SDavid van Moolenbroek 		n = requeue_lookup(l, ISC_TRUE);
3642*00b67f09SDavid van Moolenbroek 		n->tcp_mode = ISC_TRUE;
3643*00b67f09SDavid van Moolenbroek 		n->origin = query->lookup->origin;
3644*00b67f09SDavid van Moolenbroek 		dns_message_destroy(&msg);
3645*00b67f09SDavid van Moolenbroek 		isc_event_free(&event);
3646*00b67f09SDavid van Moolenbroek 		clear_query(query);
3647*00b67f09SDavid van Moolenbroek 		cancel_lookup(l);
3648*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
3649*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
3650*00b67f09SDavid van Moolenbroek 		return;
3651*00b67f09SDavid van Moolenbroek 	}
3652*00b67f09SDavid van Moolenbroek 	if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3653*00b67f09SDavid van Moolenbroek 	    (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3654*00b67f09SDavid van Moolenbroek 	{
3655*00b67f09SDavid van Moolenbroek 		dig_query_t *next = ISC_LIST_NEXT(query, link);
3656*00b67f09SDavid van Moolenbroek 		if (l->current_query == query)
3657*00b67f09SDavid van Moolenbroek 			l->current_query = NULL;
3658*00b67f09SDavid van Moolenbroek 		if (next != NULL) {
3659*00b67f09SDavid van Moolenbroek 			debug("sending query %p\n", next);
3660*00b67f09SDavid van Moolenbroek 			if (l->tcp_mode)
3661*00b67f09SDavid van Moolenbroek 				send_tcp_connect(next);
3662*00b67f09SDavid van Moolenbroek 			else
3663*00b67f09SDavid van Moolenbroek 				send_udp(next);
3664*00b67f09SDavid van Moolenbroek 		}
3665*00b67f09SDavid van Moolenbroek 		/*
3666*00b67f09SDavid van Moolenbroek 		 * If our query is at the head of the list and there
3667*00b67f09SDavid van Moolenbroek 		 * is no next, we're the only one left, so fall
3668*00b67f09SDavid van Moolenbroek 		 * through to print the message.
3669*00b67f09SDavid van Moolenbroek 		 */
3670*00b67f09SDavid van Moolenbroek 		if ((ISC_LIST_HEAD(l->q) != query) ||
3671*00b67f09SDavid van Moolenbroek 		    (ISC_LIST_NEXT(query, link) != NULL)) {
3672*00b67f09SDavid van Moolenbroek 			if (l->comments)
3673*00b67f09SDavid van Moolenbroek 				printf(";; Got %s from %s, "
3674*00b67f09SDavid van Moolenbroek 				       "trying next server\n",
3675*00b67f09SDavid van Moolenbroek 				       msg->rcode == dns_rcode_servfail ?
3676*00b67f09SDavid van Moolenbroek 				       "SERVFAIL reply" :
3677*00b67f09SDavid van Moolenbroek 				       "recursion not available",
3678*00b67f09SDavid van Moolenbroek 				       query->servname);
3679*00b67f09SDavid van Moolenbroek 			clear_query(query);
3680*00b67f09SDavid van Moolenbroek 			check_next_lookup(l);
3681*00b67f09SDavid van Moolenbroek 			dns_message_destroy(&msg);
3682*00b67f09SDavid van Moolenbroek 			isc_event_free(&event);
3683*00b67f09SDavid van Moolenbroek 			UNLOCK_LOOKUP;
3684*00b67f09SDavid van Moolenbroek 			return;
3685*00b67f09SDavid van Moolenbroek 		}
3686*00b67f09SDavid van Moolenbroek 	}
3687*00b67f09SDavid van Moolenbroek 
3688*00b67f09SDavid van Moolenbroek 	if (key != NULL) {
3689*00b67f09SDavid van Moolenbroek 		result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
3690*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
3691*00b67f09SDavid van Moolenbroek 			printf(";; Couldn't verify signature: %s\n",
3692*00b67f09SDavid van Moolenbroek 			       isc_result_totext(result));
3693*00b67f09SDavid van Moolenbroek 			validated = ISC_FALSE;
3694*00b67f09SDavid van Moolenbroek 		}
3695*00b67f09SDavid van Moolenbroek 		l->tsigctx = msg->tsigctx;
3696*00b67f09SDavid van Moolenbroek 		msg->tsigctx = NULL;
3697*00b67f09SDavid van Moolenbroek 		if (l->querysig != NULL) {
3698*00b67f09SDavid van Moolenbroek 			debug("freeing querysig buffer %p", l->querysig);
3699*00b67f09SDavid van Moolenbroek 			isc_buffer_free(&l->querysig);
3700*00b67f09SDavid van Moolenbroek 		}
3701*00b67f09SDavid van Moolenbroek 		result = dns_message_getquerytsig(msg, mctx, &l->querysig);
3702*00b67f09SDavid van Moolenbroek 		check_result(result,"dns_message_getquerytsig");
3703*00b67f09SDavid van Moolenbroek 	}
3704*00b67f09SDavid van Moolenbroek 
3705*00b67f09SDavid van Moolenbroek 	extrabytes = isc_buffer_remaininglength(b);
3706*00b67f09SDavid van Moolenbroek 
3707*00b67f09SDavid van Moolenbroek 	debug("after parse");
3708*00b67f09SDavid van Moolenbroek 	if (l->doing_xfr && l->xfr_q == NULL) {
3709*00b67f09SDavid van Moolenbroek 		l->xfr_q = query;
3710*00b67f09SDavid van Moolenbroek 		/*
3711*00b67f09SDavid van Moolenbroek 		 * Once we are in the XFR message, increase
3712*00b67f09SDavid van Moolenbroek 		 * the timeout to much longer, so brief network
3713*00b67f09SDavid van Moolenbroek 		 * outages won't cause the XFR to abort
3714*00b67f09SDavid van Moolenbroek 		 */
3715*00b67f09SDavid van Moolenbroek 		if (timeout != INT_MAX && l->timer != NULL) {
3716*00b67f09SDavid van Moolenbroek 			unsigned int local_timeout;
3717*00b67f09SDavid van Moolenbroek 
3718*00b67f09SDavid van Moolenbroek 			if (timeout == 0) {
3719*00b67f09SDavid van Moolenbroek 				if (l->tcp_mode)
3720*00b67f09SDavid van Moolenbroek 					local_timeout = TCP_TIMEOUT * 4;
3721*00b67f09SDavid van Moolenbroek 				else
3722*00b67f09SDavid van Moolenbroek 					local_timeout = UDP_TIMEOUT * 4;
3723*00b67f09SDavid van Moolenbroek 			} else {
3724*00b67f09SDavid van Moolenbroek 				if (timeout < (INT_MAX / 4))
3725*00b67f09SDavid van Moolenbroek 					local_timeout = timeout * 4;
3726*00b67f09SDavid van Moolenbroek 				else
3727*00b67f09SDavid van Moolenbroek 					local_timeout = INT_MAX;
3728*00b67f09SDavid van Moolenbroek 			}
3729*00b67f09SDavid van Moolenbroek 			debug("have local timeout of %d", local_timeout);
3730*00b67f09SDavid van Moolenbroek 			isc_interval_set(&l->interval, local_timeout, 0);
3731*00b67f09SDavid van Moolenbroek 			result = isc_timer_reset(l->timer,
3732*00b67f09SDavid van Moolenbroek 						 isc_timertype_once,
3733*00b67f09SDavid van Moolenbroek 						 NULL,
3734*00b67f09SDavid van Moolenbroek 						 &l->interval,
3735*00b67f09SDavid van Moolenbroek 						 ISC_FALSE);
3736*00b67f09SDavid van Moolenbroek 			check_result(result, "isc_timer_reset");
3737*00b67f09SDavid van Moolenbroek 		}
3738*00b67f09SDavid van Moolenbroek 	}
3739*00b67f09SDavid van Moolenbroek 
3740*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USESIT
3741*00b67f09SDavid van Moolenbroek 	if (l->sitvalue != NULL) {
3742*00b67f09SDavid van Moolenbroek 		if (msg->opt == NULL)
3743*00b67f09SDavid van Moolenbroek 			printf(";; expected opt record in response\n");
3744*00b67f09SDavid van Moolenbroek 		else
3745*00b67f09SDavid van Moolenbroek 			process_opt(l, msg);
3746*00b67f09SDavid van Moolenbroek 	} else if (l->sit && msg->opt != NULL)
3747*00b67f09SDavid van Moolenbroek 		process_opt(l, msg);
3748*00b67f09SDavid van Moolenbroek #endif
3749*00b67f09SDavid van Moolenbroek 
3750*00b67f09SDavid van Moolenbroek 	if (!l->doing_xfr || l->xfr_q == query) {
3751*00b67f09SDavid van Moolenbroek 		if (msg->rcode == dns_rcode_nxdomain &&
3752*00b67f09SDavid van Moolenbroek 		    (l->origin != NULL || l->need_search)) {
3753*00b67f09SDavid van Moolenbroek 			if (!next_origin(query->lookup) || showsearch) {
3754*00b67f09SDavid van Moolenbroek 				printmessage(query, msg, ISC_TRUE);
3755*00b67f09SDavid van Moolenbroek 				received(b->used, &sevent->address, query);
3756*00b67f09SDavid van Moolenbroek 			}
3757*00b67f09SDavid van Moolenbroek 		} else if (!l->trace && !l->ns_search_only) {
3758*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3759*00b67f09SDavid van Moolenbroek 			if (!do_sigchase)
3760*00b67f09SDavid van Moolenbroek #endif
3761*00b67f09SDavid van Moolenbroek 				printmessage(query, msg, ISC_TRUE);
3762*00b67f09SDavid van Moolenbroek 		} else if (l->trace) {
3763*00b67f09SDavid van Moolenbroek 			int nl = 0;
3764*00b67f09SDavid van Moolenbroek 			int count = msg->counts[DNS_SECTION_ANSWER];
3765*00b67f09SDavid van Moolenbroek 
3766*00b67f09SDavid van Moolenbroek 			debug("in TRACE code");
3767*00b67f09SDavid van Moolenbroek 			if (!l->ns_search_only)
3768*00b67f09SDavid van Moolenbroek 				printmessage(query, msg, ISC_TRUE);
3769*00b67f09SDavid van Moolenbroek 
3770*00b67f09SDavid van Moolenbroek 			l->rdtype = l->qrdtype;
3771*00b67f09SDavid van Moolenbroek 			if (l->trace_root || (l->ns_search_only && count > 0)) {
3772*00b67f09SDavid van Moolenbroek 				if (!l->trace_root)
3773*00b67f09SDavid van Moolenbroek 					l->rdtype = dns_rdatatype_soa;
3774*00b67f09SDavid van Moolenbroek 				nl = followup_lookup(msg, query,
3775*00b67f09SDavid van Moolenbroek 						     DNS_SECTION_ANSWER);
3776*00b67f09SDavid van Moolenbroek 				l->trace_root = ISC_FALSE;
3777*00b67f09SDavid van Moolenbroek 			} else if (count == 0)
3778*00b67f09SDavid van Moolenbroek 				nl = followup_lookup(msg, query,
3779*00b67f09SDavid van Moolenbroek 						     DNS_SECTION_AUTHORITY);
3780*00b67f09SDavid van Moolenbroek 			if (nl == 0)
3781*00b67f09SDavid van Moolenbroek 				docancel = ISC_TRUE;
3782*00b67f09SDavid van Moolenbroek 		} else {
3783*00b67f09SDavid van Moolenbroek 			debug("in NSSEARCH code");
3784*00b67f09SDavid van Moolenbroek 
3785*00b67f09SDavid van Moolenbroek 			if (l->trace_root) {
3786*00b67f09SDavid van Moolenbroek 				/*
3787*00b67f09SDavid van Moolenbroek 				 * This is the initial NS query.
3788*00b67f09SDavid van Moolenbroek 				 */
3789*00b67f09SDavid van Moolenbroek 				int nl;
3790*00b67f09SDavid van Moolenbroek 
3791*00b67f09SDavid van Moolenbroek 				l->rdtype = dns_rdatatype_soa;
3792*00b67f09SDavid van Moolenbroek 				nl = followup_lookup(msg, query,
3793*00b67f09SDavid van Moolenbroek 						     DNS_SECTION_ANSWER);
3794*00b67f09SDavid van Moolenbroek 				if (nl == 0)
3795*00b67f09SDavid van Moolenbroek 					docancel = ISC_TRUE;
3796*00b67f09SDavid van Moolenbroek 				l->trace_root = ISC_FALSE;
3797*00b67f09SDavid van Moolenbroek 				usesearch = ISC_FALSE;
3798*00b67f09SDavid van Moolenbroek 			} else
3799*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3800*00b67f09SDavid van Moolenbroek 				if (!do_sigchase)
3801*00b67f09SDavid van Moolenbroek #endif
3802*00b67f09SDavid van Moolenbroek 				printmessage(query, msg, ISC_TRUE);
3803*00b67f09SDavid van Moolenbroek 		}
3804*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3805*00b67f09SDavid van Moolenbroek 		if (do_sigchase) {
3806*00b67f09SDavid van Moolenbroek 			chase_msg = isc_mem_allocate(mctx,
3807*00b67f09SDavid van Moolenbroek 						     sizeof(dig_message_t));
3808*00b67f09SDavid van Moolenbroek 			if (chase_msg == NULL) {
3809*00b67f09SDavid van Moolenbroek 				fatal("Memory allocation failure in %s:%d",
3810*00b67f09SDavid van Moolenbroek 				      __FILE__, __LINE__);
3811*00b67f09SDavid van Moolenbroek 			}
3812*00b67f09SDavid van Moolenbroek 			ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
3813*00b67f09SDavid van Moolenbroek 					       link);
3814*00b67f09SDavid van Moolenbroek 			if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3815*00b67f09SDavid van Moolenbroek 					       &msg_temp) != ISC_R_SUCCESS) {
3816*00b67f09SDavid van Moolenbroek 				fatal("dns_message_create in %s:%d",
3817*00b67f09SDavid van Moolenbroek 				      __FILE__, __LINE__);
3818*00b67f09SDavid van Moolenbroek 			}
3819*00b67f09SDavid van Moolenbroek 
3820*00b67f09SDavid van Moolenbroek 			isc_buffer_usedregion(b, &r);
3821*00b67f09SDavid van Moolenbroek 			result = isc_buffer_allocate(mctx, &buf, r.length);
3822*00b67f09SDavid van Moolenbroek 
3823*00b67f09SDavid van Moolenbroek 			check_result(result, "isc_buffer_allocate");
3824*00b67f09SDavid van Moolenbroek 			result =  isc_buffer_copyregion(buf, &r);
3825*00b67f09SDavid van Moolenbroek 			check_result(result, "isc_buffer_copyregion");
3826*00b67f09SDavid van Moolenbroek 
3827*00b67f09SDavid van Moolenbroek 			result =  dns_message_parse(msg_temp, buf, 0);
3828*00b67f09SDavid van Moolenbroek 
3829*00b67f09SDavid van Moolenbroek 			isc_buffer_free(&buf);
3830*00b67f09SDavid van Moolenbroek 			chase_msg->msg = msg_temp;
3831*00b67f09SDavid van Moolenbroek 
3832*00b67f09SDavid van Moolenbroek 			chase_msg2 = isc_mem_allocate(mctx,
3833*00b67f09SDavid van Moolenbroek 						      sizeof(dig_message_t));
3834*00b67f09SDavid van Moolenbroek 			if (chase_msg2 == NULL) {
3835*00b67f09SDavid van Moolenbroek 				fatal("Memory allocation failure in %s:%d",
3836*00b67f09SDavid van Moolenbroek 				      __FILE__, __LINE__);
3837*00b67f09SDavid van Moolenbroek 			}
3838*00b67f09SDavid van Moolenbroek 			ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
3839*00b67f09SDavid van Moolenbroek 					       link);
3840*00b67f09SDavid van Moolenbroek 			chase_msg2->msg = msg;
3841*00b67f09SDavid van Moolenbroek 		}
3842*00b67f09SDavid van Moolenbroek #endif
3843*00b67f09SDavid van Moolenbroek 	}
3844*00b67f09SDavid van Moolenbroek 
3845*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3846*00b67f09SDavid van Moolenbroek 	if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
3847*00b67f09SDavid van Moolenbroek 		sigchase(msg_temp);
3848*00b67f09SDavid van Moolenbroek 	}
3849*00b67f09SDavid van Moolenbroek #endif
3850*00b67f09SDavid van Moolenbroek 
3851*00b67f09SDavid van Moolenbroek 	if (l->pending)
3852*00b67f09SDavid van Moolenbroek 		debug("still pending.");
3853*00b67f09SDavid van Moolenbroek 	if (l->doing_xfr) {
3854*00b67f09SDavid van Moolenbroek 		if (query != l->xfr_q) {
3855*00b67f09SDavid van Moolenbroek 			dns_message_destroy(&msg);
3856*00b67f09SDavid van Moolenbroek 			isc_event_free(&event);
3857*00b67f09SDavid van Moolenbroek 			query->waiting_connect = ISC_FALSE;
3858*00b67f09SDavid van Moolenbroek 			UNLOCK_LOOKUP;
3859*00b67f09SDavid van Moolenbroek 			return;
3860*00b67f09SDavid van Moolenbroek 		}
3861*00b67f09SDavid van Moolenbroek 		if (!docancel)
3862*00b67f09SDavid van Moolenbroek 			docancel = check_for_more_data(query, msg, sevent);
3863*00b67f09SDavid van Moolenbroek 		if (docancel) {
3864*00b67f09SDavid van Moolenbroek 			dns_message_destroy(&msg);
3865*00b67f09SDavid van Moolenbroek 			clear_query(query);
3866*00b67f09SDavid van Moolenbroek 			cancel_lookup(l);
3867*00b67f09SDavid van Moolenbroek 			check_next_lookup(l);
3868*00b67f09SDavid van Moolenbroek 		}
3869*00b67f09SDavid van Moolenbroek 	} else {
3870*00b67f09SDavid van Moolenbroek 
3871*00b67f09SDavid van Moolenbroek 		if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3872*00b67f09SDavid van Moolenbroek 
3873*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3874*00b67f09SDavid van Moolenbroek 			if (!l->sigchase)
3875*00b67f09SDavid van Moolenbroek #endif
3876*00b67f09SDavid van Moolenbroek 				received(b->used, &sevent->address, query);
3877*00b67f09SDavid van Moolenbroek 		}
3878*00b67f09SDavid van Moolenbroek 
3879*00b67f09SDavid van Moolenbroek 		if (!query->lookup->ns_search_only)
3880*00b67f09SDavid van Moolenbroek 			query->lookup->pending = ISC_FALSE;
3881*00b67f09SDavid van Moolenbroek 		if (!query->lookup->ns_search_only ||
3882*00b67f09SDavid van Moolenbroek 		    query->lookup->trace_root || docancel) {
3883*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3884*00b67f09SDavid van Moolenbroek 			if (!do_sigchase)
3885*00b67f09SDavid van Moolenbroek #endif
3886*00b67f09SDavid van Moolenbroek 				dns_message_destroy(&msg);
3887*00b67f09SDavid van Moolenbroek 
3888*00b67f09SDavid van Moolenbroek 			cancel_lookup(l);
3889*00b67f09SDavid van Moolenbroek 		}
3890*00b67f09SDavid van Moolenbroek 		clear_query(query);
3891*00b67f09SDavid van Moolenbroek 		check_next_lookup(l);
3892*00b67f09SDavid van Moolenbroek 	}
3893*00b67f09SDavid van Moolenbroek 	if (msg != NULL) {
3894*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
3895*00b67f09SDavid van Moolenbroek 		if (do_sigchase)
3896*00b67f09SDavid van Moolenbroek 			msg = NULL;
3897*00b67f09SDavid van Moolenbroek 		else
3898*00b67f09SDavid van Moolenbroek #endif
3899*00b67f09SDavid van Moolenbroek 			dns_message_destroy(&msg);
3900*00b67f09SDavid van Moolenbroek 	}
3901*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
3902*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
3903*00b67f09SDavid van Moolenbroek 	return;
3904*00b67f09SDavid van Moolenbroek 
3905*00b67f09SDavid van Moolenbroek  udp_mismatch:
3906*00b67f09SDavid van Moolenbroek 	isc_buffer_invalidate(&query->recvbuf);
3907*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3908*00b67f09SDavid van Moolenbroek 	ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3909*00b67f09SDavid van Moolenbroek 	result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3910*00b67f09SDavid van Moolenbroek 				  global_task, recv_done, query);
3911*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_socket_recvv");
3912*00b67f09SDavid van Moolenbroek 	recvcount++;
3913*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
3914*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
3915*00b67f09SDavid van Moolenbroek 	return;
3916*00b67f09SDavid van Moolenbroek }
3917*00b67f09SDavid van Moolenbroek 
3918*00b67f09SDavid van Moolenbroek /*%
3919*00b67f09SDavid van Moolenbroek  * Turn a name into an address, using system-supplied routines.  This is
3920*00b67f09SDavid van Moolenbroek  * used in looking up server names, etc... and needs to use system-supplied
3921*00b67f09SDavid van Moolenbroek  * routines, since they may be using a non-DNS system for these lookups.
3922*00b67f09SDavid van Moolenbroek  */
3923*00b67f09SDavid van Moolenbroek isc_result_t
get_address(char * host,in_port_t myport,isc_sockaddr_t * sockaddr)3924*00b67f09SDavid van Moolenbroek get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
3925*00b67f09SDavid van Moolenbroek 	int count;
3926*00b67f09SDavid van Moolenbroek 	isc_result_t result;
3927*00b67f09SDavid van Moolenbroek 
3928*00b67f09SDavid van Moolenbroek 	isc_app_block();
3929*00b67f09SDavid van Moolenbroek 	result = bind9_getaddresses(host, myport, sockaddr, 1, &count);
3930*00b67f09SDavid van Moolenbroek 	isc_app_unblock();
3931*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
3932*00b67f09SDavid van Moolenbroek 		return (result);
3933*00b67f09SDavid van Moolenbroek 
3934*00b67f09SDavid van Moolenbroek 	INSIST(count == 1);
3935*00b67f09SDavid van Moolenbroek 
3936*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
3937*00b67f09SDavid van Moolenbroek }
3938*00b67f09SDavid van Moolenbroek 
3939*00b67f09SDavid van Moolenbroek int
getaddresses(dig_lookup_t * lookup,const char * host,isc_result_t * resultp)3940*00b67f09SDavid van Moolenbroek getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3941*00b67f09SDavid van Moolenbroek 	isc_result_t result;
3942*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
3943*00b67f09SDavid van Moolenbroek 	isc_netaddr_t netaddr;
3944*00b67f09SDavid van Moolenbroek 	int count, i;
3945*00b67f09SDavid van Moolenbroek 	dig_server_t *srv;
3946*00b67f09SDavid van Moolenbroek 	char tmp[ISC_NETADDR_FORMATSIZE];
3947*00b67f09SDavid van Moolenbroek 
3948*00b67f09SDavid van Moolenbroek 	result = bind9_getaddresses(host, 0, sockaddrs,
3949*00b67f09SDavid van Moolenbroek 				    DIG_MAX_ADDRESSES, &count);
3950*00b67f09SDavid van Moolenbroek 	if (resultp != NULL)
3951*00b67f09SDavid van Moolenbroek 		*resultp = result;
3952*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
3953*00b67f09SDavid van Moolenbroek 		if (resultp == NULL)
3954*00b67f09SDavid van Moolenbroek 			fatal("couldn't get address for '%s': %s",
3955*00b67f09SDavid van Moolenbroek 			      host, isc_result_totext(result));
3956*00b67f09SDavid van Moolenbroek 		return 0;
3957*00b67f09SDavid van Moolenbroek 	}
3958*00b67f09SDavid van Moolenbroek 
3959*00b67f09SDavid van Moolenbroek 	for (i = 0; i < count; i++) {
3960*00b67f09SDavid van Moolenbroek 		isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
3961*00b67f09SDavid van Moolenbroek 		isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
3962*00b67f09SDavid van Moolenbroek 		srv = make_server(tmp, host);
3963*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3964*00b67f09SDavid van Moolenbroek 	}
3965*00b67f09SDavid van Moolenbroek 
3966*00b67f09SDavid van Moolenbroek 	return count;
3967*00b67f09SDavid van Moolenbroek }
3968*00b67f09SDavid van Moolenbroek 
3969*00b67f09SDavid van Moolenbroek /*%
3970*00b67f09SDavid van Moolenbroek  * Initiate either a TCP or UDP lookup
3971*00b67f09SDavid van Moolenbroek  */
3972*00b67f09SDavid van Moolenbroek void
do_lookup(dig_lookup_t * lookup)3973*00b67f09SDavid van Moolenbroek do_lookup(dig_lookup_t *lookup) {
3974*00b67f09SDavid van Moolenbroek 	dig_query_t *query;
3975*00b67f09SDavid van Moolenbroek 
3976*00b67f09SDavid van Moolenbroek 	REQUIRE(lookup != NULL);
3977*00b67f09SDavid van Moolenbroek 
3978*00b67f09SDavid van Moolenbroek 	debug("do_lookup()");
3979*00b67f09SDavid van Moolenbroek 	lookup->pending = ISC_TRUE;
3980*00b67f09SDavid van Moolenbroek 	query = ISC_LIST_HEAD(lookup->q);
3981*00b67f09SDavid van Moolenbroek 	if (query != NULL) {
3982*00b67f09SDavid van Moolenbroek 		if (lookup->tcp_mode)
3983*00b67f09SDavid van Moolenbroek 			send_tcp_connect(query);
3984*00b67f09SDavid van Moolenbroek 		else
3985*00b67f09SDavid van Moolenbroek 			send_udp(query);
3986*00b67f09SDavid van Moolenbroek 	}
3987*00b67f09SDavid van Moolenbroek }
3988*00b67f09SDavid van Moolenbroek 
3989*00b67f09SDavid van Moolenbroek /*%
3990*00b67f09SDavid van Moolenbroek  * Start everything in action upon task startup.
3991*00b67f09SDavid van Moolenbroek  */
3992*00b67f09SDavid van Moolenbroek void
onrun_callback(isc_task_t * task,isc_event_t * event)3993*00b67f09SDavid van Moolenbroek onrun_callback(isc_task_t *task, isc_event_t *event) {
3994*00b67f09SDavid van Moolenbroek 	UNUSED(task);
3995*00b67f09SDavid van Moolenbroek 
3996*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
3997*00b67f09SDavid van Moolenbroek 	LOCK_LOOKUP;
3998*00b67f09SDavid van Moolenbroek 	start_lookup();
3999*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
4000*00b67f09SDavid van Moolenbroek }
4001*00b67f09SDavid van Moolenbroek 
4002*00b67f09SDavid van Moolenbroek /*%
4003*00b67f09SDavid van Moolenbroek  * Make everything on the lookup queue go away.  Mainly used by the
4004*00b67f09SDavid van Moolenbroek  * SIGINT handler.
4005*00b67f09SDavid van Moolenbroek  */
4006*00b67f09SDavid van Moolenbroek void
cancel_all(void)4007*00b67f09SDavid van Moolenbroek cancel_all(void) {
4008*00b67f09SDavid van Moolenbroek 	dig_lookup_t *l, *n;
4009*00b67f09SDavid van Moolenbroek 	dig_query_t *q, *nq;
4010*00b67f09SDavid van Moolenbroek 
4011*00b67f09SDavid van Moolenbroek 	debug("cancel_all()");
4012*00b67f09SDavid van Moolenbroek 
4013*00b67f09SDavid van Moolenbroek 	LOCK_LOOKUP;
4014*00b67f09SDavid van Moolenbroek 	if (free_now) {
4015*00b67f09SDavid van Moolenbroek 		UNLOCK_LOOKUP;
4016*00b67f09SDavid van Moolenbroek 		return;
4017*00b67f09SDavid van Moolenbroek 	}
4018*00b67f09SDavid van Moolenbroek 	cancel_now = ISC_TRUE;
4019*00b67f09SDavid van Moolenbroek 	if (current_lookup != NULL) {
4020*00b67f09SDavid van Moolenbroek 		if (current_lookup->timer != NULL)
4021*00b67f09SDavid van Moolenbroek 			isc_timer_detach(&current_lookup->timer);
4022*00b67f09SDavid van Moolenbroek 		for (q = ISC_LIST_HEAD(current_lookup->q);
4023*00b67f09SDavid van Moolenbroek 		     q != NULL;
4024*00b67f09SDavid van Moolenbroek 		     q = nq)
4025*00b67f09SDavid van Moolenbroek 		{
4026*00b67f09SDavid van Moolenbroek 			nq = ISC_LIST_NEXT(q, link);
4027*00b67f09SDavid van Moolenbroek 			debug("canceling pending query %p, belonging to %p",
4028*00b67f09SDavid van Moolenbroek 			      q, current_lookup);
4029*00b67f09SDavid van Moolenbroek 			if (q->sock != NULL)
4030*00b67f09SDavid van Moolenbroek 				isc_socket_cancel(q->sock, NULL,
4031*00b67f09SDavid van Moolenbroek 						  ISC_SOCKCANCEL_ALL);
4032*00b67f09SDavid van Moolenbroek 			else
4033*00b67f09SDavid van Moolenbroek 				clear_query(q);
4034*00b67f09SDavid van Moolenbroek 		}
4035*00b67f09SDavid van Moolenbroek 		for (q = ISC_LIST_HEAD(current_lookup->connecting);
4036*00b67f09SDavid van Moolenbroek 		     q != NULL;
4037*00b67f09SDavid van Moolenbroek 		     q = nq)
4038*00b67f09SDavid van Moolenbroek 		{
4039*00b67f09SDavid van Moolenbroek 			nq = ISC_LIST_NEXT(q, clink);
4040*00b67f09SDavid van Moolenbroek 			debug("canceling connecting query %p, belonging to %p",
4041*00b67f09SDavid van Moolenbroek 			      q, current_lookup);
4042*00b67f09SDavid van Moolenbroek 			if (q->sock != NULL)
4043*00b67f09SDavid van Moolenbroek 				isc_socket_cancel(q->sock, NULL,
4044*00b67f09SDavid van Moolenbroek 						  ISC_SOCKCANCEL_ALL);
4045*00b67f09SDavid van Moolenbroek 			else
4046*00b67f09SDavid van Moolenbroek 				clear_query(q);
4047*00b67f09SDavid van Moolenbroek 		}
4048*00b67f09SDavid van Moolenbroek 	}
4049*00b67f09SDavid van Moolenbroek 	l = ISC_LIST_HEAD(lookup_list);
4050*00b67f09SDavid van Moolenbroek 	while (l != NULL) {
4051*00b67f09SDavid van Moolenbroek 		n = ISC_LIST_NEXT(l, link);
4052*00b67f09SDavid van Moolenbroek 		ISC_LIST_DEQUEUE(lookup_list, l, link);
4053*00b67f09SDavid van Moolenbroek 		try_clear_lookup(l);
4054*00b67f09SDavid van Moolenbroek 		l = n;
4055*00b67f09SDavid van Moolenbroek 	}
4056*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
4057*00b67f09SDavid van Moolenbroek }
4058*00b67f09SDavid van Moolenbroek 
4059*00b67f09SDavid van Moolenbroek /*%
4060*00b67f09SDavid van Moolenbroek  * Destroy all of the libs we are using, and get everything ready for a
4061*00b67f09SDavid van Moolenbroek  * clean shutdown.
4062*00b67f09SDavid van Moolenbroek  */
4063*00b67f09SDavid van Moolenbroek void
destroy_libs(void)4064*00b67f09SDavid van Moolenbroek destroy_libs(void) {
4065*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
4066*00b67f09SDavid van Moolenbroek 	void * ptr;
4067*00b67f09SDavid van Moolenbroek 	dig_message_t *chase_msg;
4068*00b67f09SDavid van Moolenbroek #endif
4069*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
4070*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4071*00b67f09SDavid van Moolenbroek #endif
4072*00b67f09SDavid van Moolenbroek 
4073*00b67f09SDavid van Moolenbroek 	if (keep != NULL)
4074*00b67f09SDavid van Moolenbroek 		isc_socket_detach(&keep);
4075*00b67f09SDavid van Moolenbroek 	debug("destroy_libs()");
4076*00b67f09SDavid van Moolenbroek 	if (global_task != NULL) {
4077*00b67f09SDavid van Moolenbroek 		debug("freeing task");
4078*00b67f09SDavid van Moolenbroek 		isc_task_detach(&global_task);
4079*00b67f09SDavid van Moolenbroek 	}
4080*00b67f09SDavid van Moolenbroek 	/*
4081*00b67f09SDavid van Moolenbroek 	 * The taskmgr_destroy() call blocks until all events are cleared
4082*00b67f09SDavid van Moolenbroek 	 * from the task.
4083*00b67f09SDavid van Moolenbroek 	 */
4084*00b67f09SDavid van Moolenbroek 	if (taskmgr != NULL) {
4085*00b67f09SDavid van Moolenbroek 		debug("freeing taskmgr");
4086*00b67f09SDavid van Moolenbroek 		isc_taskmgr_destroy(&taskmgr);
4087*00b67f09SDavid van Moolenbroek 	}
4088*00b67f09SDavid van Moolenbroek 	LOCK_LOOKUP;
4089*00b67f09SDavid van Moolenbroek 	REQUIRE(sockcount == 0);
4090*00b67f09SDavid van Moolenbroek 	REQUIRE(recvcount == 0);
4091*00b67f09SDavid van Moolenbroek 	REQUIRE(sendcount == 0);
4092*00b67f09SDavid van Moolenbroek 
4093*00b67f09SDavid van Moolenbroek 	INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
4094*00b67f09SDavid van Moolenbroek 	INSIST(current_lookup == NULL);
4095*00b67f09SDavid van Moolenbroek 	INSIST(!free_now);
4096*00b67f09SDavid van Moolenbroek 
4097*00b67f09SDavid van Moolenbroek 	free_now = ISC_TRUE;
4098*00b67f09SDavid van Moolenbroek 
4099*00b67f09SDavid van Moolenbroek 	lwres_conf_clear(lwctx);
4100*00b67f09SDavid van Moolenbroek 	lwres_context_destroy(&lwctx);
4101*00b67f09SDavid van Moolenbroek 
4102*00b67f09SDavid van Moolenbroek 	flush_server_list();
4103*00b67f09SDavid van Moolenbroek 
4104*00b67f09SDavid van Moolenbroek 	clear_searchlist();
4105*00b67f09SDavid van Moolenbroek 
4106*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
4107*00b67f09SDavid van Moolenbroek 	result = dns_name_settotextfilter(NULL);
4108*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_name_settotextfilter");
4109*00b67f09SDavid van Moolenbroek #endif
4110*00b67f09SDavid van Moolenbroek 	dns_name_destroy();
4111*00b67f09SDavid van Moolenbroek 
4112*00b67f09SDavid van Moolenbroek 	if (commctx != NULL) {
4113*00b67f09SDavid van Moolenbroek 		debug("freeing commctx");
4114*00b67f09SDavid van Moolenbroek 		isc_mempool_destroy(&commctx);
4115*00b67f09SDavid van Moolenbroek 	}
4116*00b67f09SDavid van Moolenbroek 	if (socketmgr != NULL) {
4117*00b67f09SDavid van Moolenbroek 		debug("freeing socketmgr");
4118*00b67f09SDavid van Moolenbroek 		isc_socketmgr_destroy(&socketmgr);
4119*00b67f09SDavid van Moolenbroek 	}
4120*00b67f09SDavid van Moolenbroek 	if (timermgr != NULL) {
4121*00b67f09SDavid van Moolenbroek 		debug("freeing timermgr");
4122*00b67f09SDavid van Moolenbroek 		isc_timermgr_destroy(&timermgr);
4123*00b67f09SDavid van Moolenbroek 	}
4124*00b67f09SDavid van Moolenbroek 	if (key != NULL) {
4125*00b67f09SDavid van Moolenbroek 		debug("freeing key %p", key);
4126*00b67f09SDavid van Moolenbroek 		dns_tsigkey_detach(&key);
4127*00b67f09SDavid van Moolenbroek 	}
4128*00b67f09SDavid van Moolenbroek 	if (namebuf != NULL)
4129*00b67f09SDavid van Moolenbroek 		isc_buffer_free(&namebuf);
4130*00b67f09SDavid van Moolenbroek 
4131*00b67f09SDavid van Moolenbroek 	if (is_dst_up) {
4132*00b67f09SDavid van Moolenbroek 		debug("destroy DST lib");
4133*00b67f09SDavid van Moolenbroek 		dst_lib_destroy();
4134*00b67f09SDavid van Moolenbroek 		is_dst_up = ISC_FALSE;
4135*00b67f09SDavid van Moolenbroek 	}
4136*00b67f09SDavid van Moolenbroek 	if (entp != NULL) {
4137*00b67f09SDavid van Moolenbroek 		debug("detach from entropy");
4138*00b67f09SDavid van Moolenbroek 		isc_entropy_detach(&entp);
4139*00b67f09SDavid van Moolenbroek 	}
4140*00b67f09SDavid van Moolenbroek 
4141*00b67f09SDavid van Moolenbroek 	UNLOCK_LOOKUP;
4142*00b67f09SDavid van Moolenbroek 	DESTROYLOCK(&lookup_lock);
4143*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
4144*00b67f09SDavid van Moolenbroek 
4145*00b67f09SDavid van Moolenbroek 	debug("Destroy the messages kept for sigchase");
4146*00b67f09SDavid van Moolenbroek 	/* Destroy the messages kept for sigchase */
4147*00b67f09SDavid van Moolenbroek 	chase_msg = ISC_LIST_HEAD(chase_message_list);
4148*00b67f09SDavid van Moolenbroek 
4149*00b67f09SDavid van Moolenbroek 	while (chase_msg != NULL) {
4150*00b67f09SDavid van Moolenbroek 		INSIST(chase_msg->msg != NULL);
4151*00b67f09SDavid van Moolenbroek 		dns_message_destroy(&(chase_msg->msg));
4152*00b67f09SDavid van Moolenbroek 		ptr = chase_msg;
4153*00b67f09SDavid van Moolenbroek 		chase_msg = ISC_LIST_NEXT(chase_msg, link);
4154*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, ptr);
4155*00b67f09SDavid van Moolenbroek 	}
4156*00b67f09SDavid van Moolenbroek 
4157*00b67f09SDavid van Moolenbroek 	chase_msg = ISC_LIST_HEAD(chase_message_list2);
4158*00b67f09SDavid van Moolenbroek 
4159*00b67f09SDavid van Moolenbroek 	while (chase_msg != NULL) {
4160*00b67f09SDavid van Moolenbroek 		INSIST(chase_msg->msg != NULL);
4161*00b67f09SDavid van Moolenbroek 		dns_message_destroy(&(chase_msg->msg));
4162*00b67f09SDavid van Moolenbroek 		ptr = chase_msg;
4163*00b67f09SDavid van Moolenbroek 		chase_msg = ISC_LIST_NEXT(chase_msg, link);
4164*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, ptr);
4165*00b67f09SDavid van Moolenbroek 	}
4166*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(&chase_name))
4167*00b67f09SDavid van Moolenbroek 		free_name(&chase_name, mctx);
4168*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
4169*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(&chase_current_name))
4170*00b67f09SDavid van Moolenbroek 		free_name(&chase_current_name, mctx);
4171*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(&chase_authority_name))
4172*00b67f09SDavid van Moolenbroek 		free_name(&chase_authority_name, mctx);
4173*00b67f09SDavid van Moolenbroek #endif
4174*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_BU
4175*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(&chase_signame))
4176*00b67f09SDavid van Moolenbroek 		free_name(&chase_signame, mctx);
4177*00b67f09SDavid van Moolenbroek #endif
4178*00b67f09SDavid van Moolenbroek 
4179*00b67f09SDavid van Moolenbroek #endif
4180*00b67f09SDavid van Moolenbroek 	debug("Removing log context");
4181*00b67f09SDavid van Moolenbroek 	isc_log_destroy(&lctx);
4182*00b67f09SDavid van Moolenbroek 
4183*00b67f09SDavid van Moolenbroek 	debug("Destroy memory");
4184*00b67f09SDavid van Moolenbroek 	if (memdebugging != 0)
4185*00b67f09SDavid van Moolenbroek 		isc_mem_stats(mctx, stderr);
4186*00b67f09SDavid van Moolenbroek 	if (mctx != NULL)
4187*00b67f09SDavid van Moolenbroek 		isc_mem_destroy(&mctx);
4188*00b67f09SDavid van Moolenbroek }
4189*00b67f09SDavid van Moolenbroek 
4190*00b67f09SDavid van Moolenbroek #ifdef WITH_IDN
4191*00b67f09SDavid van Moolenbroek static void
initialize_idn(void)4192*00b67f09SDavid van Moolenbroek initialize_idn(void) {
4193*00b67f09SDavid van Moolenbroek 	idn_result_t r;
4194*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4195*00b67f09SDavid van Moolenbroek 
4196*00b67f09SDavid van Moolenbroek #ifdef HAVE_SETLOCALE
4197*00b67f09SDavid van Moolenbroek 	/* Set locale */
4198*00b67f09SDavid van Moolenbroek 	(void)setlocale(LC_ALL, "");
4199*00b67f09SDavid van Moolenbroek #endif
4200*00b67f09SDavid van Moolenbroek 	/* Create configuration context. */
4201*00b67f09SDavid van Moolenbroek 	r = idn_nameinit(1);
4202*00b67f09SDavid van Moolenbroek 	if (r != idn_success)
4203*00b67f09SDavid van Moolenbroek 		fatal("idn api initialization failed: %s",
4204*00b67f09SDavid van Moolenbroek 		      idn_result_tostring(r));
4205*00b67f09SDavid van Moolenbroek 
4206*00b67f09SDavid van Moolenbroek 	/* Set domain name -> text post-conversion filter. */
4207*00b67f09SDavid van Moolenbroek 	result = dns_name_settotextfilter(output_filter);
4208*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_name_settotextfilter");
4209*00b67f09SDavid van Moolenbroek }
4210*00b67f09SDavid van Moolenbroek 
4211*00b67f09SDavid van Moolenbroek static isc_result_t
output_filter(isc_buffer_t * buffer,unsigned int used_org,isc_boolean_t absolute)4212*00b67f09SDavid van Moolenbroek output_filter(isc_buffer_t *buffer, unsigned int used_org,
4213*00b67f09SDavid van Moolenbroek 	      isc_boolean_t absolute)
4214*00b67f09SDavid van Moolenbroek {
4215*00b67f09SDavid van Moolenbroek 	char tmp1[MAXDLEN], tmp2[MAXDLEN];
4216*00b67f09SDavid van Moolenbroek 	size_t fromlen, tolen;
4217*00b67f09SDavid van Moolenbroek 	isc_boolean_t end_with_dot;
4218*00b67f09SDavid van Moolenbroek 
4219*00b67f09SDavid van Moolenbroek 	/*
4220*00b67f09SDavid van Moolenbroek 	 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
4221*00b67f09SDavid van Moolenbroek 	 * if 'absolute' is true, and terminate with NUL.
4222*00b67f09SDavid van Moolenbroek 	 */
4223*00b67f09SDavid van Moolenbroek 	fromlen = isc_buffer_usedlength(buffer) - used_org;
4224*00b67f09SDavid van Moolenbroek 	if (fromlen >= MAXDLEN)
4225*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
4226*00b67f09SDavid van Moolenbroek 	memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
4227*00b67f09SDavid van Moolenbroek 	end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
4228*00b67f09SDavid van Moolenbroek 	if (absolute && !end_with_dot) {
4229*00b67f09SDavid van Moolenbroek 		fromlen++;
4230*00b67f09SDavid van Moolenbroek 		if (fromlen >= MAXDLEN)
4231*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
4232*00b67f09SDavid van Moolenbroek 		tmp1[fromlen - 1] = '.';
4233*00b67f09SDavid van Moolenbroek 	}
4234*00b67f09SDavid van Moolenbroek 	tmp1[fromlen] = '\0';
4235*00b67f09SDavid van Moolenbroek 
4236*00b67f09SDavid van Moolenbroek 	/*
4237*00b67f09SDavid van Moolenbroek 	 * Convert contents of 'tmp1' to local encoding.
4238*00b67f09SDavid van Moolenbroek 	 */
4239*00b67f09SDavid van Moolenbroek 	if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
4240*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
4241*00b67f09SDavid van Moolenbroek 	strcpy(tmp1, tmp2);
4242*00b67f09SDavid van Moolenbroek 
4243*00b67f09SDavid van Moolenbroek 	/*
4244*00b67f09SDavid van Moolenbroek 	 * Copy the converted contents in 'tmp1' back to 'buffer'.
4245*00b67f09SDavid van Moolenbroek 	 * If we have appended trailing dot, remove it.
4246*00b67f09SDavid van Moolenbroek 	 */
4247*00b67f09SDavid van Moolenbroek 	tolen = strlen(tmp1);
4248*00b67f09SDavid van Moolenbroek 	if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
4249*00b67f09SDavid van Moolenbroek 		tolen--;
4250*00b67f09SDavid van Moolenbroek 
4251*00b67f09SDavid van Moolenbroek 	if (isc_buffer_length(buffer) < used_org + tolen)
4252*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
4253*00b67f09SDavid van Moolenbroek 
4254*00b67f09SDavid van Moolenbroek 	isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
4255*00b67f09SDavid van Moolenbroek 	memmove(isc_buffer_used(buffer), tmp1, tolen);
4256*00b67f09SDavid van Moolenbroek 	isc_buffer_add(buffer, (unsigned int)tolen);
4257*00b67f09SDavid van Moolenbroek 
4258*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
4259*00b67f09SDavid van Moolenbroek }
4260*00b67f09SDavid van Moolenbroek 
4261*00b67f09SDavid van Moolenbroek static idn_result_t
append_textname(char * name,const char * origin,size_t namesize)4262*00b67f09SDavid van Moolenbroek append_textname(char *name, const char *origin, size_t namesize) {
4263*00b67f09SDavid van Moolenbroek 	size_t namelen = strlen(name);
4264*00b67f09SDavid van Moolenbroek 	size_t originlen = strlen(origin);
4265*00b67f09SDavid van Moolenbroek 
4266*00b67f09SDavid van Moolenbroek 	/* Already absolute? */
4267*00b67f09SDavid van Moolenbroek 	if (namelen > 0 && name[namelen - 1] == '.')
4268*00b67f09SDavid van Moolenbroek 		return idn_success;
4269*00b67f09SDavid van Moolenbroek 
4270*00b67f09SDavid van Moolenbroek 	/* Append dot and origin */
4271*00b67f09SDavid van Moolenbroek 
4272*00b67f09SDavid van Moolenbroek 	if (namelen + 1 + originlen >= namesize)
4273*00b67f09SDavid van Moolenbroek 		return idn_buffer_overflow;
4274*00b67f09SDavid van Moolenbroek 
4275*00b67f09SDavid van Moolenbroek 	if (*origin != '.')
4276*00b67f09SDavid van Moolenbroek 		name[namelen++] = '.';
4277*00b67f09SDavid van Moolenbroek 	(void)strcpy(name + namelen, origin);
4278*00b67f09SDavid van Moolenbroek 	return idn_success;
4279*00b67f09SDavid van Moolenbroek }
4280*00b67f09SDavid van Moolenbroek 
4281*00b67f09SDavid van Moolenbroek static void
idn_check_result(idn_result_t r,const char * msg)4282*00b67f09SDavid van Moolenbroek idn_check_result(idn_result_t r, const char *msg) {
4283*00b67f09SDavid van Moolenbroek 	if (r != idn_success) {
4284*00b67f09SDavid van Moolenbroek 		exitcode = 1;
4285*00b67f09SDavid van Moolenbroek 		fatal("%s: %s", msg, idn_result_tostring(r));
4286*00b67f09SDavid van Moolenbroek 	}
4287*00b67f09SDavid van Moolenbroek }
4288*00b67f09SDavid van Moolenbroek #endif /* WITH_IDN */
4289*00b67f09SDavid van Moolenbroek 
4290*00b67f09SDavid van Moolenbroek #ifdef DIG_SIGCHASE
4291*00b67f09SDavid van Moolenbroek void
print_type(dns_rdatatype_t type)4292*00b67f09SDavid van Moolenbroek print_type(dns_rdatatype_t type)
4293*00b67f09SDavid van Moolenbroek {
4294*00b67f09SDavid van Moolenbroek 	isc_buffer_t * b = NULL;
4295*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4296*00b67f09SDavid van Moolenbroek 	isc_region_t r;
4297*00b67f09SDavid van Moolenbroek 
4298*00b67f09SDavid van Moolenbroek 	result = isc_buffer_allocate(mctx, &b, 4000);
4299*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_buffer_allocate");
4300*00b67f09SDavid van Moolenbroek 
4301*00b67f09SDavid van Moolenbroek 	result = dns_rdatatype_totext(type, b);
4302*00b67f09SDavid van Moolenbroek 	check_result(result, "print_type");
4303*00b67f09SDavid van Moolenbroek 
4304*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(b, &r);
4305*00b67f09SDavid van Moolenbroek 	r.base[r.length] = '\0';
4306*00b67f09SDavid van Moolenbroek 
4307*00b67f09SDavid van Moolenbroek 	printf("%s", r.base);
4308*00b67f09SDavid van Moolenbroek 
4309*00b67f09SDavid van Moolenbroek 	isc_buffer_free(&b);
4310*00b67f09SDavid van Moolenbroek }
4311*00b67f09SDavid van Moolenbroek 
4312*00b67f09SDavid van Moolenbroek void
dump_database_section(dns_message_t * msg,int section)4313*00b67f09SDavid van Moolenbroek dump_database_section(dns_message_t *msg, int section)
4314*00b67f09SDavid van Moolenbroek {
4315*00b67f09SDavid van Moolenbroek 	dns_name_t *msg_name=NULL;
4316*00b67f09SDavid van Moolenbroek 
4317*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset;
4318*00b67f09SDavid van Moolenbroek 
4319*00b67f09SDavid van Moolenbroek 	do {
4320*00b67f09SDavid van Moolenbroek 		dns_message_currentname(msg, section, &msg_name);
4321*00b67f09SDavid van Moolenbroek 
4322*00b67f09SDavid van Moolenbroek 		for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
4323*00b67f09SDavid van Moolenbroek 		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
4324*00b67f09SDavid van Moolenbroek 			dns_name_print(msg_name, stdout);
4325*00b67f09SDavid van Moolenbroek 			printf("\n");
4326*00b67f09SDavid van Moolenbroek 			print_rdataset(msg_name, rdataset, mctx);
4327*00b67f09SDavid van Moolenbroek 			printf("end\n");
4328*00b67f09SDavid van Moolenbroek 		}
4329*00b67f09SDavid van Moolenbroek 		msg_name = NULL;
4330*00b67f09SDavid van Moolenbroek 	} while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4331*00b67f09SDavid van Moolenbroek }
4332*00b67f09SDavid van Moolenbroek 
4333*00b67f09SDavid van Moolenbroek void
dump_database(void)4334*00b67f09SDavid van Moolenbroek dump_database(void) {
4335*00b67f09SDavid van Moolenbroek 	dig_message_t * msg;
4336*00b67f09SDavid van Moolenbroek 
4337*00b67f09SDavid van Moolenbroek 	for (msg = ISC_LIST_HEAD(chase_message_list);  msg != NULL;
4338*00b67f09SDavid van Moolenbroek 	     msg = ISC_LIST_NEXT(msg, link)) {
4339*00b67f09SDavid van Moolenbroek 		if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4340*00b67f09SDavid van Moolenbroek 		    == ISC_R_SUCCESS)
4341*00b67f09SDavid van Moolenbroek 			dump_database_section(msg->msg, DNS_SECTION_ANSWER);
4342*00b67f09SDavid van Moolenbroek 
4343*00b67f09SDavid van Moolenbroek 		if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4344*00b67f09SDavid van Moolenbroek 		    == ISC_R_SUCCESS)
4345*00b67f09SDavid van Moolenbroek 			dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
4346*00b67f09SDavid van Moolenbroek 
4347*00b67f09SDavid van Moolenbroek 		if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4348*00b67f09SDavid van Moolenbroek 		    == ISC_R_SUCCESS)
4349*00b67f09SDavid van Moolenbroek 			dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
4350*00b67f09SDavid van Moolenbroek 	}
4351*00b67f09SDavid van Moolenbroek }
4352*00b67f09SDavid van Moolenbroek 
4353*00b67f09SDavid van Moolenbroek 
4354*00b67f09SDavid van Moolenbroek dns_rdataset_t *
search_type(dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers)4355*00b67f09SDavid van Moolenbroek search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
4356*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset;
4357*00b67f09SDavid van Moolenbroek 	dns_rdata_sig_t siginfo;
4358*00b67f09SDavid van Moolenbroek 	dns_rdata_t sigrdata = DNS_RDATA_INIT;
4359*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4360*00b67f09SDavid van Moolenbroek 
4361*00b67f09SDavid van Moolenbroek 	for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
4362*00b67f09SDavid van Moolenbroek 	     rdataset = ISC_LIST_NEXT(rdataset, link)) {
4363*00b67f09SDavid van Moolenbroek 		if (type == dns_rdatatype_any) {
4364*00b67f09SDavid van Moolenbroek 			if (rdataset->type != dns_rdatatype_rrsig)
4365*00b67f09SDavid van Moolenbroek 				return (rdataset);
4366*00b67f09SDavid van Moolenbroek 		} else if ((type == dns_rdatatype_rrsig) &&
4367*00b67f09SDavid van Moolenbroek 			   (rdataset->type == dns_rdatatype_rrsig)) {
4368*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_first(rdataset);
4369*00b67f09SDavid van Moolenbroek 			check_result(result, "empty rdataset");
4370*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(rdataset, &sigrdata);
4371*00b67f09SDavid van Moolenbroek 			result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4372*00b67f09SDavid van Moolenbroek 			check_result(result, "sigrdata tostruct siginfo");
4373*00b67f09SDavid van Moolenbroek 
4374*00b67f09SDavid van Moolenbroek 			if ((siginfo.covered == covers) ||
4375*00b67f09SDavid van Moolenbroek 			    (covers == dns_rdatatype_any)) {
4376*00b67f09SDavid van Moolenbroek 				dns_rdata_reset(&sigrdata);
4377*00b67f09SDavid van Moolenbroek 				dns_rdata_freestruct(&siginfo);
4378*00b67f09SDavid van Moolenbroek 				return (rdataset);
4379*00b67f09SDavid van Moolenbroek 			}
4380*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&sigrdata);
4381*00b67f09SDavid van Moolenbroek 			dns_rdata_freestruct(&siginfo);
4382*00b67f09SDavid van Moolenbroek 		} else if (rdataset->type == type)
4383*00b67f09SDavid van Moolenbroek 			return (rdataset);
4384*00b67f09SDavid van Moolenbroek 	}
4385*00b67f09SDavid van Moolenbroek 	return (NULL);
4386*00b67f09SDavid van Moolenbroek }
4387*00b67f09SDavid van Moolenbroek 
4388*00b67f09SDavid van Moolenbroek dns_rdataset_t *
chase_scanname_section(dns_message_t * msg,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,int section)4389*00b67f09SDavid van Moolenbroek chase_scanname_section(dns_message_t *msg, dns_name_t *name,
4390*00b67f09SDavid van Moolenbroek 		       dns_rdatatype_t type, dns_rdatatype_t covers,
4391*00b67f09SDavid van Moolenbroek 		       int section)
4392*00b67f09SDavid van Moolenbroek {
4393*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset;
4394*00b67f09SDavid van Moolenbroek 	dns_name_t *msg_name = NULL;
4395*00b67f09SDavid van Moolenbroek 
4396*00b67f09SDavid van Moolenbroek 	if (msg->counts[section] == 0)
4397*00b67f09SDavid van Moolenbroek 		return (NULL);
4398*00b67f09SDavid van Moolenbroek 
4399*00b67f09SDavid van Moolenbroek 	do {
4400*00b67f09SDavid van Moolenbroek 		dns_message_currentname(msg, section, &msg_name);
4401*00b67f09SDavid van Moolenbroek 		if (dns_name_compare(msg_name, name) == 0) {
4402*00b67f09SDavid van Moolenbroek 			rdataset = search_type(msg_name, type, covers);
4403*00b67f09SDavid van Moolenbroek 			if (rdataset != NULL)
4404*00b67f09SDavid van Moolenbroek 				return (rdataset);
4405*00b67f09SDavid van Moolenbroek 		}
4406*00b67f09SDavid van Moolenbroek 		msg_name = NULL;
4407*00b67f09SDavid van Moolenbroek 	} while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4408*00b67f09SDavid van Moolenbroek 
4409*00b67f09SDavid van Moolenbroek 	return (NULL);
4410*00b67f09SDavid van Moolenbroek }
4411*00b67f09SDavid van Moolenbroek 
4412*00b67f09SDavid van Moolenbroek 
4413*00b67f09SDavid van Moolenbroek dns_rdataset_t *
chase_scanname(dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers)4414*00b67f09SDavid van Moolenbroek chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
4415*00b67f09SDavid van Moolenbroek {
4416*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *rdataset = NULL;
4417*00b67f09SDavid van Moolenbroek 	dig_message_t * msg;
4418*00b67f09SDavid van Moolenbroek 
4419*00b67f09SDavid van Moolenbroek 	for (msg = ISC_LIST_HEAD(chase_message_list2);  msg != NULL;
4420*00b67f09SDavid van Moolenbroek 	     msg = ISC_LIST_NEXT(msg, link)) {
4421*00b67f09SDavid van Moolenbroek 		if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4422*00b67f09SDavid van Moolenbroek 		    == ISC_R_SUCCESS)
4423*00b67f09SDavid van Moolenbroek 			rdataset = chase_scanname_section(msg->msg, name,
4424*00b67f09SDavid van Moolenbroek 							  type, covers,
4425*00b67f09SDavid van Moolenbroek 							  DNS_SECTION_ANSWER);
4426*00b67f09SDavid van Moolenbroek 			if (rdataset != NULL)
4427*00b67f09SDavid van Moolenbroek 				return (rdataset);
4428*00b67f09SDavid van Moolenbroek 		if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4429*00b67f09SDavid van Moolenbroek 		    == ISC_R_SUCCESS)
4430*00b67f09SDavid van Moolenbroek 			rdataset =
4431*00b67f09SDavid van Moolenbroek 				chase_scanname_section(msg->msg, name,
4432*00b67f09SDavid van Moolenbroek 						       type, covers,
4433*00b67f09SDavid van Moolenbroek 						       DNS_SECTION_AUTHORITY);
4434*00b67f09SDavid van Moolenbroek 			if (rdataset != NULL)
4435*00b67f09SDavid van Moolenbroek 				return (rdataset);
4436*00b67f09SDavid van Moolenbroek 		if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4437*00b67f09SDavid van Moolenbroek 		    == ISC_R_SUCCESS)
4438*00b67f09SDavid van Moolenbroek 			rdataset =
4439*00b67f09SDavid van Moolenbroek 				chase_scanname_section(msg->msg, name, type,
4440*00b67f09SDavid van Moolenbroek 						       covers,
4441*00b67f09SDavid van Moolenbroek 						       DNS_SECTION_ADDITIONAL);
4442*00b67f09SDavid van Moolenbroek 			if (rdataset != NULL)
4443*00b67f09SDavid van Moolenbroek 				return (rdataset);
4444*00b67f09SDavid van Moolenbroek 	}
4445*00b67f09SDavid van Moolenbroek 
4446*00b67f09SDavid van Moolenbroek 	return (NULL);
4447*00b67f09SDavid van Moolenbroek }
4448*00b67f09SDavid van Moolenbroek 
4449*00b67f09SDavid van Moolenbroek dns_rdataset_t *
sigchase_scanname(dns_rdatatype_t type,dns_rdatatype_t covers,isc_boolean_t * lookedup,dns_name_t * rdata_name)4450*00b67f09SDavid van Moolenbroek sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
4451*00b67f09SDavid van Moolenbroek 		  isc_boolean_t * lookedup, dns_name_t *rdata_name)
4452*00b67f09SDavid van Moolenbroek {
4453*00b67f09SDavid van Moolenbroek 	dig_lookup_t *lookup;
4454*00b67f09SDavid van Moolenbroek 	isc_buffer_t *b = NULL;
4455*00b67f09SDavid van Moolenbroek 	isc_region_t r;
4456*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4457*00b67f09SDavid van Moolenbroek 	dns_rdataset_t * temp;
4458*00b67f09SDavid van Moolenbroek 	dns_rdatatype_t querytype;
4459*00b67f09SDavid van Moolenbroek 
4460*00b67f09SDavid van Moolenbroek 	temp = chase_scanname(rdata_name, type, covers);
4461*00b67f09SDavid van Moolenbroek 	if (temp != NULL)
4462*00b67f09SDavid van Moolenbroek 		return (temp);
4463*00b67f09SDavid van Moolenbroek 
4464*00b67f09SDavid van Moolenbroek 	if (*lookedup == ISC_TRUE)
4465*00b67f09SDavid van Moolenbroek 		return (NULL);
4466*00b67f09SDavid van Moolenbroek 
4467*00b67f09SDavid van Moolenbroek 	lookup = clone_lookup(current_lookup, ISC_TRUE);
4468*00b67f09SDavid van Moolenbroek 	lookup->trace_root = ISC_FALSE;
4469*00b67f09SDavid van Moolenbroek 	lookup->new_search = ISC_TRUE;
4470*00b67f09SDavid van Moolenbroek 
4471*00b67f09SDavid van Moolenbroek 	result = isc_buffer_allocate(mctx, &b, BUFSIZE);
4472*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_buffer_allocate");
4473*00b67f09SDavid van Moolenbroek 	result = dns_name_totext(rdata_name, ISC_FALSE, b);
4474*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_name_totext");
4475*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(b, &r);
4476*00b67f09SDavid van Moolenbroek 	r.base[r.length] = '\0';
4477*00b67f09SDavid van Moolenbroek 	strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname));
4478*00b67f09SDavid van Moolenbroek 	isc_buffer_free(&b);
4479*00b67f09SDavid van Moolenbroek 
4480*00b67f09SDavid van Moolenbroek 	if (type ==  dns_rdatatype_rrsig)
4481*00b67f09SDavid van Moolenbroek 		querytype = covers;
4482*00b67f09SDavid van Moolenbroek 	else
4483*00b67f09SDavid van Moolenbroek 		querytype = type;
4484*00b67f09SDavid van Moolenbroek 
4485*00b67f09SDavid van Moolenbroek 	if (querytype == 0 || querytype == 255) {
4486*00b67f09SDavid van Moolenbroek 		printf("Error in the queried type: %d\n", querytype);
4487*00b67f09SDavid van Moolenbroek 		return (NULL);
4488*00b67f09SDavid van Moolenbroek 	}
4489*00b67f09SDavid van Moolenbroek 
4490*00b67f09SDavid van Moolenbroek 	lookup->rdtype = querytype;
4491*00b67f09SDavid van Moolenbroek 	lookup->rdtypeset = ISC_TRUE;
4492*00b67f09SDavid van Moolenbroek 	lookup->qrdtype = querytype;
4493*00b67f09SDavid van Moolenbroek 	*lookedup = ISC_TRUE;
4494*00b67f09SDavid van Moolenbroek 
4495*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(lookup_list, lookup, link);
4496*00b67f09SDavid van Moolenbroek 	printf("\n\nLaunch a query to find a RRset of type ");
4497*00b67f09SDavid van Moolenbroek 	print_type(type);
4498*00b67f09SDavid van Moolenbroek 	printf(" for zone: %s\n", lookup->textname);
4499*00b67f09SDavid van Moolenbroek 	return (NULL);
4500*00b67f09SDavid van Moolenbroek }
4501*00b67f09SDavid van Moolenbroek 
4502*00b67f09SDavid van Moolenbroek isc_result_t
insert_trustedkey(void * arg,dns_name_t * name,dns_rdataset_t * rdataset)4503*00b67f09SDavid van Moolenbroek insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
4504*00b67f09SDavid van Moolenbroek {
4505*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4506*00b67f09SDavid van Moolenbroek 	dst_key_t *key;
4507*00b67f09SDavid van Moolenbroek 
4508*00b67f09SDavid van Moolenbroek 	UNUSED(arg);
4509*00b67f09SDavid van Moolenbroek 
4510*00b67f09SDavid van Moolenbroek 	if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
4511*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
4512*00b67f09SDavid van Moolenbroek 
4513*00b67f09SDavid van Moolenbroek 	for (result = dns_rdataset_first(rdataset);
4514*00b67f09SDavid van Moolenbroek 	     result == ISC_R_SUCCESS;
4515*00b67f09SDavid van Moolenbroek 	     result = dns_rdataset_next(rdataset)) {
4516*00b67f09SDavid van Moolenbroek 		dns_rdata_t rdata = DNS_RDATA_INIT;
4517*00b67f09SDavid van Moolenbroek 		isc_buffer_t b;
4518*00b67f09SDavid van Moolenbroek 
4519*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(rdataset, &rdata);
4520*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&b, rdata.data, rdata.length);
4521*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&b, rdata.length);
4522*00b67f09SDavid van Moolenbroek 		if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
4523*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
4524*00b67f09SDavid van Moolenbroek 		key = NULL;
4525*00b67f09SDavid van Moolenbroek 		result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &key);
4526*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
4527*00b67f09SDavid van Moolenbroek 			continue;
4528*00b67f09SDavid van Moolenbroek 		tk_list.key[tk_list.nb_tk++] = key;
4529*00b67f09SDavid van Moolenbroek 	}
4530*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
4531*00b67f09SDavid van Moolenbroek }
4532*00b67f09SDavid van Moolenbroek 
4533*00b67f09SDavid van Moolenbroek void
clean_trustedkey()4534*00b67f09SDavid van Moolenbroek clean_trustedkey()
4535*00b67f09SDavid van Moolenbroek {
4536*00b67f09SDavid van Moolenbroek 	int i = 0;
4537*00b67f09SDavid van Moolenbroek 
4538*00b67f09SDavid van Moolenbroek 	for (i= 0; i < MAX_TRUSTED_KEY; i++) {
4539*00b67f09SDavid van Moolenbroek 		if (tk_list.key[i] != NULL) {
4540*00b67f09SDavid van Moolenbroek 			dst_key_free(&tk_list.key[i]);
4541*00b67f09SDavid van Moolenbroek 			tk_list.key[i] = NULL;
4542*00b67f09SDavid van Moolenbroek 		} else
4543*00b67f09SDavid van Moolenbroek 			break;
4544*00b67f09SDavid van Moolenbroek 	}
4545*00b67f09SDavid van Moolenbroek 	tk_list.nb_tk = 0;
4546*00b67f09SDavid van Moolenbroek 	return;
4547*00b67f09SDavid van Moolenbroek }
4548*00b67f09SDavid van Moolenbroek 
4549*00b67f09SDavid van Moolenbroek char alphnum[] =
4550*00b67f09SDavid van Moolenbroek 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4551*00b67f09SDavid van Moolenbroek 
4552*00b67f09SDavid van Moolenbroek isc_result_t
removetmpkey(isc_mem_t * mctx,const char * file)4553*00b67f09SDavid van Moolenbroek removetmpkey(isc_mem_t *mctx, const char *file)
4554*00b67f09SDavid van Moolenbroek {
4555*00b67f09SDavid van Moolenbroek 	char *tempnamekey = NULL;
4556*00b67f09SDavid van Moolenbroek 	int tempnamekeylen;
4557*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4558*00b67f09SDavid van Moolenbroek 
4559*00b67f09SDavid van Moolenbroek 	tempnamekeylen = strlen(file)+10;
4560*00b67f09SDavid van Moolenbroek 
4561*00b67f09SDavid van Moolenbroek 	tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4562*00b67f09SDavid van Moolenbroek 	if (tempnamekey == NULL)
4563*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
4564*00b67f09SDavid van Moolenbroek 
4565*00b67f09SDavid van Moolenbroek 	memset(tempnamekey, 0, tempnamekeylen);
4566*00b67f09SDavid van Moolenbroek 
4567*00b67f09SDavid van Moolenbroek 	strcat(tempnamekey, file);
4568*00b67f09SDavid van Moolenbroek 	strcat(tempnamekey,".key");
4569*00b67f09SDavid van Moolenbroek 	isc_file_remove(tempnamekey);
4570*00b67f09SDavid van Moolenbroek 
4571*00b67f09SDavid van Moolenbroek 	result = isc_file_remove(tempnamekey);
4572*00b67f09SDavid van Moolenbroek 	isc_mem_free(mctx, tempnamekey);
4573*00b67f09SDavid van Moolenbroek 	return (result);
4574*00b67f09SDavid van Moolenbroek }
4575*00b67f09SDavid van Moolenbroek 
4576*00b67f09SDavid van Moolenbroek isc_result_t
get_trusted_key(isc_mem_t * mctx)4577*00b67f09SDavid van Moolenbroek get_trusted_key(isc_mem_t *mctx)
4578*00b67f09SDavid van Moolenbroek {
4579*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4580*00b67f09SDavid van Moolenbroek 	const char *filename = NULL;
4581*00b67f09SDavid van Moolenbroek 	dns_rdatacallbacks_t callbacks;
4582*00b67f09SDavid van Moolenbroek 
4583*00b67f09SDavid van Moolenbroek 	result = isc_file_exists(trustedkey);
4584*00b67f09SDavid van Moolenbroek 	if (result !=  ISC_TRUE) {
4585*00b67f09SDavid van Moolenbroek 		result = isc_file_exists("/etc/trusted-key.key");
4586*00b67f09SDavid van Moolenbroek 		if (result !=  ISC_TRUE) {
4587*00b67f09SDavid van Moolenbroek 			result = isc_file_exists("./trusted-key.key");
4588*00b67f09SDavid van Moolenbroek 			if (result !=  ISC_TRUE)
4589*00b67f09SDavid van Moolenbroek 				return (ISC_R_FAILURE);
4590*00b67f09SDavid van Moolenbroek 			else
4591*00b67f09SDavid van Moolenbroek 				filename = "./trusted-key.key";
4592*00b67f09SDavid van Moolenbroek 		} else
4593*00b67f09SDavid van Moolenbroek 			filename = "/etc/trusted-key.key";
4594*00b67f09SDavid van Moolenbroek 	} else
4595*00b67f09SDavid van Moolenbroek 		filename = trustedkey;
4596*00b67f09SDavid van Moolenbroek 
4597*00b67f09SDavid van Moolenbroek 	if (filename == NULL) {
4598*00b67f09SDavid van Moolenbroek 		printf("No trusted key\n");
4599*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
4600*00b67f09SDavid van Moolenbroek 	}
4601*00b67f09SDavid van Moolenbroek 
4602*00b67f09SDavid van Moolenbroek 	dns_rdatacallbacks_init_stdio(&callbacks);
4603*00b67f09SDavid van Moolenbroek 	callbacks.add = insert_trustedkey;
4604*00b67f09SDavid van Moolenbroek 	return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
4605*00b67f09SDavid van Moolenbroek 				    current_lookup->rdclass, DNS_MASTER_NOTTL,
4606*00b67f09SDavid van Moolenbroek 				    &callbacks, mctx));
4607*00b67f09SDavid van Moolenbroek }
4608*00b67f09SDavid van Moolenbroek 
4609*00b67f09SDavid van Moolenbroek 
4610*00b67f09SDavid van Moolenbroek static void
nameFromString(const char * str,dns_name_t * p_ret)4611*00b67f09SDavid van Moolenbroek nameFromString(const char *str, dns_name_t *p_ret) {
4612*00b67f09SDavid van Moolenbroek 	size_t len = strlen(str);
4613*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4614*00b67f09SDavid van Moolenbroek 	isc_buffer_t buffer;
4615*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixedname;
4616*00b67f09SDavid van Moolenbroek 
4617*00b67f09SDavid van Moolenbroek 	REQUIRE(p_ret != NULL);
4618*00b67f09SDavid van Moolenbroek 	REQUIRE(str != NULL);
4619*00b67f09SDavid van Moolenbroek 
4620*00b67f09SDavid van Moolenbroek 	isc_buffer_constinit(&buffer, str, len);
4621*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&buffer, len);
4622*00b67f09SDavid van Moolenbroek 
4623*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixedname);
4624*00b67f09SDavid van Moolenbroek 	result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
4625*00b67f09SDavid van Moolenbroek 				   dns_rootname, DNS_NAME_DOWNCASE, NULL);
4626*00b67f09SDavid van Moolenbroek 	check_result(result, "nameFromString");
4627*00b67f09SDavid van Moolenbroek 
4628*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(p_ret))
4629*00b67f09SDavid van Moolenbroek 		free_name(p_ret, mctx);
4630*00b67f09SDavid van Moolenbroek 
4631*00b67f09SDavid van Moolenbroek 	result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
4632*00b67f09SDavid van Moolenbroek 	check_result(result, "nameFromString");
4633*00b67f09SDavid van Moolenbroek }
4634*00b67f09SDavid van Moolenbroek 
4635*00b67f09SDavid van Moolenbroek 
4636*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
4637*00b67f09SDavid van Moolenbroek isc_result_t
prepare_lookup(dns_name_t * name)4638*00b67f09SDavid van Moolenbroek prepare_lookup(dns_name_t *name)
4639*00b67f09SDavid van Moolenbroek {
4640*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4641*00b67f09SDavid van Moolenbroek 	dig_lookup_t *lookup = NULL;
4642*00b67f09SDavid van Moolenbroek 	dig_server_t *s;
4643*00b67f09SDavid van Moolenbroek 	void *ptr;
4644*00b67f09SDavid van Moolenbroek 
4645*00b67f09SDavid van Moolenbroek 	lookup = clone_lookup(current_lookup, ISC_TRUE);
4646*00b67f09SDavid van Moolenbroek 	lookup->trace_root = ISC_FALSE;
4647*00b67f09SDavid van Moolenbroek 	lookup->new_search = ISC_TRUE;
4648*00b67f09SDavid van Moolenbroek 	lookup->trace_root_sigchase = ISC_FALSE;
4649*00b67f09SDavid van Moolenbroek 
4650*00b67f09SDavid van Moolenbroek 	strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME);
4651*00b67f09SDavid van Moolenbroek 
4652*00b67f09SDavid van Moolenbroek 	lookup->rdtype = lookup->rdtype_sigchase;
4653*00b67f09SDavid van Moolenbroek 	lookup->rdtypeset = ISC_TRUE;
4654*00b67f09SDavid van Moolenbroek 	lookup->qrdtype = lookup->qrdtype_sigchase;
4655*00b67f09SDavid van Moolenbroek 
4656*00b67f09SDavid van Moolenbroek 	s = ISC_LIST_HEAD(lookup->my_server_list);
4657*00b67f09SDavid van Moolenbroek 	while (s != NULL) {
4658*00b67f09SDavid van Moolenbroek 		debug("freeing server %p belonging to %p",
4659*00b67f09SDavid van Moolenbroek 		      s, lookup);
4660*00b67f09SDavid van Moolenbroek 		ptr = s;
4661*00b67f09SDavid van Moolenbroek 		s = ISC_LIST_NEXT(s, link);
4662*00b67f09SDavid van Moolenbroek 		ISC_LIST_DEQUEUE(lookup->my_server_list,
4663*00b67f09SDavid van Moolenbroek 				 (dig_server_t *)ptr, link);
4664*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, ptr);
4665*00b67f09SDavid van Moolenbroek 	}
4666*00b67f09SDavid van Moolenbroek 
4667*00b67f09SDavid van Moolenbroek 
4668*00b67f09SDavid van Moolenbroek 	for (result = dns_rdataset_first(chase_nsrdataset);
4669*00b67f09SDavid van Moolenbroek 	     result == ISC_R_SUCCESS;
4670*00b67f09SDavid van Moolenbroek 	     result = dns_rdataset_next(chase_nsrdataset)) {
4671*00b67f09SDavid van Moolenbroek 		char namestr[DNS_NAME_FORMATSIZE];
4672*00b67f09SDavid van Moolenbroek 		dns_rdata_ns_t ns;
4673*00b67f09SDavid van Moolenbroek 		dns_rdata_t rdata = DNS_RDATA_INIT;
4674*00b67f09SDavid van Moolenbroek 		dig_server_t * srv = NULL;
4675*00b67f09SDavid van Moolenbroek #define __FOLLOW_GLUE__
4676*00b67f09SDavid van Moolenbroek #ifdef __FOLLOW_GLUE__
4677*00b67f09SDavid van Moolenbroek 		isc_buffer_t *b = NULL;
4678*00b67f09SDavid van Moolenbroek 		isc_result_t result;
4679*00b67f09SDavid van Moolenbroek 		isc_region_t r;
4680*00b67f09SDavid van Moolenbroek 		dns_rdataset_t *rdataset = NULL;
4681*00b67f09SDavid van Moolenbroek 		isc_boolean_t true = ISC_TRUE;
4682*00b67f09SDavid van Moolenbroek #endif
4683*00b67f09SDavid van Moolenbroek 
4684*00b67f09SDavid van Moolenbroek 		memset(namestr, 0, DNS_NAME_FORMATSIZE);
4685*00b67f09SDavid van Moolenbroek 
4686*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(chase_nsrdataset, &rdata);
4687*00b67f09SDavid van Moolenbroek 
4688*00b67f09SDavid van Moolenbroek 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
4689*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_rdata_tostruct");
4690*00b67f09SDavid van Moolenbroek 
4691*00b67f09SDavid van Moolenbroek #ifdef __FOLLOW_GLUE__
4692*00b67f09SDavid van Moolenbroek 
4693*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&rdataset, &ns.name,
4694*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_aaaa,
4695*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_any, &true);
4696*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
4697*00b67f09SDavid van Moolenbroek 			for (result = dns_rdataset_first(rdataset);
4698*00b67f09SDavid van Moolenbroek 			     result == ISC_R_SUCCESS;
4699*00b67f09SDavid van Moolenbroek 			     result = dns_rdataset_next(rdataset)) {
4700*00b67f09SDavid van Moolenbroek 				dns_rdata_t aaaa = DNS_RDATA_INIT;
4701*00b67f09SDavid van Moolenbroek 				dns_rdataset_current(rdataset, &aaaa);
4702*00b67f09SDavid van Moolenbroek 
4703*00b67f09SDavid van Moolenbroek 				result = isc_buffer_allocate(mctx, &b, 80);
4704*00b67f09SDavid van Moolenbroek 				check_result(result, "isc_buffer_allocate");
4705*00b67f09SDavid van Moolenbroek 
4706*00b67f09SDavid van Moolenbroek 				dns_rdata_totext(&aaaa, &ns.name, b);
4707*00b67f09SDavid van Moolenbroek 				isc_buffer_usedregion(b, &r);
4708*00b67f09SDavid van Moolenbroek 				r.base[r.length] = '\0';
4709*00b67f09SDavid van Moolenbroek 				strlcpy(namestr, (char*)r.base,
4710*00b67f09SDavid van Moolenbroek 					DNS_NAME_FORMATSIZE);
4711*00b67f09SDavid van Moolenbroek 				isc_buffer_free(&b);
4712*00b67f09SDavid van Moolenbroek 				dns_rdata_reset(&aaaa);
4713*00b67f09SDavid van Moolenbroek 
4714*00b67f09SDavid van Moolenbroek 
4715*00b67f09SDavid van Moolenbroek 				srv = make_server(namestr, namestr);
4716*00b67f09SDavid van Moolenbroek 
4717*00b67f09SDavid van Moolenbroek 				ISC_LIST_APPEND(lookup->my_server_list,
4718*00b67f09SDavid van Moolenbroek 						srv, link);
4719*00b67f09SDavid van Moolenbroek 			}
4720*00b67f09SDavid van Moolenbroek 		}
4721*00b67f09SDavid van Moolenbroek 
4722*00b67f09SDavid van Moolenbroek 		rdataset = NULL;
4723*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
4724*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_any, &true);
4725*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
4726*00b67f09SDavid van Moolenbroek 			for (result = dns_rdataset_first(rdataset);
4727*00b67f09SDavid van Moolenbroek 			     result == ISC_R_SUCCESS;
4728*00b67f09SDavid van Moolenbroek 			     result = dns_rdataset_next(rdataset)) {
4729*00b67f09SDavid van Moolenbroek 				dns_rdata_t a = DNS_RDATA_INIT;
4730*00b67f09SDavid van Moolenbroek 				dns_rdataset_current(rdataset, &a);
4731*00b67f09SDavid van Moolenbroek 
4732*00b67f09SDavid van Moolenbroek 				result = isc_buffer_allocate(mctx, &b, 80);
4733*00b67f09SDavid van Moolenbroek 				check_result(result, "isc_buffer_allocate");
4734*00b67f09SDavid van Moolenbroek 
4735*00b67f09SDavid van Moolenbroek 				dns_rdata_totext(&a, &ns.name, b);
4736*00b67f09SDavid van Moolenbroek 				isc_buffer_usedregion(b, &r);
4737*00b67f09SDavid van Moolenbroek 				r.base[r.length] = '\0';
4738*00b67f09SDavid van Moolenbroek 				strlcpy(namestr, (char*)r.base,
4739*00b67f09SDavid van Moolenbroek 					DNS_NAME_FORMATSIZE);
4740*00b67f09SDavid van Moolenbroek 				isc_buffer_free(&b);
4741*00b67f09SDavid van Moolenbroek 				dns_rdata_reset(&a);
4742*00b67f09SDavid van Moolenbroek 				printf("ns name: %s\n", namestr);
4743*00b67f09SDavid van Moolenbroek 
4744*00b67f09SDavid van Moolenbroek 
4745*00b67f09SDavid van Moolenbroek 				srv = make_server(namestr, namestr);
4746*00b67f09SDavid van Moolenbroek 
4747*00b67f09SDavid van Moolenbroek 				ISC_LIST_APPEND(lookup->my_server_list,
4748*00b67f09SDavid van Moolenbroek 						srv, link);
4749*00b67f09SDavid van Moolenbroek 			}
4750*00b67f09SDavid van Moolenbroek 		}
4751*00b67f09SDavid van Moolenbroek #else
4752*00b67f09SDavid van Moolenbroek 
4753*00b67f09SDavid van Moolenbroek 		dns_name_format(&ns.name, namestr, sizeof(namestr));
4754*00b67f09SDavid van Moolenbroek 		printf("ns name: ");
4755*00b67f09SDavid van Moolenbroek 		dns_name_print(&ns.name, stdout);
4756*00b67f09SDavid van Moolenbroek 		printf("\n");
4757*00b67f09SDavid van Moolenbroek 		srv = make_server(namestr, namestr);
4758*00b67f09SDavid van Moolenbroek 
4759*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(lookup->my_server_list, srv, link);
4760*00b67f09SDavid van Moolenbroek 
4761*00b67f09SDavid van Moolenbroek #endif
4762*00b67f09SDavid van Moolenbroek 		dns_rdata_freestruct(&ns);
4763*00b67f09SDavid van Moolenbroek 		dns_rdata_reset(&rdata);
4764*00b67f09SDavid van Moolenbroek 
4765*00b67f09SDavid van Moolenbroek 	}
4766*00b67f09SDavid van Moolenbroek 
4767*00b67f09SDavid van Moolenbroek 	ISC_LIST_APPEND(lookup_list, lookup, link);
4768*00b67f09SDavid van Moolenbroek 	printf("\nLaunch a query to find a RRset of type ");
4769*00b67f09SDavid van Moolenbroek 	print_type(lookup->rdtype);
4770*00b67f09SDavid van Moolenbroek 	printf(" for zone: %s", lookup->textname);
4771*00b67f09SDavid van Moolenbroek 	printf(" with nameservers:");
4772*00b67f09SDavid van Moolenbroek 	printf("\n");
4773*00b67f09SDavid van Moolenbroek 	print_rdataset(name, chase_nsrdataset, mctx);
4774*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
4775*00b67f09SDavid van Moolenbroek }
4776*00b67f09SDavid van Moolenbroek 
4777*00b67f09SDavid van Moolenbroek 
4778*00b67f09SDavid van Moolenbroek isc_result_t
child_of_zone(dns_name_t * name,dns_name_t * zone_name,dns_name_t * child_name)4779*00b67f09SDavid van Moolenbroek child_of_zone(dns_name_t * name, dns_name_t * zone_name,
4780*00b67f09SDavid van Moolenbroek 	      dns_name_t * child_name)
4781*00b67f09SDavid van Moolenbroek {
4782*00b67f09SDavid van Moolenbroek 	dns_namereln_t name_reln;
4783*00b67f09SDavid van Moolenbroek 	int orderp;
4784*00b67f09SDavid van Moolenbroek 	unsigned int nlabelsp;
4785*00b67f09SDavid van Moolenbroek 
4786*00b67f09SDavid van Moolenbroek 	name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
4787*00b67f09SDavid van Moolenbroek 	if (name_reln != dns_namereln_subdomain ||
4788*00b67f09SDavid van Moolenbroek 	    dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
4789*00b67f09SDavid van Moolenbroek 		printf("\n;; ERROR : ");
4790*00b67f09SDavid van Moolenbroek 		dns_name_print(name, stdout);
4791*00b67f09SDavid van Moolenbroek 		printf(" is not a subdomain of: ");
4792*00b67f09SDavid van Moolenbroek 		dns_name_print(zone_name, stdout);
4793*00b67f09SDavid van Moolenbroek 		printf(" FAILED\n\n");
4794*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
4795*00b67f09SDavid van Moolenbroek 	}
4796*00b67f09SDavid van Moolenbroek 
4797*00b67f09SDavid van Moolenbroek 	dns_name_getlabelsequence(name,
4798*00b67f09SDavid van Moolenbroek 				  dns_name_countlabels(name) -
4799*00b67f09SDavid van Moolenbroek 				  dns_name_countlabels(zone_name) -1,
4800*00b67f09SDavid van Moolenbroek 				  dns_name_countlabels(zone_name) +1,
4801*00b67f09SDavid van Moolenbroek 				  child_name);
4802*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
4803*00b67f09SDavid van Moolenbroek }
4804*00b67f09SDavid van Moolenbroek 
4805*00b67f09SDavid van Moolenbroek isc_result_t
grandfather_pb_test(dns_name_t * zone_name,dns_rdataset_t * sigrdataset)4806*00b67f09SDavid van Moolenbroek grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t  *sigrdataset) {
4807*00b67f09SDavid van Moolenbroek 	dns_rdata_sig_t siginfo;
4808*00b67f09SDavid van Moolenbroek 	dns_rdataset_t mysigrdataset;
4809*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4810*00b67f09SDavid van Moolenbroek 
4811*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&mysigrdataset);
4812*00b67f09SDavid van Moolenbroek 	dns_rdataset_clone(sigrdataset, &mysigrdataset);
4813*00b67f09SDavid van Moolenbroek 
4814*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(&mysigrdataset);
4815*00b67f09SDavid van Moolenbroek 	check_result(result, "empty RRSIG dataset");
4816*00b67f09SDavid van Moolenbroek 
4817*00b67f09SDavid van Moolenbroek 	do {
4818*00b67f09SDavid van Moolenbroek 		dns_rdata_t sigrdata = DNS_RDATA_INIT;
4819*00b67f09SDavid van Moolenbroek 
4820*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(&mysigrdataset, &sigrdata);
4821*00b67f09SDavid van Moolenbroek 
4822*00b67f09SDavid van Moolenbroek 		result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4823*00b67f09SDavid van Moolenbroek 		check_result(result, "sigrdata tostruct siginfo");
4824*00b67f09SDavid van Moolenbroek 
4825*00b67f09SDavid van Moolenbroek 		if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
4826*00b67f09SDavid van Moolenbroek 			result = ISC_R_SUCCESS;
4827*00b67f09SDavid van Moolenbroek 			goto cleanup;
4828*00b67f09SDavid van Moolenbroek 		}
4829*00b67f09SDavid van Moolenbroek 	} while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
4830*00b67f09SDavid van Moolenbroek 
4831*00b67f09SDavid van Moolenbroek 	result = ISC_R_FAILURE;
4832*00b67f09SDavid van Moolenbroek cleanup:
4833*00b67f09SDavid van Moolenbroek 	dns_rdataset_disassociate(&mysigrdataset);
4834*00b67f09SDavid van Moolenbroek 
4835*00b67f09SDavid van Moolenbroek 	return (result);
4836*00b67f09SDavid van Moolenbroek }
4837*00b67f09SDavid van Moolenbroek 
4838*00b67f09SDavid van Moolenbroek 
4839*00b67f09SDavid van Moolenbroek isc_result_t
initialization(dns_name_t * name)4840*00b67f09SDavid van Moolenbroek initialization(dns_name_t *name)
4841*00b67f09SDavid van Moolenbroek {
4842*00b67f09SDavid van Moolenbroek 	isc_result_t   result;
4843*00b67f09SDavid van Moolenbroek 	isc_boolean_t  true = ISC_TRUE;
4844*00b67f09SDavid van Moolenbroek 
4845*00b67f09SDavid van Moolenbroek 	chase_nsrdataset = NULL;
4846*00b67f09SDavid van Moolenbroek 	result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
4847*00b67f09SDavid van Moolenbroek 				   dns_rdatatype_any, &true);
4848*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
4849*00b67f09SDavid van Moolenbroek 		printf("\n;; NS RRset is missing to continue validation:"
4850*00b67f09SDavid van Moolenbroek 		       " FAILED\n\n");
4851*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
4852*00b67f09SDavid van Moolenbroek 	}
4853*00b67f09SDavid van Moolenbroek 	INSIST(chase_nsrdataset != NULL);
4854*00b67f09SDavid van Moolenbroek 	prepare_lookup(name);
4855*00b67f09SDavid van Moolenbroek 
4856*00b67f09SDavid van Moolenbroek 	dup_name(name, &chase_current_name, mctx);
4857*00b67f09SDavid van Moolenbroek 
4858*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
4859*00b67f09SDavid van Moolenbroek }
4860*00b67f09SDavid van Moolenbroek #endif
4861*00b67f09SDavid van Moolenbroek 
4862*00b67f09SDavid van Moolenbroek void
print_rdataset(dns_name_t * name,dns_rdataset_t * rdataset,isc_mem_t * mctx)4863*00b67f09SDavid van Moolenbroek print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
4864*00b67f09SDavid van Moolenbroek {
4865*00b67f09SDavid van Moolenbroek 	isc_buffer_t *b = NULL;
4866*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4867*00b67f09SDavid van Moolenbroek 	isc_region_t r;
4868*00b67f09SDavid van Moolenbroek 
4869*00b67f09SDavid van Moolenbroek 	result = isc_buffer_allocate(mctx, &b, 9000);
4870*00b67f09SDavid van Moolenbroek 	check_result(result, "isc_buffer_allocate");
4871*00b67f09SDavid van Moolenbroek 
4872*00b67f09SDavid van Moolenbroek 	printrdataset(name, rdataset, b);
4873*00b67f09SDavid van Moolenbroek 
4874*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(b, &r);
4875*00b67f09SDavid van Moolenbroek 	r.base[r.length] = '\0';
4876*00b67f09SDavid van Moolenbroek 
4877*00b67f09SDavid van Moolenbroek 
4878*00b67f09SDavid van Moolenbroek 	printf("%s\n", r.base);
4879*00b67f09SDavid van Moolenbroek 
4880*00b67f09SDavid van Moolenbroek 	isc_buffer_free(&b);
4881*00b67f09SDavid van Moolenbroek }
4882*00b67f09SDavid van Moolenbroek 
4883*00b67f09SDavid van Moolenbroek 
4884*00b67f09SDavid van Moolenbroek void
dup_name(dns_name_t * source,dns_name_t * target,isc_mem_t * mctx)4885*00b67f09SDavid van Moolenbroek dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) {
4886*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4887*00b67f09SDavid van Moolenbroek 
4888*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(target))
4889*00b67f09SDavid van Moolenbroek 		free_name(target, mctx);
4890*00b67f09SDavid van Moolenbroek 	result = dns_name_dup(source, mctx, target);
4891*00b67f09SDavid van Moolenbroek 	check_result(result, "dns_name_dup");
4892*00b67f09SDavid van Moolenbroek }
4893*00b67f09SDavid van Moolenbroek 
4894*00b67f09SDavid van Moolenbroek void
free_name(dns_name_t * name,isc_mem_t * mctx)4895*00b67f09SDavid van Moolenbroek free_name(dns_name_t *name, isc_mem_t *mctx) {
4896*00b67f09SDavid van Moolenbroek 	dns_name_free(name, mctx);
4897*00b67f09SDavid van Moolenbroek 	dns_name_init(name, NULL);
4898*00b67f09SDavid van Moolenbroek }
4899*00b67f09SDavid van Moolenbroek 
4900*00b67f09SDavid van Moolenbroek /*
4901*00b67f09SDavid van Moolenbroek  *
4902*00b67f09SDavid van Moolenbroek  * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4903*00b67f09SDavid van Moolenbroek  * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4904*00b67f09SDavid van Moolenbroek  * 			and the RRset is valid
4905*00b67f09SDavid van Moolenbroek  * return ISC_R_NOTFOUND if not contains trusted key
4906*00b67f09SDavid van Moolenbroek 			or if the RRset isn't valid
4907*00b67f09SDavid van Moolenbroek  * return ISC_R_FAILURE if problem
4908*00b67f09SDavid van Moolenbroek  *
4909*00b67f09SDavid van Moolenbroek  */
4910*00b67f09SDavid van Moolenbroek isc_result_t
contains_trusted_key(dns_name_t * name,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,isc_mem_t * mctx)4911*00b67f09SDavid van Moolenbroek contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
4912*00b67f09SDavid van Moolenbroek 		     dns_rdataset_t *sigrdataset,
4913*00b67f09SDavid van Moolenbroek 		     isc_mem_t *mctx)
4914*00b67f09SDavid van Moolenbroek {
4915*00b67f09SDavid van Moolenbroek 	dns_rdataset_t myrdataset;
4916*00b67f09SDavid van Moolenbroek 	dst_key_t *dnsseckey = NULL;
4917*00b67f09SDavid van Moolenbroek 	int i;
4918*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4919*00b67f09SDavid van Moolenbroek 
4920*00b67f09SDavid van Moolenbroek 	if (name == NULL || rdataset == NULL)
4921*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
4922*00b67f09SDavid van Moolenbroek 
4923*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&myrdataset);
4924*00b67f09SDavid van Moolenbroek 	dns_rdataset_clone(rdataset, &myrdataset);
4925*00b67f09SDavid van Moolenbroek 
4926*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(&myrdataset);
4927*00b67f09SDavid van Moolenbroek 	check_result(result, "empty rdataset");
4928*00b67f09SDavid van Moolenbroek 
4929*00b67f09SDavid van Moolenbroek 	do {
4930*00b67f09SDavid van Moolenbroek 		dns_rdata_t rdata = DNS_RDATA_INIT;
4931*00b67f09SDavid van Moolenbroek 
4932*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(&myrdataset, &rdata);
4933*00b67f09SDavid van Moolenbroek 		INSIST(rdata.type == dns_rdatatype_dnskey);
4934*00b67f09SDavid van Moolenbroek 
4935*00b67f09SDavid van Moolenbroek 		result = dns_dnssec_keyfromrdata(name, &rdata,
4936*00b67f09SDavid van Moolenbroek 						 mctx, &dnsseckey);
4937*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_dnssec_keyfromrdata");
4938*00b67f09SDavid van Moolenbroek 
4939*00b67f09SDavid van Moolenbroek 		for (i = 0; i < tk_list.nb_tk; i++) {
4940*00b67f09SDavid van Moolenbroek 			if (dst_key_compare(tk_list.key[i], dnsseckey)
4941*00b67f09SDavid van Moolenbroek 			    == ISC_TRUE) {
4942*00b67f09SDavid van Moolenbroek 				dns_rdata_reset(&rdata);
4943*00b67f09SDavid van Moolenbroek 
4944*00b67f09SDavid van Moolenbroek 				printf(";; Ok, find a Trusted Key in the "
4945*00b67f09SDavid van Moolenbroek 				       "DNSKEY RRset: %d\n",
4946*00b67f09SDavid van Moolenbroek 				       dst_key_id(dnsseckey));
4947*00b67f09SDavid van Moolenbroek 				result = sigchase_verify_sig_key(name, rdataset,
4948*00b67f09SDavid van Moolenbroek 								 dnsseckey,
4949*00b67f09SDavid van Moolenbroek 								 sigrdataset,
4950*00b67f09SDavid van Moolenbroek 								 mctx);
4951*00b67f09SDavid van Moolenbroek 				if (result == ISC_R_SUCCESS)
4952*00b67f09SDavid van Moolenbroek 					goto cleanup;
4953*00b67f09SDavid van Moolenbroek 			}
4954*00b67f09SDavid van Moolenbroek 		}
4955*00b67f09SDavid van Moolenbroek 		dst_key_free(&dnsseckey);
4956*00b67f09SDavid van Moolenbroek 	} while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS);
4957*00b67f09SDavid van Moolenbroek 
4958*00b67f09SDavid van Moolenbroek cleanup:
4959*00b67f09SDavid van Moolenbroek 	if (dnsseckey != NULL)
4960*00b67f09SDavid van Moolenbroek 		dst_key_free(&dnsseckey);
4961*00b67f09SDavid van Moolenbroek 	dns_rdataset_disassociate(&myrdataset);
4962*00b67f09SDavid van Moolenbroek 
4963*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTFOUND);
4964*00b67f09SDavid van Moolenbroek }
4965*00b67f09SDavid van Moolenbroek 
4966*00b67f09SDavid van Moolenbroek isc_result_t
sigchase_verify_sig(dns_name_t * name,dns_rdataset_t * rdataset,dns_rdataset_t * keyrdataset,dns_rdataset_t * sigrdataset,isc_mem_t * mctx)4967*00b67f09SDavid van Moolenbroek sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
4968*00b67f09SDavid van Moolenbroek 		    dns_rdataset_t *keyrdataset,
4969*00b67f09SDavid van Moolenbroek 		    dns_rdataset_t *sigrdataset,
4970*00b67f09SDavid van Moolenbroek 		    isc_mem_t *mctx)
4971*00b67f09SDavid van Moolenbroek {
4972*00b67f09SDavid van Moolenbroek 	dns_rdataset_t mykeyrdataset;
4973*00b67f09SDavid van Moolenbroek 	dst_key_t *dnsseckey = NULL;
4974*00b67f09SDavid van Moolenbroek 	isc_result_t result;
4975*00b67f09SDavid van Moolenbroek 
4976*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&mykeyrdataset);
4977*00b67f09SDavid van Moolenbroek 	dns_rdataset_clone(keyrdataset, &mykeyrdataset);
4978*00b67f09SDavid van Moolenbroek 
4979*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(&mykeyrdataset);
4980*00b67f09SDavid van Moolenbroek 	check_result(result, "empty DNSKEY dataset");
4981*00b67f09SDavid van Moolenbroek 
4982*00b67f09SDavid van Moolenbroek 	do {
4983*00b67f09SDavid van Moolenbroek 		dns_rdata_t keyrdata = DNS_RDATA_INIT;
4984*00b67f09SDavid van Moolenbroek 
4985*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(&mykeyrdataset, &keyrdata);
4986*00b67f09SDavid van Moolenbroek 		INSIST(keyrdata.type == dns_rdatatype_dnskey);
4987*00b67f09SDavid van Moolenbroek 
4988*00b67f09SDavid van Moolenbroek 		result = dns_dnssec_keyfromrdata(name, &keyrdata,
4989*00b67f09SDavid van Moolenbroek 						 mctx, &dnsseckey);
4990*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_dnssec_keyfromrdata");
4991*00b67f09SDavid van Moolenbroek 
4992*00b67f09SDavid van Moolenbroek 		result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
4993*00b67f09SDavid van Moolenbroek 						 sigrdataset, mctx);
4994*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS)
4995*00b67f09SDavid van Moolenbroek 			goto cleanup;
4996*00b67f09SDavid van Moolenbroek 		dst_key_free(&dnsseckey);
4997*00b67f09SDavid van Moolenbroek 	} while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
4998*00b67f09SDavid van Moolenbroek 
4999*00b67f09SDavid van Moolenbroek 	result = ISC_R_NOTFOUND;
5000*00b67f09SDavid van Moolenbroek 
5001*00b67f09SDavid van Moolenbroek  cleanup:
5002*00b67f09SDavid van Moolenbroek 	if (dnsseckey != NULL)
5003*00b67f09SDavid van Moolenbroek 		dst_key_free(&dnsseckey);
5004*00b67f09SDavid van Moolenbroek 	dns_rdataset_disassociate(&mykeyrdataset);
5005*00b67f09SDavid van Moolenbroek 
5006*00b67f09SDavid van Moolenbroek 	return (result);
5007*00b67f09SDavid van Moolenbroek }
5008*00b67f09SDavid van Moolenbroek 
5009*00b67f09SDavid van Moolenbroek isc_result_t
sigchase_verify_sig_key(dns_name_t * name,dns_rdataset_t * rdataset,dst_key_t * dnsseckey,dns_rdataset_t * sigrdataset,isc_mem_t * mctx)5010*00b67f09SDavid van Moolenbroek sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
5011*00b67f09SDavid van Moolenbroek 			dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
5012*00b67f09SDavid van Moolenbroek 			isc_mem_t *mctx)
5013*00b67f09SDavid van Moolenbroek {
5014*00b67f09SDavid van Moolenbroek 	dns_rdata_sig_t siginfo;
5015*00b67f09SDavid van Moolenbroek 	dns_rdataset_t myrdataset;
5016*00b67f09SDavid van Moolenbroek 	dns_rdataset_t mysigrdataset;
5017*00b67f09SDavid van Moolenbroek 	isc_result_t result;
5018*00b67f09SDavid van Moolenbroek 
5019*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&myrdataset);
5020*00b67f09SDavid van Moolenbroek 	dns_rdataset_clone(rdataset, &myrdataset);
5021*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&mysigrdataset);
5022*00b67f09SDavid van Moolenbroek 	dns_rdataset_clone(sigrdataset, &mysigrdataset);
5023*00b67f09SDavid van Moolenbroek 
5024*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(&mysigrdataset);
5025*00b67f09SDavid van Moolenbroek 	check_result(result, "empty RRSIG dataset");
5026*00b67f09SDavid van Moolenbroek 
5027*00b67f09SDavid van Moolenbroek 	do {
5028*00b67f09SDavid van Moolenbroek 		dns_rdata_t sigrdata = DNS_RDATA_INIT;
5029*00b67f09SDavid van Moolenbroek 
5030*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(&mysigrdataset, &sigrdata);
5031*00b67f09SDavid van Moolenbroek 
5032*00b67f09SDavid van Moolenbroek 		result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
5033*00b67f09SDavid van Moolenbroek 		check_result(result, "sigrdata tostruct siginfo");
5034*00b67f09SDavid van Moolenbroek 
5035*00b67f09SDavid van Moolenbroek 		/*
5036*00b67f09SDavid van Moolenbroek 		 * Test if the id of the DNSKEY is
5037*00b67f09SDavid van Moolenbroek 		 * the id of the DNSKEY signer's
5038*00b67f09SDavid van Moolenbroek 		 */
5039*00b67f09SDavid van Moolenbroek 		if (siginfo.keyid == dst_key_id(dnsseckey)) {
5040*00b67f09SDavid van Moolenbroek 
5041*00b67f09SDavid van Moolenbroek 			result = dns_rdataset_first(&myrdataset);
5042*00b67f09SDavid van Moolenbroek 			check_result(result, "empty DS dataset");
5043*00b67f09SDavid van Moolenbroek 
5044*00b67f09SDavid van Moolenbroek 			result = dns_dnssec_verify(name, &myrdataset, dnsseckey,
5045*00b67f09SDavid van Moolenbroek 						   ISC_FALSE, mctx, &sigrdata);
5046*00b67f09SDavid van Moolenbroek 
5047*00b67f09SDavid van Moolenbroek 			printf(";; VERIFYING ");
5048*00b67f09SDavid van Moolenbroek 			print_type(rdataset->type);
5049*00b67f09SDavid van Moolenbroek 			printf(" RRset for ");
5050*00b67f09SDavid van Moolenbroek 			dns_name_print(name, stdout);
5051*00b67f09SDavid van Moolenbroek 			printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
5052*00b67f09SDavid van Moolenbroek 			       isc_result_totext(result));
5053*00b67f09SDavid van Moolenbroek 
5054*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS)
5055*00b67f09SDavid van Moolenbroek 				goto cleanup;
5056*00b67f09SDavid van Moolenbroek 		}
5057*00b67f09SDavid van Moolenbroek 	} while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
5058*00b67f09SDavid van Moolenbroek 
5059*00b67f09SDavid van Moolenbroek 	result = ISC_R_NOTFOUND;
5060*00b67f09SDavid van Moolenbroek 
5061*00b67f09SDavid van Moolenbroek  cleanup:
5062*00b67f09SDavid van Moolenbroek 	dns_rdataset_disassociate(&myrdataset);
5063*00b67f09SDavid van Moolenbroek 	dns_rdataset_disassociate(&mysigrdataset);
5064*00b67f09SDavid van Moolenbroek 
5065*00b67f09SDavid van Moolenbroek 	return (result);
5066*00b67f09SDavid van Moolenbroek }
5067*00b67f09SDavid van Moolenbroek 
5068*00b67f09SDavid van Moolenbroek 
5069*00b67f09SDavid van Moolenbroek isc_result_t
sigchase_verify_ds(dns_name_t * name,dns_rdataset_t * keyrdataset,dns_rdataset_t * dsrdataset,isc_mem_t * mctx)5070*00b67f09SDavid van Moolenbroek sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
5071*00b67f09SDavid van Moolenbroek 		   dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
5072*00b67f09SDavid van Moolenbroek {
5073*00b67f09SDavid van Moolenbroek 	dns_rdata_ds_t dsinfo;
5074*00b67f09SDavid van Moolenbroek 	dns_rdataset_t mydsrdataset;
5075*00b67f09SDavid van Moolenbroek 	dns_rdataset_t mykeyrdataset;
5076*00b67f09SDavid van Moolenbroek 	dst_key_t *dnsseckey = NULL;
5077*00b67f09SDavid van Moolenbroek 	isc_result_t result;
5078*00b67f09SDavid van Moolenbroek 	unsigned char dsbuf[DNS_DS_BUFFERSIZE];
5079*00b67f09SDavid van Moolenbroek 
5080*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&mydsrdataset);
5081*00b67f09SDavid van Moolenbroek 	dns_rdataset_clone(dsrdataset, &mydsrdataset);
5082*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&mykeyrdataset);
5083*00b67f09SDavid van Moolenbroek 	dns_rdataset_clone(keyrdataset, &mykeyrdataset);
5084*00b67f09SDavid van Moolenbroek 
5085*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(&mydsrdataset);
5086*00b67f09SDavid van Moolenbroek 	check_result(result, "empty DSset dataset");
5087*00b67f09SDavid van Moolenbroek 	do {
5088*00b67f09SDavid van Moolenbroek 		dns_rdata_t dsrdata = DNS_RDATA_INIT;
5089*00b67f09SDavid van Moolenbroek 
5090*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(&mydsrdataset, &dsrdata);
5091*00b67f09SDavid van Moolenbroek 
5092*00b67f09SDavid van Moolenbroek 		result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
5093*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_rdata_tostruct for DS");
5094*00b67f09SDavid van Moolenbroek 
5095*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_first(&mykeyrdataset);
5096*00b67f09SDavid van Moolenbroek 		check_result(result, "empty KEY dataset");
5097*00b67f09SDavid van Moolenbroek 
5098*00b67f09SDavid van Moolenbroek 		do {
5099*00b67f09SDavid van Moolenbroek 			dns_rdata_t keyrdata = DNS_RDATA_INIT;
5100*00b67f09SDavid van Moolenbroek 
5101*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(&mykeyrdataset, &keyrdata);
5102*00b67f09SDavid van Moolenbroek 			INSIST(keyrdata.type == dns_rdatatype_dnskey);
5103*00b67f09SDavid van Moolenbroek 
5104*00b67f09SDavid van Moolenbroek 			result = dns_dnssec_keyfromrdata(name, &keyrdata,
5105*00b67f09SDavid van Moolenbroek 							 mctx, &dnsseckey);
5106*00b67f09SDavid van Moolenbroek 			check_result(result, "dns_dnssec_keyfromrdata");
5107*00b67f09SDavid van Moolenbroek 
5108*00b67f09SDavid van Moolenbroek 			/*
5109*00b67f09SDavid van Moolenbroek 			 * Test if the id of the DNSKEY is the
5110*00b67f09SDavid van Moolenbroek 			 * id of DNSKEY referenced by the DS
5111*00b67f09SDavid van Moolenbroek 			 */
5112*00b67f09SDavid van Moolenbroek 			if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
5113*00b67f09SDavid van Moolenbroek 				dns_rdata_t newdsrdata = DNS_RDATA_INIT;
5114*00b67f09SDavid van Moolenbroek 
5115*00b67f09SDavid van Moolenbroek 				result = dns_ds_buildrdata(name, &keyrdata,
5116*00b67f09SDavid van Moolenbroek 							   dsinfo.digest_type,
5117*00b67f09SDavid van Moolenbroek 							   dsbuf, &newdsrdata);
5118*00b67f09SDavid van Moolenbroek 				dns_rdata_freestruct(&dsinfo);
5119*00b67f09SDavid van Moolenbroek 
5120*00b67f09SDavid van Moolenbroek 				if (result != ISC_R_SUCCESS) {
5121*00b67f09SDavid van Moolenbroek 					printf("Oops: impossible to build"
5122*00b67f09SDavid van Moolenbroek 					       " new DS rdata\n");
5123*00b67f09SDavid van Moolenbroek 					goto cleanup;
5124*00b67f09SDavid van Moolenbroek 				}
5125*00b67f09SDavid van Moolenbroek 
5126*00b67f09SDavid van Moolenbroek 
5127*00b67f09SDavid van Moolenbroek 				if (dns_rdata_compare(&dsrdata,
5128*00b67f09SDavid van Moolenbroek 						      &newdsrdata) == 0) {
5129*00b67f09SDavid van Moolenbroek 					printf(";; OK a DS valids a DNSKEY"
5130*00b67f09SDavid van Moolenbroek 					       " in the RRset\n");
5131*00b67f09SDavid van Moolenbroek 					printf(";; Now verify that this"
5132*00b67f09SDavid van Moolenbroek 					       " DNSKEY validates the "
5133*00b67f09SDavid van Moolenbroek 					       "DNSKEY RRset\n");
5134*00b67f09SDavid van Moolenbroek 
5135*00b67f09SDavid van Moolenbroek 					result = sigchase_verify_sig_key(name,
5136*00b67f09SDavid van Moolenbroek 							 keyrdataset,
5137*00b67f09SDavid van Moolenbroek 							 dnsseckey,
5138*00b67f09SDavid van Moolenbroek 							 chase_sigkeyrdataset,
5139*00b67f09SDavid van Moolenbroek 							 mctx);
5140*00b67f09SDavid van Moolenbroek 					if (result ==  ISC_R_SUCCESS)
5141*00b67f09SDavid van Moolenbroek 						goto cleanup;
5142*00b67f09SDavid van Moolenbroek 				} else {
5143*00b67f09SDavid van Moolenbroek 					printf(";; This DS is NOT the DS for"
5144*00b67f09SDavid van Moolenbroek 					       " the chasing KEY: FAILED\n");
5145*00b67f09SDavid van Moolenbroek 				}
5146*00b67f09SDavid van Moolenbroek 			}
5147*00b67f09SDavid van Moolenbroek 			dst_key_free(&dnsseckey);
5148*00b67f09SDavid van Moolenbroek 		} while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
5149*00b67f09SDavid van Moolenbroek 	} while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS);
5150*00b67f09SDavid van Moolenbroek 
5151*00b67f09SDavid van Moolenbroek 	result = ISC_R_NOTFOUND;
5152*00b67f09SDavid van Moolenbroek 
5153*00b67f09SDavid van Moolenbroek  cleanup:
5154*00b67f09SDavid van Moolenbroek 	if (dnsseckey != NULL)
5155*00b67f09SDavid van Moolenbroek 		dst_key_free(&dnsseckey);
5156*00b67f09SDavid van Moolenbroek 	dns_rdataset_disassociate(&mydsrdataset);
5157*00b67f09SDavid van Moolenbroek 	dns_rdataset_disassociate(&mykeyrdataset);
5158*00b67f09SDavid van Moolenbroek 
5159*00b67f09SDavid van Moolenbroek 	return (result);
5160*00b67f09SDavid van Moolenbroek }
5161*00b67f09SDavid van Moolenbroek 
5162*00b67f09SDavid van Moolenbroek /*
5163*00b67f09SDavid van Moolenbroek  *
5164*00b67f09SDavid van Moolenbroek  * take a pointer on a rdataset in parameter and try to resolv it.
5165*00b67f09SDavid van Moolenbroek  * the searched rrset is a rrset on 'name' with type 'type'
5166*00b67f09SDavid van Moolenbroek  * (and if the type is a rrsig the signature cover 'covers').
5167*00b67f09SDavid van Moolenbroek  * the lookedup is to known if you have already done the query on the net.
5168*00b67f09SDavid van Moolenbroek  * ISC_R_SUCCESS: if we found the rrset
5169*00b67f09SDavid van Moolenbroek  * ISC_R_NOTFOUND: we do not found the rrset in cache
5170*00b67f09SDavid van Moolenbroek  * and we do a query on the net
5171*00b67f09SDavid van Moolenbroek  * ISC_R_FAILURE: rrset not found
5172*00b67f09SDavid van Moolenbroek  */
5173*00b67f09SDavid van Moolenbroek isc_result_t
advanced_rrsearch(dns_rdataset_t ** rdataset,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,isc_boolean_t * lookedup)5174*00b67f09SDavid van Moolenbroek advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
5175*00b67f09SDavid van Moolenbroek 		  dns_rdatatype_t type, dns_rdatatype_t covers,
5176*00b67f09SDavid van Moolenbroek 		  isc_boolean_t *lookedup)
5177*00b67f09SDavid van Moolenbroek {
5178*00b67f09SDavid van Moolenbroek 	isc_boolean_t  tmplookedup;
5179*00b67f09SDavid van Moolenbroek 
5180*00b67f09SDavid van Moolenbroek 	INSIST(rdataset != NULL);
5181*00b67f09SDavid van Moolenbroek 
5182*00b67f09SDavid van Moolenbroek 	if (*rdataset != NULL)
5183*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
5184*00b67f09SDavid van Moolenbroek 
5185*00b67f09SDavid van Moolenbroek 	tmplookedup = *lookedup;
5186*00b67f09SDavid van Moolenbroek 	if ((*rdataset = sigchase_scanname(type, covers,
5187*00b67f09SDavid van Moolenbroek 					   lookedup, name)) == NULL) {
5188*00b67f09SDavid van Moolenbroek 		if (tmplookedup)
5189*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
5190*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
5191*00b67f09SDavid van Moolenbroek 	}
5192*00b67f09SDavid van Moolenbroek 	*lookedup = ISC_FALSE;
5193*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
5194*00b67f09SDavid van Moolenbroek }
5195*00b67f09SDavid van Moolenbroek 
5196*00b67f09SDavid van Moolenbroek 
5197*00b67f09SDavid van Moolenbroek 
5198*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
5199*00b67f09SDavid van Moolenbroek void
sigchase_td(dns_message_t * msg)5200*00b67f09SDavid van Moolenbroek sigchase_td(dns_message_t *msg)
5201*00b67f09SDavid van Moolenbroek {
5202*00b67f09SDavid van Moolenbroek 	isc_result_t result;
5203*00b67f09SDavid van Moolenbroek 	dns_name_t *name = NULL;
5204*00b67f09SDavid van Moolenbroek 	isc_boolean_t have_answer = ISC_FALSE;
5205*00b67f09SDavid van Moolenbroek 	isc_boolean_t true = ISC_TRUE;
5206*00b67f09SDavid van Moolenbroek 
5207*00b67f09SDavid van Moolenbroek 	if (msg->rcode != dns_rcode_noerror &&
5208*00b67f09SDavid van Moolenbroek 	    msg->rcode != dns_rcode_nxdomain) {
5209*00b67f09SDavid van Moolenbroek 		char buf[20];
5210*00b67f09SDavid van Moolenbroek 		isc_buffer_t b;
5211*00b67f09SDavid van Moolenbroek 
5212*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&b, buf, sizeof(buf));
5213*00b67f09SDavid van Moolenbroek 		result = dns_rcode_totext(msg->rcode, &b);
5214*00b67f09SDavid van Moolenbroek 		check_result(result, "dns_rcode_totext failed");
5215*00b67f09SDavid van Moolenbroek 		printf("error response code %.*s\n",
5216*00b67f09SDavid van Moolenbroek 		       (int)isc_buffer_usedlength(&b), buf);
5217*00b67f09SDavid van Moolenbroek 		error_message = msg;
5218*00b67f09SDavid van Moolenbroek 		return;
5219*00b67f09SDavid van Moolenbroek 	}
5220*00b67f09SDavid van Moolenbroek 
5221*00b67f09SDavid van Moolenbroek 	if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
5222*00b67f09SDavid van Moolenbroek 	    == ISC_R_SUCCESS) {
5223*00b67f09SDavid van Moolenbroek 		dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
5224*00b67f09SDavid van Moolenbroek 		if (current_lookup->trace_root_sigchase) {
5225*00b67f09SDavid van Moolenbroek 			initialization(name);
5226*00b67f09SDavid van Moolenbroek 			return;
5227*00b67f09SDavid van Moolenbroek 		}
5228*00b67f09SDavid van Moolenbroek 		have_answer = true;
5229*00b67f09SDavid van Moolenbroek 	} else {
5230*00b67f09SDavid van Moolenbroek 		if (!current_lookup->trace_root_sigchase) {
5231*00b67f09SDavid van Moolenbroek 			result = dns_message_firstname(msg,
5232*00b67f09SDavid van Moolenbroek 						       DNS_SECTION_AUTHORITY);
5233*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS) {
5234*00b67f09SDavid van Moolenbroek 				printf("no answer or authority section\n");
5235*00b67f09SDavid van Moolenbroek 				error_message = msg;
5236*00b67f09SDavid van Moolenbroek 				return;
5237*00b67f09SDavid van Moolenbroek 			}
5238*00b67f09SDavid van Moolenbroek 			dns_message_currentname(msg, DNS_SECTION_AUTHORITY,
5239*00b67f09SDavid van Moolenbroek 						&name);
5240*00b67f09SDavid van Moolenbroek 			chase_nsrdataset
5241*00b67f09SDavid van Moolenbroek 				= chase_scanname_section(msg, name,
5242*00b67f09SDavid van Moolenbroek 							 dns_rdatatype_ns,
5243*00b67f09SDavid van Moolenbroek 							 dns_rdatatype_any,
5244*00b67f09SDavid van Moolenbroek 							 DNS_SECTION_AUTHORITY);
5245*00b67f09SDavid van Moolenbroek 			dup_name(name, &chase_authority_name, mctx);
5246*00b67f09SDavid van Moolenbroek 			if (chase_nsrdataset != NULL) {
5247*00b67f09SDavid van Moolenbroek 				have_delegation_ns = ISC_TRUE;
5248*00b67f09SDavid van Moolenbroek 				printf("no response but there is a delegation"
5249*00b67f09SDavid van Moolenbroek 				       " in authority section: ");
5250*00b67f09SDavid van Moolenbroek 				dns_name_print(name, stdout);
5251*00b67f09SDavid van Moolenbroek 				printf("\n");
5252*00b67f09SDavid van Moolenbroek 			} else {
5253*00b67f09SDavid van Moolenbroek 				printf("no response and no delegation in "
5254*00b67f09SDavid van Moolenbroek 				       "authority section but a reference"
5255*00b67f09SDavid van Moolenbroek 				       " to: ");
5256*00b67f09SDavid van Moolenbroek 				dns_name_print(name, stdout);
5257*00b67f09SDavid van Moolenbroek 				printf("\n");
5258*00b67f09SDavid van Moolenbroek 				error_message = msg;
5259*00b67f09SDavid van Moolenbroek 			}
5260*00b67f09SDavid van Moolenbroek 		} else {
5261*00b67f09SDavid van Moolenbroek 			printf(";; NO ANSWERS: %s\n",
5262*00b67f09SDavid van Moolenbroek 			       isc_result_totext(result));
5263*00b67f09SDavid van Moolenbroek 			free_name(&chase_name, mctx);
5264*00b67f09SDavid van Moolenbroek 			clean_trustedkey();
5265*00b67f09SDavid van Moolenbroek 			return;
5266*00b67f09SDavid van Moolenbroek 		}
5267*00b67f09SDavid van Moolenbroek 	}
5268*00b67f09SDavid van Moolenbroek 
5269*00b67f09SDavid van Moolenbroek 
5270*00b67f09SDavid van Moolenbroek 	if (have_answer) {
5271*00b67f09SDavid van Moolenbroek 		chase_rdataset
5272*00b67f09SDavid van Moolenbroek 			= chase_scanname_section(msg, &chase_name,
5273*00b67f09SDavid van Moolenbroek 						 current_lookup
5274*00b67f09SDavid van Moolenbroek 						 ->rdtype_sigchase,
5275*00b67f09SDavid van Moolenbroek 						 dns_rdatatype_any,
5276*00b67f09SDavid van Moolenbroek 						 DNS_SECTION_ANSWER);
5277*00b67f09SDavid van Moolenbroek 		if (chase_rdataset != NULL)
5278*00b67f09SDavid van Moolenbroek 			have_response = ISC_TRUE;
5279*00b67f09SDavid van Moolenbroek 	}
5280*00b67f09SDavid van Moolenbroek 
5281*00b67f09SDavid van Moolenbroek 	result = advanced_rrsearch(&chase_keyrdataset,
5282*00b67f09SDavid van Moolenbroek 				   &chase_current_name,
5283*00b67f09SDavid van Moolenbroek 				   dns_rdatatype_dnskey,
5284*00b67f09SDavid van Moolenbroek 				   dns_rdatatype_any,
5285*00b67f09SDavid van Moolenbroek 				   &chase_keylookedup);
5286*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_FAILURE) {
5287*00b67f09SDavid van Moolenbroek 		printf("\n;; DNSKEY is missing to continue validation:"
5288*00b67f09SDavid van Moolenbroek 		       " FAILED\n\n");
5289*00b67f09SDavid van Moolenbroek 		goto cleanandgo;
5290*00b67f09SDavid van Moolenbroek 	}
5291*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOTFOUND)
5292*00b67f09SDavid van Moolenbroek 		return;
5293*00b67f09SDavid van Moolenbroek 	INSIST(chase_keyrdataset != NULL);
5294*00b67f09SDavid van Moolenbroek 	printf("\n;; DNSKEYset:\n");
5295*00b67f09SDavid van Moolenbroek 	print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
5296*00b67f09SDavid van Moolenbroek 
5297*00b67f09SDavid van Moolenbroek 
5298*00b67f09SDavid van Moolenbroek 	result = advanced_rrsearch(&chase_sigkeyrdataset,
5299*00b67f09SDavid van Moolenbroek 				   &chase_current_name,
5300*00b67f09SDavid van Moolenbroek 				   dns_rdatatype_rrsig,
5301*00b67f09SDavid van Moolenbroek 				   dns_rdatatype_dnskey,
5302*00b67f09SDavid van Moolenbroek 				   &chase_sigkeylookedup);
5303*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_FAILURE) {
5304*00b67f09SDavid van Moolenbroek 		printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
5305*00b67f09SDavid van Moolenbroek 		       " FAILED\n\n");
5306*00b67f09SDavid van Moolenbroek 		goto cleanandgo;
5307*00b67f09SDavid van Moolenbroek 	}
5308*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOTFOUND)
5309*00b67f09SDavid van Moolenbroek 		return;
5310*00b67f09SDavid van Moolenbroek 	INSIST(chase_sigkeyrdataset != NULL);
5311*00b67f09SDavid van Moolenbroek 	printf("\n;; RRSIG of the DNSKEYset:\n");
5312*00b67f09SDavid van Moolenbroek 	print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
5313*00b67f09SDavid van Moolenbroek 
5314*00b67f09SDavid van Moolenbroek 
5315*00b67f09SDavid van Moolenbroek 	if (!chase_dslookedup && !chase_nslookedup) {
5316*00b67f09SDavid van Moolenbroek 		if (!delegation_follow) {
5317*00b67f09SDavid van Moolenbroek 			result = contains_trusted_key(&chase_current_name,
5318*00b67f09SDavid van Moolenbroek 						      chase_keyrdataset,
5319*00b67f09SDavid van Moolenbroek 						      chase_sigkeyrdataset,
5320*00b67f09SDavid van Moolenbroek 						      mctx);
5321*00b67f09SDavid van Moolenbroek 		} else {
5322*00b67f09SDavid van Moolenbroek 			INSIST(chase_dsrdataset != NULL);
5323*00b67f09SDavid van Moolenbroek 			INSIST(chase_sigdsrdataset != NULL);
5324*00b67f09SDavid van Moolenbroek 			result = sigchase_verify_ds(&chase_current_name,
5325*00b67f09SDavid van Moolenbroek 						    chase_keyrdataset,
5326*00b67f09SDavid van Moolenbroek 						    chase_dsrdataset,
5327*00b67f09SDavid van Moolenbroek 						    mctx);
5328*00b67f09SDavid van Moolenbroek 		}
5329*00b67f09SDavid van Moolenbroek 
5330*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
5331*00b67f09SDavid van Moolenbroek 			printf("\n;; chain of trust can't be validated:"
5332*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5333*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5334*00b67f09SDavid van Moolenbroek 		} else {
5335*00b67f09SDavid van Moolenbroek 			chase_dsrdataset = NULL;
5336*00b67f09SDavid van Moolenbroek 			chase_sigdsrdataset = NULL;
5337*00b67f09SDavid van Moolenbroek 		}
5338*00b67f09SDavid van Moolenbroek 	}
5339*00b67f09SDavid van Moolenbroek 
5340*00b67f09SDavid van Moolenbroek 	if (have_response || (!have_delegation_ns && !have_response)) {
5341*00b67f09SDavid van Moolenbroek 		/* test if it's a grand father case */
5342*00b67f09SDavid van Moolenbroek 
5343*00b67f09SDavid van Moolenbroek 		if (have_response) {
5344*00b67f09SDavid van Moolenbroek 			result = advanced_rrsearch(&chase_sigrdataset,
5345*00b67f09SDavid van Moolenbroek 						   &chase_name,
5346*00b67f09SDavid van Moolenbroek 						   dns_rdatatype_rrsig,
5347*00b67f09SDavid van Moolenbroek 						   current_lookup
5348*00b67f09SDavid van Moolenbroek 						   ->rdtype_sigchase,
5349*00b67f09SDavid van Moolenbroek 						   &true);
5350*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_FAILURE) {
5351*00b67f09SDavid van Moolenbroek 				printf("\n;; RRset is missing to continue"
5352*00b67f09SDavid van Moolenbroek 				       " validation SHOULD NOT APPEND:"
5353*00b67f09SDavid van Moolenbroek 				       " FAILED\n\n");
5354*00b67f09SDavid van Moolenbroek 				goto cleanandgo;
5355*00b67f09SDavid van Moolenbroek 			}
5356*00b67f09SDavid van Moolenbroek 
5357*00b67f09SDavid van Moolenbroek 		} else {
5358*00b67f09SDavid van Moolenbroek 			result = advanced_rrsearch(&chase_sigrdataset,
5359*00b67f09SDavid van Moolenbroek 						   &chase_authority_name,
5360*00b67f09SDavid van Moolenbroek 						   dns_rdatatype_rrsig,
5361*00b67f09SDavid van Moolenbroek 						   dns_rdatatype_any,
5362*00b67f09SDavid van Moolenbroek 						   &true);
5363*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_FAILURE) {
5364*00b67f09SDavid van Moolenbroek 				printf("\n;; RRSIG is missing  to continue"
5365*00b67f09SDavid van Moolenbroek 				       " validation SHOULD NOT APPEND:"
5366*00b67f09SDavid van Moolenbroek 				       " FAILED\n\n");
5367*00b67f09SDavid van Moolenbroek 				goto cleanandgo;
5368*00b67f09SDavid van Moolenbroek 			}
5369*00b67f09SDavid van Moolenbroek 		}
5370*00b67f09SDavid van Moolenbroek 		result =  grandfather_pb_test(&chase_current_name,
5371*00b67f09SDavid van Moolenbroek 					      chase_sigrdataset);
5372*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
5373*00b67f09SDavid van Moolenbroek 			dns_name_t tmp_name;
5374*00b67f09SDavid van Moolenbroek 
5375*00b67f09SDavid van Moolenbroek 			printf("\n;; We are in a Grand Father Problem:"
5376*00b67f09SDavid van Moolenbroek 			       " See 2.2.1 in RFC 3658\n");
5377*00b67f09SDavid van Moolenbroek 			chase_rdataset = NULL;
5378*00b67f09SDavid van Moolenbroek 			chase_sigrdataset = NULL;
5379*00b67f09SDavid van Moolenbroek 			have_response = ISC_FALSE;
5380*00b67f09SDavid van Moolenbroek 			have_delegation_ns = ISC_FALSE;
5381*00b67f09SDavid van Moolenbroek 
5382*00b67f09SDavid van Moolenbroek 			dns_name_init(&tmp_name, NULL);
5383*00b67f09SDavid van Moolenbroek 			result = child_of_zone(&chase_name, &chase_current_name,
5384*00b67f09SDavid van Moolenbroek 					       &tmp_name);
5385*00b67f09SDavid van Moolenbroek 			if (dns_name_dynamic(&chase_authority_name))
5386*00b67f09SDavid van Moolenbroek 				free_name(&chase_authority_name, mctx);
5387*00b67f09SDavid van Moolenbroek 			dup_name(&tmp_name, &chase_authority_name, mctx);
5388*00b67f09SDavid van Moolenbroek 			printf(";; and we try to continue chain of trust"
5389*00b67f09SDavid van Moolenbroek 			       " validation of the zone: ");
5390*00b67f09SDavid van Moolenbroek 			dns_name_print(&chase_authority_name, stdout);
5391*00b67f09SDavid van Moolenbroek 			printf("\n");
5392*00b67f09SDavid van Moolenbroek 			have_delegation_ns = ISC_TRUE;
5393*00b67f09SDavid van Moolenbroek 		} else {
5394*00b67f09SDavid van Moolenbroek 			if (have_response)
5395*00b67f09SDavid van Moolenbroek 				goto finalstep;
5396*00b67f09SDavid van Moolenbroek 			else
5397*00b67f09SDavid van Moolenbroek 				chase_sigrdataset = NULL;
5398*00b67f09SDavid van Moolenbroek 		}
5399*00b67f09SDavid van Moolenbroek 	}
5400*00b67f09SDavid van Moolenbroek 
5401*00b67f09SDavid van Moolenbroek 	if (have_delegation_ns) {
5402*00b67f09SDavid van Moolenbroek 		chase_nsrdataset = NULL;
5403*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_nsrdataset,
5404*00b67f09SDavid van Moolenbroek 					   &chase_authority_name,
5405*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_ns,
5406*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_any,
5407*00b67f09SDavid van Moolenbroek 					   &chase_nslookedup);
5408*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_FAILURE) {
5409*00b67f09SDavid van Moolenbroek 			printf("\n;;NSset is missing to continue validation:"
5410*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5411*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5412*00b67f09SDavid van Moolenbroek 		}
5413*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_NOTFOUND) {
5414*00b67f09SDavid van Moolenbroek 			return;
5415*00b67f09SDavid van Moolenbroek 		}
5416*00b67f09SDavid van Moolenbroek 		INSIST(chase_nsrdataset != NULL);
5417*00b67f09SDavid van Moolenbroek 
5418*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_dsrdataset,
5419*00b67f09SDavid van Moolenbroek 					   &chase_authority_name,
5420*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_ds,
5421*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_any,
5422*00b67f09SDavid van Moolenbroek 					   &chase_dslookedup);
5423*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_FAILURE) {
5424*00b67f09SDavid van Moolenbroek 			printf("\n;; DSset is missing to continue validation:"
5425*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5426*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5427*00b67f09SDavid van Moolenbroek 		}
5428*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_NOTFOUND)
5429*00b67f09SDavid van Moolenbroek 			return;
5430*00b67f09SDavid van Moolenbroek 		INSIST(chase_dsrdataset != NULL);
5431*00b67f09SDavid van Moolenbroek 		printf("\n;; DSset:\n");
5432*00b67f09SDavid van Moolenbroek 		print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
5433*00b67f09SDavid van Moolenbroek 
5434*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_sigdsrdataset,
5435*00b67f09SDavid van Moolenbroek 					   &chase_authority_name,
5436*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_rrsig,
5437*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_ds,
5438*00b67f09SDavid van Moolenbroek 					   &true);
5439*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
5440*00b67f09SDavid van Moolenbroek 			printf("\n;; DSset is missing to continue validation:"
5441*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5442*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5443*00b67f09SDavid van Moolenbroek 		}
5444*00b67f09SDavid van Moolenbroek 		printf("\n;; RRSIGset of DSset\n");
5445*00b67f09SDavid van Moolenbroek 		print_rdataset(&chase_authority_name,
5446*00b67f09SDavid van Moolenbroek 			       chase_sigdsrdataset, mctx);
5447*00b67f09SDavid van Moolenbroek 		INSIST(chase_sigdsrdataset != NULL);
5448*00b67f09SDavid van Moolenbroek 
5449*00b67f09SDavid van Moolenbroek 		result = sigchase_verify_sig(&chase_authority_name,
5450*00b67f09SDavid van Moolenbroek 					     chase_dsrdataset,
5451*00b67f09SDavid van Moolenbroek 					     chase_keyrdataset,
5452*00b67f09SDavid van Moolenbroek 					     chase_sigdsrdataset, mctx);
5453*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
5454*00b67f09SDavid van Moolenbroek 			printf("\n;; Impossible to verify the DSset:"
5455*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5456*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5457*00b67f09SDavid van Moolenbroek 		}
5458*00b67f09SDavid van Moolenbroek 		chase_keyrdataset = NULL;
5459*00b67f09SDavid van Moolenbroek 		chase_sigkeyrdataset = NULL;
5460*00b67f09SDavid van Moolenbroek 
5461*00b67f09SDavid van Moolenbroek 
5462*00b67f09SDavid van Moolenbroek 		prepare_lookup(&chase_authority_name);
5463*00b67f09SDavid van Moolenbroek 
5464*00b67f09SDavid van Moolenbroek 		have_response = ISC_FALSE;
5465*00b67f09SDavid van Moolenbroek 		have_delegation_ns = ISC_FALSE;
5466*00b67f09SDavid van Moolenbroek 		delegation_follow = ISC_TRUE;
5467*00b67f09SDavid van Moolenbroek 		error_message = NULL;
5468*00b67f09SDavid van Moolenbroek 		dup_name(&chase_authority_name, &chase_current_name, mctx);
5469*00b67f09SDavid van Moolenbroek 		free_name(&chase_authority_name, mctx);
5470*00b67f09SDavid van Moolenbroek 		return;
5471*00b67f09SDavid van Moolenbroek 	}
5472*00b67f09SDavid van Moolenbroek 
5473*00b67f09SDavid van Moolenbroek 
5474*00b67f09SDavid van Moolenbroek 	if (error_message != NULL) {
5475*00b67f09SDavid van Moolenbroek 		dns_rdataset_t *rdataset;
5476*00b67f09SDavid van Moolenbroek 		dns_rdataset_t *sigrdataset;
5477*00b67f09SDavid van Moolenbroek 		dns_name_t rdata_name;
5478*00b67f09SDavid van Moolenbroek 		isc_result_t ret = ISC_R_FAILURE;
5479*00b67f09SDavid van Moolenbroek 
5480*00b67f09SDavid van Moolenbroek 		dns_name_init(&rdata_name, NULL);
5481*00b67f09SDavid van Moolenbroek 		result = prove_nx(error_message, &chase_name,
5482*00b67f09SDavid van Moolenbroek 				  current_lookup->rdclass_sigchase,
5483*00b67f09SDavid van Moolenbroek 				  current_lookup->rdtype_sigchase, &rdata_name,
5484*00b67f09SDavid van Moolenbroek 				  &rdataset, &sigrdataset);
5485*00b67f09SDavid van Moolenbroek 		if (rdataset == NULL || sigrdataset == NULL ||
5486*00b67f09SDavid van Moolenbroek 		    dns_name_countlabels(&rdata_name) == 0) {
5487*00b67f09SDavid van Moolenbroek 			printf("\n;; Impossible to verify the non-existence,"
5488*00b67f09SDavid van Moolenbroek 			       " the NSEC RRset can't be validated:"
5489*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5490*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5491*00b67f09SDavid van Moolenbroek 		}
5492*00b67f09SDavid van Moolenbroek 		ret = sigchase_verify_sig(&rdata_name, rdataset,
5493*00b67f09SDavid van Moolenbroek 					  chase_keyrdataset,
5494*00b67f09SDavid van Moolenbroek 					  sigrdataset, mctx);
5495*00b67f09SDavid van Moolenbroek 		if (ret != ISC_R_SUCCESS) {
5496*00b67f09SDavid van Moolenbroek 			free_name(&rdata_name, mctx);
5497*00b67f09SDavid van Moolenbroek 			printf("\n;; Impossible to verify the NSEC RR to prove"
5498*00b67f09SDavid van Moolenbroek 			       " the non-existence : FAILED\n\n");
5499*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5500*00b67f09SDavid van Moolenbroek 		}
5501*00b67f09SDavid van Moolenbroek 		free_name(&rdata_name, mctx);
5502*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
5503*00b67f09SDavid van Moolenbroek 			printf("\n;; Impossible to verify the non-existence:"
5504*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5505*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5506*00b67f09SDavid van Moolenbroek 		} else {
5507*00b67f09SDavid van Moolenbroek 			printf("\n;; OK the query doesn't have response but"
5508*00b67f09SDavid van Moolenbroek 			       " we have validate this fact : SUCCESS\n\n");
5509*00b67f09SDavid van Moolenbroek 			goto cleanandgo;
5510*00b67f09SDavid van Moolenbroek 		}
5511*00b67f09SDavid van Moolenbroek 	}
5512*00b67f09SDavid van Moolenbroek 
5513*00b67f09SDavid van Moolenbroek  cleanandgo:
5514*00b67f09SDavid van Moolenbroek 	printf(";; cleanandgo \n");
5515*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(&chase_current_name))
5516*00b67f09SDavid van Moolenbroek 		free_name(&chase_current_name, mctx);
5517*00b67f09SDavid van Moolenbroek 	if (dns_name_dynamic(&chase_authority_name))
5518*00b67f09SDavid van Moolenbroek 		free_name(&chase_authority_name, mctx);
5519*00b67f09SDavid van Moolenbroek 	clean_trustedkey();
5520*00b67f09SDavid van Moolenbroek 	return;
5521*00b67f09SDavid van Moolenbroek 
5522*00b67f09SDavid van Moolenbroek 	finalstep :
5523*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_rdataset, &chase_name,
5524*00b67f09SDavid van Moolenbroek 					   current_lookup->rdtype_sigchase,
5525*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_any ,
5526*00b67f09SDavid van Moolenbroek 					   &true);
5527*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_FAILURE) {
5528*00b67f09SDavid van Moolenbroek 		printf("\n;; RRsig of RRset is missing to continue validation"
5529*00b67f09SDavid van Moolenbroek 		       " SHOULD NOT APPEND: FAILED\n\n");
5530*00b67f09SDavid van Moolenbroek 		goto cleanandgo;
5531*00b67f09SDavid van Moolenbroek 	}
5532*00b67f09SDavid van Moolenbroek 	result = sigchase_verify_sig(&chase_name, chase_rdataset,
5533*00b67f09SDavid van Moolenbroek 				     chase_keyrdataset,
5534*00b67f09SDavid van Moolenbroek 				     chase_sigrdataset, mctx);
5535*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
5536*00b67f09SDavid van Moolenbroek 		printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5537*00b67f09SDavid van Moolenbroek 		/*
5538*00b67f09SDavid van Moolenbroek 		  printf("RRset:\n");
5539*00b67f09SDavid van Moolenbroek 		  print_rdataset(&chase_name , chase_rdataset, mctx);
5540*00b67f09SDavid van Moolenbroek 		  printf("DNSKEYset:\n");
5541*00b67f09SDavid van Moolenbroek 		  print_rdataset(&chase_name , chase_keyrdataset, mctx);
5542*00b67f09SDavid van Moolenbroek 		  printf("RRSIG of RRset:\n");
5543*00b67f09SDavid van Moolenbroek 		  print_rdataset(&chase_name , chase_sigrdataset, mctx);
5544*00b67f09SDavid van Moolenbroek 		  printf("\n");
5545*00b67f09SDavid van Moolenbroek 		*/
5546*00b67f09SDavid van Moolenbroek 		goto cleanandgo;
5547*00b67f09SDavid van Moolenbroek 	} else {
5548*00b67f09SDavid van Moolenbroek 		printf("\n;; The Answer:\n");
5549*00b67f09SDavid van Moolenbroek 		print_rdataset(&chase_name , chase_rdataset, mctx);
5550*00b67f09SDavid van Moolenbroek 
5551*00b67f09SDavid van Moolenbroek 		printf("\n;; FINISH : we have validate the DNSSEC chain"
5552*00b67f09SDavid van Moolenbroek 		       " of trust: SUCCESS\n\n");
5553*00b67f09SDavid van Moolenbroek 		goto cleanandgo;
5554*00b67f09SDavid van Moolenbroek 	}
5555*00b67f09SDavid van Moolenbroek }
5556*00b67f09SDavid van Moolenbroek 
5557*00b67f09SDavid van Moolenbroek #endif
5558*00b67f09SDavid van Moolenbroek 
5559*00b67f09SDavid van Moolenbroek 
5560*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_BU
5561*00b67f09SDavid van Moolenbroek 
5562*00b67f09SDavid van Moolenbroek isc_result_t
getneededrr(dns_message_t * msg)5563*00b67f09SDavid van Moolenbroek getneededrr(dns_message_t *msg)
5564*00b67f09SDavid van Moolenbroek {
5565*00b67f09SDavid van Moolenbroek 	isc_result_t result;
5566*00b67f09SDavid van Moolenbroek 	dns_name_t *name = NULL;
5567*00b67f09SDavid van Moolenbroek 	dns_rdata_t sigrdata = DNS_RDATA_INIT;
5568*00b67f09SDavid van Moolenbroek 	dns_rdata_sig_t siginfo;
5569*00b67f09SDavid van Moolenbroek 	isc_boolean_t   true = ISC_TRUE;
5570*00b67f09SDavid van Moolenbroek 
5571*00b67f09SDavid van Moolenbroek 	if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
5572*00b67f09SDavid van Moolenbroek 	    != ISC_R_SUCCESS) {
5573*00b67f09SDavid van Moolenbroek 		printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
5574*00b67f09SDavid van Moolenbroek 
5575*00b67f09SDavid van Moolenbroek 		if (chase_name.ndata == NULL)
5576*00b67f09SDavid van Moolenbroek 			return (ISC_R_ADDRNOTAVAIL);
5577*00b67f09SDavid van Moolenbroek 	} else {
5578*00b67f09SDavid van Moolenbroek 		dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
5579*00b67f09SDavid van Moolenbroek 	}
5580*00b67f09SDavid van Moolenbroek 
5581*00b67f09SDavid van Moolenbroek 	/* What do we chase? */
5582*00b67f09SDavid van Moolenbroek 	if (chase_rdataset == NULL) {
5583*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_rdataset, name,
5584*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_any,
5585*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_any, &true);
5586*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
5587*00b67f09SDavid van Moolenbroek 			printf("\n;; No Answers: Validation FAILED\n\n");
5588*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOTFOUND);
5589*00b67f09SDavid van Moolenbroek 		}
5590*00b67f09SDavid van Moolenbroek 		dup_name(name, &chase_name, mctx);
5591*00b67f09SDavid van Moolenbroek 		printf(";; RRset to chase:\n");
5592*00b67f09SDavid van Moolenbroek 		print_rdataset(&chase_name, chase_rdataset, mctx);
5593*00b67f09SDavid van Moolenbroek 	}
5594*00b67f09SDavid van Moolenbroek 	INSIST(chase_rdataset != NULL);
5595*00b67f09SDavid van Moolenbroek 
5596*00b67f09SDavid van Moolenbroek 
5597*00b67f09SDavid van Moolenbroek 	if (chase_sigrdataset == NULL) {
5598*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_sigrdataset, name,
5599*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_rrsig,
5600*00b67f09SDavid van Moolenbroek 					   chase_rdataset->type,
5601*00b67f09SDavid van Moolenbroek 					   &chase_siglookedup);
5602*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_FAILURE) {
5603*00b67f09SDavid van Moolenbroek 			printf("\n;; RRSIG is missing for continue validation:"
5604*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5605*00b67f09SDavid van Moolenbroek 			if (dns_name_dynamic(&chase_name))
5606*00b67f09SDavid van Moolenbroek 				free_name(&chase_name, mctx);
5607*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOTFOUND);
5608*00b67f09SDavid van Moolenbroek 		}
5609*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_NOTFOUND) {
5610*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOTFOUND);
5611*00b67f09SDavid van Moolenbroek 		}
5612*00b67f09SDavid van Moolenbroek 		printf("\n;; RRSIG of the RRset to chase:\n");
5613*00b67f09SDavid van Moolenbroek 		print_rdataset(&chase_name, chase_sigrdataset, mctx);
5614*00b67f09SDavid van Moolenbroek 	}
5615*00b67f09SDavid van Moolenbroek 	INSIST(chase_sigrdataset != NULL);
5616*00b67f09SDavid van Moolenbroek 
5617*00b67f09SDavid van Moolenbroek 
5618*00b67f09SDavid van Moolenbroek 	/* first find the DNSKEY name */
5619*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(chase_sigrdataset);
5620*00b67f09SDavid van Moolenbroek 	check_result(result, "empty RRSIG dataset");
5621*00b67f09SDavid van Moolenbroek 	dns_rdataset_current(chase_sigrdataset, &sigrdata);
5622*00b67f09SDavid van Moolenbroek 	result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
5623*00b67f09SDavid van Moolenbroek 	check_result(result, "sigrdata tostruct siginfo");
5624*00b67f09SDavid van Moolenbroek 	dup_name(&siginfo.signer, &chase_signame, mctx);
5625*00b67f09SDavid van Moolenbroek 	dns_rdata_freestruct(&siginfo);
5626*00b67f09SDavid van Moolenbroek 	dns_rdata_reset(&sigrdata);
5627*00b67f09SDavid van Moolenbroek 
5628*00b67f09SDavid van Moolenbroek 	/* Do we have a key?  */
5629*00b67f09SDavid van Moolenbroek 	if (chase_keyrdataset == NULL) {
5630*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_keyrdataset,
5631*00b67f09SDavid van Moolenbroek 					   &chase_signame,
5632*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_dnskey,
5633*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_any,
5634*00b67f09SDavid van Moolenbroek 					   &chase_keylookedup);
5635*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_FAILURE) {
5636*00b67f09SDavid van Moolenbroek 			printf("\n;; DNSKEY is missing to continue validation:"
5637*00b67f09SDavid van Moolenbroek 			       " FAILED\n\n");
5638*00b67f09SDavid van Moolenbroek 			free_name(&chase_signame, mctx);
5639*00b67f09SDavid van Moolenbroek 			if (dns_name_dynamic(&chase_name))
5640*00b67f09SDavid van Moolenbroek 				free_name(&chase_name, mctx);
5641*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOTFOUND);
5642*00b67f09SDavid van Moolenbroek 		}
5643*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_NOTFOUND) {
5644*00b67f09SDavid van Moolenbroek 			free_name(&chase_signame, mctx);
5645*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOTFOUND);
5646*00b67f09SDavid van Moolenbroek 		}
5647*00b67f09SDavid van Moolenbroek 		printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5648*00b67f09SDavid van Moolenbroek 		print_rdataset(&chase_signame, chase_keyrdataset, mctx);
5649*00b67f09SDavid van Moolenbroek 	}
5650*00b67f09SDavid van Moolenbroek 	INSIST(chase_keyrdataset != NULL);
5651*00b67f09SDavid van Moolenbroek 
5652*00b67f09SDavid van Moolenbroek 	if (chase_sigkeyrdataset == NULL) {
5653*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_sigkeyrdataset,
5654*00b67f09SDavid van Moolenbroek 					   &chase_signame,
5655*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_rrsig,
5656*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_dnskey,
5657*00b67f09SDavid van Moolenbroek 					   &chase_sigkeylookedup);
5658*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_FAILURE) {
5659*00b67f09SDavid van Moolenbroek 			printf("\n;; RRSIG for DNSKEY is missing  to continue"
5660*00b67f09SDavid van Moolenbroek 			       " validation : FAILED\n\n");
5661*00b67f09SDavid van Moolenbroek 			free_name(&chase_signame, mctx);
5662*00b67f09SDavid van Moolenbroek 			if (dns_name_dynamic(&chase_name))
5663*00b67f09SDavid van Moolenbroek 				free_name(&chase_name, mctx);
5664*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOTFOUND);
5665*00b67f09SDavid van Moolenbroek 		}
5666*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_NOTFOUND) {
5667*00b67f09SDavid van Moolenbroek 			free_name(&chase_signame, mctx);
5668*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOTFOUND);
5669*00b67f09SDavid van Moolenbroek 		}
5670*00b67f09SDavid van Moolenbroek 		printf("\n;; RRSIG of the DNSKEYset that signs the "
5671*00b67f09SDavid van Moolenbroek 		       "RRset to chase:\n");
5672*00b67f09SDavid van Moolenbroek 		print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
5673*00b67f09SDavid van Moolenbroek 	}
5674*00b67f09SDavid van Moolenbroek 	INSIST(chase_sigkeyrdataset != NULL);
5675*00b67f09SDavid van Moolenbroek 
5676*00b67f09SDavid van Moolenbroek 
5677*00b67f09SDavid van Moolenbroek 	if (chase_dsrdataset == NULL) {
5678*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
5679*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_ds, dns_rdatatype_any,
5680*00b67f09SDavid van Moolenbroek 					   &chase_dslookedup);
5681*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_FAILURE) {
5682*00b67f09SDavid van Moolenbroek 			printf("\n;; WARNING There is no DS for the zone: ");
5683*00b67f09SDavid van Moolenbroek 			dns_name_print(&chase_signame, stdout);
5684*00b67f09SDavid van Moolenbroek 			printf("\n");
5685*00b67f09SDavid van Moolenbroek 		}
5686*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_NOTFOUND) {
5687*00b67f09SDavid van Moolenbroek 			free_name(&chase_signame, mctx);
5688*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOTFOUND);
5689*00b67f09SDavid van Moolenbroek 		}
5690*00b67f09SDavid van Moolenbroek 		if (chase_dsrdataset != NULL) {
5691*00b67f09SDavid van Moolenbroek 			printf("\n;; DSset of the DNSKEYset\n");
5692*00b67f09SDavid van Moolenbroek 			print_rdataset(&chase_signame, chase_dsrdataset, mctx);
5693*00b67f09SDavid van Moolenbroek 		}
5694*00b67f09SDavid van Moolenbroek 	}
5695*00b67f09SDavid van Moolenbroek 
5696*00b67f09SDavid van Moolenbroek 	if (chase_dsrdataset != NULL) {
5697*00b67f09SDavid van Moolenbroek 		/*
5698*00b67f09SDavid van Moolenbroek 		 * if there is no RRSIG of DS,
5699*00b67f09SDavid van Moolenbroek 		 * we don't want to search on the network
5700*00b67f09SDavid van Moolenbroek 		 */
5701*00b67f09SDavid van Moolenbroek 		result = advanced_rrsearch(&chase_sigdsrdataset,
5702*00b67f09SDavid van Moolenbroek 					   &chase_signame,
5703*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_rrsig,
5704*00b67f09SDavid van Moolenbroek 					   dns_rdatatype_ds, &true);
5705*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_FAILURE) {
5706*00b67f09SDavid van Moolenbroek 			printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5707*00b67f09SDavid van Moolenbroek 			       " should come with DS\n");
5708*00b67f09SDavid van Moolenbroek 			/*
5709*00b67f09SDavid van Moolenbroek 			 * We continue even the DS couldn't be validated,
5710*00b67f09SDavid van Moolenbroek 			 * because the DNSKEY could be a Trusted Key.
5711*00b67f09SDavid van Moolenbroek 			 */
5712*00b67f09SDavid van Moolenbroek 			chase_dsrdataset = NULL;
5713*00b67f09SDavid van Moolenbroek 		} else {
5714*00b67f09SDavid van Moolenbroek 			printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5715*00b67f09SDavid van Moolenbroek 			print_rdataset(&chase_signame, chase_sigdsrdataset,
5716*00b67f09SDavid van Moolenbroek 				       mctx);
5717*00b67f09SDavid van Moolenbroek 		}
5718*00b67f09SDavid van Moolenbroek 	}
5719*00b67f09SDavid van Moolenbroek 	return (1);
5720*00b67f09SDavid van Moolenbroek }
5721*00b67f09SDavid van Moolenbroek 
5722*00b67f09SDavid van Moolenbroek 
5723*00b67f09SDavid van Moolenbroek 
5724*00b67f09SDavid van Moolenbroek void
sigchase_bu(dns_message_t * msg)5725*00b67f09SDavid van Moolenbroek sigchase_bu(dns_message_t *msg)
5726*00b67f09SDavid van Moolenbroek {
5727*00b67f09SDavid van Moolenbroek 	isc_result_t result;
5728*00b67f09SDavid van Moolenbroek 	int ret;
5729*00b67f09SDavid van Moolenbroek 
5730*00b67f09SDavid van Moolenbroek 	if (tk_list.nb_tk == 0) {
5731*00b67f09SDavid van Moolenbroek 		result = get_trusted_key(mctx);
5732*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
5733*00b67f09SDavid van Moolenbroek 			printf("No trusted keys present\n");
5734*00b67f09SDavid van Moolenbroek 			return;
5735*00b67f09SDavid van Moolenbroek 		}
5736*00b67f09SDavid van Moolenbroek 	}
5737*00b67f09SDavid van Moolenbroek 
5738*00b67f09SDavid van Moolenbroek 
5739*00b67f09SDavid van Moolenbroek 	ret = getneededrr(msg);
5740*00b67f09SDavid van Moolenbroek 	if (ret == ISC_R_NOTFOUND)
5741*00b67f09SDavid van Moolenbroek 		return;
5742*00b67f09SDavid van Moolenbroek 
5743*00b67f09SDavid van Moolenbroek 	if (ret == ISC_R_ADDRNOTAVAIL) {
5744*00b67f09SDavid van Moolenbroek 		/* We have no response */
5745*00b67f09SDavid van Moolenbroek 		dns_rdataset_t *rdataset;
5746*00b67f09SDavid van Moolenbroek 		dns_rdataset_t *sigrdataset;
5747*00b67f09SDavid van Moolenbroek 		dns_name_t rdata_name;
5748*00b67f09SDavid van Moolenbroek 		dns_name_t query_name;
5749*00b67f09SDavid van Moolenbroek 
5750*00b67f09SDavid van Moolenbroek 
5751*00b67f09SDavid van Moolenbroek 		dns_name_init(&query_name, NULL);
5752*00b67f09SDavid van Moolenbroek 		dns_name_init(&rdata_name, NULL);
5753*00b67f09SDavid van Moolenbroek 		nameFromString(current_lookup->textname, &query_name);
5754*00b67f09SDavid van Moolenbroek 
5755*00b67f09SDavid van Moolenbroek 		result = prove_nx(msg, &query_name, current_lookup->rdclass,
5756*00b67f09SDavid van Moolenbroek 				  current_lookup->rdtype, &rdata_name,
5757*00b67f09SDavid van Moolenbroek 				  &rdataset, &sigrdataset);
5758*00b67f09SDavid van Moolenbroek 		free_name(&query_name, mctx);
5759*00b67f09SDavid van Moolenbroek 		if (rdataset == NULL || sigrdataset == NULL ||
5760*00b67f09SDavid van Moolenbroek 		    dns_name_countlabels(&rdata_name) == 0) {
5761*00b67f09SDavid van Moolenbroek 			printf("\n;; Impossible to verify the Non-existence,"
5762*00b67f09SDavid van Moolenbroek 			       " the NSEC RRset can't be validated: "
5763*00b67f09SDavid van Moolenbroek 			       "FAILED\n\n");
5764*00b67f09SDavid van Moolenbroek 			clean_trustedkey();
5765*00b67f09SDavid van Moolenbroek 			return;
5766*00b67f09SDavid van Moolenbroek 		}
5767*00b67f09SDavid van Moolenbroek 
5768*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
5769*00b67f09SDavid van Moolenbroek 			printf("\n No Answers and impossible to prove the"
5770*00b67f09SDavid van Moolenbroek 			       " unsecurity : Validation FAILED\n\n");
5771*00b67f09SDavid van Moolenbroek 			clean_trustedkey();
5772*00b67f09SDavid van Moolenbroek 			return;
5773*00b67f09SDavid van Moolenbroek 		}
5774*00b67f09SDavid van Moolenbroek 		printf(";; An NSEC prove the non-existence of a answers,"
5775*00b67f09SDavid van Moolenbroek 		       " Now we want validate this NSEC\n");
5776*00b67f09SDavid van Moolenbroek 
5777*00b67f09SDavid van Moolenbroek 		dup_name(&rdata_name, &chase_name, mctx);
5778*00b67f09SDavid van Moolenbroek 		free_name(&rdata_name, mctx);
5779*00b67f09SDavid van Moolenbroek 		chase_rdataset =  rdataset;
5780*00b67f09SDavid van Moolenbroek 		chase_sigrdataset = sigrdataset;
5781*00b67f09SDavid van Moolenbroek 		chase_keyrdataset = NULL;
5782*00b67f09SDavid van Moolenbroek 		chase_sigkeyrdataset = NULL;
5783*00b67f09SDavid van Moolenbroek 		chase_dsrdataset = NULL;
5784*00b67f09SDavid van Moolenbroek 		chase_sigdsrdataset = NULL;
5785*00b67f09SDavid van Moolenbroek 		chase_siglookedup = ISC_FALSE;
5786*00b67f09SDavid van Moolenbroek 		chase_keylookedup = ISC_FALSE;
5787*00b67f09SDavid van Moolenbroek 		chase_dslookedup = ISC_FALSE;
5788*00b67f09SDavid van Moolenbroek 		chase_sigdslookedup = ISC_FALSE;
5789*00b67f09SDavid van Moolenbroek 		sigchase(msg);
5790*00b67f09SDavid van Moolenbroek 		clean_trustedkey();
5791*00b67f09SDavid van Moolenbroek 		return;
5792*00b67f09SDavid van Moolenbroek 	}
5793*00b67f09SDavid van Moolenbroek 
5794*00b67f09SDavid van Moolenbroek 
5795*00b67f09SDavid van Moolenbroek 	printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5796*00b67f09SDavid van Moolenbroek 
5797*00b67f09SDavid van Moolenbroek 	result = sigchase_verify_sig(&chase_name, chase_rdataset,
5798*00b67f09SDavid van Moolenbroek 				     chase_keyrdataset,
5799*00b67f09SDavid van Moolenbroek 				     chase_sigrdataset, mctx);
5800*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
5801*00b67f09SDavid van Moolenbroek 		free_name(&chase_name, mctx);
5802*00b67f09SDavid van Moolenbroek 		free_name(&chase_signame, mctx);
5803*00b67f09SDavid van Moolenbroek 		printf(";; No DNSKEY is valid to check the RRSIG"
5804*00b67f09SDavid van Moolenbroek 		       " of the RRset: FAILED\n");
5805*00b67f09SDavid van Moolenbroek 		clean_trustedkey();
5806*00b67f09SDavid van Moolenbroek 		return;
5807*00b67f09SDavid van Moolenbroek 	}
5808*00b67f09SDavid van Moolenbroek 	printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5809*00b67f09SDavid van Moolenbroek 
5810*00b67f09SDavid van Moolenbroek 	result = contains_trusted_key(&chase_signame, chase_keyrdataset,
5811*00b67f09SDavid van Moolenbroek 				      chase_sigkeyrdataset, mctx);
5812*00b67f09SDavid van Moolenbroek 	if (result ==  ISC_R_SUCCESS) {
5813*00b67f09SDavid van Moolenbroek 		free_name(&chase_name, mctx);
5814*00b67f09SDavid van Moolenbroek 		free_name(&chase_signame, mctx);
5815*00b67f09SDavid van Moolenbroek 		printf("\n;; Ok this DNSKEY is a Trusted Key,"
5816*00b67f09SDavid van Moolenbroek 		       " DNSSEC validation is ok: SUCCESS\n\n");
5817*00b67f09SDavid van Moolenbroek 		clean_trustedkey();
5818*00b67f09SDavid van Moolenbroek 		return;
5819*00b67f09SDavid van Moolenbroek 	}
5820*00b67f09SDavid van Moolenbroek 
5821*00b67f09SDavid van Moolenbroek 	printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5822*00b67f09SDavid van Moolenbroek 
5823*00b67f09SDavid van Moolenbroek 	if (chase_dsrdataset == NULL) {
5824*00b67f09SDavid van Moolenbroek 		free_name(&chase_name, mctx);
5825*00b67f09SDavid van Moolenbroek 		free_name(&chase_signame, mctx);
5826*00b67f09SDavid van Moolenbroek 		printf(";; the DNSKEY isn't trusted-key and there isn't"
5827*00b67f09SDavid van Moolenbroek 		       " DS to validate the DNSKEY: FAILED\n");
5828*00b67f09SDavid van Moolenbroek 		clean_trustedkey();
5829*00b67f09SDavid van Moolenbroek 		return;
5830*00b67f09SDavid van Moolenbroek 	}
5831*00b67f09SDavid van Moolenbroek 
5832*00b67f09SDavid van Moolenbroek 	result =  sigchase_verify_ds(&chase_signame, chase_keyrdataset,
5833*00b67f09SDavid van Moolenbroek 				     chase_dsrdataset, mctx);
5834*00b67f09SDavid van Moolenbroek 	if (result !=  ISC_R_SUCCESS) {
5835*00b67f09SDavid van Moolenbroek 		free_name(&chase_signame, mctx);
5836*00b67f09SDavid van Moolenbroek 		free_name(&chase_name, mctx);
5837*00b67f09SDavid van Moolenbroek 		printf(";; ERROR no DS validates a DNSKEY in the"
5838*00b67f09SDavid van Moolenbroek 		       " DNSKEY RRset: FAILED\n");
5839*00b67f09SDavid van Moolenbroek 		clean_trustedkey();
5840*00b67f09SDavid van Moolenbroek 		return;
5841*00b67f09SDavid van Moolenbroek 	} else
5842*00b67f09SDavid van Moolenbroek 		printf(";; OK this DNSKEY (validated by the DS) validates"
5843*00b67f09SDavid van Moolenbroek 		       " the RRset of the DNSKEYs, thus the DNSKEY validates"
5844*00b67f09SDavid van Moolenbroek 		       " the RRset\n");
5845*00b67f09SDavid van Moolenbroek 	INSIST(chase_sigdsrdataset != NULL);
5846*00b67f09SDavid van Moolenbroek 
5847*00b67f09SDavid van Moolenbroek 	dup_name(&chase_signame, &chase_name, mctx);
5848*00b67f09SDavid van Moolenbroek 	free_name(&chase_signame, mctx);
5849*00b67f09SDavid van Moolenbroek 	chase_rdataset = chase_dsrdataset;
5850*00b67f09SDavid van Moolenbroek 	chase_sigrdataset = chase_sigdsrdataset;
5851*00b67f09SDavid van Moolenbroek 	chase_keyrdataset = NULL;
5852*00b67f09SDavid van Moolenbroek 	chase_sigkeyrdataset = NULL;
5853*00b67f09SDavid van Moolenbroek 	chase_dsrdataset = NULL;
5854*00b67f09SDavid van Moolenbroek 	chase_sigdsrdataset = NULL;
5855*00b67f09SDavid van Moolenbroek 	chase_siglookedup = chase_keylookedup = ISC_FALSE;
5856*00b67f09SDavid van Moolenbroek 	chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
5857*00b67f09SDavid van Moolenbroek 
5858*00b67f09SDavid van Moolenbroek 	printf(";; Now, we want to validate the DS :  recursive call\n");
5859*00b67f09SDavid van Moolenbroek 	sigchase(msg);
5860*00b67f09SDavid van Moolenbroek 	return;
5861*00b67f09SDavid van Moolenbroek }
5862*00b67f09SDavid van Moolenbroek #endif
5863*00b67f09SDavid van Moolenbroek 
5864*00b67f09SDavid van Moolenbroek void
sigchase(dns_message_t * msg)5865*00b67f09SDavid van Moolenbroek sigchase(dns_message_t *msg) {
5866*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_TD
5867*00b67f09SDavid van Moolenbroek 	if (current_lookup->do_topdown) {
5868*00b67f09SDavid van Moolenbroek 		sigchase_td(msg);
5869*00b67f09SDavid van Moolenbroek 		return;
5870*00b67f09SDavid van Moolenbroek 	}
5871*00b67f09SDavid van Moolenbroek #endif
5872*00b67f09SDavid van Moolenbroek #if DIG_SIGCHASE_BU
5873*00b67f09SDavid van Moolenbroek 	sigchase_bu(msg);
5874*00b67f09SDavid van Moolenbroek 	return;
5875*00b67f09SDavid van Moolenbroek #endif
5876*00b67f09SDavid van Moolenbroek }
5877*00b67f09SDavid van Moolenbroek 
5878*00b67f09SDavid van Moolenbroek 
5879*00b67f09SDavid van Moolenbroek /*
5880*00b67f09SDavid van Moolenbroek  * return 1  if name1  <  name2
5881*00b67f09SDavid van Moolenbroek  *	  0  if name1  == name2
5882*00b67f09SDavid van Moolenbroek  *	  -1 if name1  >  name2
5883*00b67f09SDavid van Moolenbroek  *    and -2 if problem
5884*00b67f09SDavid van Moolenbroek  */
5885*00b67f09SDavid van Moolenbroek int
inf_name(dns_name_t * name1,dns_name_t * name2)5886*00b67f09SDavid van Moolenbroek inf_name(dns_name_t *name1, dns_name_t *name2)
5887*00b67f09SDavid van Moolenbroek {
5888*00b67f09SDavid van Moolenbroek 	dns_label_t  label1;
5889*00b67f09SDavid van Moolenbroek 	dns_label_t  label2;
5890*00b67f09SDavid van Moolenbroek 	unsigned int nblabel1;
5891*00b67f09SDavid van Moolenbroek 	unsigned int nblabel2;
5892*00b67f09SDavid van Moolenbroek 	int min_lum_label;
5893*00b67f09SDavid van Moolenbroek 	int i;
5894*00b67f09SDavid van Moolenbroek 	int ret = -2;
5895*00b67f09SDavid van Moolenbroek 
5896*00b67f09SDavid van Moolenbroek 	nblabel1 = dns_name_countlabels(name1);
5897*00b67f09SDavid van Moolenbroek 	nblabel2 = dns_name_countlabels(name2);
5898*00b67f09SDavid van Moolenbroek 
5899*00b67f09SDavid van Moolenbroek 	if (nblabel1 >= nblabel2)
5900*00b67f09SDavid van Moolenbroek 		min_lum_label = nblabel2;
5901*00b67f09SDavid van Moolenbroek 	else
5902*00b67f09SDavid van Moolenbroek 		min_lum_label = nblabel1;
5903*00b67f09SDavid van Moolenbroek 
5904*00b67f09SDavid van Moolenbroek 
5905*00b67f09SDavid van Moolenbroek 	for (i=1 ; i < min_lum_label; i++) {
5906*00b67f09SDavid van Moolenbroek 		dns_name_getlabel(name1, nblabel1 -1  - i, &label1);
5907*00b67f09SDavid van Moolenbroek 		dns_name_getlabel(name2, nblabel2 -1  - i, &label2);
5908*00b67f09SDavid van Moolenbroek 		if ((ret = isc_region_compare(&label1, &label2)) != 0) {
5909*00b67f09SDavid van Moolenbroek 			if (ret < 0)
5910*00b67f09SDavid van Moolenbroek 				return (-1);
5911*00b67f09SDavid van Moolenbroek 			else if (ret > 0)
5912*00b67f09SDavid van Moolenbroek 				return (1);
5913*00b67f09SDavid van Moolenbroek 		}
5914*00b67f09SDavid van Moolenbroek 	}
5915*00b67f09SDavid van Moolenbroek 	if (nblabel1 == nblabel2)
5916*00b67f09SDavid van Moolenbroek 		return (0);
5917*00b67f09SDavid van Moolenbroek 
5918*00b67f09SDavid van Moolenbroek 	if (nblabel1 < nblabel2)
5919*00b67f09SDavid van Moolenbroek 		return (-1);
5920*00b67f09SDavid van Moolenbroek 	else
5921*00b67f09SDavid van Moolenbroek 		return (1);
5922*00b67f09SDavid van Moolenbroek }
5923*00b67f09SDavid van Moolenbroek 
5924*00b67f09SDavid van Moolenbroek /**
5925*00b67f09SDavid van Moolenbroek  *
5926*00b67f09SDavid van Moolenbroek  *
5927*00b67f09SDavid van Moolenbroek  *
5928*00b67f09SDavid van Moolenbroek  */
5929*00b67f09SDavid van Moolenbroek isc_result_t
prove_nx_domain(dns_message_t * msg,dns_name_t * name,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)5930*00b67f09SDavid van Moolenbroek prove_nx_domain(dns_message_t *msg,
5931*00b67f09SDavid van Moolenbroek 		dns_name_t *name,
5932*00b67f09SDavid van Moolenbroek 		dns_name_t *rdata_name,
5933*00b67f09SDavid van Moolenbroek 		dns_rdataset_t **rdataset,
5934*00b67f09SDavid van Moolenbroek 		dns_rdataset_t **sigrdataset)
5935*00b67f09SDavid van Moolenbroek {
5936*00b67f09SDavid van Moolenbroek 	isc_result_t ret = ISC_R_FAILURE;
5937*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_NOTFOUND;
5938*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *nsecset = NULL;
5939*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *signsecset = NULL ;
5940*00b67f09SDavid van Moolenbroek 	dns_rdata_t nsec = DNS_RDATA_INIT;
5941*00b67f09SDavid van Moolenbroek 	dns_name_t *nsecname;
5942*00b67f09SDavid van Moolenbroek 	dns_rdata_nsec_t nsecstruct;
5943*00b67f09SDavid van Moolenbroek 
5944*00b67f09SDavid van Moolenbroek 	if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5945*00b67f09SDavid van Moolenbroek 	    != ISC_R_SUCCESS) {
5946*00b67f09SDavid van Moolenbroek 		printf(";; nothing in authority section : impossible to"
5947*00b67f09SDavid van Moolenbroek 		       " validate the non-existence : FAILED\n");
5948*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
5949*00b67f09SDavid van Moolenbroek 	}
5950*00b67f09SDavid van Moolenbroek 
5951*00b67f09SDavid van Moolenbroek 	do {
5952*00b67f09SDavid van Moolenbroek 		nsecname = NULL;
5953*00b67f09SDavid van Moolenbroek 		dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
5954*00b67f09SDavid van Moolenbroek 		nsecset = search_type(nsecname, dns_rdatatype_nsec,
5955*00b67f09SDavid van Moolenbroek 				      dns_rdatatype_any);
5956*00b67f09SDavid van Moolenbroek 		if (nsecset == NULL)
5957*00b67f09SDavid van Moolenbroek 			continue;
5958*00b67f09SDavid van Moolenbroek 
5959*00b67f09SDavid van Moolenbroek 		printf("There is a NSEC for this zone in the"
5960*00b67f09SDavid van Moolenbroek 		       " AUTHORITY section:\n");
5961*00b67f09SDavid van Moolenbroek 		print_rdataset(nsecname, nsecset, mctx);
5962*00b67f09SDavid van Moolenbroek 
5963*00b67f09SDavid van Moolenbroek 		for (result = dns_rdataset_first(nsecset);
5964*00b67f09SDavid van Moolenbroek 		     result == ISC_R_SUCCESS;
5965*00b67f09SDavid van Moolenbroek 		     result = dns_rdataset_next(nsecset)) {
5966*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(nsecset, &nsec);
5967*00b67f09SDavid van Moolenbroek 
5968*00b67f09SDavid van Moolenbroek 			signsecset
5969*00b67f09SDavid van Moolenbroek 				= chase_scanname_section(msg, nsecname,
5970*00b67f09SDavid van Moolenbroek 						 dns_rdatatype_rrsig,
5971*00b67f09SDavid van Moolenbroek 						 dns_rdatatype_nsec,
5972*00b67f09SDavid van Moolenbroek 						 DNS_SECTION_AUTHORITY);
5973*00b67f09SDavid van Moolenbroek 			if (signsecset == NULL) {
5974*00b67f09SDavid van Moolenbroek 				printf(";; no RRSIG NSEC in authority section:"
5975*00b67f09SDavid van Moolenbroek 				       " impossible to validate the "
5976*00b67f09SDavid van Moolenbroek 				       "non-existence: FAILED\n");
5977*00b67f09SDavid van Moolenbroek 				return (ISC_R_FAILURE);
5978*00b67f09SDavid van Moolenbroek 			}
5979*00b67f09SDavid van Moolenbroek 
5980*00b67f09SDavid van Moolenbroek 			ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
5981*00b67f09SDavid van Moolenbroek 			check_result(ret,"dns_rdata_tostruct");
5982*00b67f09SDavid van Moolenbroek 
5983*00b67f09SDavid van Moolenbroek 			if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
5984*00b67f09SDavid van Moolenbroek 			     inf_name(name, &nsecstruct.next) == 1) ||
5985*00b67f09SDavid van Moolenbroek 			    (inf_name(name, nsecname) == 1 &&
5986*00b67f09SDavid van Moolenbroek 			     inf_name(&nsecstruct.next, name) == 1)) {
5987*00b67f09SDavid van Moolenbroek 				dns_rdata_freestruct(&nsecstruct);
5988*00b67f09SDavid van Moolenbroek 				*rdataset = nsecset;
5989*00b67f09SDavid van Moolenbroek 				*sigrdataset = signsecset;
5990*00b67f09SDavid van Moolenbroek 				dup_name(nsecname, rdata_name, mctx);
5991*00b67f09SDavid van Moolenbroek 
5992*00b67f09SDavid van Moolenbroek 				return (ISC_R_SUCCESS);
5993*00b67f09SDavid van Moolenbroek 			}
5994*00b67f09SDavid van Moolenbroek 
5995*00b67f09SDavid van Moolenbroek 			dns_rdata_freestruct(&nsecstruct);
5996*00b67f09SDavid van Moolenbroek 			dns_rdata_reset(&nsec);
5997*00b67f09SDavid van Moolenbroek 		}
5998*00b67f09SDavid van Moolenbroek 	} while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
5999*00b67f09SDavid van Moolenbroek 		 == ISC_R_SUCCESS);
6000*00b67f09SDavid van Moolenbroek 
6001*00b67f09SDavid van Moolenbroek 	*rdataset = NULL;
6002*00b67f09SDavid van Moolenbroek 	*sigrdataset =  NULL;
6003*00b67f09SDavid van Moolenbroek 	rdata_name = NULL;
6004*00b67f09SDavid van Moolenbroek 	return (ISC_R_FAILURE);
6005*00b67f09SDavid van Moolenbroek }
6006*00b67f09SDavid van Moolenbroek 
6007*00b67f09SDavid van Moolenbroek /**
6008*00b67f09SDavid van Moolenbroek  *
6009*00b67f09SDavid van Moolenbroek  *
6010*00b67f09SDavid van Moolenbroek  *
6011*00b67f09SDavid van Moolenbroek  *
6012*00b67f09SDavid van Moolenbroek  *
6013*00b67f09SDavid van Moolenbroek  */
6014*00b67f09SDavid van Moolenbroek isc_result_t
prove_nx_type(dns_message_t * msg,dns_name_t * name,dns_rdataset_t * nsecset,dns_rdataclass_t class,dns_rdatatype_t type,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)6015*00b67f09SDavid van Moolenbroek prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
6016*00b67f09SDavid van Moolenbroek 	      dns_rdataclass_t class, dns_rdatatype_t type,
6017*00b67f09SDavid van Moolenbroek 	      dns_name_t *rdata_name, dns_rdataset_t **rdataset,
6018*00b67f09SDavid van Moolenbroek 	      dns_rdataset_t **sigrdataset)
6019*00b67f09SDavid van Moolenbroek {
6020*00b67f09SDavid van Moolenbroek 	isc_result_t ret;
6021*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *signsecset;
6022*00b67f09SDavid van Moolenbroek 	dns_rdata_t nsec = DNS_RDATA_INIT;
6023*00b67f09SDavid van Moolenbroek 
6024*00b67f09SDavid van Moolenbroek 	UNUSED(class);
6025*00b67f09SDavid van Moolenbroek 
6026*00b67f09SDavid van Moolenbroek 	ret = dns_rdataset_first(nsecset);
6027*00b67f09SDavid van Moolenbroek 	check_result(ret,"dns_rdataset_first");
6028*00b67f09SDavid van Moolenbroek 
6029*00b67f09SDavid van Moolenbroek 	dns_rdataset_current(nsecset, &nsec);
6030*00b67f09SDavid van Moolenbroek 
6031*00b67f09SDavid van Moolenbroek 	ret = dns_nsec_typepresent(&nsec, type);
6032*00b67f09SDavid van Moolenbroek 	if (ret == ISC_R_SUCCESS)
6033*00b67f09SDavid van Moolenbroek 		printf("OK the NSEC said that the type doesn't exist \n");
6034*00b67f09SDavid van Moolenbroek 
6035*00b67f09SDavid van Moolenbroek 	signsecset = chase_scanname_section(msg, name,
6036*00b67f09SDavid van Moolenbroek 					    dns_rdatatype_rrsig,
6037*00b67f09SDavid van Moolenbroek 					    dns_rdatatype_nsec,
6038*00b67f09SDavid van Moolenbroek 					    DNS_SECTION_AUTHORITY);
6039*00b67f09SDavid van Moolenbroek 	if (signsecset == NULL) {
6040*00b67f09SDavid van Moolenbroek 		printf("There isn't RRSIG NSEC for the zone \n");
6041*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
6042*00b67f09SDavid van Moolenbroek 	}
6043*00b67f09SDavid van Moolenbroek 	dup_name(name, rdata_name, mctx);
6044*00b67f09SDavid van Moolenbroek 	*rdataset = nsecset;
6045*00b67f09SDavid van Moolenbroek 	*sigrdataset = signsecset;
6046*00b67f09SDavid van Moolenbroek 
6047*00b67f09SDavid van Moolenbroek 	return (ret);
6048*00b67f09SDavid van Moolenbroek }
6049*00b67f09SDavid van Moolenbroek 
6050*00b67f09SDavid van Moolenbroek /**
6051*00b67f09SDavid van Moolenbroek  *
6052*00b67f09SDavid van Moolenbroek  *
6053*00b67f09SDavid van Moolenbroek  *
6054*00b67f09SDavid van Moolenbroek  *
6055*00b67f09SDavid van Moolenbroek  */
6056*00b67f09SDavid van Moolenbroek isc_result_t
prove_nx(dns_message_t * msg,dns_name_t * name,dns_rdataclass_t class,dns_rdatatype_t type,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)6057*00b67f09SDavid van Moolenbroek prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
6058*00b67f09SDavid van Moolenbroek 	 dns_rdatatype_t type, dns_name_t *rdata_name,
6059*00b67f09SDavid van Moolenbroek 	 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
6060*00b67f09SDavid van Moolenbroek {
6061*00b67f09SDavid van Moolenbroek 	isc_result_t ret;
6062*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *nsecset = NULL;
6063*00b67f09SDavid van Moolenbroek 
6064*00b67f09SDavid van Moolenbroek 	printf("We want to prove the non-existence of a type of rdata %d"
6065*00b67f09SDavid van Moolenbroek 	       " or of the zone: \n", type);
6066*00b67f09SDavid van Moolenbroek 
6067*00b67f09SDavid van Moolenbroek 	if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
6068*00b67f09SDavid van Moolenbroek 	    != ISC_R_SUCCESS) {
6069*00b67f09SDavid van Moolenbroek 		printf(";; nothing in authority section : impossible to"
6070*00b67f09SDavid van Moolenbroek 		       " validate the non-existence : FAILED\n");
6071*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
6072*00b67f09SDavid van Moolenbroek 	}
6073*00b67f09SDavid van Moolenbroek 
6074*00b67f09SDavid van Moolenbroek 	nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
6075*00b67f09SDavid van Moolenbroek 					 dns_rdatatype_any,
6076*00b67f09SDavid van Moolenbroek 					 DNS_SECTION_AUTHORITY);
6077*00b67f09SDavid van Moolenbroek 	if (nsecset != NULL) {
6078*00b67f09SDavid van Moolenbroek 		printf("We have a NSEC for this zone :OK\n");
6079*00b67f09SDavid van Moolenbroek 		ret = prove_nx_type(msg, name, nsecset, class,
6080*00b67f09SDavid van Moolenbroek 				    type, rdata_name, rdataset,
6081*00b67f09SDavid van Moolenbroek 				    sigrdataset);
6082*00b67f09SDavid van Moolenbroek 		if (ret != ISC_R_SUCCESS) {
6083*00b67f09SDavid van Moolenbroek 			printf("prove_nx: ERROR type exist\n");
6084*00b67f09SDavid van Moolenbroek 			return (ret);
6085*00b67f09SDavid van Moolenbroek 		} else {
6086*00b67f09SDavid van Moolenbroek 			printf("prove_nx: OK type does not exist\n");
6087*00b67f09SDavid van Moolenbroek 			return (ISC_R_SUCCESS);
6088*00b67f09SDavid van Moolenbroek 		}
6089*00b67f09SDavid van Moolenbroek 	} else {
6090*00b67f09SDavid van Moolenbroek 		printf("there is no NSEC for this zone: validating "
6091*00b67f09SDavid van Moolenbroek 		       "that the zone doesn't exist\n");
6092*00b67f09SDavid van Moolenbroek 		ret = prove_nx_domain(msg, name, rdata_name,
6093*00b67f09SDavid van Moolenbroek 				      rdataset, sigrdataset);
6094*00b67f09SDavid van Moolenbroek 		return (ret);
6095*00b67f09SDavid van Moolenbroek 	}
6096*00b67f09SDavid van Moolenbroek 	/* Never get here */
6097*00b67f09SDavid van Moolenbroek }
6098*00b67f09SDavid van Moolenbroek #endif
6099