xref: /dflybsd-src/contrib/ldns/resolver.c (revision 7733acb50455a11cc2ee36edd926ff0fa3361e9a)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * resolver.c
3825eb42bSJan Lentfer  *
4825eb42bSJan Lentfer  * resolver implementation
5825eb42bSJan Lentfer  *
6825eb42bSJan Lentfer  * a Net::DNS like library for C
7825eb42bSJan Lentfer  *
8825eb42bSJan Lentfer  * (c) NLnet Labs, 2004-2006
9825eb42bSJan Lentfer  *
10825eb42bSJan Lentfer  * See the file LICENSE for the license
11825eb42bSJan Lentfer  */
12825eb42bSJan Lentfer 
13825eb42bSJan Lentfer #include <ldns/config.h>
14825eb42bSJan Lentfer 
15825eb42bSJan Lentfer #include <ldns/ldns.h>
16825eb42bSJan Lentfer #include <strings.h>
17825eb42bSJan Lentfer 
18825eb42bSJan Lentfer /* Access function for reading
19825eb42bSJan Lentfer  * and setting the different Resolver
20825eb42bSJan Lentfer  * options */
21825eb42bSJan Lentfer 
22825eb42bSJan Lentfer /* read */
23825eb42bSJan Lentfer uint16_t
ldns_resolver_port(const ldns_resolver * r)24825eb42bSJan Lentfer ldns_resolver_port(const ldns_resolver *r)
25825eb42bSJan Lentfer {
26825eb42bSJan Lentfer 	return r->_port;
27825eb42bSJan Lentfer }
28825eb42bSJan Lentfer 
295340022aSzrj ldns_rdf *
ldns_resolver_source(const ldns_resolver * r)305340022aSzrj ldns_resolver_source(const ldns_resolver *r)
315340022aSzrj {
325340022aSzrj 	return r->_source;
335340022aSzrj }
345340022aSzrj 
35825eb42bSJan Lentfer uint16_t
ldns_resolver_edns_udp_size(const ldns_resolver * r)36825eb42bSJan Lentfer ldns_resolver_edns_udp_size(const ldns_resolver *r)
37825eb42bSJan Lentfer {
38825eb42bSJan Lentfer 	        return r->_edns_udp_size;
39825eb42bSJan Lentfer }
40825eb42bSJan Lentfer 
41825eb42bSJan Lentfer uint8_t
ldns_resolver_retry(const ldns_resolver * r)42825eb42bSJan Lentfer ldns_resolver_retry(const ldns_resolver *r)
43825eb42bSJan Lentfer {
44825eb42bSJan Lentfer 	return r->_retry;
45825eb42bSJan Lentfer }
46825eb42bSJan Lentfer 
47825eb42bSJan Lentfer uint8_t
ldns_resolver_retrans(const ldns_resolver * r)48825eb42bSJan Lentfer ldns_resolver_retrans(const ldns_resolver *r)
49825eb42bSJan Lentfer {
50825eb42bSJan Lentfer 	return r->_retrans;
51825eb42bSJan Lentfer }
52825eb42bSJan Lentfer 
53825eb42bSJan Lentfer bool
ldns_resolver_fallback(const ldns_resolver * r)54825eb42bSJan Lentfer ldns_resolver_fallback(const ldns_resolver *r)
55825eb42bSJan Lentfer {
56825eb42bSJan Lentfer 	return r->_fallback;
57825eb42bSJan Lentfer }
58825eb42bSJan Lentfer 
59825eb42bSJan Lentfer uint8_t
ldns_resolver_ip6(const ldns_resolver * r)60825eb42bSJan Lentfer ldns_resolver_ip6(const ldns_resolver *r)
61825eb42bSJan Lentfer {
62825eb42bSJan Lentfer 	return r->_ip6;
63825eb42bSJan Lentfer }
64825eb42bSJan Lentfer 
65825eb42bSJan Lentfer bool
ldns_resolver_recursive(const ldns_resolver * r)66825eb42bSJan Lentfer ldns_resolver_recursive(const ldns_resolver *r)
67825eb42bSJan Lentfer {
68825eb42bSJan Lentfer 	return r->_recursive;
69825eb42bSJan Lentfer }
70825eb42bSJan Lentfer 
71825eb42bSJan Lentfer bool
ldns_resolver_debug(const ldns_resolver * r)72825eb42bSJan Lentfer ldns_resolver_debug(const ldns_resolver *r)
73825eb42bSJan Lentfer {
74825eb42bSJan Lentfer 	return r->_debug;
75825eb42bSJan Lentfer }
76825eb42bSJan Lentfer 
77825eb42bSJan Lentfer bool
ldns_resolver_dnsrch(const ldns_resolver * r)78825eb42bSJan Lentfer ldns_resolver_dnsrch(const ldns_resolver *r)
79825eb42bSJan Lentfer {
80825eb42bSJan Lentfer 	return r->_dnsrch;
81825eb42bSJan Lentfer }
82825eb42bSJan Lentfer 
83825eb42bSJan Lentfer bool
ldns_resolver_fail(const ldns_resolver * r)84825eb42bSJan Lentfer ldns_resolver_fail(const ldns_resolver *r)
85825eb42bSJan Lentfer {
86825eb42bSJan Lentfer 	return r->_fail;
87825eb42bSJan Lentfer }
88825eb42bSJan Lentfer 
89825eb42bSJan Lentfer bool
ldns_resolver_defnames(const ldns_resolver * r)90825eb42bSJan Lentfer ldns_resolver_defnames(const ldns_resolver *r)
91825eb42bSJan Lentfer {
92825eb42bSJan Lentfer 	return r->_defnames;
93825eb42bSJan Lentfer }
94825eb42bSJan Lentfer 
95825eb42bSJan Lentfer ldns_rdf *
ldns_resolver_domain(const ldns_resolver * r)96825eb42bSJan Lentfer ldns_resolver_domain(const ldns_resolver *r)
97825eb42bSJan Lentfer {
98825eb42bSJan Lentfer 	return r->_domain;
99825eb42bSJan Lentfer }
100825eb42bSJan Lentfer 
101825eb42bSJan Lentfer ldns_rdf **
ldns_resolver_searchlist(const ldns_resolver * r)102825eb42bSJan Lentfer ldns_resolver_searchlist(const ldns_resolver *r)
103825eb42bSJan Lentfer {
104825eb42bSJan Lentfer 	return r->_searchlist;
105825eb42bSJan Lentfer }
106825eb42bSJan Lentfer 
107825eb42bSJan Lentfer ldns_rdf **
ldns_resolver_nameservers(const ldns_resolver * r)108825eb42bSJan Lentfer ldns_resolver_nameservers(const ldns_resolver *r)
109825eb42bSJan Lentfer {
110825eb42bSJan Lentfer 	return r->_nameservers;
111825eb42bSJan Lentfer }
112825eb42bSJan Lentfer 
113825eb42bSJan Lentfer size_t
ldns_resolver_nameserver_count(const ldns_resolver * r)114825eb42bSJan Lentfer ldns_resolver_nameserver_count(const ldns_resolver *r)
115825eb42bSJan Lentfer {
116825eb42bSJan Lentfer 	return r->_nameserver_count;
117825eb42bSJan Lentfer }
118825eb42bSJan Lentfer 
119825eb42bSJan Lentfer bool
ldns_resolver_dnssec(const ldns_resolver * r)120825eb42bSJan Lentfer ldns_resolver_dnssec(const ldns_resolver *r)
121825eb42bSJan Lentfer {
122825eb42bSJan Lentfer 	return r->_dnssec;
123825eb42bSJan Lentfer }
124825eb42bSJan Lentfer 
125825eb42bSJan Lentfer bool
ldns_resolver_dnssec_cd(const ldns_resolver * r)126825eb42bSJan Lentfer ldns_resolver_dnssec_cd(const ldns_resolver *r)
127825eb42bSJan Lentfer {
128825eb42bSJan Lentfer 	return r->_dnssec_cd;
129825eb42bSJan Lentfer }
130825eb42bSJan Lentfer 
131825eb42bSJan Lentfer ldns_rr_list *
ldns_resolver_dnssec_anchors(const ldns_resolver * r)132825eb42bSJan Lentfer ldns_resolver_dnssec_anchors(const ldns_resolver *r)
133825eb42bSJan Lentfer {
134825eb42bSJan Lentfer     return r->_dnssec_anchors;
135825eb42bSJan Lentfer }
136825eb42bSJan Lentfer 
137825eb42bSJan Lentfer bool
ldns_resolver_trusted_key(const ldns_resolver * r,ldns_rr_list * keys,ldns_rr_list * trusted_keys)138825eb42bSJan Lentfer ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
139825eb42bSJan Lentfer {
140825eb42bSJan Lentfer   size_t i;
141825eb42bSJan Lentfer   bool result = false;
142825eb42bSJan Lentfer 
143825eb42bSJan Lentfer   ldns_rr_list * trust_anchors;
144825eb42bSJan Lentfer   ldns_rr * cur_rr;
145825eb42bSJan Lentfer 
146825eb42bSJan Lentfer   if (!r || !keys) { return false; }
147825eb42bSJan Lentfer 
148825eb42bSJan Lentfer   trust_anchors = ldns_resolver_dnssec_anchors(r);
149825eb42bSJan Lentfer 
150825eb42bSJan Lentfer   if (!trust_anchors) { return false; }
151825eb42bSJan Lentfer 
152825eb42bSJan Lentfer   for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
153825eb42bSJan Lentfer 
154825eb42bSJan Lentfer     cur_rr = ldns_rr_list_rr(keys, i);
155825eb42bSJan Lentfer     if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
156825eb42bSJan Lentfer       if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
157825eb42bSJan Lentfer       result = true;
158825eb42bSJan Lentfer     }
159825eb42bSJan Lentfer   }
160825eb42bSJan Lentfer 
161825eb42bSJan Lentfer   return result;
162825eb42bSJan Lentfer }
163825eb42bSJan Lentfer 
164825eb42bSJan Lentfer bool
ldns_resolver_igntc(const ldns_resolver * r)165825eb42bSJan Lentfer ldns_resolver_igntc(const ldns_resolver *r)
166825eb42bSJan Lentfer {
167825eb42bSJan Lentfer 	return r->_igntc;
168825eb42bSJan Lentfer }
169825eb42bSJan Lentfer 
170825eb42bSJan Lentfer bool
ldns_resolver_usevc(const ldns_resolver * r)171825eb42bSJan Lentfer ldns_resolver_usevc(const ldns_resolver *r)
172825eb42bSJan Lentfer {
173825eb42bSJan Lentfer 	return r->_usevc;
174825eb42bSJan Lentfer }
175825eb42bSJan Lentfer 
176825eb42bSJan Lentfer size_t *
ldns_resolver_rtt(const ldns_resolver * r)177825eb42bSJan Lentfer ldns_resolver_rtt(const ldns_resolver *r)
178825eb42bSJan Lentfer {
179825eb42bSJan Lentfer 	return r->_rtt;
180825eb42bSJan Lentfer }
181825eb42bSJan Lentfer 
182825eb42bSJan Lentfer size_t
ldns_resolver_nameserver_rtt(const ldns_resolver * r,size_t pos)183825eb42bSJan Lentfer ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
184825eb42bSJan Lentfer {
185825eb42bSJan Lentfer 	size_t *rtt;
186825eb42bSJan Lentfer 
187825eb42bSJan Lentfer 	assert(r != NULL);
188825eb42bSJan Lentfer 
189825eb42bSJan Lentfer 	rtt = ldns_resolver_rtt(r);
190825eb42bSJan Lentfer 
191825eb42bSJan Lentfer 	if (pos >= ldns_resolver_nameserver_count(r)) {
192825eb42bSJan Lentfer 		/* error ?*/
193825eb42bSJan Lentfer 		return 0;
194825eb42bSJan Lentfer 	} else {
195825eb42bSJan Lentfer 		return rtt[pos];
196825eb42bSJan Lentfer 	}
197825eb42bSJan Lentfer 
198825eb42bSJan Lentfer }
199825eb42bSJan Lentfer 
200825eb42bSJan Lentfer struct timeval
ldns_resolver_timeout(const ldns_resolver * r)201825eb42bSJan Lentfer ldns_resolver_timeout(const ldns_resolver *r)
202825eb42bSJan Lentfer {
203825eb42bSJan Lentfer 	return r->_timeout;
204825eb42bSJan Lentfer }
205825eb42bSJan Lentfer 
2065340022aSzrj const char *
ldns_resolver_tsig_keyname(const ldns_resolver * r)207825eb42bSJan Lentfer ldns_resolver_tsig_keyname(const ldns_resolver *r)
208825eb42bSJan Lentfer {
209825eb42bSJan Lentfer 	return r->_tsig_keyname;
210825eb42bSJan Lentfer }
211825eb42bSJan Lentfer 
2125340022aSzrj const char *
ldns_resolver_tsig_algorithm(const ldns_resolver * r)213825eb42bSJan Lentfer ldns_resolver_tsig_algorithm(const ldns_resolver *r)
214825eb42bSJan Lentfer {
215825eb42bSJan Lentfer 	return r->_tsig_algorithm;
216825eb42bSJan Lentfer }
217825eb42bSJan Lentfer 
2185340022aSzrj const char *
ldns_resolver_tsig_keydata(const ldns_resolver * r)219825eb42bSJan Lentfer ldns_resolver_tsig_keydata(const ldns_resolver *r)
220825eb42bSJan Lentfer {
221825eb42bSJan Lentfer 	return r->_tsig_keydata;
222825eb42bSJan Lentfer }
223825eb42bSJan Lentfer 
224825eb42bSJan Lentfer bool
ldns_resolver_random(const ldns_resolver * r)225825eb42bSJan Lentfer ldns_resolver_random(const ldns_resolver *r)
226825eb42bSJan Lentfer {
227825eb42bSJan Lentfer 	return r->_random;
228825eb42bSJan Lentfer }
229825eb42bSJan Lentfer 
230825eb42bSJan Lentfer size_t
ldns_resolver_searchlist_count(const ldns_resolver * r)231825eb42bSJan Lentfer ldns_resolver_searchlist_count(const ldns_resolver *r)
232825eb42bSJan Lentfer {
233825eb42bSJan Lentfer 	return r->_searchlist_count;
234825eb42bSJan Lentfer }
235825eb42bSJan Lentfer 
236825eb42bSJan Lentfer /* write */
237825eb42bSJan Lentfer void
ldns_resolver_set_port(ldns_resolver * r,uint16_t p)238825eb42bSJan Lentfer ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
239825eb42bSJan Lentfer {
240825eb42bSJan Lentfer 	r->_port = p;
241825eb42bSJan Lentfer }
242825eb42bSJan Lentfer 
2435340022aSzrj void
ldns_resolver_set_source(ldns_resolver * r,ldns_rdf * s)2445340022aSzrj ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
2455340022aSzrj {
2465340022aSzrj 	r->_source = s;
2475340022aSzrj }
2485340022aSzrj 
249825eb42bSJan Lentfer ldns_rdf *
ldns_resolver_pop_nameserver(ldns_resolver * r)250825eb42bSJan Lentfer ldns_resolver_pop_nameserver(ldns_resolver *r)
251825eb42bSJan Lentfer {
252825eb42bSJan Lentfer 	ldns_rdf **nameservers;
253825eb42bSJan Lentfer 	ldns_rdf *pop;
254825eb42bSJan Lentfer 	size_t ns_count;
255825eb42bSJan Lentfer 	size_t *rtt;
256825eb42bSJan Lentfer 
257825eb42bSJan Lentfer 	assert(r != NULL);
258825eb42bSJan Lentfer 
259825eb42bSJan Lentfer 	ns_count = ldns_resolver_nameserver_count(r);
260825eb42bSJan Lentfer 	nameservers = ldns_resolver_nameservers(r);
261825eb42bSJan Lentfer 	rtt = ldns_resolver_rtt(r);
262825eb42bSJan Lentfer 	if (ns_count == 0 || !nameservers) {
263825eb42bSJan Lentfer 		return NULL;
264825eb42bSJan Lentfer 	}
265825eb42bSJan Lentfer 
266825eb42bSJan Lentfer 	pop = nameservers[ns_count - 1];
267825eb42bSJan Lentfer 
268d1b2b5caSJohn Marino 	if (ns_count == 1) {
269d1b2b5caSJohn Marino 		LDNS_FREE(nameservers);
270d1b2b5caSJohn Marino 		LDNS_FREE(rtt);
271d1b2b5caSJohn Marino 
272d1b2b5caSJohn Marino 		ldns_resolver_set_nameservers(r, NULL);
273d1b2b5caSJohn Marino 		ldns_resolver_set_rtt(r, NULL);
274d1b2b5caSJohn Marino 	} else {
275d1b2b5caSJohn Marino 		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *,
276d1b2b5caSJohn Marino 				(ns_count - 1));
277825eb42bSJan Lentfer 		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
278825eb42bSJan Lentfer 
279825eb42bSJan Lentfer 	        ldns_resolver_set_nameservers(r, nameservers);
280825eb42bSJan Lentfer 	        ldns_resolver_set_rtt(r, rtt);
281d1b2b5caSJohn Marino 	}
282825eb42bSJan Lentfer 	/* decr the count */
283825eb42bSJan Lentfer 	ldns_resolver_dec_nameserver_count(r);
284825eb42bSJan Lentfer 	return pop;
285825eb42bSJan Lentfer }
286825eb42bSJan Lentfer 
287825eb42bSJan Lentfer ldns_status
ldns_resolver_push_nameserver(ldns_resolver * r,const ldns_rdf * n)2885340022aSzrj ldns_resolver_push_nameserver(ldns_resolver *r, const ldns_rdf *n)
289825eb42bSJan Lentfer {
290825eb42bSJan Lentfer 	ldns_rdf **nameservers;
291825eb42bSJan Lentfer 	size_t ns_count;
292825eb42bSJan Lentfer 	size_t *rtt;
293825eb42bSJan Lentfer 
294825eb42bSJan Lentfer 	if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
295825eb42bSJan Lentfer 			ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
296825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
297825eb42bSJan Lentfer 	}
298825eb42bSJan Lentfer 
299825eb42bSJan Lentfer 	ns_count = ldns_resolver_nameserver_count(r);
300825eb42bSJan Lentfer 	nameservers = ldns_resolver_nameservers(r);
301825eb42bSJan Lentfer 	rtt = ldns_resolver_rtt(r);
302825eb42bSJan Lentfer 
303825eb42bSJan Lentfer 	/* make room for the next one */
304fd185f4dSJan Lentfer 	if (ns_count == 0) {
305fd185f4dSJan Lentfer 		nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
306fd185f4dSJan Lentfer 	} else {
307825eb42bSJan Lentfer 		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
308fd185f4dSJan Lentfer 	}
309fd185f4dSJan Lentfer         if(!nameservers)
310fd185f4dSJan Lentfer                 return LDNS_STATUS_MEM_ERR;
311825eb42bSJan Lentfer 
312825eb42bSJan Lentfer 	/* set the new value in the resolver */
313825eb42bSJan Lentfer 	ldns_resolver_set_nameservers(r, nameservers);
314825eb42bSJan Lentfer 
315fd185f4dSJan Lentfer 	/* don't forget the rtt */
316fd185f4dSJan Lentfer 	if (ns_count == 0) {
317fd185f4dSJan Lentfer 		rtt = LDNS_XMALLOC(size_t, 1);
318fd185f4dSJan Lentfer 	} else {
319fd185f4dSJan Lentfer 		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
320fd185f4dSJan Lentfer 	}
321fd185f4dSJan Lentfer         if(!rtt)
322fd185f4dSJan Lentfer                 return LDNS_STATUS_MEM_ERR;
323fd185f4dSJan Lentfer 
324825eb42bSJan Lentfer 	/* slide n in its slot. */
325825eb42bSJan Lentfer 	/* we clone it here, because then we can free the original
326825eb42bSJan Lentfer 	 * rr's where it stood */
327825eb42bSJan Lentfer 	nameservers[ns_count] = ldns_rdf_clone(n);
328825eb42bSJan Lentfer 	rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
329825eb42bSJan Lentfer 	ldns_resolver_incr_nameserver_count(r);
330825eb42bSJan Lentfer 	ldns_resolver_set_rtt(r, rtt);
331825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
332825eb42bSJan Lentfer }
333825eb42bSJan Lentfer 
334825eb42bSJan Lentfer ldns_status
ldns_resolver_push_nameserver_rr(ldns_resolver * r,const ldns_rr * rr)3355340022aSzrj ldns_resolver_push_nameserver_rr(ldns_resolver *r, const ldns_rr *rr)
336825eb42bSJan Lentfer {
337825eb42bSJan Lentfer 	ldns_rdf *address;
338825eb42bSJan Lentfer 	if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
339825eb42bSJan Lentfer 			ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
340825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
341825eb42bSJan Lentfer 	}
342825eb42bSJan Lentfer 	address = ldns_rr_rdf(rr, 0); /* extract the ip number */
343825eb42bSJan Lentfer 	if (address) {
344825eb42bSJan Lentfer 		return ldns_resolver_push_nameserver(r, address);
345825eb42bSJan Lentfer 	} else {
346825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
347825eb42bSJan Lentfer 	}
348825eb42bSJan Lentfer }
349825eb42bSJan Lentfer 
350825eb42bSJan Lentfer ldns_status
ldns_resolver_push_nameserver_rr_list(ldns_resolver * r,const ldns_rr_list * rrlist)3515340022aSzrj ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, const ldns_rr_list *rrlist)
352825eb42bSJan Lentfer {
353825eb42bSJan Lentfer 	ldns_rr *rr;
354825eb42bSJan Lentfer 	ldns_status stat;
355825eb42bSJan Lentfer 	size_t i;
356825eb42bSJan Lentfer 
357825eb42bSJan Lentfer 	stat = LDNS_STATUS_OK;
358825eb42bSJan Lentfer 	if (rrlist) {
359825eb42bSJan Lentfer 		for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
360825eb42bSJan Lentfer 			rr = ldns_rr_list_rr(rrlist, i);
361825eb42bSJan Lentfer 			if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
362825eb42bSJan Lentfer 				stat = LDNS_STATUS_ERR;
363fd185f4dSJan Lentfer 				break;
364825eb42bSJan Lentfer 			}
365825eb42bSJan Lentfer 		}
366825eb42bSJan Lentfer 		return stat;
367825eb42bSJan Lentfer 	} else {
368825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
369825eb42bSJan Lentfer 	}
370825eb42bSJan Lentfer }
371825eb42bSJan Lentfer 
372825eb42bSJan Lentfer void
ldns_resolver_set_edns_udp_size(ldns_resolver * r,uint16_t s)373825eb42bSJan Lentfer ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
374825eb42bSJan Lentfer {
375825eb42bSJan Lentfer 	        r->_edns_udp_size = s;
376825eb42bSJan Lentfer }
377825eb42bSJan Lentfer 
378825eb42bSJan Lentfer void
ldns_resolver_set_recursive(ldns_resolver * r,bool re)379825eb42bSJan Lentfer ldns_resolver_set_recursive(ldns_resolver *r, bool re)
380825eb42bSJan Lentfer {
381825eb42bSJan Lentfer 	r->_recursive = re;
382825eb42bSJan Lentfer }
383825eb42bSJan Lentfer 
384825eb42bSJan Lentfer void
ldns_resolver_set_dnssec(ldns_resolver * r,bool d)385825eb42bSJan Lentfer ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
386825eb42bSJan Lentfer {
387825eb42bSJan Lentfer 	r->_dnssec = d;
388825eb42bSJan Lentfer }
389825eb42bSJan Lentfer 
390825eb42bSJan Lentfer void
ldns_resolver_set_dnssec_cd(ldns_resolver * r,bool d)391825eb42bSJan Lentfer ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
392825eb42bSJan Lentfer {
393825eb42bSJan Lentfer 	r->_dnssec_cd = d;
394825eb42bSJan Lentfer }
395825eb42bSJan Lentfer 
396825eb42bSJan Lentfer void
ldns_resolver_set_dnssec_anchors(ldns_resolver * r,ldns_rr_list * l)397825eb42bSJan Lentfer ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
398825eb42bSJan Lentfer {
399825eb42bSJan Lentfer   r->_dnssec_anchors = l;
400825eb42bSJan Lentfer }
401825eb42bSJan Lentfer 
402825eb42bSJan Lentfer ldns_status
ldns_resolver_push_dnssec_anchor(ldns_resolver * r,ldns_rr * rr)403825eb42bSJan Lentfer ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
404825eb42bSJan Lentfer {
405825eb42bSJan Lentfer   ldns_rr_list * trust_anchors;
406825eb42bSJan Lentfer 
407d1b2b5caSJohn Marino   if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
408d1b2b5caSJohn Marino                 ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
409d1b2b5caSJohn Marino 
410825eb42bSJan Lentfer     return LDNS_STATUS_ERR;
411825eb42bSJan Lentfer   }
412825eb42bSJan Lentfer 
413825eb42bSJan Lentfer   if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
414825eb42bSJan Lentfer     trust_anchors = ldns_rr_list_new();
415825eb42bSJan Lentfer     ldns_resolver_set_dnssec_anchors(r, trust_anchors);
416825eb42bSJan Lentfer   }
417825eb42bSJan Lentfer 
418825eb42bSJan Lentfer   return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
419825eb42bSJan Lentfer }
420825eb42bSJan Lentfer 
421825eb42bSJan Lentfer void
ldns_resolver_set_igntc(ldns_resolver * r,bool i)422825eb42bSJan Lentfer ldns_resolver_set_igntc(ldns_resolver *r, bool i)
423825eb42bSJan Lentfer {
424825eb42bSJan Lentfer 	r->_igntc = i;
425825eb42bSJan Lentfer }
426825eb42bSJan Lentfer 
427825eb42bSJan Lentfer void
ldns_resolver_set_usevc(ldns_resolver * r,bool vc)428825eb42bSJan Lentfer ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
429825eb42bSJan Lentfer {
430825eb42bSJan Lentfer 	r->_usevc = vc;
431825eb42bSJan Lentfer }
432825eb42bSJan Lentfer 
433825eb42bSJan Lentfer void
ldns_resolver_set_debug(ldns_resolver * r,bool d)434825eb42bSJan Lentfer ldns_resolver_set_debug(ldns_resolver *r, bool d)
435825eb42bSJan Lentfer {
436825eb42bSJan Lentfer 	r->_debug = d;
437825eb42bSJan Lentfer }
438825eb42bSJan Lentfer 
439825eb42bSJan Lentfer void
ldns_resolver_set_ip6(ldns_resolver * r,uint8_t ip6)440825eb42bSJan Lentfer ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
441825eb42bSJan Lentfer {
442825eb42bSJan Lentfer 	r->_ip6 = ip6;
443825eb42bSJan Lentfer }
444825eb42bSJan Lentfer 
445825eb42bSJan Lentfer void
ldns_resolver_set_fail(ldns_resolver * r,bool f)446825eb42bSJan Lentfer ldns_resolver_set_fail(ldns_resolver *r, bool f)
447825eb42bSJan Lentfer {
448825eb42bSJan Lentfer 	r->_fail =f;
449825eb42bSJan Lentfer }
450825eb42bSJan Lentfer 
4515340022aSzrj static void
ldns_resolver_set_searchlist_count(ldns_resolver * r,size_t c)452825eb42bSJan Lentfer ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
453825eb42bSJan Lentfer {
454825eb42bSJan Lentfer 	r->_searchlist_count = c;
455825eb42bSJan Lentfer }
456825eb42bSJan Lentfer 
457825eb42bSJan Lentfer void
ldns_resolver_set_nameserver_count(ldns_resolver * r,size_t c)458825eb42bSJan Lentfer ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
459825eb42bSJan Lentfer {
460825eb42bSJan Lentfer 	r->_nameserver_count = c;
461825eb42bSJan Lentfer }
462825eb42bSJan Lentfer 
463825eb42bSJan Lentfer void
ldns_resolver_set_dnsrch(ldns_resolver * r,bool d)464825eb42bSJan Lentfer ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
465825eb42bSJan Lentfer {
466825eb42bSJan Lentfer 	r->_dnsrch = d;
467825eb42bSJan Lentfer }
468825eb42bSJan Lentfer 
469825eb42bSJan Lentfer void
ldns_resolver_set_retry(ldns_resolver * r,uint8_t retry)470825eb42bSJan Lentfer ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
471825eb42bSJan Lentfer {
472825eb42bSJan Lentfer 	r->_retry = retry;
473825eb42bSJan Lentfer }
474825eb42bSJan Lentfer 
475825eb42bSJan Lentfer void
ldns_resolver_set_retrans(ldns_resolver * r,uint8_t retrans)476825eb42bSJan Lentfer ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
477825eb42bSJan Lentfer {
478825eb42bSJan Lentfer 	r->_retrans = retrans;
479825eb42bSJan Lentfer }
480825eb42bSJan Lentfer 
481825eb42bSJan Lentfer void
ldns_resolver_set_fallback(ldns_resolver * r,bool fallback)482825eb42bSJan Lentfer ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
483825eb42bSJan Lentfer {
484825eb42bSJan Lentfer 	r->_fallback = fallback;
485825eb42bSJan Lentfer }
486825eb42bSJan Lentfer 
487825eb42bSJan Lentfer void
ldns_resolver_set_nameservers(ldns_resolver * r,ldns_rdf ** n)488825eb42bSJan Lentfer ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
489825eb42bSJan Lentfer {
490825eb42bSJan Lentfer 	r->_nameservers = n;
491825eb42bSJan Lentfer }
492825eb42bSJan Lentfer 
493825eb42bSJan Lentfer void
ldns_resolver_set_defnames(ldns_resolver * r,bool d)494825eb42bSJan Lentfer ldns_resolver_set_defnames(ldns_resolver *r, bool d)
495825eb42bSJan Lentfer {
496825eb42bSJan Lentfer 	r->_defnames = d;
497825eb42bSJan Lentfer }
498825eb42bSJan Lentfer 
499825eb42bSJan Lentfer void
ldns_resolver_set_rtt(ldns_resolver * r,size_t * rtt)500825eb42bSJan Lentfer ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
501825eb42bSJan Lentfer {
502825eb42bSJan Lentfer 	r->_rtt = rtt;
503825eb42bSJan Lentfer }
504825eb42bSJan Lentfer 
505825eb42bSJan Lentfer void
ldns_resolver_set_nameserver_rtt(ldns_resolver * r,size_t pos,size_t value)506825eb42bSJan Lentfer ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
507825eb42bSJan Lentfer {
508825eb42bSJan Lentfer 	size_t *rtt;
509825eb42bSJan Lentfer 
510825eb42bSJan Lentfer 	assert(r != NULL);
511825eb42bSJan Lentfer 
512825eb42bSJan Lentfer 	rtt = ldns_resolver_rtt(r);
513825eb42bSJan Lentfer 
514825eb42bSJan Lentfer 	if (pos >= ldns_resolver_nameserver_count(r)) {
515825eb42bSJan Lentfer 		/* error ?*/
516825eb42bSJan Lentfer 	} else {
517825eb42bSJan Lentfer 		rtt[pos] = value;
518825eb42bSJan Lentfer 	}
519825eb42bSJan Lentfer 
520825eb42bSJan Lentfer }
521825eb42bSJan Lentfer 
522825eb42bSJan Lentfer void
ldns_resolver_incr_nameserver_count(ldns_resolver * r)523825eb42bSJan Lentfer ldns_resolver_incr_nameserver_count(ldns_resolver *r)
524825eb42bSJan Lentfer {
525825eb42bSJan Lentfer 	size_t c;
526825eb42bSJan Lentfer 
527825eb42bSJan Lentfer 	c = ldns_resolver_nameserver_count(r);
528825eb42bSJan Lentfer 	ldns_resolver_set_nameserver_count(r, ++c);
529825eb42bSJan Lentfer }
530825eb42bSJan Lentfer 
531825eb42bSJan Lentfer void
ldns_resolver_dec_nameserver_count(ldns_resolver * r)532825eb42bSJan Lentfer ldns_resolver_dec_nameserver_count(ldns_resolver *r)
533825eb42bSJan Lentfer {
534825eb42bSJan Lentfer 	size_t c;
535825eb42bSJan Lentfer 
536825eb42bSJan Lentfer 	c = ldns_resolver_nameserver_count(r);
537825eb42bSJan Lentfer 	if (c == 0) {
538825eb42bSJan Lentfer 		return;
539825eb42bSJan Lentfer 	} else {
540825eb42bSJan Lentfer 		ldns_resolver_set_nameserver_count(r, --c);
541825eb42bSJan Lentfer 	}
542825eb42bSJan Lentfer }
543825eb42bSJan Lentfer 
544825eb42bSJan Lentfer void
ldns_resolver_set_domain(ldns_resolver * r,ldns_rdf * d)545825eb42bSJan Lentfer ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
546825eb42bSJan Lentfer {
547825eb42bSJan Lentfer 	r->_domain = d;
548825eb42bSJan Lentfer }
549825eb42bSJan Lentfer 
550825eb42bSJan Lentfer void
ldns_resolver_set_timeout(ldns_resolver * r,struct timeval timeout)551825eb42bSJan Lentfer ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
552825eb42bSJan Lentfer {
553825eb42bSJan Lentfer 	r->_timeout.tv_sec = timeout.tv_sec;
554825eb42bSJan Lentfer 	r->_timeout.tv_usec = timeout.tv_usec;
555825eb42bSJan Lentfer }
556825eb42bSJan Lentfer 
557825eb42bSJan Lentfer void
ldns_resolver_push_searchlist(ldns_resolver * r,ldns_rdf * d)558825eb42bSJan Lentfer ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
559825eb42bSJan Lentfer {
560825eb42bSJan Lentfer 	ldns_rdf **searchlist;
561825eb42bSJan Lentfer 	size_t list_count;
562825eb42bSJan Lentfer 
563825eb42bSJan Lentfer 	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
564825eb42bSJan Lentfer 		return;
565825eb42bSJan Lentfer 	}
566825eb42bSJan Lentfer 
567825eb42bSJan Lentfer 	list_count = ldns_resolver_searchlist_count(r);
568825eb42bSJan Lentfer 	searchlist = ldns_resolver_searchlist(r);
569825eb42bSJan Lentfer 
570825eb42bSJan Lentfer 	searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
571825eb42bSJan Lentfer 	if (searchlist) {
572825eb42bSJan Lentfer 		r->_searchlist = searchlist;
573825eb42bSJan Lentfer 
574825eb42bSJan Lentfer 		searchlist[list_count] = ldns_rdf_clone(d);
575825eb42bSJan Lentfer 		ldns_resolver_set_searchlist_count(r, list_count + 1);
576fd185f4dSJan Lentfer 	} /* no way to report mem err */
577825eb42bSJan Lentfer }
578825eb42bSJan Lentfer 
579825eb42bSJan Lentfer void
ldns_resolver_set_tsig_keyname(ldns_resolver * r,const char * tsig_keyname)5805340022aSzrj ldns_resolver_set_tsig_keyname(ldns_resolver *r, const char *tsig_keyname)
581825eb42bSJan Lentfer {
582ac996e71SJan Lentfer 	LDNS_FREE(r->_tsig_keyname);
583ac996e71SJan Lentfer 	r->_tsig_keyname = strdup(tsig_keyname);
584825eb42bSJan Lentfer }
585825eb42bSJan Lentfer 
586825eb42bSJan Lentfer void
ldns_resolver_set_tsig_algorithm(ldns_resolver * r,const char * tsig_algorithm)5875340022aSzrj ldns_resolver_set_tsig_algorithm(ldns_resolver *r, const char *tsig_algorithm)
588825eb42bSJan Lentfer {
589ac996e71SJan Lentfer 	LDNS_FREE(r->_tsig_algorithm);
590ac996e71SJan Lentfer 	r->_tsig_algorithm = strdup(tsig_algorithm);
591825eb42bSJan Lentfer }
592825eb42bSJan Lentfer 
593825eb42bSJan Lentfer void
ldns_resolver_set_tsig_keydata(ldns_resolver * r,const char * tsig_keydata)5945340022aSzrj ldns_resolver_set_tsig_keydata(ldns_resolver *r, const char *tsig_keydata)
595825eb42bSJan Lentfer {
596ac996e71SJan Lentfer 	LDNS_FREE(r->_tsig_keydata);
597ac996e71SJan Lentfer 	r->_tsig_keydata = strdup(tsig_keydata);
598825eb42bSJan Lentfer }
599825eb42bSJan Lentfer 
600825eb42bSJan Lentfer void
ldns_resolver_set_random(ldns_resolver * r,bool b)601825eb42bSJan Lentfer ldns_resolver_set_random(ldns_resolver *r, bool b)
602825eb42bSJan Lentfer {
603825eb42bSJan Lentfer 	r->_random = b;
604825eb42bSJan Lentfer }
605825eb42bSJan Lentfer 
606825eb42bSJan Lentfer /* more sophisticated functions */
607825eb42bSJan Lentfer ldns_resolver *
ldns_resolver_new(void)608825eb42bSJan Lentfer ldns_resolver_new(void)
609825eb42bSJan Lentfer {
610825eb42bSJan Lentfer 	ldns_resolver *r;
611825eb42bSJan Lentfer 
612825eb42bSJan Lentfer 	r = LDNS_MALLOC(ldns_resolver);
613825eb42bSJan Lentfer 	if (!r) {
614825eb42bSJan Lentfer 		return NULL;
615825eb42bSJan Lentfer 	}
616825eb42bSJan Lentfer 
617825eb42bSJan Lentfer 	r->_searchlist = NULL;
618825eb42bSJan Lentfer 	r->_nameservers = NULL;
619825eb42bSJan Lentfer 	r->_rtt = NULL;
620825eb42bSJan Lentfer 
621825eb42bSJan Lentfer 	/* defaults are filled out */
622825eb42bSJan Lentfer 	ldns_resolver_set_searchlist_count(r, 0);
623825eb42bSJan Lentfer 	ldns_resolver_set_nameserver_count(r, 0);
624825eb42bSJan Lentfer 	ldns_resolver_set_usevc(r, 0);
625825eb42bSJan Lentfer 	ldns_resolver_set_port(r, LDNS_PORT);
626825eb42bSJan Lentfer 	ldns_resolver_set_domain(r, NULL);
627825eb42bSJan Lentfer 	ldns_resolver_set_defnames(r, false);
628825eb42bSJan Lentfer 	ldns_resolver_set_retry(r, 3);
629825eb42bSJan Lentfer 	ldns_resolver_set_retrans(r, 2);
630825eb42bSJan Lentfer 	ldns_resolver_set_fallback(r, true);
631825eb42bSJan Lentfer 	ldns_resolver_set_fail(r, false);
632825eb42bSJan Lentfer 	ldns_resolver_set_edns_udp_size(r, 0);
633825eb42bSJan Lentfer 	ldns_resolver_set_dnssec(r, false);
634825eb42bSJan Lentfer 	ldns_resolver_set_dnssec_cd(r, false);
635825eb42bSJan Lentfer 	ldns_resolver_set_dnssec_anchors(r, NULL);
636825eb42bSJan Lentfer 	ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
637ac996e71SJan Lentfer 	ldns_resolver_set_igntc(r, false);
638ac996e71SJan Lentfer 	ldns_resolver_set_recursive(r, false);
639ac996e71SJan Lentfer 	ldns_resolver_set_dnsrch(r, true);
6405340022aSzrj 	ldns_resolver_set_source(r, NULL);
6415340022aSzrj 	ldns_resolver_set_ixfr_serial(r, 0);
642825eb42bSJan Lentfer 
643825eb42bSJan Lentfer 	/* randomize the nameserver to be queried
644825eb42bSJan Lentfer 	 * when there are multiple
645825eb42bSJan Lentfer 	 */
646825eb42bSJan Lentfer 	ldns_resolver_set_random(r, true);
647825eb42bSJan Lentfer 
648825eb42bSJan Lentfer 	ldns_resolver_set_debug(r, 0);
649825eb42bSJan Lentfer 
650825eb42bSJan Lentfer 	r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
651825eb42bSJan Lentfer 	r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
652825eb42bSJan Lentfer 
6535340022aSzrj 	r->_socket = -1;
654825eb42bSJan Lentfer 	r->_axfr_soa_count = 0;
655825eb42bSJan Lentfer 	r->_axfr_i = 0;
656825eb42bSJan Lentfer 	r->_cur_axfr_pkt = NULL;
657825eb42bSJan Lentfer 
658825eb42bSJan Lentfer 	r->_tsig_keyname = NULL;
659825eb42bSJan Lentfer 	r->_tsig_keydata = NULL;
660825eb42bSJan Lentfer 	r->_tsig_algorithm = NULL;
661825eb42bSJan Lentfer 	return r;
662825eb42bSJan Lentfer }
663825eb42bSJan Lentfer 
6645340022aSzrj ldns_resolver *
ldns_resolver_clone(ldns_resolver * src)6655340022aSzrj ldns_resolver_clone(ldns_resolver *src)
6665340022aSzrj {
6675340022aSzrj 	ldns_resolver *dst;
6685340022aSzrj 	size_t i;
6695340022aSzrj 
6705340022aSzrj 	assert(src != NULL);
6715340022aSzrj 
6725340022aSzrj 	if (!(dst = LDNS_MALLOC(ldns_resolver))) return NULL;
6735340022aSzrj 	(void) memcpy(dst, src, sizeof(ldns_resolver));
6745340022aSzrj 
6755340022aSzrj 	if (dst->_searchlist_count == 0)
6765340022aSzrj 		dst->_searchlist = NULL;
6775340022aSzrj 	else {
6785340022aSzrj 		if (!(dst->_searchlist =
6795340022aSzrj 		    LDNS_XMALLOC(ldns_rdf *, dst->_searchlist_count)))
6805340022aSzrj 			goto error;
6815340022aSzrj 		for (i = 0; i < dst->_searchlist_count; i++)
6825340022aSzrj 			if (!(dst->_searchlist[i] =
6835340022aSzrj 			    ldns_rdf_clone(src->_searchlist[i]))) {
6845340022aSzrj 				dst->_searchlist_count = i;
6855340022aSzrj 				goto error_searchlist;
6865340022aSzrj 			}
6875340022aSzrj 	}
6885340022aSzrj 	if (dst->_nameserver_count == 0) {
6895340022aSzrj 		dst->_nameservers = NULL;
6905340022aSzrj 		dst->_rtt = NULL;
6915340022aSzrj 	} else {
6925340022aSzrj 		if (!(dst->_nameservers =
6935340022aSzrj 		    LDNS_XMALLOC(ldns_rdf *, dst->_nameserver_count)))
6945340022aSzrj 			goto error_searchlist;
6955340022aSzrj 		for (i = 0; i < dst->_nameserver_count; i++)
6965340022aSzrj 			if (!(dst->_nameservers[i] =
6975340022aSzrj 			    ldns_rdf_clone(src->_nameservers[i]))) {
6985340022aSzrj 				dst->_nameserver_count = i;
6995340022aSzrj 				goto error_nameservers;
7005340022aSzrj 			}
7015340022aSzrj 		if (!(dst->_rtt =
7025340022aSzrj 		    LDNS_XMALLOC(size_t, dst->_nameserver_count)))
7035340022aSzrj 			goto error_nameservers;
7045340022aSzrj 		(void) memcpy(dst->_rtt, src->_rtt,
7055340022aSzrj 		    sizeof(size_t) * dst->_nameserver_count);
7065340022aSzrj 	}
7075340022aSzrj 	if (dst->_domain && (!(dst->_domain = ldns_rdf_clone(src->_domain))))
7085340022aSzrj 		goto error_rtt;
7095340022aSzrj 
7105340022aSzrj 	if (dst->_tsig_keyname &&
7115340022aSzrj 	    (!(dst->_tsig_keyname = strdup(src->_tsig_keyname))))
7125340022aSzrj 		goto error_domain;
7135340022aSzrj 
7145340022aSzrj 	if (dst->_tsig_keydata &&
7155340022aSzrj 	    (!(dst->_tsig_keydata = strdup(src->_tsig_keydata))))
7165340022aSzrj 		goto error_tsig_keyname;
7175340022aSzrj 
7185340022aSzrj 	if (dst->_tsig_algorithm &&
7195340022aSzrj 	    (!(dst->_tsig_algorithm = strdup(src->_tsig_algorithm))))
7205340022aSzrj 		goto error_tsig_keydata;
7215340022aSzrj 
7225340022aSzrj 	if (dst->_cur_axfr_pkt &&
7235340022aSzrj 	    (!(dst->_cur_axfr_pkt = ldns_pkt_clone(src->_cur_axfr_pkt))))
7245340022aSzrj 		goto error_tsig_algorithm;
7255340022aSzrj 
7265340022aSzrj 	if (dst->_dnssec_anchors &&
7275340022aSzrj 	    (!(dst->_dnssec_anchors=ldns_rr_list_clone(src->_dnssec_anchors))))
7285340022aSzrj 		goto error_cur_axfr_pkt;
7295340022aSzrj 
7305340022aSzrj 	return dst;
7315340022aSzrj 
7325340022aSzrj error_cur_axfr_pkt:
7335340022aSzrj 	ldns_pkt_free(dst->_cur_axfr_pkt);
7345340022aSzrj error_tsig_algorithm:
7355340022aSzrj 	LDNS_FREE(dst->_tsig_algorithm);
7365340022aSzrj error_tsig_keydata:
7375340022aSzrj 	LDNS_FREE(dst->_tsig_keydata);
7385340022aSzrj error_tsig_keyname:
7395340022aSzrj 	LDNS_FREE(dst->_tsig_keyname);
7405340022aSzrj error_domain:
7415340022aSzrj 	ldns_rdf_deep_free(dst->_domain);
7425340022aSzrj error_rtt:
7435340022aSzrj 	LDNS_FREE(dst->_rtt);
7445340022aSzrj error_nameservers:
7455340022aSzrj 	for (i = 0; i < dst->_nameserver_count; i++)
7465340022aSzrj 		ldns_rdf_deep_free(dst->_nameservers[i]);
7475340022aSzrj 	LDNS_FREE(dst->_nameservers);
7485340022aSzrj error_searchlist:
7495340022aSzrj 	for (i = 0; i < dst->_searchlist_count; i++)
7505340022aSzrj 		ldns_rdf_deep_free(dst->_searchlist[i]);
7515340022aSzrj 	LDNS_FREE(dst->_searchlist);
7525340022aSzrj error:
7535340022aSzrj 	LDNS_FREE(dst);
7545340022aSzrj 	return NULL;
7555340022aSzrj }
7565340022aSzrj 
7575340022aSzrj 
758825eb42bSJan Lentfer ldns_status
ldns_resolver_new_frm_fp(ldns_resolver ** res,FILE * fp)759825eb42bSJan Lentfer ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
760825eb42bSJan Lentfer {
761825eb42bSJan Lentfer 	return ldns_resolver_new_frm_fp_l(res, fp, NULL);
762825eb42bSJan Lentfer }
763825eb42bSJan Lentfer 
764825eb42bSJan Lentfer ldns_status
ldns_resolver_new_frm_fp_l(ldns_resolver ** res,FILE * fp,int * line_nr)765825eb42bSJan Lentfer ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
766825eb42bSJan Lentfer {
767819dec71SDaniel Fojt 	ldns_resolver *r = NULL;
768825eb42bSJan Lentfer 	const char *keyword[LDNS_RESOLV_KEYWORDS];
769825eb42bSJan Lentfer 	char word[LDNS_MAX_LINELEN + 1];
770825eb42bSJan Lentfer 	int8_t expect;
771825eb42bSJan Lentfer 	uint8_t i;
772825eb42bSJan Lentfer 	ldns_rdf *tmp;
773825eb42bSJan Lentfer #ifdef HAVE_SSL
774825eb42bSJan Lentfer 	ldns_rr *tmp_rr;
775825eb42bSJan Lentfer #endif
776ac996e71SJan Lentfer 	ssize_t gtr, bgtr;
777825eb42bSJan Lentfer 	ldns_buffer *b;
778ac996e71SJan Lentfer         int lnr = 0, oldline;
7795340022aSzrj 	FILE* myfp = fp;
780ac996e71SJan Lentfer         if(!line_nr) line_nr = &lnr;
781825eb42bSJan Lentfer 
7825340022aSzrj 	if(!fp) {
783*ee791febSAntonio Huete Jimenez 		myfp = fopen(LDNS_RESOLV_CONF, "r");
7845340022aSzrj 		if(!myfp)
7855340022aSzrj 			return LDNS_STATUS_FILE_ERR;
7865340022aSzrj 	}
7875340022aSzrj 
788825eb42bSJan Lentfer 	/* do this better
789825eb42bSJan Lentfer 	 * expect =
790825eb42bSJan Lentfer 	 * 0: keyword
791825eb42bSJan Lentfer 	 * 1: default domain dname
792825eb42bSJan Lentfer 	 * 2: NS aaaa or a record
793825eb42bSJan Lentfer 	 */
794825eb42bSJan Lentfer 
795825eb42bSJan Lentfer 	/* recognized keywords */
796825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
797825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
798825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_SEARCH] = "search";
799825eb42bSJan Lentfer 	/* these two are read but not used atm TODO */
800825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
801825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_OPTIONS] = "options";
802825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
803825eb42bSJan Lentfer 
804825eb42bSJan Lentfer 	r = ldns_resolver_new();
805825eb42bSJan Lentfer 	if (!r) {
8065340022aSzrj 		if(!fp) fclose(myfp);
807825eb42bSJan Lentfer 		return LDNS_STATUS_MEM_ERR;
808825eb42bSJan Lentfer 	}
809825eb42bSJan Lentfer 
810825eb42bSJan Lentfer 	gtr = 1;
811825eb42bSJan Lentfer 	word[0] = 0;
812ac996e71SJan Lentfer         oldline = *line_nr;
813ac996e71SJan Lentfer         expect = LDNS_RESOLV_KEYWORD;
814825eb42bSJan Lentfer 	while (gtr > 0) {
815825eb42bSJan Lentfer 		/* check comments */
816825eb42bSJan Lentfer 		if (word[0] == '#') {
817ac996e71SJan Lentfer                         word[0]='x';
818ac996e71SJan Lentfer                         if(oldline == *line_nr) {
819ac996e71SJan Lentfer                                 /* skip until end of line */
820ac996e71SJan Lentfer                                 int c;
821ac996e71SJan Lentfer                                 do {
8225340022aSzrj                                         c = fgetc(myfp);
823ac996e71SJan Lentfer                                 } while(c != EOF && c != '\n');
8245340022aSzrj                                 if(c=='\n') (*line_nr)++;
825ac996e71SJan Lentfer                         }
826ac996e71SJan Lentfer 			/* and read next to prepare for further parsing */
827ac996e71SJan Lentfer                         oldline = *line_nr;
828825eb42bSJan Lentfer 			continue;
829825eb42bSJan Lentfer 		}
830ac996e71SJan Lentfer                 oldline = *line_nr;
831825eb42bSJan Lentfer 		switch(expect) {
832825eb42bSJan Lentfer 			case LDNS_RESOLV_KEYWORD:
833825eb42bSJan Lentfer 				/* keyword */
8345340022aSzrj 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
835825eb42bSJan Lentfer 				if (gtr != 0) {
836ac996e71SJan Lentfer                                         if(word[0] == '#') continue;
837825eb42bSJan Lentfer 					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
838825eb42bSJan Lentfer 						if (strcasecmp(keyword[i], word) == 0) {
839825eb42bSJan Lentfer 							/* chosen the keyword and
840825eb42bSJan Lentfer 							 * expect values carefully
841825eb42bSJan Lentfer 	        					 */
842825eb42bSJan Lentfer 							expect = i;
843825eb42bSJan Lentfer 							break;
844825eb42bSJan Lentfer 						}
845825eb42bSJan Lentfer 					}
846825eb42bSJan Lentfer 					/* no keyword recognized */
847825eb42bSJan Lentfer 					if (expect == LDNS_RESOLV_KEYWORD) {
848825eb42bSJan Lentfer 						/* skip line */
849825eb42bSJan Lentfer 						/*
850825eb42bSJan Lentfer 						ldns_resolver_deep_free(r);
8515340022aSzrj 						if(!fp) fclose(myfp);
852825eb42bSJan Lentfer 						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
853825eb42bSJan Lentfer 						*/
854825eb42bSJan Lentfer 					}
855825eb42bSJan Lentfer 				}
856825eb42bSJan Lentfer 				break;
857825eb42bSJan Lentfer 			case LDNS_RESOLV_DEFDOMAIN:
858825eb42bSJan Lentfer 				/* default domain dname */
8595340022aSzrj 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
860825eb42bSJan Lentfer 				if (gtr == 0) {
8615340022aSzrj 					if(!fp) fclose(myfp);
862819dec71SDaniel Fojt 					ldns_resolver_deep_free(r);
863825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
864825eb42bSJan Lentfer 				}
865ac996e71SJan Lentfer                                 if(word[0] == '#') {
866ac996e71SJan Lentfer                                         expect = LDNS_RESOLV_KEYWORD;
867ac996e71SJan Lentfer                                         continue;
868ac996e71SJan Lentfer                                 }
869825eb42bSJan Lentfer 				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
870825eb42bSJan Lentfer 				if (!tmp) {
8715340022aSzrj 					if(!fp) fclose(myfp);
872819dec71SDaniel Fojt 					ldns_resolver_deep_free(r);
873825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_DNAME_ERR;
874825eb42bSJan Lentfer 				}
875825eb42bSJan Lentfer 
876825eb42bSJan Lentfer 				/* DOn't free, because we copy the pointer */
877825eb42bSJan Lentfer 				ldns_resolver_set_domain(r, tmp);
878825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
879825eb42bSJan Lentfer 				break;
880825eb42bSJan Lentfer 			case LDNS_RESOLV_NAMESERVER:
881825eb42bSJan Lentfer 				/* NS aaaa or a record */
8825340022aSzrj 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
883825eb42bSJan Lentfer 				if (gtr == 0) {
8845340022aSzrj 					if(!fp) fclose(myfp);
885819dec71SDaniel Fojt 					ldns_resolver_deep_free(r);
886825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
887825eb42bSJan Lentfer 				}
888ac996e71SJan Lentfer                                 if(word[0] == '#') {
889ac996e71SJan Lentfer                                         expect = LDNS_RESOLV_KEYWORD;
890ac996e71SJan Lentfer                                         continue;
891ac996e71SJan Lentfer                                 }
892ac996e71SJan Lentfer                                 if(strchr(word, '%')) {
893ac996e71SJan Lentfer                                         /* snip off interface labels,
894ac996e71SJan Lentfer                                          * fe80::222:19ff:fe31:4222%eth0 */
895ac996e71SJan Lentfer                                         strchr(word, '%')[0]=0;
896ac996e71SJan Lentfer                                 }
897825eb42bSJan Lentfer 				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
898825eb42bSJan Lentfer 				if (!tmp) {
899825eb42bSJan Lentfer 					/* try ip4 */
900825eb42bSJan Lentfer 					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
901825eb42bSJan Lentfer 				}
902825eb42bSJan Lentfer 				/* could not parse it, exit */
903825eb42bSJan Lentfer 				if (!tmp) {
904825eb42bSJan Lentfer 					ldns_resolver_deep_free(r);
9055340022aSzrj 					if(!fp) fclose(myfp);
906825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_ERR;
907825eb42bSJan Lentfer 				}
908825eb42bSJan Lentfer 				(void)ldns_resolver_push_nameserver(r, tmp);
909825eb42bSJan Lentfer 				ldns_rdf_deep_free(tmp);
910825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
911825eb42bSJan Lentfer 				break;
912825eb42bSJan Lentfer 			case LDNS_RESOLV_SEARCH:
913825eb42bSJan Lentfer 				/* search list domain dname */
9145340022aSzrj 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
915825eb42bSJan Lentfer 				b = LDNS_MALLOC(ldns_buffer);
916ac996e71SJan Lentfer 				if(!b) {
917ac996e71SJan Lentfer 					ldns_resolver_deep_free(r);
9185340022aSzrj 					if(!fp) fclose(myfp);
919ac996e71SJan Lentfer 					return LDNS_STATUS_MEM_ERR;
920ac996e71SJan Lentfer 				}
921825eb42bSJan Lentfer 
922ac996e71SJan Lentfer 				ldns_buffer_new_frm_data(b, word, (size_t) gtr);
923ac996e71SJan Lentfer 				if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
924ac996e71SJan Lentfer 					LDNS_FREE(b);
925ac996e71SJan Lentfer 					ldns_resolver_deep_free(r);
9265340022aSzrj 					if(!fp) fclose(myfp);
927ac996e71SJan Lentfer 					return LDNS_STATUS_MEM_ERR;
928ac996e71SJan Lentfer 				}
929ac996e71SJan Lentfer 				bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
930ac996e71SJan Lentfer 				while (bgtr > 0) {
931ac996e71SJan Lentfer 					gtr -= bgtr;
932ac996e71SJan Lentfer                                         if(word[0] == '#') {
933ac996e71SJan Lentfer                                                 expect = LDNS_RESOLV_KEYWORD;
934d1b2b5caSJohn Marino                                                 break;
935ac996e71SJan Lentfer                                         }
936825eb42bSJan Lentfer 					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
937825eb42bSJan Lentfer 					if (!tmp) {
938825eb42bSJan Lentfer 						ldns_resolver_deep_free(r);
939ac996e71SJan Lentfer 						ldns_buffer_free(b);
9405340022aSzrj 						if(!fp) fclose(myfp);
941825eb42bSJan Lentfer 						return LDNS_STATUS_SYNTAX_DNAME_ERR;
942825eb42bSJan Lentfer 					}
943825eb42bSJan Lentfer 
944825eb42bSJan Lentfer 					ldns_resolver_push_searchlist(r, tmp);
945825eb42bSJan Lentfer 
946825eb42bSJan Lentfer 					ldns_rdf_deep_free(tmp);
947ac996e71SJan Lentfer 					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
948ac996e71SJan Lentfer 					    (size_t) gtr + 1);
949825eb42bSJan Lentfer 				}
950825eb42bSJan Lentfer 				ldns_buffer_free(b);
951d1b2b5caSJohn Marino 				if (expect != LDNS_RESOLV_KEYWORD) {
952825eb42bSJan Lentfer 					gtr = 1;
953825eb42bSJan Lentfer 					expect = LDNS_RESOLV_KEYWORD;
954d1b2b5caSJohn Marino 				}
955825eb42bSJan Lentfer 				break;
956825eb42bSJan Lentfer 			case LDNS_RESOLV_SORTLIST:
9575340022aSzrj 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
958825eb42bSJan Lentfer 				/* sortlist not implemented atm */
959825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
960825eb42bSJan Lentfer 				break;
961825eb42bSJan Lentfer 			case LDNS_RESOLV_OPTIONS:
9625340022aSzrj 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
963825eb42bSJan Lentfer 				/* options not implemented atm */
964825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
965825eb42bSJan Lentfer 				break;
966825eb42bSJan Lentfer 			case LDNS_RESOLV_ANCHOR:
967825eb42bSJan Lentfer 				/* a file containing a DNSSEC trust anchor */
9685340022aSzrj 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
969825eb42bSJan Lentfer 				if (gtr == 0) {
970ac996e71SJan Lentfer 					ldns_resolver_deep_free(r);
9715340022aSzrj 					if(!fp) fclose(myfp);
972825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
973825eb42bSJan Lentfer 				}
974ac996e71SJan Lentfer                                 if(word[0] == '#') {
975ac996e71SJan Lentfer                                         expect = LDNS_RESOLV_KEYWORD;
976ac996e71SJan Lentfer                                         continue;
977ac996e71SJan Lentfer                                 }
978825eb42bSJan Lentfer 
979825eb42bSJan Lentfer #ifdef HAVE_SSL
980825eb42bSJan Lentfer 				tmp_rr = ldns_read_anchor_file(word);
981825eb42bSJan Lentfer 				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
982825eb42bSJan Lentfer 				ldns_rr_free(tmp_rr);
983825eb42bSJan Lentfer #endif
984825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
985825eb42bSJan Lentfer 				break;
986825eb42bSJan Lentfer 		}
987825eb42bSJan Lentfer 	}
988825eb42bSJan Lentfer 
9895340022aSzrj 	if(!fp)
9905340022aSzrj 		fclose(myfp);
9915340022aSzrj 
992825eb42bSJan Lentfer 	if (res) {
993825eb42bSJan Lentfer 		*res = r;
994825eb42bSJan Lentfer 		return LDNS_STATUS_OK;
995825eb42bSJan Lentfer 	} else {
996ac996e71SJan Lentfer 		ldns_resolver_deep_free(r);
997825eb42bSJan Lentfer 		return LDNS_STATUS_NULL;
998825eb42bSJan Lentfer 	}
999825eb42bSJan Lentfer }
1000825eb42bSJan Lentfer 
1001825eb42bSJan Lentfer ldns_status
ldns_resolver_new_frm_file(ldns_resolver ** res,const char * filename)1002825eb42bSJan Lentfer ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
1003825eb42bSJan Lentfer {
1004825eb42bSJan Lentfer 	ldns_resolver *r;
1005825eb42bSJan Lentfer 	FILE *fp;
1006825eb42bSJan Lentfer 	ldns_status s;
1007825eb42bSJan Lentfer 
1008825eb42bSJan Lentfer 	if (!filename) {
1009825eb42bSJan Lentfer 		fp = fopen(LDNS_RESOLV_CONF, "r");
1010825eb42bSJan Lentfer 
1011825eb42bSJan Lentfer 	} else {
1012825eb42bSJan Lentfer 		fp = fopen(filename, "r");
1013825eb42bSJan Lentfer 	}
1014825eb42bSJan Lentfer 	if (!fp) {
1015825eb42bSJan Lentfer 		return LDNS_STATUS_FILE_ERR;
1016825eb42bSJan Lentfer 	}
1017825eb42bSJan Lentfer 
1018825eb42bSJan Lentfer 	s = ldns_resolver_new_frm_fp(&r, fp);
1019825eb42bSJan Lentfer 	fclose(fp);
1020825eb42bSJan Lentfer 	if (s == LDNS_STATUS_OK) {
1021825eb42bSJan Lentfer 		if (res) {
1022825eb42bSJan Lentfer 			*res = r;
1023825eb42bSJan Lentfer 			return LDNS_STATUS_OK;
1024825eb42bSJan Lentfer 		} else  {
1025d1b2b5caSJohn Marino 			ldns_resolver_free(r);
1026825eb42bSJan Lentfer 			return LDNS_STATUS_NULL;
1027825eb42bSJan Lentfer 		}
1028825eb42bSJan Lentfer 	}
1029825eb42bSJan Lentfer 	return s;
1030825eb42bSJan Lentfer }
1031825eb42bSJan Lentfer 
1032825eb42bSJan Lentfer void
ldns_resolver_free(ldns_resolver * res)1033825eb42bSJan Lentfer ldns_resolver_free(ldns_resolver *res)
1034825eb42bSJan Lentfer {
1035825eb42bSJan Lentfer 	LDNS_FREE(res);
1036825eb42bSJan Lentfer }
1037825eb42bSJan Lentfer 
1038825eb42bSJan Lentfer void
ldns_resolver_deep_free(ldns_resolver * res)1039825eb42bSJan Lentfer ldns_resolver_deep_free(ldns_resolver *res)
1040825eb42bSJan Lentfer {
1041825eb42bSJan Lentfer 	size_t i;
1042825eb42bSJan Lentfer 
1043825eb42bSJan Lentfer 	if (res) {
10445340022aSzrj 		close_socket(res->_socket);
10455340022aSzrj 
1046825eb42bSJan Lentfer 		if (res->_searchlist) {
1047825eb42bSJan Lentfer 			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
1048825eb42bSJan Lentfer 				ldns_rdf_deep_free(res->_searchlist[i]);
1049825eb42bSJan Lentfer 			}
1050825eb42bSJan Lentfer 			LDNS_FREE(res->_searchlist);
1051825eb42bSJan Lentfer 		}
1052825eb42bSJan Lentfer 		if (res->_nameservers) {
1053825eb42bSJan Lentfer 			for (i = 0; i < res->_nameserver_count; i++) {
1054825eb42bSJan Lentfer 				ldns_rdf_deep_free(res->_nameservers[i]);
1055825eb42bSJan Lentfer 			}
1056825eb42bSJan Lentfer 			LDNS_FREE(res->_nameservers);
1057825eb42bSJan Lentfer 		}
1058825eb42bSJan Lentfer 		if (ldns_resolver_domain(res)) {
1059825eb42bSJan Lentfer 			ldns_rdf_deep_free(ldns_resolver_domain(res));
1060825eb42bSJan Lentfer 		}
1061ac996e71SJan Lentfer 		if (res->_tsig_keyname) {
1062825eb42bSJan Lentfer 			LDNS_FREE(res->_tsig_keyname);
1063825eb42bSJan Lentfer 		}
1064ac996e71SJan Lentfer 		if (res->_tsig_keydata) {
1065ac996e71SJan Lentfer 			LDNS_FREE(res->_tsig_keydata);
1066ac996e71SJan Lentfer 		}
1067ac996e71SJan Lentfer 		if (res->_tsig_algorithm) {
1068ac996e71SJan Lentfer 			LDNS_FREE(res->_tsig_algorithm);
1069ac996e71SJan Lentfer 		}
1070825eb42bSJan Lentfer 
1071825eb42bSJan Lentfer 		if (res->_cur_axfr_pkt) {
1072825eb42bSJan Lentfer 			ldns_pkt_free(res->_cur_axfr_pkt);
1073825eb42bSJan Lentfer 		}
1074825eb42bSJan Lentfer 
1075825eb42bSJan Lentfer 		if (res->_rtt) {
1076825eb42bSJan Lentfer 			LDNS_FREE(res->_rtt);
1077825eb42bSJan Lentfer 		}
1078825eb42bSJan Lentfer 		if (res->_dnssec_anchors) {
1079825eb42bSJan Lentfer 			ldns_rr_list_deep_free(res->_dnssec_anchors);
1080825eb42bSJan Lentfer 		}
1081825eb42bSJan Lentfer 		LDNS_FREE(res);
1082825eb42bSJan Lentfer 	}
1083825eb42bSJan Lentfer }
1084825eb42bSJan Lentfer 
10855340022aSzrj ldns_status
ldns_resolver_search_status(ldns_pkt ** pkt,ldns_resolver * r,const ldns_rdf * name,ldns_rr_type t,ldns_rr_class c,uint16_t flags)10865340022aSzrj ldns_resolver_search_status(ldns_pkt** pkt,
10875340022aSzrj 		ldns_resolver *r, const  ldns_rdf *name,
10885340022aSzrj 		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
10895340022aSzrj {
10905340022aSzrj 	ldns_rdf *new_name;
10915340022aSzrj 	ldns_rdf **search_list;
10925340022aSzrj 	size_t i;
10935340022aSzrj 	ldns_status s = LDNS_STATUS_OK;
10945340022aSzrj 	ldns_rdf root_dname = { 1, LDNS_RDF_TYPE_DNAME, (void *)"" };
10955340022aSzrj 
10965340022aSzrj 	if (ldns_dname_absolute(name)) {
10975340022aSzrj 		/* query as-is */
10985340022aSzrj 		return ldns_resolver_query_status(pkt, r, name, t, c, flags);
10995340022aSzrj 	} else if (ldns_resolver_dnsrch(r)) {
11005340022aSzrj 		search_list = ldns_resolver_searchlist(r);
11015340022aSzrj 		for (i = 0; i <= ldns_resolver_searchlist_count(r); i++) {
11025340022aSzrj 			if (i == ldns_resolver_searchlist_count(r)) {
11035340022aSzrj 				new_name = ldns_dname_cat_clone(name,
11045340022aSzrj 						&root_dname);
11055340022aSzrj 			} else {
11065340022aSzrj 				new_name = ldns_dname_cat_clone(name,
11075340022aSzrj 						search_list[i]);
11085340022aSzrj 			}
11095340022aSzrj 
11105340022aSzrj 			s = ldns_resolver_query_status(pkt, r,
11115340022aSzrj 					new_name, t, c, flags);
1112819dec71SDaniel Fojt 			ldns_rdf_deep_free(new_name);
1113819dec71SDaniel Fojt 
11145340022aSzrj 			if (pkt && *pkt) {
11155340022aSzrj 				if (s == LDNS_STATUS_OK &&
11165340022aSzrj 						ldns_pkt_get_rcode(*pkt) ==
11175340022aSzrj 						LDNS_RCODE_NOERROR) {
11185340022aSzrj 
11195340022aSzrj 					return LDNS_STATUS_OK;
11205340022aSzrj 				}
11215340022aSzrj 				ldns_pkt_free(*pkt);
11225340022aSzrj 				*pkt = NULL;
11235340022aSzrj 			}
11245340022aSzrj 		}
11255340022aSzrj 	}
11265340022aSzrj 	return s;
11275340022aSzrj }
11285340022aSzrj 
1129825eb42bSJan Lentfer ldns_pkt *
ldns_resolver_search(const ldns_resolver * r,const ldns_rdf * name,ldns_rr_type t,ldns_rr_class c,uint16_t flags)1130825eb42bSJan Lentfer ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
1131825eb42bSJan Lentfer 	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1132825eb42bSJan Lentfer {
11335340022aSzrj 	ldns_pkt* pkt = NULL;
11345340022aSzrj 	if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
11355340022aSzrj 				name, t, c, flags) != LDNS_STATUS_OK) {
11365340022aSzrj 		ldns_pkt_free(pkt);
1137819dec71SDaniel Fojt 		return NULL;
11385340022aSzrj 	}
11395340022aSzrj 	return pkt;
11405340022aSzrj }
1141825eb42bSJan Lentfer 
11425340022aSzrj ldns_status
ldns_resolver_query_status(ldns_pkt ** pkt,ldns_resolver * r,const ldns_rdf * name,ldns_rr_type t,ldns_rr_class c,uint16_t flags)11435340022aSzrj ldns_resolver_query_status(ldns_pkt** pkt,
11445340022aSzrj 		ldns_resolver *r, const ldns_rdf *name,
11455340022aSzrj 		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
11465340022aSzrj {
11475340022aSzrj 	ldns_rdf *newname;
11485340022aSzrj 	ldns_status status;
1149825eb42bSJan Lentfer 
11505340022aSzrj 	if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
11515340022aSzrj 		return ldns_resolver_send(pkt, r, name, t, c, flags);
11525340022aSzrj 	}
1153825eb42bSJan Lentfer 
11545340022aSzrj 	newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
11555340022aSzrj 	if (!newname) {
11565340022aSzrj 		return LDNS_STATUS_MEM_ERR;
1157ac996e71SJan Lentfer 	}
11585340022aSzrj 	status = ldns_resolver_send(pkt, r, newname, t, c, flags);
11595340022aSzrj 	ldns_rdf_free(newname);
11605340022aSzrj 	return status;
1161825eb42bSJan Lentfer }
1162825eb42bSJan Lentfer 
1163825eb42bSJan Lentfer ldns_pkt *
ldns_resolver_query(const ldns_resolver * r,const ldns_rdf * name,ldns_rr_type t,ldns_rr_class c,uint16_t flags)1164825eb42bSJan Lentfer ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
1165825eb42bSJan Lentfer 	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1166825eb42bSJan Lentfer {
11675340022aSzrj 	ldns_pkt* pkt = NULL;
11685340022aSzrj 	if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
11695340022aSzrj 				name, t, c, flags) != LDNS_STATUS_OK) {
1170825eb42bSJan Lentfer 		ldns_pkt_free(pkt);
1171819dec71SDaniel Fojt 		return NULL;
1172825eb42bSJan Lentfer 	}
1173825eb42bSJan Lentfer 	return pkt;
1174825eb42bSJan Lentfer }
1175825eb42bSJan Lentfer 
1176b5dedccaSJan Lentfer static size_t *
ldns_resolver_backup_rtt(ldns_resolver * r)1177b5dedccaSJan Lentfer ldns_resolver_backup_rtt(ldns_resolver *r)
1178b5dedccaSJan Lentfer {
1179b5dedccaSJan Lentfer 	size_t *new_rtt;
1180b5dedccaSJan Lentfer 	size_t *old_rtt = ldns_resolver_rtt(r);
1181b5dedccaSJan Lentfer 
1182b5dedccaSJan Lentfer 	if (old_rtt && ldns_resolver_nameserver_count(r)) {
1183b5dedccaSJan Lentfer 		new_rtt = LDNS_XMALLOC(size_t
1184b5dedccaSJan Lentfer 				, ldns_resolver_nameserver_count(r));
1185819dec71SDaniel Fojt 		if (!new_rtt) return NULL;
1186b5dedccaSJan Lentfer 		memcpy(new_rtt, old_rtt, sizeof(size_t)
1187b5dedccaSJan Lentfer 				* ldns_resolver_nameserver_count(r));
1188b5dedccaSJan Lentfer 		ldns_resolver_set_rtt(r, new_rtt);
1189b5dedccaSJan Lentfer 		return old_rtt;
1190b5dedccaSJan Lentfer 	}
1191b5dedccaSJan Lentfer 	return NULL;
1192b5dedccaSJan Lentfer }
1193b5dedccaSJan Lentfer 
1194b5dedccaSJan Lentfer static void
ldns_resolver_restore_rtt(ldns_resolver * r,size_t * old_rtt)1195b5dedccaSJan Lentfer ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
1196b5dedccaSJan Lentfer {
1197b5dedccaSJan Lentfer 	size_t *cur_rtt = ldns_resolver_rtt(r);
1198b5dedccaSJan Lentfer 
1199b5dedccaSJan Lentfer 	if (cur_rtt) {
1200b5dedccaSJan Lentfer 		LDNS_FREE(cur_rtt);
1201b5dedccaSJan Lentfer 	}
1202b5dedccaSJan Lentfer 	ldns_resolver_set_rtt(r, old_rtt);
1203b5dedccaSJan Lentfer }
1204b5dedccaSJan Lentfer 
1205825eb42bSJan Lentfer ldns_status
ldns_resolver_send_pkt(ldns_pkt ** answer,ldns_resolver * r,ldns_pkt * query_pkt)1206825eb42bSJan Lentfer ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1207825eb42bSJan Lentfer 				   ldns_pkt *query_pkt)
1208825eb42bSJan Lentfer {
1209825eb42bSJan Lentfer 	ldns_pkt *answer_pkt = NULL;
1210825eb42bSJan Lentfer 	ldns_status stat = LDNS_STATUS_OK;
1211b5dedccaSJan Lentfer 	size_t *rtt;
1212825eb42bSJan Lentfer 
1213825eb42bSJan Lentfer 	stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
1214825eb42bSJan Lentfer 	if (stat != LDNS_STATUS_OK) {
1215825eb42bSJan Lentfer 		if(answer_pkt) {
1216825eb42bSJan Lentfer 			ldns_pkt_free(answer_pkt);
1217825eb42bSJan Lentfer 			answer_pkt = NULL;
1218825eb42bSJan Lentfer 		}
1219825eb42bSJan Lentfer 	} else {
1220825eb42bSJan Lentfer 		/* if tc=1 fall back to EDNS and/or TCP */
1221825eb42bSJan Lentfer 		/* check for tcp first (otherwise we don't care about tc=1) */
1222825eb42bSJan Lentfer 		if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
1223825eb42bSJan Lentfer 			if (ldns_pkt_tc(answer_pkt)) {
1224825eb42bSJan Lentfer 				/* was EDNS0 set? */
1225825eb42bSJan Lentfer 				if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
1226b5dedccaSJan Lentfer 					ldns_pkt_set_edns_udp_size(query_pkt
1227b5dedccaSJan Lentfer 							, 4096);
1228825eb42bSJan Lentfer 					ldns_pkt_free(answer_pkt);
12295340022aSzrj 					answer_pkt = NULL;
1230b5dedccaSJan Lentfer 					/* Nameservers should not become
1231b5dedccaSJan Lentfer 					 * unreachable because fragments are
1232b5dedccaSJan Lentfer 					 * dropped (network error). We might
1233b5dedccaSJan Lentfer 					 * still have success with TCP.
1234b5dedccaSJan Lentfer 					 * Therefore maintain reachability
1235b5dedccaSJan Lentfer 					 * statuses of the nameservers by
1236b5dedccaSJan Lentfer 					 * backup and restore the rtt list.
1237b5dedccaSJan Lentfer 					 */
1238b5dedccaSJan Lentfer 					rtt = ldns_resolver_backup_rtt(r);
1239b5dedccaSJan Lentfer 					stat = ldns_send(&answer_pkt, r
1240b5dedccaSJan Lentfer 							, query_pkt);
1241b5dedccaSJan Lentfer 					ldns_resolver_restore_rtt(r, rtt);
1242825eb42bSJan Lentfer 				}
1243825eb42bSJan Lentfer 				/* either way, if it is still truncated, use TCP */
1244825eb42bSJan Lentfer 				if (stat != LDNS_STATUS_OK ||
1245825eb42bSJan Lentfer 				    ldns_pkt_tc(answer_pkt)) {
1246825eb42bSJan Lentfer 					ldns_resolver_set_usevc(r, true);
1247825eb42bSJan Lentfer 					ldns_pkt_free(answer_pkt);
1248819dec71SDaniel Fojt 					answer_pkt = NULL;
1249825eb42bSJan Lentfer 					stat = ldns_send(&answer_pkt, r, query_pkt);
1250825eb42bSJan Lentfer 					ldns_resolver_set_usevc(r, false);
1251825eb42bSJan Lentfer 				}
1252825eb42bSJan Lentfer 			}
1253825eb42bSJan Lentfer 		}
1254825eb42bSJan Lentfer 	}
1255825eb42bSJan Lentfer 
1256819dec71SDaniel Fojt 	if (answer && answer_pkt) {
1257825eb42bSJan Lentfer 		*answer = answer_pkt;
1258825eb42bSJan Lentfer 	}
1259825eb42bSJan Lentfer 
1260825eb42bSJan Lentfer 	return stat;
1261825eb42bSJan Lentfer }
1262825eb42bSJan Lentfer 
1263825eb42bSJan Lentfer ldns_status
ldns_resolver_prepare_query_pkt(ldns_pkt ** query_pkt,ldns_resolver * r,const ldns_rdf * name,ldns_rr_type t,ldns_rr_class c,uint16_t flags)1264825eb42bSJan Lentfer ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
1265825eb42bSJan Lentfer                                 const ldns_rdf *name, ldns_rr_type t,
1266825eb42bSJan Lentfer                                 ldns_rr_class c, uint16_t flags)
1267825eb42bSJan Lentfer {
1268fd185f4dSJan Lentfer 	struct timeval now;
12695340022aSzrj 	ldns_rr* soa = NULL;
1270fd185f4dSJan Lentfer 
1271825eb42bSJan Lentfer 	/* prepare a question pkt from the parameters
1272825eb42bSJan Lentfer 	 * and then send this */
12735340022aSzrj 	if (t == LDNS_RR_TYPE_IXFR) {
12745340022aSzrj 		ldns_rdf *owner_rdf;
12755340022aSzrj 		ldns_rdf *mname_rdf;
12765340022aSzrj 		ldns_rdf *rname_rdf;
12775340022aSzrj 		ldns_rdf *serial_rdf;
12785340022aSzrj 		ldns_rdf *refresh_rdf;
12795340022aSzrj 		ldns_rdf *retry_rdf;
12805340022aSzrj 		ldns_rdf *expire_rdf;
12815340022aSzrj 		ldns_rdf *minimum_rdf;
12825340022aSzrj 		soa = ldns_rr_new();
12835340022aSzrj 
12845340022aSzrj 		if (!soa) {
12855340022aSzrj 			return LDNS_STATUS_ERR;
12865340022aSzrj 		}
12875340022aSzrj 		owner_rdf = ldns_rdf_clone(name);
12885340022aSzrj 		if (!owner_rdf) {
12895340022aSzrj 			ldns_rr_free(soa);
12905340022aSzrj 			return LDNS_STATUS_ERR;
12915340022aSzrj 		}
12925340022aSzrj 		ldns_rr_set_owner(soa, owner_rdf);
12935340022aSzrj 		ldns_rr_set_type(soa, LDNS_RR_TYPE_SOA);
12945340022aSzrj 		ldns_rr_set_class(soa, c);
12955340022aSzrj 		ldns_rr_set_question(soa, false);
12965340022aSzrj 		if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
12975340022aSzrj 			ldns_rr_free(soa);
12985340022aSzrj 			return LDNS_STATUS_ERR;
12995340022aSzrj 		} else	ldns_rr_push_rdf(soa, mname_rdf);
13005340022aSzrj 		if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
13015340022aSzrj 			ldns_rr_free(soa);
13025340022aSzrj 			return LDNS_STATUS_ERR;
13035340022aSzrj 		} else	ldns_rr_push_rdf(soa, rname_rdf);
13045340022aSzrj 		serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, ldns_resolver_get_ixfr_serial(r));
13055340022aSzrj 		if (!serial_rdf) {
13065340022aSzrj 			ldns_rr_free(soa);
13075340022aSzrj 			return LDNS_STATUS_ERR;
13085340022aSzrj 		} else	ldns_rr_push_rdf(soa, serial_rdf);
13095340022aSzrj 		refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
13105340022aSzrj 		if (!refresh_rdf) {
13115340022aSzrj 			ldns_rr_free(soa);
13125340022aSzrj 			return LDNS_STATUS_ERR;
13135340022aSzrj 		} else	ldns_rr_push_rdf(soa, refresh_rdf);
13145340022aSzrj 		retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
13155340022aSzrj 		if (!retry_rdf) {
13165340022aSzrj 			ldns_rr_free(soa);
13175340022aSzrj 			return LDNS_STATUS_ERR;
13185340022aSzrj 		} else	ldns_rr_push_rdf(soa, retry_rdf);
13195340022aSzrj 		expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
13205340022aSzrj 		if (!expire_rdf) {
13215340022aSzrj 			ldns_rr_free(soa);
13225340022aSzrj 			return LDNS_STATUS_ERR;
13235340022aSzrj 		} else	ldns_rr_push_rdf(soa, expire_rdf);
13245340022aSzrj 		minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
13255340022aSzrj 		if (!minimum_rdf) {
13265340022aSzrj 			ldns_rr_free(soa);
13275340022aSzrj 			return LDNS_STATUS_ERR;
13285340022aSzrj 		} else	ldns_rr_push_rdf(soa, minimum_rdf);
13295340022aSzrj 
13305340022aSzrj 		*query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name),
13315340022aSzrj 			c, flags, soa);
13325340022aSzrj 	} else {
1333825eb42bSJan Lentfer 		*query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
13345340022aSzrj 	}
1335825eb42bSJan Lentfer 	if (!*query_pkt) {
13365340022aSzrj 		ldns_rr_free(soa);
1337825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
1338825eb42bSJan Lentfer 	}
1339825eb42bSJan Lentfer 
1340825eb42bSJan Lentfer 	/* set DO bit if necessary */
1341825eb42bSJan Lentfer 	if (ldns_resolver_dnssec(r)) {
1342825eb42bSJan Lentfer 		if (ldns_resolver_edns_udp_size(r) == 0) {
1343825eb42bSJan Lentfer 			ldns_resolver_set_edns_udp_size(r, 4096);
1344825eb42bSJan Lentfer 		}
1345825eb42bSJan Lentfer 		ldns_pkt_set_edns_do(*query_pkt, true);
1346825eb42bSJan Lentfer 		if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
1347825eb42bSJan Lentfer 			ldns_pkt_set_cd(*query_pkt, true);
1348825eb42bSJan Lentfer 		}
1349825eb42bSJan Lentfer 	}
1350825eb42bSJan Lentfer 
1351825eb42bSJan Lentfer 	/* transfer the udp_edns_size from the resolver to the packet */
1352825eb42bSJan Lentfer 	if (ldns_resolver_edns_udp_size(r) != 0) {
1353825eb42bSJan Lentfer 		ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
1354825eb42bSJan Lentfer 	}
1355825eb42bSJan Lentfer 
1356fd185f4dSJan Lentfer 	/* set the timestamp */
1357fd185f4dSJan Lentfer 	now.tv_sec = time(NULL);
1358fd185f4dSJan Lentfer 	now.tv_usec = 0;
1359fd185f4dSJan Lentfer 	ldns_pkt_set_timestamp(*query_pkt, now);
1360fd185f4dSJan Lentfer 
1361fd185f4dSJan Lentfer 
1362825eb42bSJan Lentfer 	if (ldns_resolver_debug(r)) {
1363825eb42bSJan Lentfer 		ldns_pkt_print(stdout, *query_pkt);
1364825eb42bSJan Lentfer 	}
1365825eb42bSJan Lentfer 
1366825eb42bSJan Lentfer 	/* only set the id if it is not set yet */
1367825eb42bSJan Lentfer 	if (ldns_pkt_id(*query_pkt) == 0) {
1368825eb42bSJan Lentfer 		ldns_pkt_set_random_id(*query_pkt);
1369825eb42bSJan Lentfer 	}
1370825eb42bSJan Lentfer 
1371825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
1372825eb42bSJan Lentfer }
1373825eb42bSJan Lentfer 
1374825eb42bSJan Lentfer ldns_status
ldns_resolver_send(ldns_pkt ** answer,ldns_resolver * r,const ldns_rdf * name,ldns_rr_type t,ldns_rr_class c,uint16_t flags)1375825eb42bSJan Lentfer ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
1376825eb42bSJan Lentfer 		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1377825eb42bSJan Lentfer {
1378825eb42bSJan Lentfer 	ldns_pkt *query_pkt;
1379825eb42bSJan Lentfer 	ldns_pkt *answer_pkt;
1380825eb42bSJan Lentfer 	ldns_status status;
1381825eb42bSJan Lentfer 
1382825eb42bSJan Lentfer 	assert(r != NULL);
1383825eb42bSJan Lentfer 	assert(name != NULL);
1384825eb42bSJan Lentfer 
1385825eb42bSJan Lentfer 	answer_pkt = NULL;
1386825eb42bSJan Lentfer 
1387825eb42bSJan Lentfer 	/* do all the preprocessing here, then fire of an query to
1388825eb42bSJan Lentfer 	 * the network */
1389825eb42bSJan Lentfer 
1390825eb42bSJan Lentfer 	if (0 == t) {
1391825eb42bSJan Lentfer 		t= LDNS_RR_TYPE_A;
1392825eb42bSJan Lentfer 	}
1393825eb42bSJan Lentfer 	if (0 == c) {
1394825eb42bSJan Lentfer 		c= LDNS_RR_CLASS_IN;
1395825eb42bSJan Lentfer 	}
1396825eb42bSJan Lentfer 	if (0 == ldns_resolver_nameserver_count(r)) {
1397825eb42bSJan Lentfer 		return LDNS_STATUS_RES_NO_NS;
1398825eb42bSJan Lentfer 	}
1399825eb42bSJan Lentfer 	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1400825eb42bSJan Lentfer 		return LDNS_STATUS_RES_QUERY;
1401825eb42bSJan Lentfer 	}
1402825eb42bSJan Lentfer 
1403825eb42bSJan Lentfer 	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1404825eb42bSJan Lentfer 	                                         t, c, flags);
1405825eb42bSJan Lentfer 	if (status != LDNS_STATUS_OK) {
1406825eb42bSJan Lentfer 		return status;
1407825eb42bSJan Lentfer 	}
1408825eb42bSJan Lentfer 
1409825eb42bSJan Lentfer 	/* if tsig values are set, tsign it */
1410825eb42bSJan Lentfer 	/* TODO: make last 3 arguments optional too? maybe make complete
14115340022aSzrj 	         rr instead of separate values in resolver (and packet)
1412825eb42bSJan Lentfer 	  Jelte
1413825eb42bSJan Lentfer 	  should this go in pkt_prepare?
1414825eb42bSJan Lentfer 	*/
1415825eb42bSJan Lentfer 	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
1416fd185f4dSJan Lentfer #ifdef HAVE_SSL
1417825eb42bSJan Lentfer 		status = ldns_pkt_tsig_sign(query_pkt,
1418825eb42bSJan Lentfer 		                            ldns_resolver_tsig_keyname(r),
1419825eb42bSJan Lentfer 		                            ldns_resolver_tsig_keydata(r),
1420825eb42bSJan Lentfer 		                            300, ldns_resolver_tsig_algorithm(r), NULL);
1421825eb42bSJan Lentfer 		if (status != LDNS_STATUS_OK) {
1422d1b2b5caSJohn Marino 			ldns_pkt_free(query_pkt);
1423825eb42bSJan Lentfer 			return LDNS_STATUS_CRYPTO_TSIG_ERR;
1424825eb42bSJan Lentfer 		}
1425825eb42bSJan Lentfer #else
1426d1b2b5caSJohn Marino 		ldns_pkt_free(query_pkt);
1427825eb42bSJan Lentfer 	        return LDNS_STATUS_CRYPTO_TSIG_ERR;
1428825eb42bSJan Lentfer #endif /* HAVE_SSL */
1429fd185f4dSJan Lentfer 	}
1430ac996e71SJan Lentfer 
1431825eb42bSJan Lentfer 	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1432825eb42bSJan Lentfer 	ldns_pkt_free(query_pkt);
1433825eb42bSJan Lentfer 
1434825eb42bSJan Lentfer 	/* allows answer to be NULL when not interested in return value */
1435825eb42bSJan Lentfer 	if (answer) {
1436825eb42bSJan Lentfer 		*answer = answer_pkt;
1437825eb42bSJan Lentfer 	}
1438825eb42bSJan Lentfer 	return status;
1439825eb42bSJan Lentfer }
1440825eb42bSJan Lentfer 
1441825eb42bSJan Lentfer ldns_rr *
ldns_axfr_next(ldns_resolver * resolver)1442825eb42bSJan Lentfer ldns_axfr_next(ldns_resolver *resolver)
1443825eb42bSJan Lentfer {
1444825eb42bSJan Lentfer 	ldns_rr *cur_rr;
1445825eb42bSJan Lentfer 	uint8_t *packet_wire;
1446825eb42bSJan Lentfer 	size_t packet_wire_size;
1447825eb42bSJan Lentfer 	ldns_status status;
1448825eb42bSJan Lentfer 
1449825eb42bSJan Lentfer 	/* check if start() has been called */
14505340022aSzrj 	if (!resolver || resolver->_socket == -1) {
1451825eb42bSJan Lentfer 		return NULL;
1452825eb42bSJan Lentfer 	}
1453825eb42bSJan Lentfer 
1454825eb42bSJan Lentfer 	if (resolver->_cur_axfr_pkt) {
1455825eb42bSJan Lentfer 		if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
1456825eb42bSJan Lentfer 			ldns_pkt_free(resolver->_cur_axfr_pkt);
1457825eb42bSJan Lentfer 			resolver->_cur_axfr_pkt = NULL;
1458825eb42bSJan Lentfer 			return ldns_axfr_next(resolver);
1459825eb42bSJan Lentfer 		}
1460825eb42bSJan Lentfer 		cur_rr = ldns_rr_clone(ldns_rr_list_rr(
1461825eb42bSJan Lentfer 					ldns_pkt_answer(resolver->_cur_axfr_pkt),
1462825eb42bSJan Lentfer 					resolver->_axfr_i));
1463825eb42bSJan Lentfer 		resolver->_axfr_i++;
1464825eb42bSJan Lentfer 		if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
1465825eb42bSJan Lentfer 			resolver->_axfr_soa_count++;
1466825eb42bSJan Lentfer 			if (resolver->_axfr_soa_count >= 2) {
14675340022aSzrj 
14685340022aSzrj 				close_socket(resolver->_socket);
14695340022aSzrj 
1470825eb42bSJan Lentfer 				ldns_pkt_free(resolver->_cur_axfr_pkt);
1471825eb42bSJan Lentfer 				resolver->_cur_axfr_pkt = NULL;
1472825eb42bSJan Lentfer 			}
1473825eb42bSJan Lentfer 		}
1474825eb42bSJan Lentfer 		return cur_rr;
1475825eb42bSJan Lentfer 	} else {
14765340022aSzrj                packet_wire = ldns_tcp_read_wire_timeout(resolver->_socket, &packet_wire_size, resolver->_timeout);
1477825eb42bSJan Lentfer 		if(!packet_wire)
1478825eb42bSJan Lentfer 			return NULL;
1479825eb42bSJan Lentfer 
1480825eb42bSJan Lentfer 		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1481825eb42bSJan Lentfer 				     packet_wire_size);
1482d1b2b5caSJohn Marino 		LDNS_FREE(packet_wire);
1483825eb42bSJan Lentfer 
1484825eb42bSJan Lentfer 		resolver->_axfr_i = 0;
1485825eb42bSJan Lentfer 		if (status != LDNS_STATUS_OK) {
1486825eb42bSJan Lentfer 			/* TODO: make status return type of this function (...api change) */
14875340022aSzrj #ifdef STDERR_MSGS
1488825eb42bSJan Lentfer 			fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
14895340022aSzrj #endif
1490ac996e71SJan Lentfer 
14915340022aSzrj 			/* we must now also close the socket, otherwise subsequent uses of the
1492ac996e71SJan Lentfer 			   same resolver structure will fail because the link is still open or
1493ac996e71SJan Lentfer 			   in an undefined state */
14945340022aSzrj 
14955340022aSzrj 			close_socket(resolver->_socket);
1496ac996e71SJan Lentfer 
1497825eb42bSJan Lentfer 			return NULL;
1498825eb42bSJan Lentfer 		} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
14995340022aSzrj #ifdef STDERR_MSGS
15005340022aSzrj 			ldns_lookup_table *rcode = ldns_lookup_by_id(
15015340022aSzrj 				ldns_rcodes,(int) ldns_pkt_get_rcode(
15025340022aSzrj 				resolver->_cur_axfr_pkt));
1503d1b2b5caSJohn Marino 			if (rcode) {
1504d1b2b5caSJohn Marino 				fprintf(stderr, "Error in AXFR: %s\n",
1505d1b2b5caSJohn Marino 						rcode->name);
1506d1b2b5caSJohn Marino 			} else {
1507d1b2b5caSJohn Marino 				fprintf(stderr, "Error in AXFR: %d\n",
1508d1b2b5caSJohn Marino 						(int) ldns_pkt_get_rcode(
1509d1b2b5caSJohn Marino 						resolver->_cur_axfr_pkt));
1510d1b2b5caSJohn Marino 			}
15115340022aSzrj #endif
1512ac996e71SJan Lentfer 
15135340022aSzrj 			/* we must now also close the socket, otherwise subsequent uses of the
1514ac996e71SJan Lentfer 			   same resolver structure will fail because the link is still open or
1515ac996e71SJan Lentfer 			   in an undefined state */
15165340022aSzrj 
15175340022aSzrj 			close_socket(resolver->_socket);
1518ac996e71SJan Lentfer 
1519825eb42bSJan Lentfer 			return NULL;
1520825eb42bSJan Lentfer 		} else {
1521825eb42bSJan Lentfer 			return ldns_axfr_next(resolver);
1522825eb42bSJan Lentfer 		}
1523825eb42bSJan Lentfer 
1524825eb42bSJan Lentfer 	}
1525825eb42bSJan Lentfer 
1526825eb42bSJan Lentfer }
1527825eb42bSJan Lentfer 
15285340022aSzrj /* this function is needed to abort a transfer that is in progress;
15295340022aSzrj  * without it an aborted transfer will lead to the AXFR code in the
15305340022aSzrj  * library staying in an indetermined state because the socket for the
15315340022aSzrj  * AXFR is never closed
15325340022aSzrj  */
15335340022aSzrj void
ldns_axfr_abort(ldns_resolver * resolver)15345340022aSzrj ldns_axfr_abort(ldns_resolver *resolver)
15355340022aSzrj {
15365340022aSzrj 	/* Only abort if an actual AXFR is in progress */
1537819dec71SDaniel Fojt 	if (resolver->_socket != -1)
15385340022aSzrj 	{
15395340022aSzrj #ifndef USE_WINSOCK
15405340022aSzrj 		close(resolver->_socket);
15415340022aSzrj #else
15425340022aSzrj 		closesocket(resolver->_socket);
15435340022aSzrj #endif
1544819dec71SDaniel Fojt 		resolver->_socket = -1;
15455340022aSzrj 	}
15465340022aSzrj }
15475340022aSzrj 
1548825eb42bSJan Lentfer bool
ldns_axfr_complete(const ldns_resolver * res)1549825eb42bSJan Lentfer ldns_axfr_complete(const ldns_resolver *res)
1550825eb42bSJan Lentfer {
1551825eb42bSJan Lentfer 	/* complete when soa count is 2? */
1552825eb42bSJan Lentfer 	return res->_axfr_soa_count == 2;
1553825eb42bSJan Lentfer }
1554825eb42bSJan Lentfer 
1555825eb42bSJan Lentfer ldns_pkt *
ldns_axfr_last_pkt(const ldns_resolver * res)1556825eb42bSJan Lentfer ldns_axfr_last_pkt(const ldns_resolver *res)
1557825eb42bSJan Lentfer {
1558825eb42bSJan Lentfer 	return res->_cur_axfr_pkt;
1559825eb42bSJan Lentfer }
1560825eb42bSJan Lentfer 
15615340022aSzrj void
ldns_resolver_set_ixfr_serial(ldns_resolver * r,uint32_t serial)15625340022aSzrj ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial)
15635340022aSzrj {
15645340022aSzrj 	r->_serial = serial;
15655340022aSzrj }
15665340022aSzrj 
15675340022aSzrj uint32_t
ldns_resolver_get_ixfr_serial(const ldns_resolver * res)15685340022aSzrj ldns_resolver_get_ixfr_serial(const ldns_resolver *res)
15695340022aSzrj {
15705340022aSzrj 	return res->_serial;
15715340022aSzrj }
15725340022aSzrj 
15735340022aSzrj 
1574825eb42bSJan Lentfer /* random isn't really that good */
1575825eb42bSJan Lentfer void
ldns_resolver_nameservers_randomize(ldns_resolver * r)1576825eb42bSJan Lentfer ldns_resolver_nameservers_randomize(ldns_resolver *r)
1577825eb42bSJan Lentfer {
1578ac996e71SJan Lentfer 	uint16_t i, j;
1579d1b2b5caSJohn Marino 	ldns_rdf **ns, *tmpns;
1580d1b2b5caSJohn Marino 	size_t *rtt, tmprtt;
1581825eb42bSJan Lentfer 
1582825eb42bSJan Lentfer 	/* should I check for ldns_resolver_random?? */
1583825eb42bSJan Lentfer 	assert(r != NULL);
1584825eb42bSJan Lentfer 
1585825eb42bSJan Lentfer 	ns = ldns_resolver_nameservers(r);
1586d1b2b5caSJohn Marino 	rtt = ldns_resolver_rtt(r);
1587825eb42bSJan Lentfer 	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
1588ac996e71SJan Lentfer 		j = ldns_get_random() % ldns_resolver_nameserver_count(r);
1589d1b2b5caSJohn Marino 		tmpns = ns[i];
1590825eb42bSJan Lentfer 		ns[i] = ns[j];
1591d1b2b5caSJohn Marino 		ns[j] = tmpns;
1592d1b2b5caSJohn Marino 		tmprtt = rtt[i];
1593d1b2b5caSJohn Marino 		rtt[i] = rtt[j];
1594d1b2b5caSJohn Marino 		rtt[j] = tmprtt;
1595825eb42bSJan Lentfer 	}
1596825eb42bSJan Lentfer 	ldns_resolver_set_nameservers(r, ns);
1597825eb42bSJan Lentfer }
1598825eb42bSJan Lentfer 
1599