xref: /dflybsd-src/contrib/ldns/resolver.c (revision d1b2b5caec9ab35b37f82c6e75b7f14f9c9103b2)
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
24825eb42bSJan Lentfer ldns_resolver_port(const ldns_resolver *r)
25825eb42bSJan Lentfer {
26825eb42bSJan Lentfer 	return r->_port;
27825eb42bSJan Lentfer }
28825eb42bSJan Lentfer 
29825eb42bSJan Lentfer uint16_t
30825eb42bSJan Lentfer ldns_resolver_edns_udp_size(const ldns_resolver *r)
31825eb42bSJan Lentfer {
32825eb42bSJan Lentfer 	        return r->_edns_udp_size;
33825eb42bSJan Lentfer }
34825eb42bSJan Lentfer 
35825eb42bSJan Lentfer uint8_t
36825eb42bSJan Lentfer ldns_resolver_retry(const ldns_resolver *r)
37825eb42bSJan Lentfer {
38825eb42bSJan Lentfer 	return r->_retry;
39825eb42bSJan Lentfer }
40825eb42bSJan Lentfer 
41825eb42bSJan Lentfer uint8_t
42825eb42bSJan Lentfer ldns_resolver_retrans(const ldns_resolver *r)
43825eb42bSJan Lentfer {
44825eb42bSJan Lentfer 	return r->_retrans;
45825eb42bSJan Lentfer }
46825eb42bSJan Lentfer 
47825eb42bSJan Lentfer bool
48825eb42bSJan Lentfer ldns_resolver_fallback(const ldns_resolver *r)
49825eb42bSJan Lentfer {
50825eb42bSJan Lentfer 	return r->_fallback;
51825eb42bSJan Lentfer }
52825eb42bSJan Lentfer 
53825eb42bSJan Lentfer uint8_t
54825eb42bSJan Lentfer ldns_resolver_ip6(const ldns_resolver *r)
55825eb42bSJan Lentfer {
56825eb42bSJan Lentfer 	return r->_ip6;
57825eb42bSJan Lentfer }
58825eb42bSJan Lentfer 
59825eb42bSJan Lentfer bool
60825eb42bSJan Lentfer ldns_resolver_recursive(const ldns_resolver *r)
61825eb42bSJan Lentfer {
62825eb42bSJan Lentfer 	return r->_recursive;
63825eb42bSJan Lentfer }
64825eb42bSJan Lentfer 
65825eb42bSJan Lentfer bool
66825eb42bSJan Lentfer ldns_resolver_debug(const ldns_resolver *r)
67825eb42bSJan Lentfer {
68825eb42bSJan Lentfer 	return r->_debug;
69825eb42bSJan Lentfer }
70825eb42bSJan Lentfer 
71825eb42bSJan Lentfer bool
72825eb42bSJan Lentfer ldns_resolver_dnsrch(const ldns_resolver *r)
73825eb42bSJan Lentfer {
74825eb42bSJan Lentfer 	return r->_dnsrch;
75825eb42bSJan Lentfer }
76825eb42bSJan Lentfer 
77825eb42bSJan Lentfer bool
78825eb42bSJan Lentfer ldns_resolver_fail(const ldns_resolver *r)
79825eb42bSJan Lentfer {
80825eb42bSJan Lentfer 	return r->_fail;
81825eb42bSJan Lentfer }
82825eb42bSJan Lentfer 
83825eb42bSJan Lentfer bool
84825eb42bSJan Lentfer ldns_resolver_defnames(const ldns_resolver *r)
85825eb42bSJan Lentfer {
86825eb42bSJan Lentfer 	return r->_defnames;
87825eb42bSJan Lentfer }
88825eb42bSJan Lentfer 
89825eb42bSJan Lentfer ldns_rdf *
90825eb42bSJan Lentfer ldns_resolver_domain(const ldns_resolver *r)
91825eb42bSJan Lentfer {
92825eb42bSJan Lentfer 	return r->_domain;
93825eb42bSJan Lentfer }
94825eb42bSJan Lentfer 
95825eb42bSJan Lentfer ldns_rdf **
96825eb42bSJan Lentfer ldns_resolver_searchlist(const ldns_resolver *r)
97825eb42bSJan Lentfer {
98825eb42bSJan Lentfer 	return r->_searchlist;
99825eb42bSJan Lentfer }
100825eb42bSJan Lentfer 
101825eb42bSJan Lentfer ldns_rdf **
102825eb42bSJan Lentfer ldns_resolver_nameservers(const ldns_resolver *r)
103825eb42bSJan Lentfer {
104825eb42bSJan Lentfer 	return r->_nameservers;
105825eb42bSJan Lentfer }
106825eb42bSJan Lentfer 
107825eb42bSJan Lentfer size_t
108825eb42bSJan Lentfer ldns_resolver_nameserver_count(const ldns_resolver *r)
109825eb42bSJan Lentfer {
110825eb42bSJan Lentfer 	return r->_nameserver_count;
111825eb42bSJan Lentfer }
112825eb42bSJan Lentfer 
113825eb42bSJan Lentfer bool
114825eb42bSJan Lentfer ldns_resolver_dnssec(const ldns_resolver *r)
115825eb42bSJan Lentfer {
116825eb42bSJan Lentfer 	return r->_dnssec;
117825eb42bSJan Lentfer }
118825eb42bSJan Lentfer 
119825eb42bSJan Lentfer bool
120825eb42bSJan Lentfer ldns_resolver_dnssec_cd(const ldns_resolver *r)
121825eb42bSJan Lentfer {
122825eb42bSJan Lentfer 	return r->_dnssec_cd;
123825eb42bSJan Lentfer }
124825eb42bSJan Lentfer 
125825eb42bSJan Lentfer ldns_rr_list *
126825eb42bSJan Lentfer ldns_resolver_dnssec_anchors(const ldns_resolver *r)
127825eb42bSJan Lentfer {
128825eb42bSJan Lentfer     return r->_dnssec_anchors;
129825eb42bSJan Lentfer }
130825eb42bSJan Lentfer 
131825eb42bSJan Lentfer bool
132825eb42bSJan Lentfer ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
133825eb42bSJan Lentfer {
134825eb42bSJan Lentfer   size_t i;
135825eb42bSJan Lentfer   bool result = false;
136825eb42bSJan Lentfer 
137825eb42bSJan Lentfer   ldns_rr_list * trust_anchors;
138825eb42bSJan Lentfer   ldns_rr * cur_rr;
139825eb42bSJan Lentfer 
140825eb42bSJan Lentfer   if (!r || !keys) { return false; }
141825eb42bSJan Lentfer 
142825eb42bSJan Lentfer   trust_anchors = ldns_resolver_dnssec_anchors(r);
143825eb42bSJan Lentfer 
144825eb42bSJan Lentfer   if (!trust_anchors) { return false; }
145825eb42bSJan Lentfer 
146825eb42bSJan Lentfer   for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
147825eb42bSJan Lentfer 
148825eb42bSJan Lentfer     cur_rr = ldns_rr_list_rr(keys, i);
149825eb42bSJan Lentfer     if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
150825eb42bSJan Lentfer       if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
151825eb42bSJan Lentfer       result = true;
152825eb42bSJan Lentfer     }
153825eb42bSJan Lentfer   }
154825eb42bSJan Lentfer 
155825eb42bSJan Lentfer   return result;
156825eb42bSJan Lentfer }
157825eb42bSJan Lentfer 
158825eb42bSJan Lentfer bool
159825eb42bSJan Lentfer ldns_resolver_igntc(const ldns_resolver *r)
160825eb42bSJan Lentfer {
161825eb42bSJan Lentfer 	return r->_igntc;
162825eb42bSJan Lentfer }
163825eb42bSJan Lentfer 
164825eb42bSJan Lentfer bool
165825eb42bSJan Lentfer ldns_resolver_usevc(const ldns_resolver *r)
166825eb42bSJan Lentfer {
167825eb42bSJan Lentfer 	return r->_usevc;
168825eb42bSJan Lentfer }
169825eb42bSJan Lentfer 
170825eb42bSJan Lentfer size_t *
171825eb42bSJan Lentfer ldns_resolver_rtt(const ldns_resolver *r)
172825eb42bSJan Lentfer {
173825eb42bSJan Lentfer 	return r->_rtt;
174825eb42bSJan Lentfer }
175825eb42bSJan Lentfer 
176825eb42bSJan Lentfer size_t
177825eb42bSJan Lentfer ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
178825eb42bSJan Lentfer {
179825eb42bSJan Lentfer 	size_t *rtt;
180825eb42bSJan Lentfer 
181825eb42bSJan Lentfer 	assert(r != NULL);
182825eb42bSJan Lentfer 
183825eb42bSJan Lentfer 	rtt = ldns_resolver_rtt(r);
184825eb42bSJan Lentfer 
185825eb42bSJan Lentfer 	if (pos >= ldns_resolver_nameserver_count(r)) {
186825eb42bSJan Lentfer 		/* error ?*/
187825eb42bSJan Lentfer 		return 0;
188825eb42bSJan Lentfer 	} else {
189825eb42bSJan Lentfer 		return rtt[pos];
190825eb42bSJan Lentfer 	}
191825eb42bSJan Lentfer 
192825eb42bSJan Lentfer }
193825eb42bSJan Lentfer 
194825eb42bSJan Lentfer struct timeval
195825eb42bSJan Lentfer ldns_resolver_timeout(const ldns_resolver *r)
196825eb42bSJan Lentfer {
197825eb42bSJan Lentfer 	return r->_timeout;
198825eb42bSJan Lentfer }
199825eb42bSJan Lentfer 
200825eb42bSJan Lentfer char *
201825eb42bSJan Lentfer ldns_resolver_tsig_keyname(const ldns_resolver *r)
202825eb42bSJan Lentfer {
203825eb42bSJan Lentfer 	return r->_tsig_keyname;
204825eb42bSJan Lentfer }
205825eb42bSJan Lentfer 
206825eb42bSJan Lentfer char *
207825eb42bSJan Lentfer ldns_resolver_tsig_algorithm(const ldns_resolver *r)
208825eb42bSJan Lentfer {
209825eb42bSJan Lentfer 	return r->_tsig_algorithm;
210825eb42bSJan Lentfer }
211825eb42bSJan Lentfer 
212825eb42bSJan Lentfer char *
213825eb42bSJan Lentfer ldns_resolver_tsig_keydata(const ldns_resolver *r)
214825eb42bSJan Lentfer {
215825eb42bSJan Lentfer 	return r->_tsig_keydata;
216825eb42bSJan Lentfer }
217825eb42bSJan Lentfer 
218825eb42bSJan Lentfer bool
219825eb42bSJan Lentfer ldns_resolver_random(const ldns_resolver *r)
220825eb42bSJan Lentfer {
221825eb42bSJan Lentfer 	return r->_random;
222825eb42bSJan Lentfer }
223825eb42bSJan Lentfer 
224825eb42bSJan Lentfer size_t
225825eb42bSJan Lentfer ldns_resolver_searchlist_count(const ldns_resolver *r)
226825eb42bSJan Lentfer {
227825eb42bSJan Lentfer 	return r->_searchlist_count;
228825eb42bSJan Lentfer }
229825eb42bSJan Lentfer 
230825eb42bSJan Lentfer /* write */
231825eb42bSJan Lentfer void
232825eb42bSJan Lentfer ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
233825eb42bSJan Lentfer {
234825eb42bSJan Lentfer 	r->_port = p;
235825eb42bSJan Lentfer }
236825eb42bSJan Lentfer 
237825eb42bSJan Lentfer ldns_rdf *
238825eb42bSJan Lentfer ldns_resolver_pop_nameserver(ldns_resolver *r)
239825eb42bSJan Lentfer {
240825eb42bSJan Lentfer 	ldns_rdf **nameservers;
241825eb42bSJan Lentfer 	ldns_rdf *pop;
242825eb42bSJan Lentfer 	size_t ns_count;
243825eb42bSJan Lentfer 	size_t *rtt;
244825eb42bSJan Lentfer 
245825eb42bSJan Lentfer 	assert(r != NULL);
246825eb42bSJan Lentfer 
247825eb42bSJan Lentfer 	ns_count = ldns_resolver_nameserver_count(r);
248825eb42bSJan Lentfer 	nameservers = ldns_resolver_nameservers(r);
249825eb42bSJan Lentfer 	rtt = ldns_resolver_rtt(r);
250825eb42bSJan Lentfer 	if (ns_count == 0 || !nameservers) {
251825eb42bSJan Lentfer 		return NULL;
252825eb42bSJan Lentfer 	}
253825eb42bSJan Lentfer 
254825eb42bSJan Lentfer 	pop = nameservers[ns_count - 1];
255825eb42bSJan Lentfer 
256*d1b2b5caSJohn Marino 	if (ns_count == 1) {
257*d1b2b5caSJohn Marino 		LDNS_FREE(nameservers);
258*d1b2b5caSJohn Marino 		LDNS_FREE(rtt);
259*d1b2b5caSJohn Marino 
260*d1b2b5caSJohn Marino 		ldns_resolver_set_nameservers(r, NULL);
261*d1b2b5caSJohn Marino 		ldns_resolver_set_rtt(r, NULL);
262*d1b2b5caSJohn Marino 	} else {
263*d1b2b5caSJohn Marino 		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *,
264*d1b2b5caSJohn Marino 				(ns_count - 1));
265825eb42bSJan Lentfer 		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
266825eb42bSJan Lentfer 
267825eb42bSJan Lentfer 	        ldns_resolver_set_nameservers(r, nameservers);
268825eb42bSJan Lentfer 	        ldns_resolver_set_rtt(r, rtt);
269*d1b2b5caSJohn Marino 	}
270825eb42bSJan Lentfer 	/* decr the count */
271825eb42bSJan Lentfer 	ldns_resolver_dec_nameserver_count(r);
272825eb42bSJan Lentfer 	return pop;
273825eb42bSJan Lentfer }
274825eb42bSJan Lentfer 
275825eb42bSJan Lentfer ldns_status
276825eb42bSJan Lentfer ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
277825eb42bSJan Lentfer {
278825eb42bSJan Lentfer 	ldns_rdf **nameservers;
279825eb42bSJan Lentfer 	size_t ns_count;
280825eb42bSJan Lentfer 	size_t *rtt;
281825eb42bSJan Lentfer 
282825eb42bSJan Lentfer 	if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
283825eb42bSJan Lentfer 			ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
284825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
285825eb42bSJan Lentfer 	}
286825eb42bSJan Lentfer 
287825eb42bSJan Lentfer 	ns_count = ldns_resolver_nameserver_count(r);
288825eb42bSJan Lentfer 	nameservers = ldns_resolver_nameservers(r);
289825eb42bSJan Lentfer 	rtt = ldns_resolver_rtt(r);
290825eb42bSJan Lentfer 
291825eb42bSJan Lentfer 	/* make room for the next one */
292fd185f4dSJan Lentfer 	if (ns_count == 0) {
293fd185f4dSJan Lentfer 		nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
294fd185f4dSJan Lentfer 	} else {
295825eb42bSJan Lentfer 		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
296fd185f4dSJan Lentfer 	}
297fd185f4dSJan Lentfer         if(!nameservers)
298fd185f4dSJan Lentfer                 return LDNS_STATUS_MEM_ERR;
299825eb42bSJan Lentfer 
300825eb42bSJan Lentfer 	/* set the new value in the resolver */
301825eb42bSJan Lentfer 	ldns_resolver_set_nameservers(r, nameservers);
302825eb42bSJan Lentfer 
303fd185f4dSJan Lentfer 	/* don't forget the rtt */
304fd185f4dSJan Lentfer 	if (ns_count == 0) {
305fd185f4dSJan Lentfer 		rtt = LDNS_XMALLOC(size_t, 1);
306fd185f4dSJan Lentfer 	} else {
307fd185f4dSJan Lentfer 		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
308fd185f4dSJan Lentfer 	}
309fd185f4dSJan Lentfer         if(!rtt)
310fd185f4dSJan Lentfer                 return LDNS_STATUS_MEM_ERR;
311fd185f4dSJan Lentfer 
312825eb42bSJan Lentfer 	/* slide n in its slot. */
313825eb42bSJan Lentfer 	/* we clone it here, because then we can free the original
314825eb42bSJan Lentfer 	 * rr's where it stood */
315825eb42bSJan Lentfer 	nameservers[ns_count] = ldns_rdf_clone(n);
316825eb42bSJan Lentfer 	rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
317825eb42bSJan Lentfer 	ldns_resolver_incr_nameserver_count(r);
318825eb42bSJan Lentfer 	ldns_resolver_set_rtt(r, rtt);
319825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
320825eb42bSJan Lentfer }
321825eb42bSJan Lentfer 
322825eb42bSJan Lentfer ldns_status
323825eb42bSJan Lentfer ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
324825eb42bSJan Lentfer {
325825eb42bSJan Lentfer 	ldns_rdf *address;
326825eb42bSJan Lentfer 	if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
327825eb42bSJan Lentfer 			ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
328825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
329825eb42bSJan Lentfer 	}
330825eb42bSJan Lentfer 	address = ldns_rr_rdf(rr, 0); /* extract the ip number */
331825eb42bSJan Lentfer 	if (address) {
332825eb42bSJan Lentfer 		return ldns_resolver_push_nameserver(r, address);
333825eb42bSJan Lentfer 	} else {
334825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
335825eb42bSJan Lentfer 	}
336825eb42bSJan Lentfer }
337825eb42bSJan Lentfer 
338825eb42bSJan Lentfer ldns_status
339825eb42bSJan Lentfer ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
340825eb42bSJan Lentfer {
341825eb42bSJan Lentfer 	ldns_rr *rr;
342825eb42bSJan Lentfer 	ldns_status stat;
343825eb42bSJan Lentfer 	size_t i;
344825eb42bSJan Lentfer 
345825eb42bSJan Lentfer 	stat = LDNS_STATUS_OK;
346825eb42bSJan Lentfer 	if (rrlist) {
347825eb42bSJan Lentfer 		for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
348825eb42bSJan Lentfer 			rr = ldns_rr_list_rr(rrlist, i);
349825eb42bSJan Lentfer 			if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
350825eb42bSJan Lentfer 				stat = LDNS_STATUS_ERR;
351fd185f4dSJan Lentfer 				break;
352825eb42bSJan Lentfer 			}
353825eb42bSJan Lentfer 		}
354825eb42bSJan Lentfer 		return stat;
355825eb42bSJan Lentfer 	} else {
356825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
357825eb42bSJan Lentfer 	}
358825eb42bSJan Lentfer }
359825eb42bSJan Lentfer 
360825eb42bSJan Lentfer void
361825eb42bSJan Lentfer ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
362825eb42bSJan Lentfer {
363825eb42bSJan Lentfer 	        r->_edns_udp_size = s;
364825eb42bSJan Lentfer }
365825eb42bSJan Lentfer 
366825eb42bSJan Lentfer void
367825eb42bSJan Lentfer ldns_resolver_set_recursive(ldns_resolver *r, bool re)
368825eb42bSJan Lentfer {
369825eb42bSJan Lentfer 	r->_recursive = re;
370825eb42bSJan Lentfer }
371825eb42bSJan Lentfer 
372825eb42bSJan Lentfer void
373825eb42bSJan Lentfer ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
374825eb42bSJan Lentfer {
375825eb42bSJan Lentfer 	r->_dnssec = d;
376825eb42bSJan Lentfer }
377825eb42bSJan Lentfer 
378825eb42bSJan Lentfer void
379825eb42bSJan Lentfer ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
380825eb42bSJan Lentfer {
381825eb42bSJan Lentfer 	r->_dnssec_cd = d;
382825eb42bSJan Lentfer }
383825eb42bSJan Lentfer 
384825eb42bSJan Lentfer void
385825eb42bSJan Lentfer ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
386825eb42bSJan Lentfer {
387825eb42bSJan Lentfer   r->_dnssec_anchors = l;
388825eb42bSJan Lentfer }
389825eb42bSJan Lentfer 
390825eb42bSJan Lentfer ldns_status
391825eb42bSJan Lentfer ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
392825eb42bSJan Lentfer {
393825eb42bSJan Lentfer   ldns_rr_list * trust_anchors;
394825eb42bSJan Lentfer 
395*d1b2b5caSJohn Marino   if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
396*d1b2b5caSJohn Marino                 ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
397*d1b2b5caSJohn Marino 
398825eb42bSJan Lentfer     return LDNS_STATUS_ERR;
399825eb42bSJan Lentfer   }
400825eb42bSJan Lentfer 
401825eb42bSJan Lentfer   if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
402825eb42bSJan Lentfer     trust_anchors = ldns_rr_list_new();
403825eb42bSJan Lentfer     ldns_resolver_set_dnssec_anchors(r, trust_anchors);
404825eb42bSJan Lentfer   }
405825eb42bSJan Lentfer 
406825eb42bSJan Lentfer   return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
407825eb42bSJan Lentfer }
408825eb42bSJan Lentfer 
409825eb42bSJan Lentfer void
410825eb42bSJan Lentfer ldns_resolver_set_igntc(ldns_resolver *r, bool i)
411825eb42bSJan Lentfer {
412825eb42bSJan Lentfer 	r->_igntc = i;
413825eb42bSJan Lentfer }
414825eb42bSJan Lentfer 
415825eb42bSJan Lentfer void
416825eb42bSJan Lentfer ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
417825eb42bSJan Lentfer {
418825eb42bSJan Lentfer 	r->_usevc = vc;
419825eb42bSJan Lentfer }
420825eb42bSJan Lentfer 
421825eb42bSJan Lentfer void
422825eb42bSJan Lentfer ldns_resolver_set_debug(ldns_resolver *r, bool d)
423825eb42bSJan Lentfer {
424825eb42bSJan Lentfer 	r->_debug = d;
425825eb42bSJan Lentfer }
426825eb42bSJan Lentfer 
427825eb42bSJan Lentfer void
428825eb42bSJan Lentfer ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
429825eb42bSJan Lentfer {
430825eb42bSJan Lentfer 	r->_ip6 = ip6;
431825eb42bSJan Lentfer }
432825eb42bSJan Lentfer 
433825eb42bSJan Lentfer void
434825eb42bSJan Lentfer ldns_resolver_set_fail(ldns_resolver *r, bool f)
435825eb42bSJan Lentfer {
436825eb42bSJan Lentfer 	r->_fail =f;
437825eb42bSJan Lentfer }
438825eb42bSJan Lentfer 
439825eb42bSJan Lentfer void
440825eb42bSJan Lentfer ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
441825eb42bSJan Lentfer {
442825eb42bSJan Lentfer 	r->_searchlist_count = c;
443825eb42bSJan Lentfer }
444825eb42bSJan Lentfer 
445825eb42bSJan Lentfer void
446825eb42bSJan Lentfer ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
447825eb42bSJan Lentfer {
448825eb42bSJan Lentfer 	r->_nameserver_count = c;
449825eb42bSJan Lentfer }
450825eb42bSJan Lentfer 
451825eb42bSJan Lentfer void
452825eb42bSJan Lentfer ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
453825eb42bSJan Lentfer {
454825eb42bSJan Lentfer 	r->_dnsrch = d;
455825eb42bSJan Lentfer }
456825eb42bSJan Lentfer 
457825eb42bSJan Lentfer void
458825eb42bSJan Lentfer ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
459825eb42bSJan Lentfer {
460825eb42bSJan Lentfer 	r->_retry = retry;
461825eb42bSJan Lentfer }
462825eb42bSJan Lentfer 
463825eb42bSJan Lentfer void
464825eb42bSJan Lentfer ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
465825eb42bSJan Lentfer {
466825eb42bSJan Lentfer 	r->_retrans = retrans;
467825eb42bSJan Lentfer }
468825eb42bSJan Lentfer 
469825eb42bSJan Lentfer void
470825eb42bSJan Lentfer ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
471825eb42bSJan Lentfer {
472825eb42bSJan Lentfer 	r->_fallback = fallback;
473825eb42bSJan Lentfer }
474825eb42bSJan Lentfer 
475825eb42bSJan Lentfer void
476825eb42bSJan Lentfer ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
477825eb42bSJan Lentfer {
478825eb42bSJan Lentfer 	r->_nameservers = n;
479825eb42bSJan Lentfer }
480825eb42bSJan Lentfer 
481825eb42bSJan Lentfer void
482825eb42bSJan Lentfer ldns_resolver_set_defnames(ldns_resolver *r, bool d)
483825eb42bSJan Lentfer {
484825eb42bSJan Lentfer 	r->_defnames = d;
485825eb42bSJan Lentfer }
486825eb42bSJan Lentfer 
487825eb42bSJan Lentfer void
488825eb42bSJan Lentfer ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
489825eb42bSJan Lentfer {
490825eb42bSJan Lentfer 	r->_rtt = rtt;
491825eb42bSJan Lentfer }
492825eb42bSJan Lentfer 
493825eb42bSJan Lentfer void
494825eb42bSJan Lentfer ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
495825eb42bSJan Lentfer {
496825eb42bSJan Lentfer 	size_t *rtt;
497825eb42bSJan Lentfer 
498825eb42bSJan Lentfer 	assert(r != NULL);
499825eb42bSJan Lentfer 
500825eb42bSJan Lentfer 	rtt = ldns_resolver_rtt(r);
501825eb42bSJan Lentfer 
502825eb42bSJan Lentfer 	if (pos >= ldns_resolver_nameserver_count(r)) {
503825eb42bSJan Lentfer 		/* error ?*/
504825eb42bSJan Lentfer 	} else {
505825eb42bSJan Lentfer 		rtt[pos] = value;
506825eb42bSJan Lentfer 	}
507825eb42bSJan Lentfer 
508825eb42bSJan Lentfer }
509825eb42bSJan Lentfer 
510825eb42bSJan Lentfer void
511825eb42bSJan Lentfer ldns_resolver_incr_nameserver_count(ldns_resolver *r)
512825eb42bSJan Lentfer {
513825eb42bSJan Lentfer 	size_t c;
514825eb42bSJan Lentfer 
515825eb42bSJan Lentfer 	c = ldns_resolver_nameserver_count(r);
516825eb42bSJan Lentfer 	ldns_resolver_set_nameserver_count(r, ++c);
517825eb42bSJan Lentfer }
518825eb42bSJan Lentfer 
519825eb42bSJan Lentfer void
520825eb42bSJan Lentfer ldns_resolver_dec_nameserver_count(ldns_resolver *r)
521825eb42bSJan Lentfer {
522825eb42bSJan Lentfer 	size_t c;
523825eb42bSJan Lentfer 
524825eb42bSJan Lentfer 	c = ldns_resolver_nameserver_count(r);
525825eb42bSJan Lentfer 	if (c == 0) {
526825eb42bSJan Lentfer 		return;
527825eb42bSJan Lentfer 	} else {
528825eb42bSJan Lentfer 		ldns_resolver_set_nameserver_count(r, --c);
529825eb42bSJan Lentfer 	}
530825eb42bSJan Lentfer }
531825eb42bSJan Lentfer 
532825eb42bSJan Lentfer void
533825eb42bSJan Lentfer ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
534825eb42bSJan Lentfer {
535825eb42bSJan Lentfer 	r->_domain = d;
536825eb42bSJan Lentfer }
537825eb42bSJan Lentfer 
538825eb42bSJan Lentfer void
539825eb42bSJan Lentfer ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
540825eb42bSJan Lentfer {
541825eb42bSJan Lentfer 	r->_timeout.tv_sec = timeout.tv_sec;
542825eb42bSJan Lentfer 	r->_timeout.tv_usec = timeout.tv_usec;
543825eb42bSJan Lentfer }
544825eb42bSJan Lentfer 
545825eb42bSJan Lentfer void
546825eb42bSJan Lentfer ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
547825eb42bSJan Lentfer {
548825eb42bSJan Lentfer 	ldns_rdf **searchlist;
549825eb42bSJan Lentfer 	size_t list_count;
550825eb42bSJan Lentfer 
551825eb42bSJan Lentfer 	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
552825eb42bSJan Lentfer 		return;
553825eb42bSJan Lentfer 	}
554825eb42bSJan Lentfer 
555825eb42bSJan Lentfer 	list_count = ldns_resolver_searchlist_count(r);
556825eb42bSJan Lentfer 	searchlist = ldns_resolver_searchlist(r);
557825eb42bSJan Lentfer 
558825eb42bSJan Lentfer 	searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
559825eb42bSJan Lentfer 	if (searchlist) {
560825eb42bSJan Lentfer 		r->_searchlist = searchlist;
561825eb42bSJan Lentfer 
562825eb42bSJan Lentfer 		searchlist[list_count] = ldns_rdf_clone(d);
563825eb42bSJan Lentfer 		ldns_resolver_set_searchlist_count(r, list_count + 1);
564fd185f4dSJan Lentfer 	} /* no way to report mem err */
565825eb42bSJan Lentfer }
566825eb42bSJan Lentfer 
567825eb42bSJan Lentfer void
568825eb42bSJan Lentfer ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
569825eb42bSJan Lentfer {
570ac996e71SJan Lentfer 	LDNS_FREE(r->_tsig_keyname);
571ac996e71SJan Lentfer 	r->_tsig_keyname = strdup(tsig_keyname);
572825eb42bSJan Lentfer }
573825eb42bSJan Lentfer 
574825eb42bSJan Lentfer void
575825eb42bSJan Lentfer ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
576825eb42bSJan Lentfer {
577ac996e71SJan Lentfer 	LDNS_FREE(r->_tsig_algorithm);
578ac996e71SJan Lentfer 	r->_tsig_algorithm = strdup(tsig_algorithm);
579825eb42bSJan Lentfer }
580825eb42bSJan Lentfer 
581825eb42bSJan Lentfer void
582825eb42bSJan Lentfer ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
583825eb42bSJan Lentfer {
584ac996e71SJan Lentfer 	LDNS_FREE(r->_tsig_keydata);
585ac996e71SJan Lentfer 	r->_tsig_keydata = strdup(tsig_keydata);
586825eb42bSJan Lentfer }
587825eb42bSJan Lentfer 
588825eb42bSJan Lentfer void
589825eb42bSJan Lentfer ldns_resolver_set_random(ldns_resolver *r, bool b)
590825eb42bSJan Lentfer {
591825eb42bSJan Lentfer 	r->_random = b;
592825eb42bSJan Lentfer }
593825eb42bSJan Lentfer 
594825eb42bSJan Lentfer /* more sophisticated functions */
595825eb42bSJan Lentfer ldns_resolver *
596825eb42bSJan Lentfer ldns_resolver_new(void)
597825eb42bSJan Lentfer {
598825eb42bSJan Lentfer 	ldns_resolver *r;
599825eb42bSJan Lentfer 
600825eb42bSJan Lentfer 	r = LDNS_MALLOC(ldns_resolver);
601825eb42bSJan Lentfer 	if (!r) {
602825eb42bSJan Lentfer 		return NULL;
603825eb42bSJan Lentfer 	}
604825eb42bSJan Lentfer 
605825eb42bSJan Lentfer 	r->_searchlist = NULL;
606825eb42bSJan Lentfer 	r->_nameservers = NULL;
607825eb42bSJan Lentfer 	r->_rtt = NULL;
608825eb42bSJan Lentfer 
609825eb42bSJan Lentfer 	/* defaults are filled out */
610825eb42bSJan Lentfer 	ldns_resolver_set_searchlist_count(r, 0);
611825eb42bSJan Lentfer 	ldns_resolver_set_nameserver_count(r, 0);
612825eb42bSJan Lentfer 	ldns_resolver_set_usevc(r, 0);
613825eb42bSJan Lentfer 	ldns_resolver_set_port(r, LDNS_PORT);
614825eb42bSJan Lentfer 	ldns_resolver_set_domain(r, NULL);
615825eb42bSJan Lentfer 	ldns_resolver_set_defnames(r, false);
616825eb42bSJan Lentfer 	ldns_resolver_set_retry(r, 3);
617825eb42bSJan Lentfer 	ldns_resolver_set_retrans(r, 2);
618825eb42bSJan Lentfer 	ldns_resolver_set_fallback(r, true);
619825eb42bSJan Lentfer 	ldns_resolver_set_fail(r, false);
620825eb42bSJan Lentfer 	ldns_resolver_set_edns_udp_size(r, 0);
621825eb42bSJan Lentfer 	ldns_resolver_set_dnssec(r, false);
622825eb42bSJan Lentfer 	ldns_resolver_set_dnssec_cd(r, false);
623825eb42bSJan Lentfer 	ldns_resolver_set_dnssec_anchors(r, NULL);
624825eb42bSJan Lentfer 	ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
625ac996e71SJan Lentfer 	ldns_resolver_set_igntc(r, false);
626ac996e71SJan Lentfer 	ldns_resolver_set_recursive(r, false);
627ac996e71SJan Lentfer 	ldns_resolver_set_dnsrch(r, true);
628825eb42bSJan Lentfer 
629825eb42bSJan Lentfer 	/* randomize the nameserver to be queried
630825eb42bSJan Lentfer 	 * when there are multiple
631825eb42bSJan Lentfer 	 */
632825eb42bSJan Lentfer 	ldns_resolver_set_random(r, true);
633825eb42bSJan Lentfer 
634825eb42bSJan Lentfer 	ldns_resolver_set_debug(r, 0);
635825eb42bSJan Lentfer 
636825eb42bSJan Lentfer 	r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
637825eb42bSJan Lentfer 	r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
638825eb42bSJan Lentfer 
639ac996e71SJan Lentfer 	/* TODO: fd=0 is actually a valid socket (stdin),
640ac996e71SJan Lentfer            replace with -1 */
641825eb42bSJan Lentfer 	r->_socket = 0;
642825eb42bSJan Lentfer 	r->_axfr_soa_count = 0;
643825eb42bSJan Lentfer 	r->_axfr_i = 0;
644825eb42bSJan Lentfer 	r->_cur_axfr_pkt = NULL;
645825eb42bSJan Lentfer 
646825eb42bSJan Lentfer 	r->_tsig_keyname = NULL;
647825eb42bSJan Lentfer 	r->_tsig_keydata = NULL;
648825eb42bSJan Lentfer 	r->_tsig_algorithm = NULL;
649825eb42bSJan Lentfer 	return r;
650825eb42bSJan Lentfer }
651825eb42bSJan Lentfer 
652825eb42bSJan Lentfer ldns_status
653825eb42bSJan Lentfer ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
654825eb42bSJan Lentfer {
655825eb42bSJan Lentfer 	return ldns_resolver_new_frm_fp_l(res, fp, NULL);
656825eb42bSJan Lentfer }
657825eb42bSJan Lentfer 
658825eb42bSJan Lentfer ldns_status
659825eb42bSJan Lentfer ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
660825eb42bSJan Lentfer {
661825eb42bSJan Lentfer 	ldns_resolver *r;
662825eb42bSJan Lentfer 	const char *keyword[LDNS_RESOLV_KEYWORDS];
663825eb42bSJan Lentfer 	char word[LDNS_MAX_LINELEN + 1];
664825eb42bSJan Lentfer 	int8_t expect;
665825eb42bSJan Lentfer 	uint8_t i;
666825eb42bSJan Lentfer 	ldns_rdf *tmp;
667825eb42bSJan Lentfer #ifdef HAVE_SSL
668825eb42bSJan Lentfer 	ldns_rr *tmp_rr;
669825eb42bSJan Lentfer #endif
670ac996e71SJan Lentfer 	ssize_t gtr, bgtr;
671825eb42bSJan Lentfer 	ldns_buffer *b;
672ac996e71SJan Lentfer         int lnr = 0, oldline;
673ac996e71SJan Lentfer         if(!line_nr) line_nr = &lnr;
674825eb42bSJan Lentfer 
675825eb42bSJan Lentfer 	/* do this better
676825eb42bSJan Lentfer 	 * expect =
677825eb42bSJan Lentfer 	 * 0: keyword
678825eb42bSJan Lentfer 	 * 1: default domain dname
679825eb42bSJan Lentfer 	 * 2: NS aaaa or a record
680825eb42bSJan Lentfer 	 */
681825eb42bSJan Lentfer 
682825eb42bSJan Lentfer 	/* recognized keywords */
683825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
684825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
685825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_SEARCH] = "search";
686825eb42bSJan Lentfer 	/* these two are read but not used atm TODO */
687825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
688825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_OPTIONS] = "options";
689825eb42bSJan Lentfer 	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
690825eb42bSJan Lentfer 	expect = LDNS_RESOLV_KEYWORD;
691825eb42bSJan Lentfer 
692825eb42bSJan Lentfer 	r = ldns_resolver_new();
693825eb42bSJan Lentfer 	if (!r) {
694825eb42bSJan Lentfer 		return LDNS_STATUS_MEM_ERR;
695825eb42bSJan Lentfer 	}
696825eb42bSJan Lentfer 
697825eb42bSJan Lentfer 	gtr = 1;
698825eb42bSJan Lentfer 	word[0] = 0;
699ac996e71SJan Lentfer         oldline = *line_nr;
700ac996e71SJan Lentfer         expect = LDNS_RESOLV_KEYWORD;
701825eb42bSJan Lentfer 	while (gtr > 0) {
702825eb42bSJan Lentfer 		/* check comments */
703825eb42bSJan Lentfer 		if (word[0] == '#') {
704ac996e71SJan Lentfer                         word[0]='x';
705ac996e71SJan Lentfer                         if(oldline == *line_nr) {
706ac996e71SJan Lentfer                                 /* skip until end of line */
707ac996e71SJan Lentfer                                 int c;
708ac996e71SJan Lentfer                                 do {
709ac996e71SJan Lentfer                                         c = fgetc(fp);
710ac996e71SJan Lentfer                                 } while(c != EOF && c != '\n');
711ac996e71SJan Lentfer                                 if(c=='\n' && line_nr) (*line_nr)++;
712ac996e71SJan Lentfer                         }
713ac996e71SJan Lentfer 			/* and read next to prepare for further parsing */
714ac996e71SJan Lentfer                         oldline = *line_nr;
715825eb42bSJan Lentfer 			continue;
716825eb42bSJan Lentfer 		}
717ac996e71SJan Lentfer                 oldline = *line_nr;
718825eb42bSJan Lentfer 		switch(expect) {
719825eb42bSJan Lentfer 			case LDNS_RESOLV_KEYWORD:
720825eb42bSJan Lentfer 				/* keyword */
721825eb42bSJan Lentfer 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
722825eb42bSJan Lentfer 				if (gtr != 0) {
723ac996e71SJan Lentfer                                         if(word[0] == '#') continue;
724825eb42bSJan Lentfer 					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
725825eb42bSJan Lentfer 						if (strcasecmp(keyword[i], word) == 0) {
726825eb42bSJan Lentfer 							/* chosen the keyword and
727825eb42bSJan Lentfer 							 * expect values carefully
728825eb42bSJan Lentfer 	        					 */
729825eb42bSJan Lentfer 							expect = i;
730825eb42bSJan Lentfer 							break;
731825eb42bSJan Lentfer 						}
732825eb42bSJan Lentfer 					}
733825eb42bSJan Lentfer 					/* no keyword recognized */
734825eb42bSJan Lentfer 					if (expect == LDNS_RESOLV_KEYWORD) {
735825eb42bSJan Lentfer 						/* skip line */
736825eb42bSJan Lentfer 						/*
737825eb42bSJan Lentfer 						ldns_resolver_deep_free(r);
738825eb42bSJan Lentfer 						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
739825eb42bSJan Lentfer 						*/
740825eb42bSJan Lentfer 					}
741825eb42bSJan Lentfer 				}
742825eb42bSJan Lentfer 				break;
743825eb42bSJan Lentfer 			case LDNS_RESOLV_DEFDOMAIN:
744825eb42bSJan Lentfer 				/* default domain dname */
745825eb42bSJan Lentfer 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
746825eb42bSJan Lentfer 				if (gtr == 0) {
747825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
748825eb42bSJan Lentfer 				}
749ac996e71SJan Lentfer                                 if(word[0] == '#') {
750ac996e71SJan Lentfer                                         expect = LDNS_RESOLV_KEYWORD;
751ac996e71SJan Lentfer                                         continue;
752ac996e71SJan Lentfer                                 }
753825eb42bSJan Lentfer 				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
754825eb42bSJan Lentfer 				if (!tmp) {
755825eb42bSJan Lentfer 					ldns_resolver_deep_free(r);
756825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_DNAME_ERR;
757825eb42bSJan Lentfer 				}
758825eb42bSJan Lentfer 
759825eb42bSJan Lentfer 				/* DOn't free, because we copy the pointer */
760825eb42bSJan Lentfer 				ldns_resolver_set_domain(r, tmp);
761825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
762825eb42bSJan Lentfer 				break;
763825eb42bSJan Lentfer 			case LDNS_RESOLV_NAMESERVER:
764825eb42bSJan Lentfer 				/* NS aaaa or a record */
765825eb42bSJan Lentfer 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
766825eb42bSJan Lentfer 				if (gtr == 0) {
767825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
768825eb42bSJan Lentfer 				}
769ac996e71SJan Lentfer                                 if(word[0] == '#') {
770ac996e71SJan Lentfer                                         expect = LDNS_RESOLV_KEYWORD;
771ac996e71SJan Lentfer                                         continue;
772ac996e71SJan Lentfer                                 }
773ac996e71SJan Lentfer                                 if(strchr(word, '%')) {
774ac996e71SJan Lentfer                                         /* snip off interface labels,
775ac996e71SJan Lentfer                                          * fe80::222:19ff:fe31:4222%eth0 */
776ac996e71SJan Lentfer                                         strchr(word, '%')[0]=0;
777ac996e71SJan Lentfer                                 }
778825eb42bSJan Lentfer 				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
779825eb42bSJan Lentfer 				if (!tmp) {
780825eb42bSJan Lentfer 					/* try ip4 */
781825eb42bSJan Lentfer 					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
782825eb42bSJan Lentfer 				}
783825eb42bSJan Lentfer 				/* could not parse it, exit */
784825eb42bSJan Lentfer 				if (!tmp) {
785825eb42bSJan Lentfer 					ldns_resolver_deep_free(r);
786825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_ERR;
787825eb42bSJan Lentfer 				}
788825eb42bSJan Lentfer 				(void)ldns_resolver_push_nameserver(r, tmp);
789825eb42bSJan Lentfer 				ldns_rdf_deep_free(tmp);
790825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
791825eb42bSJan Lentfer 				break;
792825eb42bSJan Lentfer 			case LDNS_RESOLV_SEARCH:
793825eb42bSJan Lentfer 				/* search list domain dname */
794825eb42bSJan Lentfer 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
795825eb42bSJan Lentfer 				b = LDNS_MALLOC(ldns_buffer);
796ac996e71SJan Lentfer 				if(!b) {
797ac996e71SJan Lentfer 					ldns_resolver_deep_free(r);
798ac996e71SJan Lentfer 					return LDNS_STATUS_MEM_ERR;
799ac996e71SJan Lentfer 				}
800825eb42bSJan Lentfer 
801ac996e71SJan Lentfer 				ldns_buffer_new_frm_data(b, word, (size_t) gtr);
802ac996e71SJan Lentfer 				if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
803ac996e71SJan Lentfer 					LDNS_FREE(b);
804ac996e71SJan Lentfer 					ldns_resolver_deep_free(r);
805ac996e71SJan Lentfer 					return LDNS_STATUS_MEM_ERR;
806ac996e71SJan Lentfer 				}
807ac996e71SJan Lentfer 				bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
808ac996e71SJan Lentfer 				while (bgtr > 0) {
809ac996e71SJan Lentfer 					gtr -= bgtr;
810ac996e71SJan Lentfer                                         if(word[0] == '#') {
811ac996e71SJan Lentfer                                                 expect = LDNS_RESOLV_KEYWORD;
812*d1b2b5caSJohn Marino                                                 break;
813ac996e71SJan Lentfer                                         }
814825eb42bSJan Lentfer 					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
815825eb42bSJan Lentfer 					if (!tmp) {
816825eb42bSJan Lentfer 						ldns_resolver_deep_free(r);
817ac996e71SJan Lentfer 						ldns_buffer_free(b);
818825eb42bSJan Lentfer 						return LDNS_STATUS_SYNTAX_DNAME_ERR;
819825eb42bSJan Lentfer 					}
820825eb42bSJan Lentfer 
821825eb42bSJan Lentfer 					ldns_resolver_push_searchlist(r, tmp);
822825eb42bSJan Lentfer 
823825eb42bSJan Lentfer 					ldns_rdf_deep_free(tmp);
824ac996e71SJan Lentfer 					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
825ac996e71SJan Lentfer 					    (size_t) gtr + 1);
826825eb42bSJan Lentfer 				}
827825eb42bSJan Lentfer 				ldns_buffer_free(b);
828*d1b2b5caSJohn Marino 				if (expect != LDNS_RESOLV_KEYWORD) {
829825eb42bSJan Lentfer 					gtr = 1;
830825eb42bSJan Lentfer 					expect = LDNS_RESOLV_KEYWORD;
831*d1b2b5caSJohn Marino 				}
832825eb42bSJan Lentfer 				break;
833825eb42bSJan Lentfer 			case LDNS_RESOLV_SORTLIST:
834825eb42bSJan Lentfer 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
835825eb42bSJan Lentfer 				/* sortlist not implemented atm */
836825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
837825eb42bSJan Lentfer 				break;
838825eb42bSJan Lentfer 			case LDNS_RESOLV_OPTIONS:
839825eb42bSJan Lentfer 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
840825eb42bSJan Lentfer 				/* options not implemented atm */
841825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
842825eb42bSJan Lentfer 				break;
843825eb42bSJan Lentfer 			case LDNS_RESOLV_ANCHOR:
844825eb42bSJan Lentfer 				/* a file containing a DNSSEC trust anchor */
845825eb42bSJan Lentfer 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
846825eb42bSJan Lentfer 				if (gtr == 0) {
847ac996e71SJan Lentfer 					ldns_resolver_deep_free(r);
848825eb42bSJan Lentfer 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
849825eb42bSJan Lentfer 				}
850ac996e71SJan Lentfer                                 if(word[0] == '#') {
851ac996e71SJan Lentfer                                         expect = LDNS_RESOLV_KEYWORD;
852ac996e71SJan Lentfer                                         continue;
853ac996e71SJan Lentfer                                 }
854825eb42bSJan Lentfer 
855825eb42bSJan Lentfer #ifdef HAVE_SSL
856825eb42bSJan Lentfer 				tmp_rr = ldns_read_anchor_file(word);
857825eb42bSJan Lentfer 				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
858825eb42bSJan Lentfer 				ldns_rr_free(tmp_rr);
859825eb42bSJan Lentfer #endif
860825eb42bSJan Lentfer 				expect = LDNS_RESOLV_KEYWORD;
861825eb42bSJan Lentfer 				break;
862825eb42bSJan Lentfer 		}
863825eb42bSJan Lentfer 	}
864825eb42bSJan Lentfer 
865825eb42bSJan Lentfer 	if (res) {
866825eb42bSJan Lentfer 		*res = r;
867825eb42bSJan Lentfer 		return LDNS_STATUS_OK;
868825eb42bSJan Lentfer 	} else {
869ac996e71SJan Lentfer 		ldns_resolver_deep_free(r);
870825eb42bSJan Lentfer 		return LDNS_STATUS_NULL;
871825eb42bSJan Lentfer 	}
872825eb42bSJan Lentfer }
873825eb42bSJan Lentfer 
874825eb42bSJan Lentfer ldns_status
875825eb42bSJan Lentfer ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
876825eb42bSJan Lentfer {
877825eb42bSJan Lentfer 	ldns_resolver *r;
878825eb42bSJan Lentfer 	FILE *fp;
879825eb42bSJan Lentfer 	ldns_status s;
880825eb42bSJan Lentfer 
881825eb42bSJan Lentfer 	if (!filename) {
882825eb42bSJan Lentfer 		fp = fopen(LDNS_RESOLV_CONF, "r");
883825eb42bSJan Lentfer 
884825eb42bSJan Lentfer 	} else {
885825eb42bSJan Lentfer 		fp = fopen(filename, "r");
886825eb42bSJan Lentfer 	}
887825eb42bSJan Lentfer 	if (!fp) {
888825eb42bSJan Lentfer 		return LDNS_STATUS_FILE_ERR;
889825eb42bSJan Lentfer 	}
890825eb42bSJan Lentfer 
891825eb42bSJan Lentfer 	s = ldns_resolver_new_frm_fp(&r, fp);
892825eb42bSJan Lentfer 	fclose(fp);
893825eb42bSJan Lentfer 	if (s == LDNS_STATUS_OK) {
894825eb42bSJan Lentfer 		if (res) {
895825eb42bSJan Lentfer 			*res = r;
896825eb42bSJan Lentfer 			return LDNS_STATUS_OK;
897825eb42bSJan Lentfer 		} else  {
898*d1b2b5caSJohn Marino 			ldns_resolver_free(r);
899825eb42bSJan Lentfer 			return LDNS_STATUS_NULL;
900825eb42bSJan Lentfer 		}
901825eb42bSJan Lentfer 	}
902825eb42bSJan Lentfer 	return s;
903825eb42bSJan Lentfer }
904825eb42bSJan Lentfer 
905825eb42bSJan Lentfer void
906825eb42bSJan Lentfer ldns_resolver_free(ldns_resolver *res)
907825eb42bSJan Lentfer {
908825eb42bSJan Lentfer 	LDNS_FREE(res);
909825eb42bSJan Lentfer }
910825eb42bSJan Lentfer 
911825eb42bSJan Lentfer void
912825eb42bSJan Lentfer ldns_resolver_deep_free(ldns_resolver *res)
913825eb42bSJan Lentfer {
914825eb42bSJan Lentfer 	size_t i;
915825eb42bSJan Lentfer 
916825eb42bSJan Lentfer 	if (res) {
917825eb42bSJan Lentfer 		if (res->_searchlist) {
918825eb42bSJan Lentfer 			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
919825eb42bSJan Lentfer 				ldns_rdf_deep_free(res->_searchlist[i]);
920825eb42bSJan Lentfer 			}
921825eb42bSJan Lentfer 			LDNS_FREE(res->_searchlist);
922825eb42bSJan Lentfer 		}
923825eb42bSJan Lentfer 		if (res->_nameservers) {
924825eb42bSJan Lentfer 			for (i = 0; i < res->_nameserver_count; i++) {
925825eb42bSJan Lentfer 				ldns_rdf_deep_free(res->_nameservers[i]);
926825eb42bSJan Lentfer 			}
927825eb42bSJan Lentfer 			LDNS_FREE(res->_nameservers);
928825eb42bSJan Lentfer 		}
929825eb42bSJan Lentfer 		if (ldns_resolver_domain(res)) {
930825eb42bSJan Lentfer 			ldns_rdf_deep_free(ldns_resolver_domain(res));
931825eb42bSJan Lentfer 		}
932ac996e71SJan Lentfer 		if (res->_tsig_keyname) {
933825eb42bSJan Lentfer 			LDNS_FREE(res->_tsig_keyname);
934825eb42bSJan Lentfer 		}
935ac996e71SJan Lentfer 		if (res->_tsig_keydata) {
936ac996e71SJan Lentfer 			LDNS_FREE(res->_tsig_keydata);
937ac996e71SJan Lentfer 		}
938ac996e71SJan Lentfer 		if (res->_tsig_algorithm) {
939ac996e71SJan Lentfer 			LDNS_FREE(res->_tsig_algorithm);
940ac996e71SJan Lentfer 		}
941825eb42bSJan Lentfer 
942825eb42bSJan Lentfer 		if (res->_cur_axfr_pkt) {
943825eb42bSJan Lentfer 			ldns_pkt_free(res->_cur_axfr_pkt);
944825eb42bSJan Lentfer 		}
945825eb42bSJan Lentfer 
946825eb42bSJan Lentfer 		if (res->_rtt) {
947825eb42bSJan Lentfer 			LDNS_FREE(res->_rtt);
948825eb42bSJan Lentfer 		}
949825eb42bSJan Lentfer 		if (res->_dnssec_anchors) {
950825eb42bSJan Lentfer 			ldns_rr_list_deep_free(res->_dnssec_anchors);
951825eb42bSJan Lentfer 		}
952825eb42bSJan Lentfer 		LDNS_FREE(res);
953825eb42bSJan Lentfer 	}
954825eb42bSJan Lentfer }
955825eb42bSJan Lentfer 
956825eb42bSJan Lentfer ldns_pkt *
957825eb42bSJan Lentfer ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
958825eb42bSJan Lentfer 	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
959825eb42bSJan Lentfer {
960825eb42bSJan Lentfer 
961825eb42bSJan Lentfer 	ldns_rdf *new_name;
962825eb42bSJan Lentfer 	ldns_rdf **search_list;
963825eb42bSJan Lentfer 	size_t i;
964825eb42bSJan Lentfer 	ldns_pkt *p;
965825eb42bSJan Lentfer 
966*d1b2b5caSJohn Marino 	if (ldns_dname_absolute(name)) {
967825eb42bSJan Lentfer 		/* query as-is */
968825eb42bSJan Lentfer 		return ldns_resolver_query(r, name, t, c, flags);
969ac996e71SJan Lentfer 	} else if (ldns_resolver_dnsrch(r)) {
970825eb42bSJan Lentfer 		search_list = ldns_resolver_searchlist(r);
971825eb42bSJan Lentfer 		for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
972825eb42bSJan Lentfer 			new_name = ldns_dname_cat_clone(name, search_list[i]);
973825eb42bSJan Lentfer 
974825eb42bSJan Lentfer 			p = ldns_resolver_query(r, new_name, t, c, flags);
975825eb42bSJan Lentfer 			ldns_rdf_free(new_name);
976825eb42bSJan Lentfer 			if (p) {
977ac996e71SJan Lentfer 				if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) {
978825eb42bSJan Lentfer 					return p;
979ac996e71SJan Lentfer 				} else {
980ac996e71SJan Lentfer 					ldns_pkt_free(p);
981ac996e71SJan Lentfer 					p = NULL;
982ac996e71SJan Lentfer 				}
983825eb42bSJan Lentfer 			}
984825eb42bSJan Lentfer 		}
985825eb42bSJan Lentfer 	}
986825eb42bSJan Lentfer 	return NULL;
987825eb42bSJan Lentfer }
988825eb42bSJan Lentfer 
989825eb42bSJan Lentfer ldns_pkt *
990825eb42bSJan Lentfer ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
991825eb42bSJan Lentfer 	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
992825eb42bSJan Lentfer {
993825eb42bSJan Lentfer 	ldns_rdf *newname;
994825eb42bSJan Lentfer 	ldns_pkt *pkt;
995825eb42bSJan Lentfer 	ldns_status status;
996825eb42bSJan Lentfer 
997825eb42bSJan Lentfer 	pkt = NULL;
998825eb42bSJan Lentfer 
999825eb42bSJan Lentfer 	if (!ldns_resolver_defnames(r)) {
1000825eb42bSJan Lentfer 		status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name,
1001825eb42bSJan Lentfer 				t, c, flags);
1002825eb42bSJan Lentfer 		if (status == LDNS_STATUS_OK) {
1003825eb42bSJan Lentfer 			return pkt;
1004825eb42bSJan Lentfer 		} else {
1005825eb42bSJan Lentfer 			if (pkt) {
1006825eb42bSJan Lentfer 				ldns_pkt_free(pkt);
1007825eb42bSJan Lentfer 			}
1008825eb42bSJan Lentfer 			return NULL;
1009825eb42bSJan Lentfer 		}
1010825eb42bSJan Lentfer 	}
1011825eb42bSJan Lentfer 
1012825eb42bSJan Lentfer 	if (!ldns_resolver_domain(r)) {
1013825eb42bSJan Lentfer 		/* _defnames is set, but the domain is not....?? */
1014825eb42bSJan Lentfer 		status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name,
1015825eb42bSJan Lentfer 				t, c, flags);
1016825eb42bSJan Lentfer 		if (status == LDNS_STATUS_OK) {
1017825eb42bSJan Lentfer 			return pkt;
1018825eb42bSJan Lentfer 		} else {
1019825eb42bSJan Lentfer 			if (pkt) {
1020825eb42bSJan Lentfer 				ldns_pkt_free(pkt);
1021825eb42bSJan Lentfer 			}
1022825eb42bSJan Lentfer 			return NULL;
1023825eb42bSJan Lentfer 		}
1024825eb42bSJan Lentfer 	}
1025825eb42bSJan Lentfer 
1026825eb42bSJan Lentfer 	newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r));
1027825eb42bSJan Lentfer 	if (!newname) {
1028825eb42bSJan Lentfer 		return NULL;
1029825eb42bSJan Lentfer 	}
1030ac996e71SJan Lentfer 
1031ac996e71SJan Lentfer 	(void)ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c,
1032825eb42bSJan Lentfer 			flags);
1033825eb42bSJan Lentfer 
1034825eb42bSJan Lentfer 	ldns_rdf_free(newname);
1035825eb42bSJan Lentfer 
1036825eb42bSJan Lentfer 	return pkt;
1037825eb42bSJan Lentfer }
1038825eb42bSJan Lentfer 
1039b5dedccaSJan Lentfer static size_t *
1040b5dedccaSJan Lentfer ldns_resolver_backup_rtt(ldns_resolver *r)
1041b5dedccaSJan Lentfer {
1042b5dedccaSJan Lentfer 	size_t *new_rtt;
1043b5dedccaSJan Lentfer 	size_t *old_rtt = ldns_resolver_rtt(r);
1044b5dedccaSJan Lentfer 
1045b5dedccaSJan Lentfer 	if (old_rtt && ldns_resolver_nameserver_count(r)) {
1046b5dedccaSJan Lentfer 		new_rtt = LDNS_XMALLOC(size_t
1047b5dedccaSJan Lentfer 				, ldns_resolver_nameserver_count(r));
1048b5dedccaSJan Lentfer 		memcpy(new_rtt, old_rtt, sizeof(size_t)
1049b5dedccaSJan Lentfer 				* ldns_resolver_nameserver_count(r));
1050b5dedccaSJan Lentfer 		ldns_resolver_set_rtt(r, new_rtt);
1051b5dedccaSJan Lentfer 		return old_rtt;
1052b5dedccaSJan Lentfer 	}
1053b5dedccaSJan Lentfer 	return NULL;
1054b5dedccaSJan Lentfer }
1055b5dedccaSJan Lentfer 
1056b5dedccaSJan Lentfer static void
1057b5dedccaSJan Lentfer ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
1058b5dedccaSJan Lentfer {
1059b5dedccaSJan Lentfer 	size_t *cur_rtt = ldns_resolver_rtt(r);
1060b5dedccaSJan Lentfer 
1061b5dedccaSJan Lentfer 	if (cur_rtt) {
1062b5dedccaSJan Lentfer 		LDNS_FREE(cur_rtt);
1063b5dedccaSJan Lentfer 	}
1064b5dedccaSJan Lentfer 	ldns_resolver_set_rtt(r, old_rtt);
1065b5dedccaSJan Lentfer }
1066b5dedccaSJan Lentfer 
1067825eb42bSJan Lentfer ldns_status
1068825eb42bSJan Lentfer ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1069825eb42bSJan Lentfer 				   ldns_pkt *query_pkt)
1070825eb42bSJan Lentfer {
1071825eb42bSJan Lentfer 	ldns_pkt *answer_pkt = NULL;
1072825eb42bSJan Lentfer 	ldns_status stat = LDNS_STATUS_OK;
1073b5dedccaSJan Lentfer 	size_t *rtt;
1074825eb42bSJan Lentfer 
1075825eb42bSJan Lentfer 	stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
1076825eb42bSJan Lentfer 	if (stat != LDNS_STATUS_OK) {
1077825eb42bSJan Lentfer 		if(answer_pkt) {
1078825eb42bSJan Lentfer 			ldns_pkt_free(answer_pkt);
1079825eb42bSJan Lentfer 			answer_pkt = NULL;
1080825eb42bSJan Lentfer 		}
1081825eb42bSJan Lentfer 	} else {
1082825eb42bSJan Lentfer 		/* if tc=1 fall back to EDNS and/or TCP */
1083825eb42bSJan Lentfer 		/* check for tcp first (otherwise we don't care about tc=1) */
1084825eb42bSJan Lentfer 		if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
1085825eb42bSJan Lentfer 			if (ldns_pkt_tc(answer_pkt)) {
1086825eb42bSJan Lentfer 				/* was EDNS0 set? */
1087825eb42bSJan Lentfer 				if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
1088b5dedccaSJan Lentfer 					ldns_pkt_set_edns_udp_size(query_pkt
1089b5dedccaSJan Lentfer 							, 4096);
1090825eb42bSJan Lentfer 					ldns_pkt_free(answer_pkt);
1091b5dedccaSJan Lentfer 					/* Nameservers should not become
1092b5dedccaSJan Lentfer 					 * unreachable because fragments are
1093b5dedccaSJan Lentfer 					 * dropped (network error). We might
1094b5dedccaSJan Lentfer 					 * still have success with TCP.
1095b5dedccaSJan Lentfer 					 * Therefore maintain reachability
1096b5dedccaSJan Lentfer 					 * statuses of the nameservers by
1097b5dedccaSJan Lentfer 					 * backup and restore the rtt list.
1098b5dedccaSJan Lentfer 					 */
1099b5dedccaSJan Lentfer 					rtt = ldns_resolver_backup_rtt(r);
1100b5dedccaSJan Lentfer 					stat = ldns_send(&answer_pkt, r
1101b5dedccaSJan Lentfer 							, query_pkt);
1102b5dedccaSJan Lentfer 					ldns_resolver_restore_rtt(r, rtt);
1103825eb42bSJan Lentfer 				}
1104825eb42bSJan Lentfer 				/* either way, if it is still truncated, use TCP */
1105825eb42bSJan Lentfer 				if (stat != LDNS_STATUS_OK ||
1106825eb42bSJan Lentfer 				    ldns_pkt_tc(answer_pkt)) {
1107825eb42bSJan Lentfer 					ldns_resolver_set_usevc(r, true);
1108825eb42bSJan Lentfer 					ldns_pkt_free(answer_pkt);
1109825eb42bSJan Lentfer 					stat = ldns_send(&answer_pkt, r, query_pkt);
1110825eb42bSJan Lentfer 					ldns_resolver_set_usevc(r, false);
1111825eb42bSJan Lentfer 				}
1112825eb42bSJan Lentfer 			}
1113825eb42bSJan Lentfer 		}
1114825eb42bSJan Lentfer 	}
1115825eb42bSJan Lentfer 
1116825eb42bSJan Lentfer 	if (answer) {
1117825eb42bSJan Lentfer 		*answer = answer_pkt;
1118825eb42bSJan Lentfer 	}
1119825eb42bSJan Lentfer 
1120825eb42bSJan Lentfer 	return stat;
1121825eb42bSJan Lentfer }
1122825eb42bSJan Lentfer 
1123825eb42bSJan Lentfer ldns_status
1124825eb42bSJan Lentfer ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
1125825eb42bSJan Lentfer                                 const ldns_rdf *name, ldns_rr_type t,
1126825eb42bSJan Lentfer                                 ldns_rr_class c, uint16_t flags)
1127825eb42bSJan Lentfer {
1128fd185f4dSJan Lentfer 	struct timeval now;
1129fd185f4dSJan Lentfer 
1130825eb42bSJan Lentfer 	/* prepare a question pkt from the parameters
1131825eb42bSJan Lentfer 	 * and then send this */
1132825eb42bSJan Lentfer 	*query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
1133825eb42bSJan Lentfer 	if (!*query_pkt) {
1134825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
1135825eb42bSJan Lentfer 	}
1136825eb42bSJan Lentfer 
1137825eb42bSJan Lentfer 	/* set DO bit if necessary */
1138825eb42bSJan Lentfer 	if (ldns_resolver_dnssec(r)) {
1139825eb42bSJan Lentfer 		if (ldns_resolver_edns_udp_size(r) == 0) {
1140825eb42bSJan Lentfer 			ldns_resolver_set_edns_udp_size(r, 4096);
1141825eb42bSJan Lentfer 		}
1142825eb42bSJan Lentfer 		ldns_pkt_set_edns_do(*query_pkt, true);
1143825eb42bSJan Lentfer 		if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
1144825eb42bSJan Lentfer 			ldns_pkt_set_cd(*query_pkt, true);
1145825eb42bSJan Lentfer 		}
1146825eb42bSJan Lentfer 	}
1147825eb42bSJan Lentfer 
1148825eb42bSJan Lentfer 	/* transfer the udp_edns_size from the resolver to the packet */
1149825eb42bSJan Lentfer 	if (ldns_resolver_edns_udp_size(r) != 0) {
1150825eb42bSJan Lentfer 		ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
1151825eb42bSJan Lentfer 	}
1152825eb42bSJan Lentfer 
1153fd185f4dSJan Lentfer 	/* set the timestamp */
1154fd185f4dSJan Lentfer 	now.tv_sec = time(NULL);
1155fd185f4dSJan Lentfer 	now.tv_usec = 0;
1156fd185f4dSJan Lentfer 	ldns_pkt_set_timestamp(*query_pkt, now);
1157fd185f4dSJan Lentfer 
1158fd185f4dSJan Lentfer 
1159825eb42bSJan Lentfer 	if (ldns_resolver_debug(r)) {
1160825eb42bSJan Lentfer 		ldns_pkt_print(stdout, *query_pkt);
1161825eb42bSJan Lentfer 	}
1162825eb42bSJan Lentfer 
1163825eb42bSJan Lentfer 	/* only set the id if it is not set yet */
1164825eb42bSJan Lentfer 	if (ldns_pkt_id(*query_pkt) == 0) {
1165825eb42bSJan Lentfer 		ldns_pkt_set_random_id(*query_pkt);
1166825eb42bSJan Lentfer 	}
1167825eb42bSJan Lentfer 
1168825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
1169825eb42bSJan Lentfer }
1170825eb42bSJan Lentfer 
1171825eb42bSJan Lentfer 
1172825eb42bSJan Lentfer ldns_status
1173825eb42bSJan Lentfer ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
1174825eb42bSJan Lentfer 		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1175825eb42bSJan Lentfer {
1176825eb42bSJan Lentfer 	ldns_pkt *query_pkt;
1177825eb42bSJan Lentfer 	ldns_pkt *answer_pkt;
1178825eb42bSJan Lentfer 	ldns_status status;
1179825eb42bSJan Lentfer 
1180825eb42bSJan Lentfer 	assert(r != NULL);
1181825eb42bSJan Lentfer 	assert(name != NULL);
1182825eb42bSJan Lentfer 
1183825eb42bSJan Lentfer 	answer_pkt = NULL;
1184825eb42bSJan Lentfer 
1185825eb42bSJan Lentfer 	/* do all the preprocessing here, then fire of an query to
1186825eb42bSJan Lentfer 	 * the network */
1187825eb42bSJan Lentfer 
1188825eb42bSJan Lentfer 	if (0 == t) {
1189825eb42bSJan Lentfer 		t= LDNS_RR_TYPE_A;
1190825eb42bSJan Lentfer 	}
1191825eb42bSJan Lentfer 	if (0 == c) {
1192825eb42bSJan Lentfer 		c= LDNS_RR_CLASS_IN;
1193825eb42bSJan Lentfer 	}
1194825eb42bSJan Lentfer 	if (0 == ldns_resolver_nameserver_count(r)) {
1195825eb42bSJan Lentfer 		return LDNS_STATUS_RES_NO_NS;
1196825eb42bSJan Lentfer 	}
1197825eb42bSJan Lentfer 	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1198825eb42bSJan Lentfer 		return LDNS_STATUS_RES_QUERY;
1199825eb42bSJan Lentfer 	}
1200825eb42bSJan Lentfer 
1201825eb42bSJan Lentfer 	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1202825eb42bSJan Lentfer 	                                         t, c, flags);
1203825eb42bSJan Lentfer 	if (status != LDNS_STATUS_OK) {
1204825eb42bSJan Lentfer 		return status;
1205825eb42bSJan Lentfer 	}
1206825eb42bSJan Lentfer 
1207825eb42bSJan Lentfer 	/* if tsig values are set, tsign it */
1208825eb42bSJan Lentfer 	/* TODO: make last 3 arguments optional too? maybe make complete
1209825eb42bSJan Lentfer 	         rr instead of seperate values in resolver (and packet)
1210825eb42bSJan Lentfer 	  Jelte
1211825eb42bSJan Lentfer 	  should this go in pkt_prepare?
1212825eb42bSJan Lentfer 	*/
1213825eb42bSJan Lentfer 	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
1214fd185f4dSJan Lentfer #ifdef HAVE_SSL
1215825eb42bSJan Lentfer 		status = ldns_pkt_tsig_sign(query_pkt,
1216825eb42bSJan Lentfer 		                            ldns_resolver_tsig_keyname(r),
1217825eb42bSJan Lentfer 		                            ldns_resolver_tsig_keydata(r),
1218825eb42bSJan Lentfer 		                            300, ldns_resolver_tsig_algorithm(r), NULL);
1219825eb42bSJan Lentfer 		if (status != LDNS_STATUS_OK) {
1220*d1b2b5caSJohn Marino 			ldns_pkt_free(query_pkt);
1221825eb42bSJan Lentfer 			return LDNS_STATUS_CRYPTO_TSIG_ERR;
1222825eb42bSJan Lentfer 		}
1223825eb42bSJan Lentfer #else
1224*d1b2b5caSJohn Marino 		ldns_pkt_free(query_pkt);
1225825eb42bSJan Lentfer 	        return LDNS_STATUS_CRYPTO_TSIG_ERR;
1226825eb42bSJan Lentfer #endif /* HAVE_SSL */
1227fd185f4dSJan Lentfer 	}
1228ac996e71SJan Lentfer 
1229825eb42bSJan Lentfer 	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1230825eb42bSJan Lentfer 	ldns_pkt_free(query_pkt);
1231825eb42bSJan Lentfer 
1232825eb42bSJan Lentfer 	/* allows answer to be NULL when not interested in return value */
1233825eb42bSJan Lentfer 	if (answer) {
1234825eb42bSJan Lentfer 		*answer = answer_pkt;
1235825eb42bSJan Lentfer 	}
1236825eb42bSJan Lentfer 	return status;
1237825eb42bSJan Lentfer }
1238825eb42bSJan Lentfer 
1239825eb42bSJan Lentfer ldns_rr *
1240825eb42bSJan Lentfer ldns_axfr_next(ldns_resolver *resolver)
1241825eb42bSJan Lentfer {
1242825eb42bSJan Lentfer 	ldns_rr *cur_rr;
1243825eb42bSJan Lentfer 	uint8_t *packet_wire;
1244825eb42bSJan Lentfer 	size_t packet_wire_size;
1245825eb42bSJan Lentfer 	ldns_lookup_table *rcode;
1246825eb42bSJan Lentfer 	ldns_status status;
1247825eb42bSJan Lentfer 
1248825eb42bSJan Lentfer 	/* check if start() has been called */
1249825eb42bSJan Lentfer 	if (!resolver || resolver->_socket == 0) {
1250825eb42bSJan Lentfer 		return NULL;
1251825eb42bSJan Lentfer 	}
1252825eb42bSJan Lentfer 
1253825eb42bSJan Lentfer 	if (resolver->_cur_axfr_pkt) {
1254825eb42bSJan Lentfer 		if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
1255825eb42bSJan Lentfer 			ldns_pkt_free(resolver->_cur_axfr_pkt);
1256825eb42bSJan Lentfer 			resolver->_cur_axfr_pkt = NULL;
1257825eb42bSJan Lentfer 			return ldns_axfr_next(resolver);
1258825eb42bSJan Lentfer 		}
1259825eb42bSJan Lentfer 		cur_rr = ldns_rr_clone(ldns_rr_list_rr(
1260825eb42bSJan Lentfer 					ldns_pkt_answer(resolver->_cur_axfr_pkt),
1261825eb42bSJan Lentfer 					resolver->_axfr_i));
1262825eb42bSJan Lentfer 		resolver->_axfr_i++;
1263825eb42bSJan Lentfer 		if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
1264825eb42bSJan Lentfer 			resolver->_axfr_soa_count++;
1265825eb42bSJan Lentfer 			if (resolver->_axfr_soa_count >= 2) {
1266ac996e71SJan Lentfer #ifndef USE_WINSOCK
1267825eb42bSJan Lentfer 				close(resolver->_socket);
1268ac996e71SJan Lentfer #else
1269ac996e71SJan Lentfer 				closesocket(resolver->_socket);
1270ac996e71SJan Lentfer #endif
1271825eb42bSJan Lentfer 				resolver->_socket = 0;
1272825eb42bSJan Lentfer 				ldns_pkt_free(resolver->_cur_axfr_pkt);
1273825eb42bSJan Lentfer 				resolver->_cur_axfr_pkt = NULL;
1274825eb42bSJan Lentfer 			}
1275825eb42bSJan Lentfer 		}
1276825eb42bSJan Lentfer 		return cur_rr;
1277825eb42bSJan Lentfer 	} else {
1278825eb42bSJan Lentfer 		packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size);
1279825eb42bSJan Lentfer 		if(!packet_wire)
1280825eb42bSJan Lentfer 			return NULL;
1281825eb42bSJan Lentfer 
1282825eb42bSJan Lentfer 		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1283825eb42bSJan Lentfer 				     packet_wire_size);
1284*d1b2b5caSJohn Marino 		LDNS_FREE(packet_wire);
1285825eb42bSJan Lentfer 
1286825eb42bSJan Lentfer 		resolver->_axfr_i = 0;
1287825eb42bSJan Lentfer 		if (status != LDNS_STATUS_OK) {
1288825eb42bSJan Lentfer 			/* TODO: make status return type of this function (...api change) */
1289825eb42bSJan Lentfer 			fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
1290ac996e71SJan Lentfer 
1291ac996e71SJan Lentfer 			/* RoRi: we must now also close the socket, otherwise subsequent uses of the
1292ac996e71SJan Lentfer 			   same resolver structure will fail because the link is still open or
1293ac996e71SJan Lentfer 			   in an undefined state */
1294ac996e71SJan Lentfer #ifndef USE_WINSOCK
1295ac996e71SJan Lentfer 			close(resolver->_socket);
1296ac996e71SJan Lentfer #else
1297ac996e71SJan Lentfer 			closesocket(resolver->_socket);
1298ac996e71SJan Lentfer #endif
1299ac996e71SJan Lentfer 			resolver->_socket = 0;
1300ac996e71SJan Lentfer 
1301825eb42bSJan Lentfer 			return NULL;
1302825eb42bSJan Lentfer 		} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
1303825eb42bSJan Lentfer 			rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt));
1304*d1b2b5caSJohn Marino 			if (rcode) {
1305*d1b2b5caSJohn Marino 				fprintf(stderr, "Error in AXFR: %s\n",
1306*d1b2b5caSJohn Marino 						rcode->name);
1307*d1b2b5caSJohn Marino 			} else {
1308*d1b2b5caSJohn Marino 				fprintf(stderr, "Error in AXFR: %d\n",
1309*d1b2b5caSJohn Marino 						(int) ldns_pkt_get_rcode(
1310*d1b2b5caSJohn Marino 						resolver->_cur_axfr_pkt));
1311*d1b2b5caSJohn Marino 			}
1312ac996e71SJan Lentfer 
1313ac996e71SJan Lentfer 			/* RoRi: we must now also close the socket, otherwise subsequent uses of the
1314ac996e71SJan Lentfer 			   same resolver structure will fail because the link is still open or
1315ac996e71SJan Lentfer 			   in an undefined state */
1316ac996e71SJan Lentfer #ifndef USE_WINSOCK
1317ac996e71SJan Lentfer 			close(resolver->_socket);
1318ac996e71SJan Lentfer #else
1319ac996e71SJan Lentfer 			closesocket(resolver->_socket);
1320ac996e71SJan Lentfer #endif
1321ac996e71SJan Lentfer 			resolver->_socket = 0;
1322ac996e71SJan Lentfer 
1323825eb42bSJan Lentfer 			return NULL;
1324825eb42bSJan Lentfer 		} else {
1325825eb42bSJan Lentfer 			return ldns_axfr_next(resolver);
1326825eb42bSJan Lentfer 		}
1327825eb42bSJan Lentfer 
1328825eb42bSJan Lentfer 	}
1329825eb42bSJan Lentfer 
1330825eb42bSJan Lentfer }
1331825eb42bSJan Lentfer 
1332825eb42bSJan Lentfer bool
1333825eb42bSJan Lentfer ldns_axfr_complete(const ldns_resolver *res)
1334825eb42bSJan Lentfer {
1335825eb42bSJan Lentfer 	/* complete when soa count is 2? */
1336825eb42bSJan Lentfer 	return res->_axfr_soa_count == 2;
1337825eb42bSJan Lentfer }
1338825eb42bSJan Lentfer 
1339825eb42bSJan Lentfer ldns_pkt *
1340825eb42bSJan Lentfer ldns_axfr_last_pkt(const ldns_resolver *res)
1341825eb42bSJan Lentfer {
1342825eb42bSJan Lentfer 	return res->_cur_axfr_pkt;
1343825eb42bSJan Lentfer }
1344825eb42bSJan Lentfer 
1345825eb42bSJan Lentfer /* random isn't really that good */
1346825eb42bSJan Lentfer void
1347825eb42bSJan Lentfer ldns_resolver_nameservers_randomize(ldns_resolver *r)
1348825eb42bSJan Lentfer {
1349ac996e71SJan Lentfer 	uint16_t i, j;
1350*d1b2b5caSJohn Marino 	ldns_rdf **ns, *tmpns;
1351*d1b2b5caSJohn Marino 	size_t *rtt, tmprtt;
1352825eb42bSJan Lentfer 
1353825eb42bSJan Lentfer 	/* should I check for ldns_resolver_random?? */
1354825eb42bSJan Lentfer 	assert(r != NULL);
1355825eb42bSJan Lentfer 
1356825eb42bSJan Lentfer 	ns = ldns_resolver_nameservers(r);
1357*d1b2b5caSJohn Marino 	rtt = ldns_resolver_rtt(r);
1358825eb42bSJan Lentfer 	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
1359ac996e71SJan Lentfer 		j = ldns_get_random() % ldns_resolver_nameserver_count(r);
1360*d1b2b5caSJohn Marino 		tmpns = ns[i];
1361825eb42bSJan Lentfer 		ns[i] = ns[j];
1362*d1b2b5caSJohn Marino 		ns[j] = tmpns;
1363*d1b2b5caSJohn Marino 		tmprtt = rtt[i];
1364*d1b2b5caSJohn Marino 		rtt[i] = rtt[j];
1365*d1b2b5caSJohn Marino 		rtt[j] = tmprtt;
1366825eb42bSJan Lentfer 	}
1367825eb42bSJan Lentfer 	ldns_resolver_set_nameservers(r, ns);
1368825eb42bSJan Lentfer }
1369825eb42bSJan Lentfer 
1370