resolver.c revision 269257
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
206char *
207ldns_resolver_tsig_keyname(const ldns_resolver *r)
208{
209	return r->_tsig_keyname;
210}
211
212char *
213ldns_resolver_tsig_algorithm(const ldns_resolver *r)
214{
215	return r->_tsig_algorithm;
216}
217
218char *
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, 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, 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, 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, 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, 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, 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
642	/* randomize the nameserver to be queried
643	 * when there are multiple
644	 */
645	ldns_resolver_set_random(r, true);
646
647	ldns_resolver_set_debug(r, 0);
648
649	r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
650	r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
651
652	/* TODO: fd=0 is actually a valid socket (stdin),
653           replace with -1 */
654	r->_socket = 0;
655	r->_axfr_soa_count = 0;
656	r->_axfr_i = 0;
657	r->_cur_axfr_pkt = NULL;
658
659	r->_tsig_keyname = NULL;
660	r->_tsig_keydata = NULL;
661	r->_tsig_algorithm = NULL;
662	return r;
663}
664
665ldns_status
666ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
667{
668	return ldns_resolver_new_frm_fp_l(res, fp, NULL);
669}
670
671ldns_status
672ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
673{
674	ldns_resolver *r;
675	const char *keyword[LDNS_RESOLV_KEYWORDS];
676	char word[LDNS_MAX_LINELEN + 1];
677	int8_t expect;
678	uint8_t i;
679	ldns_rdf *tmp;
680#ifdef HAVE_SSL
681	ldns_rr *tmp_rr;
682#endif
683	ssize_t gtr, bgtr;
684	ldns_buffer *b;
685        int lnr = 0, oldline;
686	FILE* myfp = fp;
687        if(!line_nr) line_nr = &lnr;
688
689	if(!fp) {
690		myfp = fopen("/etc/resolv.conf", "r");
691		if(!myfp)
692			return LDNS_STATUS_FILE_ERR;
693	}
694
695	/* do this better
696	 * expect =
697	 * 0: keyword
698	 * 1: default domain dname
699	 * 2: NS aaaa or a record
700	 */
701
702	/* recognized keywords */
703	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
704	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
705	keyword[LDNS_RESOLV_SEARCH] = "search";
706	/* these two are read but not used atm TODO */
707	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
708	keyword[LDNS_RESOLV_OPTIONS] = "options";
709	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
710	expect = LDNS_RESOLV_KEYWORD;
711
712	r = ldns_resolver_new();
713	if (!r) {
714		if(!fp) fclose(myfp);
715		return LDNS_STATUS_MEM_ERR;
716	}
717
718	gtr = 1;
719	word[0] = 0;
720        oldline = *line_nr;
721        expect = LDNS_RESOLV_KEYWORD;
722	while (gtr > 0) {
723		/* check comments */
724		if (word[0] == '#') {
725                        word[0]='x';
726                        if(oldline == *line_nr) {
727                                /* skip until end of line */
728                                int c;
729                                do {
730                                        c = fgetc(myfp);
731                                } while(c != EOF && c != '\n');
732                                if(c=='\n') (*line_nr)++;
733                        }
734			/* and read next to prepare for further parsing */
735                        oldline = *line_nr;
736			continue;
737		}
738                oldline = *line_nr;
739		switch(expect) {
740			case LDNS_RESOLV_KEYWORD:
741				/* keyword */
742				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
743				if (gtr != 0) {
744                                        if(word[0] == '#') continue;
745					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
746						if (strcasecmp(keyword[i], word) == 0) {
747							/* chosen the keyword and
748							 * expect values carefully
749	        					 */
750							expect = i;
751							break;
752						}
753					}
754					/* no keyword recognized */
755					if (expect == LDNS_RESOLV_KEYWORD) {
756						/* skip line */
757						/*
758						ldns_resolver_deep_free(r);
759						if(!fp) fclose(myfp);
760						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
761						*/
762					}
763				}
764				break;
765			case LDNS_RESOLV_DEFDOMAIN:
766				/* default domain dname */
767				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
768				if (gtr == 0) {
769					if(!fp) fclose(myfp);
770					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
771				}
772                                if(word[0] == '#') {
773                                        expect = LDNS_RESOLV_KEYWORD;
774                                        continue;
775                                }
776				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
777				if (!tmp) {
778					ldns_resolver_deep_free(r);
779					if(!fp) fclose(myfp);
780					return LDNS_STATUS_SYNTAX_DNAME_ERR;
781				}
782
783				/* DOn't free, because we copy the pointer */
784				ldns_resolver_set_domain(r, tmp);
785				expect = LDNS_RESOLV_KEYWORD;
786				break;
787			case LDNS_RESOLV_NAMESERVER:
788				/* NS aaaa or a record */
789				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
790				if (gtr == 0) {
791					if(!fp) fclose(myfp);
792					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
793				}
794                                if(word[0] == '#') {
795                                        expect = LDNS_RESOLV_KEYWORD;
796                                        continue;
797                                }
798                                if(strchr(word, '%')) {
799                                        /* snip off interface labels,
800                                         * fe80::222:19ff:fe31:4222%eth0 */
801                                        strchr(word, '%')[0]=0;
802                                }
803				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
804				if (!tmp) {
805					/* try ip4 */
806					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
807				}
808				/* could not parse it, exit */
809				if (!tmp) {
810					ldns_resolver_deep_free(r);
811					if(!fp) fclose(myfp);
812					return LDNS_STATUS_SYNTAX_ERR;
813				}
814				(void)ldns_resolver_push_nameserver(r, tmp);
815				ldns_rdf_deep_free(tmp);
816				expect = LDNS_RESOLV_KEYWORD;
817				break;
818			case LDNS_RESOLV_SEARCH:
819				/* search list domain dname */
820				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
821				b = LDNS_MALLOC(ldns_buffer);
822				if(!b) {
823					ldns_resolver_deep_free(r);
824					if(!fp) fclose(myfp);
825					return LDNS_STATUS_MEM_ERR;
826				}
827
828				ldns_buffer_new_frm_data(b, word, (size_t) gtr);
829				if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
830					LDNS_FREE(b);
831					ldns_resolver_deep_free(r);
832					if(!fp) fclose(myfp);
833					return LDNS_STATUS_MEM_ERR;
834				}
835				bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
836				while (bgtr > 0) {
837					gtr -= bgtr;
838                                        if(word[0] == '#') {
839                                                expect = LDNS_RESOLV_KEYWORD;
840                                                break;
841                                        }
842					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
843					if (!tmp) {
844						ldns_resolver_deep_free(r);
845						ldns_buffer_free(b);
846						if(!fp) fclose(myfp);
847						return LDNS_STATUS_SYNTAX_DNAME_ERR;
848					}
849
850					ldns_resolver_push_searchlist(r, tmp);
851
852					ldns_rdf_deep_free(tmp);
853					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
854					    (size_t) gtr + 1);
855				}
856				ldns_buffer_free(b);
857				if (expect != LDNS_RESOLV_KEYWORD) {
858					gtr = 1;
859					expect = LDNS_RESOLV_KEYWORD;
860				}
861				break;
862			case LDNS_RESOLV_SORTLIST:
863				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
864				/* sortlist not implemented atm */
865				expect = LDNS_RESOLV_KEYWORD;
866				break;
867			case LDNS_RESOLV_OPTIONS:
868				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
869				/* options not implemented atm */
870				expect = LDNS_RESOLV_KEYWORD;
871				break;
872			case LDNS_RESOLV_ANCHOR:
873				/* a file containing a DNSSEC trust anchor */
874				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
875				if (gtr == 0) {
876					ldns_resolver_deep_free(r);
877					if(!fp) fclose(myfp);
878					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
879				}
880                                if(word[0] == '#') {
881                                        expect = LDNS_RESOLV_KEYWORD;
882                                        continue;
883                                }
884
885#ifdef HAVE_SSL
886				tmp_rr = ldns_read_anchor_file(word);
887				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
888				ldns_rr_free(tmp_rr);
889#endif
890				expect = LDNS_RESOLV_KEYWORD;
891				break;
892		}
893	}
894
895	if(!fp)
896		fclose(myfp);
897
898	if (res) {
899		*res = r;
900		return LDNS_STATUS_OK;
901	} else {
902		ldns_resolver_deep_free(r);
903		return LDNS_STATUS_NULL;
904	}
905}
906
907ldns_status
908ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
909{
910	ldns_resolver *r;
911	FILE *fp;
912	ldns_status s;
913
914	if (!filename) {
915		fp = fopen(LDNS_RESOLV_CONF, "r");
916
917	} else {
918		fp = fopen(filename, "r");
919	}
920	if (!fp) {
921		return LDNS_STATUS_FILE_ERR;
922	}
923
924	s = ldns_resolver_new_frm_fp(&r, fp);
925	fclose(fp);
926	if (s == LDNS_STATUS_OK) {
927		if (res) {
928			*res = r;
929			return LDNS_STATUS_OK;
930		} else  {
931			ldns_resolver_free(r);
932			return LDNS_STATUS_NULL;
933		}
934	}
935	return s;
936}
937
938void
939ldns_resolver_free(ldns_resolver *res)
940{
941	LDNS_FREE(res);
942}
943
944void
945ldns_resolver_deep_free(ldns_resolver *res)
946{
947	size_t i;
948
949	if (res) {
950		if (res->_searchlist) {
951			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
952				ldns_rdf_deep_free(res->_searchlist[i]);
953			}
954			LDNS_FREE(res->_searchlist);
955		}
956		if (res->_nameservers) {
957			for (i = 0; i < res->_nameserver_count; i++) {
958				ldns_rdf_deep_free(res->_nameservers[i]);
959			}
960			LDNS_FREE(res->_nameservers);
961		}
962		if (ldns_resolver_domain(res)) {
963			ldns_rdf_deep_free(ldns_resolver_domain(res));
964		}
965		if (res->_tsig_keyname) {
966			LDNS_FREE(res->_tsig_keyname);
967		}
968		if (res->_tsig_keydata) {
969			LDNS_FREE(res->_tsig_keydata);
970		}
971		if (res->_tsig_algorithm) {
972			LDNS_FREE(res->_tsig_algorithm);
973		}
974
975		if (res->_cur_axfr_pkt) {
976			ldns_pkt_free(res->_cur_axfr_pkt);
977		}
978
979		if (res->_rtt) {
980			LDNS_FREE(res->_rtt);
981		}
982		if (res->_dnssec_anchors) {
983			ldns_rr_list_deep_free(res->_dnssec_anchors);
984		}
985		LDNS_FREE(res);
986	}
987}
988
989ldns_status
990ldns_resolver_search_status(ldns_pkt** pkt,
991		ldns_resolver *r, const  ldns_rdf *name,
992		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
993{
994	ldns_rdf *new_name;
995	ldns_rdf **search_list;
996	size_t i;
997	ldns_status s = LDNS_STATUS_OK;
998
999	if (ldns_dname_absolute(name)) {
1000		/* query as-is */
1001		return ldns_resolver_query_status(pkt, r, name, t, c, flags);
1002	} else if (ldns_resolver_dnsrch(r)) {
1003		search_list = ldns_resolver_searchlist(r);
1004		for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
1005			new_name = ldns_dname_cat_clone(name, search_list[i]);
1006
1007			s = ldns_resolver_query_status(pkt, r,
1008					new_name, t, c, flags);
1009			ldns_rdf_free(new_name);
1010			if (pkt) {
1011				if (s == LDNS_STATUS_OK && *pkt &&
1012						ldns_pkt_get_rcode(*pkt) ==
1013						LDNS_RCODE_NOERROR) {
1014					return LDNS_STATUS_OK;
1015				}
1016				ldns_pkt_free(*pkt);
1017			}
1018		}
1019	}
1020	return s;
1021}
1022
1023ldns_pkt *
1024ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
1025	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1026{
1027	ldns_pkt* pkt = NULL;
1028	if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
1029				name, t, c, flags) != LDNS_STATUS_OK) {
1030		ldns_pkt_free(pkt);
1031	}
1032	return pkt;
1033}
1034
1035ldns_status
1036ldns_resolver_query_status(ldns_pkt** pkt,
1037		ldns_resolver *r, const ldns_rdf *name,
1038		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1039{
1040	ldns_rdf *newname;
1041	ldns_status status;
1042
1043	if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
1044		return ldns_resolver_send(pkt, r, name, t, c, flags);
1045	}
1046
1047	newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
1048	if (!newname) {
1049		return LDNS_STATUS_MEM_ERR;
1050	}
1051	status = ldns_resolver_send(pkt, r, newname, t, c, flags);
1052	ldns_rdf_free(newname);
1053	return status;
1054}
1055
1056ldns_pkt *
1057ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
1058	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1059{
1060	ldns_pkt* pkt = NULL;
1061	if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
1062				name, t, c, flags) != LDNS_STATUS_OK) {
1063		ldns_pkt_free(pkt);
1064	}
1065	return pkt;
1066}
1067
1068static size_t *
1069ldns_resolver_backup_rtt(ldns_resolver *r)
1070{
1071	size_t *new_rtt;
1072	size_t *old_rtt = ldns_resolver_rtt(r);
1073
1074	if (old_rtt && ldns_resolver_nameserver_count(r)) {
1075		new_rtt = LDNS_XMALLOC(size_t
1076				, ldns_resolver_nameserver_count(r));
1077		memcpy(new_rtt, old_rtt, sizeof(size_t)
1078				* ldns_resolver_nameserver_count(r));
1079		ldns_resolver_set_rtt(r, new_rtt);
1080		return old_rtt;
1081	}
1082	return NULL;
1083}
1084
1085static void
1086ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
1087{
1088	size_t *cur_rtt = ldns_resolver_rtt(r);
1089
1090	if (cur_rtt) {
1091		LDNS_FREE(cur_rtt);
1092	}
1093	ldns_resolver_set_rtt(r, old_rtt);
1094}
1095
1096ldns_status
1097ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1098				   ldns_pkt *query_pkt)
1099{
1100	ldns_pkt *answer_pkt = NULL;
1101	ldns_status stat = LDNS_STATUS_OK;
1102	size_t *rtt;
1103
1104	stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
1105	if (stat != LDNS_STATUS_OK) {
1106		if(answer_pkt) {
1107			ldns_pkt_free(answer_pkt);
1108			answer_pkt = NULL;
1109		}
1110	} else {
1111		/* if tc=1 fall back to EDNS and/or TCP */
1112		/* check for tcp first (otherwise we don't care about tc=1) */
1113		if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
1114			if (ldns_pkt_tc(answer_pkt)) {
1115				/* was EDNS0 set? */
1116				if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
1117					ldns_pkt_set_edns_udp_size(query_pkt
1118							, 4096);
1119					ldns_pkt_free(answer_pkt);
1120					/* Nameservers should not become
1121					 * unreachable because fragments are
1122					 * dropped (network error). We might
1123					 * still have success with TCP.
1124					 * Therefore maintain reachability
1125					 * statuses of the nameservers by
1126					 * backup and restore the rtt list.
1127					 */
1128					rtt = ldns_resolver_backup_rtt(r);
1129					stat = ldns_send(&answer_pkt, r
1130							, query_pkt);
1131					ldns_resolver_restore_rtt(r, rtt);
1132				}
1133				/* either way, if it is still truncated, use TCP */
1134				if (stat != LDNS_STATUS_OK ||
1135				    ldns_pkt_tc(answer_pkt)) {
1136					ldns_resolver_set_usevc(r, true);
1137					ldns_pkt_free(answer_pkt);
1138					stat = ldns_send(&answer_pkt, r, query_pkt);
1139					ldns_resolver_set_usevc(r, false);
1140				}
1141			}
1142		}
1143	}
1144
1145	if (answer) {
1146		*answer = answer_pkt;
1147	}
1148
1149	return stat;
1150}
1151
1152ldns_status
1153ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
1154                                const ldns_rdf *name, ldns_rr_type t,
1155                                ldns_rr_class c, uint16_t flags)
1156{
1157	struct timeval now;
1158
1159	/* prepare a question pkt from the parameters
1160	 * and then send this */
1161	if (t == LDNS_RR_TYPE_IXFR) {
1162		*query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name),
1163			c, flags, NULL);
1164	} else {
1165		*query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
1166	}
1167	if (!*query_pkt) {
1168		return LDNS_STATUS_ERR;
1169	}
1170
1171	/* set DO bit if necessary */
1172	if (ldns_resolver_dnssec(r)) {
1173		if (ldns_resolver_edns_udp_size(r) == 0) {
1174			ldns_resolver_set_edns_udp_size(r, 4096);
1175		}
1176		ldns_pkt_set_edns_do(*query_pkt, true);
1177		if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
1178			ldns_pkt_set_cd(*query_pkt, true);
1179		}
1180	}
1181
1182	/* transfer the udp_edns_size from the resolver to the packet */
1183	if (ldns_resolver_edns_udp_size(r) != 0) {
1184		ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
1185	}
1186
1187	/* set the timestamp */
1188	now.tv_sec = time(NULL);
1189	now.tv_usec = 0;
1190	ldns_pkt_set_timestamp(*query_pkt, now);
1191
1192
1193	if (ldns_resolver_debug(r)) {
1194		ldns_pkt_print(stdout, *query_pkt);
1195	}
1196
1197	/* only set the id if it is not set yet */
1198	if (ldns_pkt_id(*query_pkt) == 0) {
1199		ldns_pkt_set_random_id(*query_pkt);
1200	}
1201
1202	return LDNS_STATUS_OK;
1203}
1204
1205
1206ldns_status
1207ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
1208		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1209{
1210	ldns_pkt *query_pkt;
1211	ldns_pkt *answer_pkt;
1212	ldns_status status;
1213
1214	assert(r != NULL);
1215	assert(name != NULL);
1216
1217	answer_pkt = NULL;
1218
1219	/* do all the preprocessing here, then fire of an query to
1220	 * the network */
1221
1222	if (0 == t) {
1223		t= LDNS_RR_TYPE_A;
1224	}
1225	if (0 == c) {
1226		c= LDNS_RR_CLASS_IN;
1227	}
1228	if (0 == ldns_resolver_nameserver_count(r)) {
1229		return LDNS_STATUS_RES_NO_NS;
1230	}
1231	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1232		return LDNS_STATUS_RES_QUERY;
1233	}
1234
1235	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1236	                                         t, c, flags);
1237	if (status != LDNS_STATUS_OK) {
1238		return status;
1239	}
1240
1241	/* if tsig values are set, tsign it */
1242	/* TODO: make last 3 arguments optional too? maybe make complete
1243	         rr instead of separate values in resolver (and packet)
1244	  Jelte
1245	  should this go in pkt_prepare?
1246	*/
1247	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
1248#ifdef HAVE_SSL
1249		status = ldns_pkt_tsig_sign(query_pkt,
1250		                            ldns_resolver_tsig_keyname(r),
1251		                            ldns_resolver_tsig_keydata(r),
1252		                            300, ldns_resolver_tsig_algorithm(r), NULL);
1253		if (status != LDNS_STATUS_OK) {
1254			ldns_pkt_free(query_pkt);
1255			return LDNS_STATUS_CRYPTO_TSIG_ERR;
1256		}
1257#else
1258		ldns_pkt_free(query_pkt);
1259	        return LDNS_STATUS_CRYPTO_TSIG_ERR;
1260#endif /* HAVE_SSL */
1261	}
1262
1263	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1264	ldns_pkt_free(query_pkt);
1265
1266	/* allows answer to be NULL when not interested in return value */
1267	if (answer) {
1268		*answer = answer_pkt;
1269	}
1270	return status;
1271}
1272
1273ldns_rr *
1274ldns_axfr_next(ldns_resolver *resolver)
1275{
1276	ldns_rr *cur_rr;
1277	uint8_t *packet_wire;
1278	size_t packet_wire_size;
1279	ldns_lookup_table *rcode;
1280	ldns_status status;
1281
1282	/* check if start() has been called */
1283	if (!resolver || resolver->_socket == 0) {
1284		return NULL;
1285	}
1286
1287	if (resolver->_cur_axfr_pkt) {
1288		if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
1289			ldns_pkt_free(resolver->_cur_axfr_pkt);
1290			resolver->_cur_axfr_pkt = NULL;
1291			return ldns_axfr_next(resolver);
1292		}
1293		cur_rr = ldns_rr_clone(ldns_rr_list_rr(
1294					ldns_pkt_answer(resolver->_cur_axfr_pkt),
1295					resolver->_axfr_i));
1296		resolver->_axfr_i++;
1297		if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
1298			resolver->_axfr_soa_count++;
1299			if (resolver->_axfr_soa_count >= 2) {
1300#ifndef USE_WINSOCK
1301				close(resolver->_socket);
1302#else
1303				closesocket(resolver->_socket);
1304#endif
1305				resolver->_socket = 0;
1306				ldns_pkt_free(resolver->_cur_axfr_pkt);
1307				resolver->_cur_axfr_pkt = NULL;
1308			}
1309		}
1310		return cur_rr;
1311	} else {
1312		packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size);
1313		if(!packet_wire)
1314			return NULL;
1315
1316		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1317				     packet_wire_size);
1318		LDNS_FREE(packet_wire);
1319
1320		resolver->_axfr_i = 0;
1321		if (status != LDNS_STATUS_OK) {
1322			/* TODO: make status return type of this function (...api change) */
1323#ifdef STDERR_MSGS
1324			fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
1325#endif
1326
1327			/* we must now also close the socket, otherwise subsequent uses of the
1328			   same resolver structure will fail because the link is still open or
1329			   in an undefined state */
1330#ifndef USE_WINSOCK
1331			close(resolver->_socket);
1332#else
1333			closesocket(resolver->_socket);
1334#endif
1335			resolver->_socket = 0;
1336
1337			return NULL;
1338		} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
1339			rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt));
1340#ifdef STDERR_MSGS
1341			if (rcode) {
1342				fprintf(stderr, "Error in AXFR: %s\n",
1343						rcode->name);
1344			} else {
1345				fprintf(stderr, "Error in AXFR: %d\n",
1346						(int) ldns_pkt_get_rcode(
1347						resolver->_cur_axfr_pkt));
1348			}
1349#endif
1350
1351			/* we must now also close the socket, otherwise subsequent uses of the
1352			   same resolver structure will fail because the link is still open or
1353			   in an undefined state */
1354#ifndef USE_WINSOCK
1355			close(resolver->_socket);
1356#else
1357			closesocket(resolver->_socket);
1358#endif
1359			resolver->_socket = 0;
1360
1361			return NULL;
1362		} else {
1363			return ldns_axfr_next(resolver);
1364		}
1365
1366	}
1367
1368}
1369
1370/* this function is needed to abort a transfer that is in progress;
1371 * without it an aborted transfer will lead to the AXFR code in the
1372 * library staying in an indetermined state because the socket for the
1373 * AXFR is never closed
1374 */
1375void
1376ldns_axfr_abort(ldns_resolver *resolver)
1377{
1378	/* Only abort if an actual AXFR is in progress */
1379	if (resolver->_socket != 0)
1380	{
1381#ifndef USE_WINSOCK
1382		close(resolver->_socket);
1383#else
1384		closesocket(resolver->_socket);
1385#endif
1386		resolver->_socket = 0;
1387	}
1388}
1389
1390bool
1391ldns_axfr_complete(const ldns_resolver *res)
1392{
1393	/* complete when soa count is 2? */
1394	return res->_axfr_soa_count == 2;
1395}
1396
1397ldns_pkt *
1398ldns_axfr_last_pkt(const ldns_resolver *res)
1399{
1400	return res->_cur_axfr_pkt;
1401}
1402
1403/* random isn't really that good */
1404void
1405ldns_resolver_nameservers_randomize(ldns_resolver *r)
1406{
1407	uint16_t i, j;
1408	ldns_rdf **ns, *tmpns;
1409	size_t *rtt, tmprtt;
1410
1411	/* should I check for ldns_resolver_random?? */
1412	assert(r != NULL);
1413
1414	ns = ldns_resolver_nameservers(r);
1415	rtt = ldns_resolver_rtt(r);
1416	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
1417		j = ldns_get_random() % ldns_resolver_nameserver_count(r);
1418		tmpns = ns[i];
1419		ns[i] = ns[j];
1420		ns[j] = tmpns;
1421		tmprtt = rtt[i];
1422		rtt[i] = rtt[j];
1423		rtt[j] = tmprtt;
1424	}
1425	ldns_resolver_set_nameservers(r, ns);
1426}
1427
1428