1/*
2 * resolver.c
3 *
4 * resolver implementation
5 *
6 * a Net::DNS like library for C
7 *
8 * (c) NLnet Labs, 2004-2006
9 *
10 * See the file LICENSE for the license
11 */
12
13#include <ldns/config.h>
14
15#include <ldns/ldns.h>
16#include <strings.h>
17
18/* Access function for reading
19 * and setting the different Resolver
20 * options */
21
22/* read */
23uint16_t
24ldns_resolver_port(const ldns_resolver *r)
25{
26	return r->_port;
27}
28
29ldns_rdf *
30ldns_resolver_source(const ldns_resolver *r)
31{
32	return r->_source;
33}
34
35uint16_t
36ldns_resolver_edns_udp_size(const ldns_resolver *r)
37{
38	        return r->_edns_udp_size;
39}
40
41uint8_t
42ldns_resolver_retry(const ldns_resolver *r)
43{
44	return r->_retry;
45}
46
47uint8_t
48ldns_resolver_retrans(const ldns_resolver *r)
49{
50	return r->_retrans;
51}
52
53bool
54ldns_resolver_fallback(const ldns_resolver *r)
55{
56	return r->_fallback;
57}
58
59uint8_t
60ldns_resolver_ip6(const ldns_resolver *r)
61{
62	return r->_ip6;
63}
64
65bool
66ldns_resolver_recursive(const ldns_resolver *r)
67{
68	return r->_recursive;
69}
70
71bool
72ldns_resolver_debug(const ldns_resolver *r)
73{
74	return r->_debug;
75}
76
77bool
78ldns_resolver_dnsrch(const ldns_resolver *r)
79{
80	return r->_dnsrch;
81}
82
83bool
84ldns_resolver_fail(const ldns_resolver *r)
85{
86	return r->_fail;
87}
88
89bool
90ldns_resolver_defnames(const ldns_resolver *r)
91{
92	return r->_defnames;
93}
94
95ldns_rdf *
96ldns_resolver_domain(const ldns_resolver *r)
97{
98	return r->_domain;
99}
100
101ldns_rdf **
102ldns_resolver_searchlist(const ldns_resolver *r)
103{
104	return r->_searchlist;
105}
106
107ldns_rdf **
108ldns_resolver_nameservers(const ldns_resolver *r)
109{
110	return r->_nameservers;
111}
112
113size_t
114ldns_resolver_nameserver_count(const ldns_resolver *r)
115{
116	return r->_nameserver_count;
117}
118
119bool
120ldns_resolver_dnssec(const ldns_resolver *r)
121{
122	return r->_dnssec;
123}
124
125bool
126ldns_resolver_dnssec_cd(const ldns_resolver *r)
127{
128	return r->_dnssec_cd;
129}
130
131ldns_rr_list *
132ldns_resolver_dnssec_anchors(const ldns_resolver *r)
133{
134    return r->_dnssec_anchors;
135}
136
137bool
138ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
139{
140  size_t i;
141  bool result = false;
142
143  ldns_rr_list * trust_anchors;
144  ldns_rr * cur_rr;
145
146  if (!r || !keys) { return false; }
147
148  trust_anchors = ldns_resolver_dnssec_anchors(r);
149
150  if (!trust_anchors) { return false; }
151
152  for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
153
154    cur_rr = ldns_rr_list_rr(keys, i);
155    if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
156      if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
157      result = true;
158    }
159  }
160
161  return result;
162}
163
164bool
165ldns_resolver_igntc(const ldns_resolver *r)
166{
167	return r->_igntc;
168}
169
170bool
171ldns_resolver_usevc(const ldns_resolver *r)
172{
173	return r->_usevc;
174}
175
176size_t *
177ldns_resolver_rtt(const ldns_resolver *r)
178{
179	return r->_rtt;
180}
181
182size_t
183ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
184{
185	size_t *rtt;
186
187	assert(r != NULL);
188
189	rtt = ldns_resolver_rtt(r);
190
191	if (pos >= ldns_resolver_nameserver_count(r)) {
192		/* error ?*/
193		return 0;
194	} else {
195		return rtt[pos];
196	}
197
198}
199
200struct timeval
201ldns_resolver_timeout(const ldns_resolver *r)
202{
203	return r->_timeout;
204}
205
206const char *
207ldns_resolver_tsig_keyname(const ldns_resolver *r)
208{
209	return r->_tsig_keyname;
210}
211
212const char *
213ldns_resolver_tsig_algorithm(const ldns_resolver *r)
214{
215	return r->_tsig_algorithm;
216}
217
218const char *
219ldns_resolver_tsig_keydata(const ldns_resolver *r)
220{
221	return r->_tsig_keydata;
222}
223
224bool
225ldns_resolver_random(const ldns_resolver *r)
226{
227	return r->_random;
228}
229
230size_t
231ldns_resolver_searchlist_count(const ldns_resolver *r)
232{
233	return r->_searchlist_count;
234}
235
236/* write */
237void
238ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
239{
240	r->_port = p;
241}
242
243void
244ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
245{
246	r->_source = s;
247}
248
249ldns_rdf *
250ldns_resolver_pop_nameserver(ldns_resolver *r)
251{
252	ldns_rdf **nameservers;
253	ldns_rdf *pop;
254	size_t ns_count;
255	size_t *rtt;
256
257	assert(r != NULL);
258
259	ns_count = ldns_resolver_nameserver_count(r);
260	nameservers = ldns_resolver_nameservers(r);
261	rtt = ldns_resolver_rtt(r);
262	if (ns_count == 0 || !nameservers) {
263		return NULL;
264	}
265
266	pop = nameservers[ns_count - 1];
267
268	if (ns_count == 1) {
269		LDNS_FREE(nameservers);
270		LDNS_FREE(rtt);
271
272		ldns_resolver_set_nameservers(r, NULL);
273		ldns_resolver_set_rtt(r, NULL);
274	} else {
275		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *,
276				(ns_count - 1));
277		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
278
279	        ldns_resolver_set_nameservers(r, nameservers);
280	        ldns_resolver_set_rtt(r, rtt);
281	}
282	/* decr the count */
283	ldns_resolver_dec_nameserver_count(r);
284	return pop;
285}
286
287ldns_status
288ldns_resolver_push_nameserver(ldns_resolver *r, const ldns_rdf *n)
289{
290	ldns_rdf **nameservers;
291	size_t ns_count;
292	size_t *rtt;
293
294	if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
295			ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
296		return LDNS_STATUS_ERR;
297	}
298
299	ns_count = ldns_resolver_nameserver_count(r);
300	nameservers = ldns_resolver_nameservers(r);
301	rtt = ldns_resolver_rtt(r);
302
303	/* make room for the next one */
304	if (ns_count == 0) {
305		nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
306	} else {
307		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
308	}
309        if(!nameservers)
310                return LDNS_STATUS_MEM_ERR;
311
312	/* set the new value in the resolver */
313	ldns_resolver_set_nameservers(r, nameservers);
314
315	/* don't forget the rtt */
316	if (ns_count == 0) {
317		rtt = LDNS_XMALLOC(size_t, 1);
318	} else {
319		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
320	}
321        if(!rtt)
322                return LDNS_STATUS_MEM_ERR;
323
324	/* slide n in its slot. */
325	/* we clone it here, because then we can free the original
326	 * rr's where it stood */
327	nameservers[ns_count] = ldns_rdf_clone(n);
328	rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
329	ldns_resolver_incr_nameserver_count(r);
330	ldns_resolver_set_rtt(r, rtt);
331	return LDNS_STATUS_OK;
332}
333
334ldns_status
335ldns_resolver_push_nameserver_rr(ldns_resolver *r, const ldns_rr *rr)
336{
337	ldns_rdf *address;
338	if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
339			ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
340		return LDNS_STATUS_ERR;
341	}
342	address = ldns_rr_rdf(rr, 0); /* extract the ip number */
343	if (address) {
344		return ldns_resolver_push_nameserver(r, address);
345	} else {
346		return LDNS_STATUS_ERR;
347	}
348}
349
350ldns_status
351ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, const ldns_rr_list *rrlist)
352{
353	ldns_rr *rr;
354	ldns_status stat;
355	size_t i;
356
357	stat = LDNS_STATUS_OK;
358	if (rrlist) {
359		for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
360			rr = ldns_rr_list_rr(rrlist, i);
361			if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
362				stat = LDNS_STATUS_ERR;
363				break;
364			}
365		}
366		return stat;
367	} else {
368		return LDNS_STATUS_ERR;
369	}
370}
371
372void
373ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
374{
375	        r->_edns_udp_size = s;
376}
377
378void
379ldns_resolver_set_recursive(ldns_resolver *r, bool re)
380{
381	r->_recursive = re;
382}
383
384void
385ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
386{
387	r->_dnssec = d;
388}
389
390void
391ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
392{
393	r->_dnssec_cd = d;
394}
395
396void
397ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
398{
399  r->_dnssec_anchors = l;
400}
401
402ldns_status
403ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
404{
405  ldns_rr_list * trust_anchors;
406
407  if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
408                ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
409
410    return LDNS_STATUS_ERR;
411  }
412
413  if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
414    trust_anchors = ldns_rr_list_new();
415    ldns_resolver_set_dnssec_anchors(r, trust_anchors);
416  }
417
418  return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
419}
420
421void
422ldns_resolver_set_igntc(ldns_resolver *r, bool i)
423{
424	r->_igntc = i;
425}
426
427void
428ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
429{
430	r->_usevc = vc;
431}
432
433void
434ldns_resolver_set_debug(ldns_resolver *r, bool d)
435{
436	r->_debug = d;
437}
438
439void
440ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
441{
442	r->_ip6 = ip6;
443}
444
445void
446ldns_resolver_set_fail(ldns_resolver *r, bool f)
447{
448	r->_fail =f;
449}
450
451static void
452ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
453{
454	r->_searchlist_count = c;
455}
456
457void
458ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
459{
460	r->_nameserver_count = c;
461}
462
463void
464ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
465{
466	r->_dnsrch = d;
467}
468
469void
470ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
471{
472	r->_retry = retry;
473}
474
475void
476ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
477{
478	r->_retrans = retrans;
479}
480
481void
482ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
483{
484	r->_fallback = fallback;
485}
486
487void
488ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
489{
490	r->_nameservers = n;
491}
492
493void
494ldns_resolver_set_defnames(ldns_resolver *r, bool d)
495{
496	r->_defnames = d;
497}
498
499void
500ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
501{
502	r->_rtt = rtt;
503}
504
505void
506ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
507{
508	size_t *rtt;
509
510	assert(r != NULL);
511
512	rtt = ldns_resolver_rtt(r);
513
514	if (pos >= ldns_resolver_nameserver_count(r)) {
515		/* error ?*/
516	} else {
517		rtt[pos] = value;
518	}
519
520}
521
522void
523ldns_resolver_incr_nameserver_count(ldns_resolver *r)
524{
525	size_t c;
526
527	c = ldns_resolver_nameserver_count(r);
528	ldns_resolver_set_nameserver_count(r, ++c);
529}
530
531void
532ldns_resolver_dec_nameserver_count(ldns_resolver *r)
533{
534	size_t c;
535
536	c = ldns_resolver_nameserver_count(r);
537	if (c == 0) {
538		return;
539	} else {
540		ldns_resolver_set_nameserver_count(r, --c);
541	}
542}
543
544void
545ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
546{
547	r->_domain = d;
548}
549
550void
551ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
552{
553	r->_timeout.tv_sec = timeout.tv_sec;
554	r->_timeout.tv_usec = timeout.tv_usec;
555}
556
557void
558ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
559{
560	ldns_rdf **searchlist;
561	size_t list_count;
562
563	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
564		return;
565	}
566
567	list_count = ldns_resolver_searchlist_count(r);
568	searchlist = ldns_resolver_searchlist(r);
569
570	searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
571	if (searchlist) {
572		r->_searchlist = searchlist;
573
574		searchlist[list_count] = ldns_rdf_clone(d);
575		ldns_resolver_set_searchlist_count(r, list_count + 1);
576	} /* no way to report mem err */
577}
578
579void
580ldns_resolver_set_tsig_keyname(ldns_resolver *r, const char *tsig_keyname)
581{
582	LDNS_FREE(r->_tsig_keyname);
583	r->_tsig_keyname = strdup(tsig_keyname);
584}
585
586void
587ldns_resolver_set_tsig_algorithm(ldns_resolver *r, const char *tsig_algorithm)
588{
589	LDNS_FREE(r->_tsig_algorithm);
590	r->_tsig_algorithm = strdup(tsig_algorithm);
591}
592
593void
594ldns_resolver_set_tsig_keydata(ldns_resolver *r, const char *tsig_keydata)
595{
596	LDNS_FREE(r->_tsig_keydata);
597	r->_tsig_keydata = strdup(tsig_keydata);
598}
599
600void
601ldns_resolver_set_random(ldns_resolver *r, bool b)
602{
603	r->_random = b;
604}
605
606/* more sophisticated functions */
607ldns_resolver *
608ldns_resolver_new(void)
609{
610	ldns_resolver *r;
611
612	r = LDNS_MALLOC(ldns_resolver);
613	if (!r) {
614		return NULL;
615	}
616
617	r->_searchlist = NULL;
618	r->_nameservers = NULL;
619	r->_rtt = NULL;
620
621	/* defaults are filled out */
622	ldns_resolver_set_searchlist_count(r, 0);
623	ldns_resolver_set_nameserver_count(r, 0);
624	ldns_resolver_set_usevc(r, 0);
625	ldns_resolver_set_port(r, LDNS_PORT);
626	ldns_resolver_set_domain(r, NULL);
627	ldns_resolver_set_defnames(r, false);
628	ldns_resolver_set_retry(r, 3);
629	ldns_resolver_set_retrans(r, 2);
630	ldns_resolver_set_fallback(r, true);
631	ldns_resolver_set_fail(r, false);
632	ldns_resolver_set_edns_udp_size(r, 0);
633	ldns_resolver_set_dnssec(r, false);
634	ldns_resolver_set_dnssec_cd(r, false);
635	ldns_resolver_set_dnssec_anchors(r, NULL);
636	ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
637	ldns_resolver_set_igntc(r, false);
638	ldns_resolver_set_recursive(r, false);
639	ldns_resolver_set_dnsrch(r, true);
640	ldns_resolver_set_source(r, NULL);
641	ldns_resolver_set_ixfr_serial(r, 0);
642
643	/* randomize the nameserver to be queried
644	 * when there are multiple
645	 */
646	ldns_resolver_set_random(r, true);
647
648	ldns_resolver_set_debug(r, 0);
649
650	r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
651	r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
652
653	r->_socket = -1;
654	r->_axfr_soa_count = 0;
655	r->_axfr_i = 0;
656	r->_cur_axfr_pkt = NULL;
657
658	r->_tsig_keyname = NULL;
659	r->_tsig_keydata = NULL;
660	r->_tsig_algorithm = NULL;
661	return r;
662}
663
664ldns_resolver *
665ldns_resolver_clone(ldns_resolver *src)
666{
667	ldns_resolver *dst;
668	size_t i;
669
670	assert(src != NULL);
671
672	if (!(dst = LDNS_MALLOC(ldns_resolver))) return NULL;
673	(void) memcpy(dst, src, sizeof(ldns_resolver));
674
675	if (dst->_searchlist_count == 0)
676		dst->_searchlist = NULL;
677	else {
678		if (!(dst->_searchlist =
679		    LDNS_XMALLOC(ldns_rdf *, dst->_searchlist_count)))
680			goto error;
681		for (i = 0; i < dst->_searchlist_count; i++)
682			if (!(dst->_searchlist[i] =
683			    ldns_rdf_clone(src->_searchlist[i]))) {
684				dst->_searchlist_count = i;
685				goto error_searchlist;
686			}
687	}
688	if (dst->_nameserver_count == 0) {
689		dst->_nameservers = NULL;
690		dst->_rtt = NULL;
691	} else {
692		if (!(dst->_nameservers =
693		    LDNS_XMALLOC(ldns_rdf *, dst->_nameserver_count)))
694			goto error_searchlist;
695		for (i = 0; i < dst->_nameserver_count; i++)
696			if (!(dst->_nameservers[i] =
697			    ldns_rdf_clone(src->_nameservers[i]))) {
698				dst->_nameserver_count = i;
699				goto error_nameservers;
700			}
701		if (!(dst->_rtt =
702		    LDNS_XMALLOC(size_t, dst->_nameserver_count)))
703			goto error_nameservers;
704		(void) memcpy(dst->_rtt, src->_rtt,
705		    sizeof(size_t) * dst->_nameserver_count);
706	}
707	if (dst->_domain && (!(dst->_domain = ldns_rdf_clone(src->_domain))))
708		goto error_rtt;
709
710	if (dst->_tsig_keyname &&
711	    (!(dst->_tsig_keyname = strdup(src->_tsig_keyname))))
712		goto error_domain;
713
714	if (dst->_tsig_keydata &&
715	    (!(dst->_tsig_keydata = strdup(src->_tsig_keydata))))
716		goto error_tsig_keyname;
717
718	if (dst->_tsig_algorithm &&
719	    (!(dst->_tsig_algorithm = strdup(src->_tsig_algorithm))))
720		goto error_tsig_keydata;
721
722	if (dst->_cur_axfr_pkt &&
723	    (!(dst->_cur_axfr_pkt = ldns_pkt_clone(src->_cur_axfr_pkt))))
724		goto error_tsig_algorithm;
725
726	if (dst->_dnssec_anchors &&
727	    (!(dst->_dnssec_anchors=ldns_rr_list_clone(src->_dnssec_anchors))))
728		goto error_cur_axfr_pkt;
729
730	return dst;
731
732error_cur_axfr_pkt:
733	ldns_pkt_free(dst->_cur_axfr_pkt);
734error_tsig_algorithm:
735	LDNS_FREE(dst->_tsig_algorithm);
736error_tsig_keydata:
737	LDNS_FREE(dst->_tsig_keydata);
738error_tsig_keyname:
739	LDNS_FREE(dst->_tsig_keyname);
740error_domain:
741	ldns_rdf_deep_free(dst->_domain);
742error_rtt:
743	LDNS_FREE(dst->_rtt);
744error_nameservers:
745	for (i = 0; i < dst->_nameserver_count; i++)
746		ldns_rdf_deep_free(dst->_nameservers[i]);
747	LDNS_FREE(dst->_nameservers);
748error_searchlist:
749	for (i = 0; i < dst->_searchlist_count; i++)
750		ldns_rdf_deep_free(dst->_searchlist[i]);
751	LDNS_FREE(dst->_searchlist);
752error:
753	LDNS_FREE(dst);
754	return NULL;
755}
756
757
758ldns_status
759ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
760{
761	return ldns_resolver_new_frm_fp_l(res, fp, NULL);
762}
763
764ldns_status
765ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
766{
767	ldns_resolver *r;
768	const char *keyword[LDNS_RESOLV_KEYWORDS];
769	char word[LDNS_MAX_LINELEN + 1];
770	int8_t expect;
771	uint8_t i;
772	ldns_rdf *tmp;
773#ifdef HAVE_SSL
774	ldns_rr *tmp_rr;
775#endif
776	ssize_t gtr, bgtr;
777	ldns_buffer *b;
778        int lnr = 0, oldline;
779	FILE* myfp = fp;
780        if(!line_nr) line_nr = &lnr;
781
782	if(!fp) {
783		myfp = fopen("/etc/resolv.conf", "r");
784		if(!myfp)
785			return LDNS_STATUS_FILE_ERR;
786	}
787
788	/* do this better
789	 * expect =
790	 * 0: keyword
791	 * 1: default domain dname
792	 * 2: NS aaaa or a record
793	 */
794
795	/* recognized keywords */
796	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
797	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
798	keyword[LDNS_RESOLV_SEARCH] = "search";
799	/* these two are read but not used atm TODO */
800	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
801	keyword[LDNS_RESOLV_OPTIONS] = "options";
802	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
803	expect = LDNS_RESOLV_KEYWORD;
804
805	r = ldns_resolver_new();
806	if (!r) {
807		if(!fp) fclose(myfp);
808		return LDNS_STATUS_MEM_ERR;
809	}
810
811	gtr = 1;
812	word[0] = 0;
813        oldline = *line_nr;
814        expect = LDNS_RESOLV_KEYWORD;
815	while (gtr > 0) {
816		/* check comments */
817		if (word[0] == '#') {
818                        word[0]='x';
819                        if(oldline == *line_nr) {
820                                /* skip until end of line */
821                                int c;
822                                do {
823                                        c = fgetc(myfp);
824                                } while(c != EOF && c != '\n');
825                                if(c=='\n') (*line_nr)++;
826                        }
827			/* and read next to prepare for further parsing */
828                        oldline = *line_nr;
829			continue;
830		}
831                oldline = *line_nr;
832		switch(expect) {
833			case LDNS_RESOLV_KEYWORD:
834				/* keyword */
835				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
836				if (gtr != 0) {
837                                        if(word[0] == '#') continue;
838					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
839						if (strcasecmp(keyword[i], word) == 0) {
840							/* chosen the keyword and
841							 * expect values carefully
842	        					 */
843							expect = i;
844							break;
845						}
846					}
847					/* no keyword recognized */
848					if (expect == LDNS_RESOLV_KEYWORD) {
849						/* skip line */
850						/*
851						ldns_resolver_deep_free(r);
852						if(!fp) fclose(myfp);
853						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
854						*/
855					}
856				}
857				break;
858			case LDNS_RESOLV_DEFDOMAIN:
859				/* default domain dname */
860				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
861				if (gtr == 0) {
862					if(!fp) fclose(myfp);
863					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
864				}
865                                if(word[0] == '#') {
866                                        expect = LDNS_RESOLV_KEYWORD;
867                                        continue;
868                                }
869				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
870				if (!tmp) {
871					ldns_resolver_deep_free(r);
872					if(!fp) fclose(myfp);
873					return LDNS_STATUS_SYNTAX_DNAME_ERR;
874				}
875
876				/* DOn't free, because we copy the pointer */
877				ldns_resolver_set_domain(r, tmp);
878				expect = LDNS_RESOLV_KEYWORD;
879				break;
880			case LDNS_RESOLV_NAMESERVER:
881				/* NS aaaa or a record */
882				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
883				if (gtr == 0) {
884					if(!fp) fclose(myfp);
885					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
886				}
887                                if(word[0] == '#') {
888                                        expect = LDNS_RESOLV_KEYWORD;
889                                        continue;
890                                }
891                                if(strchr(word, '%')) {
892                                        /* snip off interface labels,
893                                         * fe80::222:19ff:fe31:4222%eth0 */
894                                        strchr(word, '%')[0]=0;
895                                }
896				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
897				if (!tmp) {
898					/* try ip4 */
899					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
900				}
901				/* could not parse it, exit */
902				if (!tmp) {
903					ldns_resolver_deep_free(r);
904					if(!fp) fclose(myfp);
905					return LDNS_STATUS_SYNTAX_ERR;
906				}
907				(void)ldns_resolver_push_nameserver(r, tmp);
908				ldns_rdf_deep_free(tmp);
909				expect = LDNS_RESOLV_KEYWORD;
910				break;
911			case LDNS_RESOLV_SEARCH:
912				/* search list domain dname */
913				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
914				b = LDNS_MALLOC(ldns_buffer);
915				if(!b) {
916					ldns_resolver_deep_free(r);
917					if(!fp) fclose(myfp);
918					return LDNS_STATUS_MEM_ERR;
919				}
920
921				ldns_buffer_new_frm_data(b, word, (size_t) gtr);
922				if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
923					LDNS_FREE(b);
924					ldns_resolver_deep_free(r);
925					if(!fp) fclose(myfp);
926					return LDNS_STATUS_MEM_ERR;
927				}
928				bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
929				while (bgtr > 0) {
930					gtr -= bgtr;
931                                        if(word[0] == '#') {
932                                                expect = LDNS_RESOLV_KEYWORD;
933                                                break;
934                                        }
935					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
936					if (!tmp) {
937						ldns_resolver_deep_free(r);
938						ldns_buffer_free(b);
939						if(!fp) fclose(myfp);
940						return LDNS_STATUS_SYNTAX_DNAME_ERR;
941					}
942
943					ldns_resolver_push_searchlist(r, tmp);
944
945					ldns_rdf_deep_free(tmp);
946					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
947					    (size_t) gtr + 1);
948				}
949				ldns_buffer_free(b);
950				if (expect != LDNS_RESOLV_KEYWORD) {
951					gtr = 1;
952					expect = LDNS_RESOLV_KEYWORD;
953				}
954				break;
955			case LDNS_RESOLV_SORTLIST:
956				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
957				/* sortlist not implemented atm */
958				expect = LDNS_RESOLV_KEYWORD;
959				break;
960			case LDNS_RESOLV_OPTIONS:
961				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
962				/* options not implemented atm */
963				expect = LDNS_RESOLV_KEYWORD;
964				break;
965			case LDNS_RESOLV_ANCHOR:
966				/* a file containing a DNSSEC trust anchor */
967				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
968				if (gtr == 0) {
969					ldns_resolver_deep_free(r);
970					if(!fp) fclose(myfp);
971					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
972				}
973                                if(word[0] == '#') {
974                                        expect = LDNS_RESOLV_KEYWORD;
975                                        continue;
976                                }
977
978#ifdef HAVE_SSL
979				tmp_rr = ldns_read_anchor_file(word);
980				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
981				ldns_rr_free(tmp_rr);
982#endif
983				expect = LDNS_RESOLV_KEYWORD;
984				break;
985		}
986	}
987
988	if(!fp)
989		fclose(myfp);
990
991	if (res) {
992		*res = r;
993		return LDNS_STATUS_OK;
994	} else {
995		ldns_resolver_deep_free(r);
996		return LDNS_STATUS_NULL;
997	}
998}
999
1000ldns_status
1001ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
1002{
1003	ldns_resolver *r;
1004	FILE *fp;
1005	ldns_status s;
1006
1007	if (!filename) {
1008		fp = fopen(LDNS_RESOLV_CONF, "r");
1009
1010	} else {
1011		fp = fopen(filename, "r");
1012	}
1013	if (!fp) {
1014		return LDNS_STATUS_FILE_ERR;
1015	}
1016
1017	s = ldns_resolver_new_frm_fp(&r, fp);
1018	fclose(fp);
1019	if (s == LDNS_STATUS_OK) {
1020		if (res) {
1021			*res = r;
1022			return LDNS_STATUS_OK;
1023		} else  {
1024			ldns_resolver_free(r);
1025			return LDNS_STATUS_NULL;
1026		}
1027	}
1028	return s;
1029}
1030
1031void
1032ldns_resolver_free(ldns_resolver *res)
1033{
1034	LDNS_FREE(res);
1035}
1036
1037void
1038ldns_resolver_deep_free(ldns_resolver *res)
1039{
1040	size_t i;
1041
1042	if (res) {
1043		close_socket(res->_socket);
1044
1045		if (res->_searchlist) {
1046			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
1047				ldns_rdf_deep_free(res->_searchlist[i]);
1048			}
1049			LDNS_FREE(res->_searchlist);
1050		}
1051		if (res->_nameservers) {
1052			for (i = 0; i < res->_nameserver_count; i++) {
1053				ldns_rdf_deep_free(res->_nameservers[i]);
1054			}
1055			LDNS_FREE(res->_nameservers);
1056		}
1057		if (ldns_resolver_domain(res)) {
1058			ldns_rdf_deep_free(ldns_resolver_domain(res));
1059		}
1060		if (res->_tsig_keyname) {
1061			LDNS_FREE(res->_tsig_keyname);
1062		}
1063		if (res->_tsig_keydata) {
1064			LDNS_FREE(res->_tsig_keydata);
1065		}
1066		if (res->_tsig_algorithm) {
1067			LDNS_FREE(res->_tsig_algorithm);
1068		}
1069
1070		if (res->_cur_axfr_pkt) {
1071			ldns_pkt_free(res->_cur_axfr_pkt);
1072		}
1073
1074		if (res->_rtt) {
1075			LDNS_FREE(res->_rtt);
1076		}
1077		if (res->_dnssec_anchors) {
1078			ldns_rr_list_deep_free(res->_dnssec_anchors);
1079		}
1080		LDNS_FREE(res);
1081	}
1082}
1083
1084ldns_status
1085ldns_resolver_search_status(ldns_pkt** pkt,
1086		ldns_resolver *r, const  ldns_rdf *name,
1087		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1088{
1089	ldns_rdf *new_name;
1090	ldns_rdf **search_list;
1091	size_t i;
1092	ldns_status s = LDNS_STATUS_OK;
1093	ldns_rdf root_dname = { 1, LDNS_RDF_TYPE_DNAME, (void *)"" };
1094
1095	if (ldns_dname_absolute(name)) {
1096		/* query as-is */
1097		return ldns_resolver_query_status(pkt, r, name, t, c, flags);
1098	} else if (ldns_resolver_dnsrch(r)) {
1099		search_list = ldns_resolver_searchlist(r);
1100		for (i = 0; i <= ldns_resolver_searchlist_count(r); i++) {
1101			if (i == ldns_resolver_searchlist_count(r)) {
1102				new_name = ldns_dname_cat_clone(name,
1103						&root_dname);
1104			} else {
1105				new_name = ldns_dname_cat_clone(name,
1106						search_list[i]);
1107			}
1108
1109			s = ldns_resolver_query_status(pkt, r,
1110					new_name, t, c, flags);
1111			ldns_rdf_free(new_name);
1112			if (pkt && *pkt) {
1113				if (s == LDNS_STATUS_OK &&
1114						ldns_pkt_get_rcode(*pkt) ==
1115						LDNS_RCODE_NOERROR) {
1116
1117					return LDNS_STATUS_OK;
1118				}
1119				ldns_pkt_free(*pkt);
1120				*pkt = NULL;
1121			}
1122		}
1123	}
1124	return s;
1125}
1126
1127ldns_pkt *
1128ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
1129	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1130{
1131	ldns_pkt* pkt = NULL;
1132	if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
1133				name, t, c, flags) != LDNS_STATUS_OK) {
1134		ldns_pkt_free(pkt);
1135	}
1136	return pkt;
1137}
1138
1139ldns_status
1140ldns_resolver_query_status(ldns_pkt** pkt,
1141		ldns_resolver *r, const ldns_rdf *name,
1142		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1143{
1144	ldns_rdf *newname;
1145	ldns_status status;
1146
1147	if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
1148		return ldns_resolver_send(pkt, r, name, t, c, flags);
1149	}
1150
1151	newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
1152	if (!newname) {
1153		return LDNS_STATUS_MEM_ERR;
1154	}
1155	status = ldns_resolver_send(pkt, r, newname, t, c, flags);
1156	ldns_rdf_free(newname);
1157	return status;
1158}
1159
1160ldns_pkt *
1161ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
1162	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1163{
1164	ldns_pkt* pkt = NULL;
1165	if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
1166				name, t, c, flags) != LDNS_STATUS_OK) {
1167		ldns_pkt_free(pkt);
1168	}
1169	return pkt;
1170}
1171
1172static size_t *
1173ldns_resolver_backup_rtt(ldns_resolver *r)
1174{
1175	size_t *new_rtt;
1176	size_t *old_rtt = ldns_resolver_rtt(r);
1177
1178	if (old_rtt && ldns_resolver_nameserver_count(r)) {
1179		new_rtt = LDNS_XMALLOC(size_t
1180				, ldns_resolver_nameserver_count(r));
1181		memcpy(new_rtt, old_rtt, sizeof(size_t)
1182				* ldns_resolver_nameserver_count(r));
1183		ldns_resolver_set_rtt(r, new_rtt);
1184		return old_rtt;
1185	}
1186	return NULL;
1187}
1188
1189static void
1190ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
1191{
1192	size_t *cur_rtt = ldns_resolver_rtt(r);
1193
1194	if (cur_rtt) {
1195		LDNS_FREE(cur_rtt);
1196	}
1197	ldns_resolver_set_rtt(r, old_rtt);
1198}
1199
1200ldns_status
1201ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1202				   ldns_pkt *query_pkt)
1203{
1204	ldns_pkt *answer_pkt = NULL;
1205	ldns_status stat = LDNS_STATUS_OK;
1206	size_t *rtt;
1207
1208	stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
1209	if (stat != LDNS_STATUS_OK) {
1210		if(answer_pkt) {
1211			ldns_pkt_free(answer_pkt);
1212			answer_pkt = NULL;
1213		}
1214	} else {
1215		/* if tc=1 fall back to EDNS and/or TCP */
1216		/* check for tcp first (otherwise we don't care about tc=1) */
1217		if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
1218			if (ldns_pkt_tc(answer_pkt)) {
1219				/* was EDNS0 set? */
1220				if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
1221					ldns_pkt_set_edns_udp_size(query_pkt
1222							, 4096);
1223					ldns_pkt_free(answer_pkt);
1224					answer_pkt = NULL;
1225					/* Nameservers should not become
1226					 * unreachable because fragments are
1227					 * dropped (network error). We might
1228					 * still have success with TCP.
1229					 * Therefore maintain reachability
1230					 * statuses of the nameservers by
1231					 * backup and restore the rtt list.
1232					 */
1233					rtt = ldns_resolver_backup_rtt(r);
1234					stat = ldns_send(&answer_pkt, r
1235							, query_pkt);
1236					ldns_resolver_restore_rtt(r, rtt);
1237				}
1238				/* either way, if it is still truncated, use TCP */
1239				if (stat != LDNS_STATUS_OK ||
1240				    ldns_pkt_tc(answer_pkt)) {
1241					ldns_resolver_set_usevc(r, true);
1242					ldns_pkt_free(answer_pkt);
1243					stat = ldns_send(&answer_pkt, r, query_pkt);
1244					ldns_resolver_set_usevc(r, false);
1245				}
1246			}
1247		}
1248	}
1249
1250	if (answer) {
1251		*answer = answer_pkt;
1252	}
1253
1254	return stat;
1255}
1256
1257ldns_status
1258ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
1259                                const ldns_rdf *name, ldns_rr_type t,
1260                                ldns_rr_class c, uint16_t flags)
1261{
1262	struct timeval now;
1263	ldns_rr* soa = NULL;
1264
1265	/* prepare a question pkt from the parameters
1266	 * and then send this */
1267	if (t == LDNS_RR_TYPE_IXFR) {
1268		ldns_rdf *owner_rdf;
1269		ldns_rdf *mname_rdf;
1270		ldns_rdf *rname_rdf;
1271		ldns_rdf *serial_rdf;
1272		ldns_rdf *refresh_rdf;
1273		ldns_rdf *retry_rdf;
1274		ldns_rdf *expire_rdf;
1275		ldns_rdf *minimum_rdf;
1276		soa = ldns_rr_new();
1277
1278		if (!soa) {
1279			return LDNS_STATUS_ERR;
1280		}
1281		owner_rdf = ldns_rdf_clone(name);
1282		if (!owner_rdf) {
1283			ldns_rr_free(soa);
1284			return LDNS_STATUS_ERR;
1285		}
1286		ldns_rr_set_owner(soa, owner_rdf);
1287		ldns_rr_set_type(soa, LDNS_RR_TYPE_SOA);
1288		ldns_rr_set_class(soa, c);
1289		ldns_rr_set_question(soa, false);
1290		if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
1291			ldns_rr_free(soa);
1292			return LDNS_STATUS_ERR;
1293		} else	ldns_rr_push_rdf(soa, mname_rdf);
1294		if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
1295			ldns_rr_free(soa);
1296			return LDNS_STATUS_ERR;
1297		} else	ldns_rr_push_rdf(soa, rname_rdf);
1298		serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, ldns_resolver_get_ixfr_serial(r));
1299		if (!serial_rdf) {
1300			ldns_rr_free(soa);
1301			return LDNS_STATUS_ERR;
1302		} else	ldns_rr_push_rdf(soa, serial_rdf);
1303		refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1304		if (!refresh_rdf) {
1305			ldns_rr_free(soa);
1306			return LDNS_STATUS_ERR;
1307		} else	ldns_rr_push_rdf(soa, refresh_rdf);
1308		retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1309		if (!retry_rdf) {
1310			ldns_rr_free(soa);
1311			return LDNS_STATUS_ERR;
1312		} else	ldns_rr_push_rdf(soa, retry_rdf);
1313		expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1314		if (!expire_rdf) {
1315			ldns_rr_free(soa);
1316			return LDNS_STATUS_ERR;
1317		} else	ldns_rr_push_rdf(soa, expire_rdf);
1318		minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1319		if (!minimum_rdf) {
1320			ldns_rr_free(soa);
1321			return LDNS_STATUS_ERR;
1322		} else	ldns_rr_push_rdf(soa, minimum_rdf);
1323
1324		*query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name),
1325			c, flags, soa);
1326	} else {
1327		*query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
1328	}
1329	if (!*query_pkt) {
1330		ldns_rr_free(soa);
1331		return LDNS_STATUS_ERR;
1332	}
1333
1334	/* set DO bit if necessary */
1335	if (ldns_resolver_dnssec(r)) {
1336		if (ldns_resolver_edns_udp_size(r) == 0) {
1337			ldns_resolver_set_edns_udp_size(r, 4096);
1338		}
1339		ldns_pkt_set_edns_do(*query_pkt, true);
1340		if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
1341			ldns_pkt_set_cd(*query_pkt, true);
1342		}
1343	}
1344
1345	/* transfer the udp_edns_size from the resolver to the packet */
1346	if (ldns_resolver_edns_udp_size(r) != 0) {
1347		ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
1348	}
1349
1350	/* set the timestamp */
1351	now.tv_sec = time(NULL);
1352	now.tv_usec = 0;
1353	ldns_pkt_set_timestamp(*query_pkt, now);
1354
1355
1356	if (ldns_resolver_debug(r)) {
1357		ldns_pkt_print(stdout, *query_pkt);
1358	}
1359
1360	/* only set the id if it is not set yet */
1361	if (ldns_pkt_id(*query_pkt) == 0) {
1362		ldns_pkt_set_random_id(*query_pkt);
1363	}
1364
1365	return LDNS_STATUS_OK;
1366}
1367
1368ldns_status
1369ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
1370		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1371{
1372	ldns_pkt *query_pkt;
1373	ldns_pkt *answer_pkt;
1374	ldns_status status;
1375
1376	assert(r != NULL);
1377	assert(name != NULL);
1378
1379	answer_pkt = NULL;
1380
1381	/* do all the preprocessing here, then fire of an query to
1382	 * the network */
1383
1384	if (0 == t) {
1385		t= LDNS_RR_TYPE_A;
1386	}
1387	if (0 == c) {
1388		c= LDNS_RR_CLASS_IN;
1389	}
1390	if (0 == ldns_resolver_nameserver_count(r)) {
1391		return LDNS_STATUS_RES_NO_NS;
1392	}
1393	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1394		return LDNS_STATUS_RES_QUERY;
1395	}
1396
1397	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1398	                                         t, c, flags);
1399	if (status != LDNS_STATUS_OK) {
1400		return status;
1401	}
1402
1403	/* if tsig values are set, tsign it */
1404	/* TODO: make last 3 arguments optional too? maybe make complete
1405	         rr instead of separate values in resolver (and packet)
1406	  Jelte
1407	  should this go in pkt_prepare?
1408	*/
1409	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
1410#ifdef HAVE_SSL
1411		status = ldns_pkt_tsig_sign(query_pkt,
1412		                            ldns_resolver_tsig_keyname(r),
1413		                            ldns_resolver_tsig_keydata(r),
1414		                            300, ldns_resolver_tsig_algorithm(r), NULL);
1415		if (status != LDNS_STATUS_OK) {
1416			ldns_pkt_free(query_pkt);
1417			return LDNS_STATUS_CRYPTO_TSIG_ERR;
1418		}
1419#else
1420		ldns_pkt_free(query_pkt);
1421	        return LDNS_STATUS_CRYPTO_TSIG_ERR;
1422#endif /* HAVE_SSL */
1423	}
1424
1425	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1426	ldns_pkt_free(query_pkt);
1427
1428	/* allows answer to be NULL when not interested in return value */
1429	if (answer) {
1430		*answer = answer_pkt;
1431	}
1432	return status;
1433}
1434
1435ldns_rr *
1436ldns_axfr_next(ldns_resolver *resolver)
1437{
1438	ldns_rr *cur_rr;
1439	uint8_t *packet_wire;
1440	size_t packet_wire_size;
1441	ldns_status status;
1442
1443	/* check if start() has been called */
1444	if (!resolver || resolver->_socket == -1) {
1445		return NULL;
1446	}
1447
1448	if (resolver->_cur_axfr_pkt) {
1449		if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
1450			ldns_pkt_free(resolver->_cur_axfr_pkt);
1451			resolver->_cur_axfr_pkt = NULL;
1452			return ldns_axfr_next(resolver);
1453		}
1454		cur_rr = ldns_rr_clone(ldns_rr_list_rr(
1455					ldns_pkt_answer(resolver->_cur_axfr_pkt),
1456					resolver->_axfr_i));
1457		resolver->_axfr_i++;
1458		if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
1459			resolver->_axfr_soa_count++;
1460			if (resolver->_axfr_soa_count >= 2) {
1461
1462				close_socket(resolver->_socket);
1463
1464				ldns_pkt_free(resolver->_cur_axfr_pkt);
1465				resolver->_cur_axfr_pkt = NULL;
1466			}
1467		}
1468		return cur_rr;
1469	} else {
1470               packet_wire = ldns_tcp_read_wire_timeout(resolver->_socket, &packet_wire_size, resolver->_timeout);
1471		if(!packet_wire)
1472			return NULL;
1473
1474		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1475				     packet_wire_size);
1476		LDNS_FREE(packet_wire);
1477
1478		resolver->_axfr_i = 0;
1479		if (status != LDNS_STATUS_OK) {
1480			/* TODO: make status return type of this function (...api change) */
1481#ifdef STDERR_MSGS
1482			fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
1483#endif
1484
1485			/* we must now also close the socket, otherwise subsequent uses of the
1486			   same resolver structure will fail because the link is still open or
1487			   in an undefined state */
1488
1489			close_socket(resolver->_socket);
1490
1491			return NULL;
1492		} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
1493#ifdef STDERR_MSGS
1494			ldns_lookup_table *rcode = ldns_lookup_by_id(
1495				ldns_rcodes,(int) ldns_pkt_get_rcode(
1496				resolver->_cur_axfr_pkt));
1497			if (rcode) {
1498				fprintf(stderr, "Error in AXFR: %s\n",
1499						rcode->name);
1500			} else {
1501				fprintf(stderr, "Error in AXFR: %d\n",
1502						(int) ldns_pkt_get_rcode(
1503						resolver->_cur_axfr_pkt));
1504			}
1505#endif
1506
1507			/* we must now also close the socket, otherwise subsequent uses of the
1508			   same resolver structure will fail because the link is still open or
1509			   in an undefined state */
1510
1511			close_socket(resolver->_socket);
1512
1513			return NULL;
1514		} else {
1515			return ldns_axfr_next(resolver);
1516		}
1517
1518	}
1519
1520}
1521
1522/* this function is needed to abort a transfer that is in progress;
1523 * without it an aborted transfer will lead to the AXFR code in the
1524 * library staying in an indetermined state because the socket for the
1525 * AXFR is never closed
1526 */
1527void
1528ldns_axfr_abort(ldns_resolver *resolver)
1529{
1530	/* Only abort if an actual AXFR is in progress */
1531	if (resolver->_socket != 0)
1532	{
1533#ifndef USE_WINSOCK
1534		close(resolver->_socket);
1535#else
1536		closesocket(resolver->_socket);
1537#endif
1538		resolver->_socket = 0;
1539	}
1540}
1541
1542bool
1543ldns_axfr_complete(const ldns_resolver *res)
1544{
1545	/* complete when soa count is 2? */
1546	return res->_axfr_soa_count == 2;
1547}
1548
1549ldns_pkt *
1550ldns_axfr_last_pkt(const ldns_resolver *res)
1551{
1552	return res->_cur_axfr_pkt;
1553}
1554
1555void
1556ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial)
1557{
1558	r->_serial = serial;
1559}
1560
1561uint32_t
1562ldns_resolver_get_ixfr_serial(const ldns_resolver *res)
1563{
1564	return res->_serial;
1565}
1566
1567
1568/* random isn't really that good */
1569void
1570ldns_resolver_nameservers_randomize(ldns_resolver *r)
1571{
1572	uint16_t i, j;
1573	ldns_rdf **ns, *tmpns;
1574	size_t *rtt, tmprtt;
1575
1576	/* should I check for ldns_resolver_random?? */
1577	assert(r != NULL);
1578
1579	ns = ldns_resolver_nameservers(r);
1580	rtt = ldns_resolver_rtt(r);
1581	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
1582		j = ldns_get_random() % ldns_resolver_nameserver_count(r);
1583		tmpns = ns[i];
1584		ns[i] = ns[j];
1585		ns[j] = tmpns;
1586		tmprtt = rtt[i];
1587		rtt[i] = rtt[j];
1588		rtt[j] = tmprtt;
1589	}
1590	ldns_resolver_set_nameservers(r, ns);
1591}
1592
1593