kernel - Fix races created by a comedy of circumstansces (3)
[dragonfly.git] / contrib / ldns / resolver.c
blob2cee9fff194a1320c3ea616fe0fe51e1f18575ef
1 /*
2 * resolver.c
4 * resolver implementation
6 * a Net::DNS like library for C
8 * (c) NLnet Labs, 2004-2006
10 * See the file LICENSE for the license
13 #include <ldns/config.h>
15 #include <ldns/ldns.h>
16 #include <strings.h>
18 /* Access function for reading
19 * and setting the different Resolver
20 * options */
22 /* read */
23 uint16_t
24 ldns_resolver_port(const ldns_resolver *r)
26 return r->_port;
29 uint16_t
30 ldns_resolver_edns_udp_size(const ldns_resolver *r)
32 return r->_edns_udp_size;
35 uint8_t
36 ldns_resolver_retry(const ldns_resolver *r)
38 return r->_retry;
41 uint8_t
42 ldns_resolver_retrans(const ldns_resolver *r)
44 return r->_retrans;
47 bool
48 ldns_resolver_fallback(const ldns_resolver *r)
50 return r->_fallback;
53 uint8_t
54 ldns_resolver_ip6(const ldns_resolver *r)
56 return r->_ip6;
59 bool
60 ldns_resolver_recursive(const ldns_resolver *r)
62 return r->_recursive;
65 bool
66 ldns_resolver_debug(const ldns_resolver *r)
68 return r->_debug;
71 bool
72 ldns_resolver_dnsrch(const ldns_resolver *r)
74 return r->_dnsrch;
77 bool
78 ldns_resolver_fail(const ldns_resolver *r)
80 return r->_fail;
83 bool
84 ldns_resolver_defnames(const ldns_resolver *r)
86 return r->_defnames;
89 ldns_rdf *
90 ldns_resolver_domain(const ldns_resolver *r)
92 return r->_domain;
95 ldns_rdf **
96 ldns_resolver_searchlist(const ldns_resolver *r)
98 return r->_searchlist;
101 ldns_rdf **
102 ldns_resolver_nameservers(const ldns_resolver *r)
104 return r->_nameservers;
107 size_t
108 ldns_resolver_nameserver_count(const ldns_resolver *r)
110 return r->_nameserver_count;
113 bool
114 ldns_resolver_dnssec(const ldns_resolver *r)
116 return r->_dnssec;
119 bool
120 ldns_resolver_dnssec_cd(const ldns_resolver *r)
122 return r->_dnssec_cd;
125 ldns_rr_list *
126 ldns_resolver_dnssec_anchors(const ldns_resolver *r)
128 return r->_dnssec_anchors;
131 bool
132 ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
134 size_t i;
135 bool result = false;
137 ldns_rr_list * trust_anchors;
138 ldns_rr * cur_rr;
140 if (!r || !keys) { return false; }
142 trust_anchors = ldns_resolver_dnssec_anchors(r);
144 if (!trust_anchors) { return false; }
146 for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
148 cur_rr = ldns_rr_list_rr(keys, i);
149 if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
150 if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
151 result = true;
155 return result;
158 bool
159 ldns_resolver_igntc(const ldns_resolver *r)
161 return r->_igntc;
164 bool
165 ldns_resolver_usevc(const ldns_resolver *r)
167 return r->_usevc;
170 size_t *
171 ldns_resolver_rtt(const ldns_resolver *r)
173 return r->_rtt;
176 size_t
177 ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
179 size_t *rtt;
181 assert(r != NULL);
183 rtt = ldns_resolver_rtt(r);
185 if (pos >= ldns_resolver_nameserver_count(r)) {
186 /* error ?*/
187 return 0;
188 } else {
189 return rtt[pos];
194 struct timeval
195 ldns_resolver_timeout(const ldns_resolver *r)
197 return r->_timeout;
200 char *
201 ldns_resolver_tsig_keyname(const ldns_resolver *r)
203 return r->_tsig_keyname;
206 char *
207 ldns_resolver_tsig_algorithm(const ldns_resolver *r)
209 return r->_tsig_algorithm;
212 char *
213 ldns_resolver_tsig_keydata(const ldns_resolver *r)
215 return r->_tsig_keydata;
218 bool
219 ldns_resolver_random(const ldns_resolver *r)
221 return r->_random;
224 size_t
225 ldns_resolver_searchlist_count(const ldns_resolver *r)
227 return r->_searchlist_count;
230 /* write */
231 void
232 ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
234 r->_port = p;
237 ldns_rdf *
238 ldns_resolver_pop_nameserver(ldns_resolver *r)
240 ldns_rdf **nameservers;
241 ldns_rdf *pop;
242 size_t ns_count;
243 size_t *rtt;
245 assert(r != NULL);
247 ns_count = ldns_resolver_nameserver_count(r);
248 nameservers = ldns_resolver_nameservers(r);
249 rtt = ldns_resolver_rtt(r);
250 if (ns_count == 0 || !nameservers) {
251 return NULL;
254 pop = nameservers[ns_count - 1];
256 if (ns_count == 1) {
257 LDNS_FREE(nameservers);
258 LDNS_FREE(rtt);
260 ldns_resolver_set_nameservers(r, NULL);
261 ldns_resolver_set_rtt(r, NULL);
262 } else {
263 nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *,
264 (ns_count - 1));
265 rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
267 ldns_resolver_set_nameservers(r, nameservers);
268 ldns_resolver_set_rtt(r, rtt);
270 /* decr the count */
271 ldns_resolver_dec_nameserver_count(r);
272 return pop;
275 ldns_status
276 ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
278 ldns_rdf **nameservers;
279 size_t ns_count;
280 size_t *rtt;
282 if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
283 ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
284 return LDNS_STATUS_ERR;
287 ns_count = ldns_resolver_nameserver_count(r);
288 nameservers = ldns_resolver_nameservers(r);
289 rtt = ldns_resolver_rtt(r);
291 /* make room for the next one */
292 if (ns_count == 0) {
293 nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
294 } else {
295 nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
297 if(!nameservers)
298 return LDNS_STATUS_MEM_ERR;
300 /* set the new value in the resolver */
301 ldns_resolver_set_nameservers(r, nameservers);
303 /* don't forget the rtt */
304 if (ns_count == 0) {
305 rtt = LDNS_XMALLOC(size_t, 1);
306 } else {
307 rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
309 if(!rtt)
310 return LDNS_STATUS_MEM_ERR;
312 /* slide n in its slot. */
313 /* we clone it here, because then we can free the original
314 * rr's where it stood */
315 nameservers[ns_count] = ldns_rdf_clone(n);
316 rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
317 ldns_resolver_incr_nameserver_count(r);
318 ldns_resolver_set_rtt(r, rtt);
319 return LDNS_STATUS_OK;
322 ldns_status
323 ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
325 ldns_rdf *address;
326 if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
327 ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
328 return LDNS_STATUS_ERR;
330 address = ldns_rr_rdf(rr, 0); /* extract the ip number */
331 if (address) {
332 return ldns_resolver_push_nameserver(r, address);
333 } else {
334 return LDNS_STATUS_ERR;
338 ldns_status
339 ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
341 ldns_rr *rr;
342 ldns_status stat;
343 size_t i;
345 stat = LDNS_STATUS_OK;
346 if (rrlist) {
347 for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
348 rr = ldns_rr_list_rr(rrlist, i);
349 if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
350 stat = LDNS_STATUS_ERR;
351 break;
354 return stat;
355 } else {
356 return LDNS_STATUS_ERR;
360 void
361 ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
363 r->_edns_udp_size = s;
366 void
367 ldns_resolver_set_recursive(ldns_resolver *r, bool re)
369 r->_recursive = re;
372 void
373 ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
375 r->_dnssec = d;
378 void
379 ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
381 r->_dnssec_cd = d;
384 void
385 ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
387 r->_dnssec_anchors = l;
390 ldns_status
391 ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
393 ldns_rr_list * trust_anchors;
395 if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
396 ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
398 return LDNS_STATUS_ERR;
401 if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
402 trust_anchors = ldns_rr_list_new();
403 ldns_resolver_set_dnssec_anchors(r, trust_anchors);
406 return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
409 void
410 ldns_resolver_set_igntc(ldns_resolver *r, bool i)
412 r->_igntc = i;
415 void
416 ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
418 r->_usevc = vc;
421 void
422 ldns_resolver_set_debug(ldns_resolver *r, bool d)
424 r->_debug = d;
427 void
428 ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
430 r->_ip6 = ip6;
433 void
434 ldns_resolver_set_fail(ldns_resolver *r, bool f)
436 r->_fail =f;
439 void
440 ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
442 r->_searchlist_count = c;
445 void
446 ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
448 r->_nameserver_count = c;
451 void
452 ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
454 r->_dnsrch = d;
457 void
458 ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
460 r->_retry = retry;
463 void
464 ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
466 r->_retrans = retrans;
469 void
470 ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
472 r->_fallback = fallback;
475 void
476 ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
478 r->_nameservers = n;
481 void
482 ldns_resolver_set_defnames(ldns_resolver *r, bool d)
484 r->_defnames = d;
487 void
488 ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
490 r->_rtt = rtt;
493 void
494 ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
496 size_t *rtt;
498 assert(r != NULL);
500 rtt = ldns_resolver_rtt(r);
502 if (pos >= ldns_resolver_nameserver_count(r)) {
503 /* error ?*/
504 } else {
505 rtt[pos] = value;
510 void
511 ldns_resolver_incr_nameserver_count(ldns_resolver *r)
513 size_t c;
515 c = ldns_resolver_nameserver_count(r);
516 ldns_resolver_set_nameserver_count(r, ++c);
519 void
520 ldns_resolver_dec_nameserver_count(ldns_resolver *r)
522 size_t c;
524 c = ldns_resolver_nameserver_count(r);
525 if (c == 0) {
526 return;
527 } else {
528 ldns_resolver_set_nameserver_count(r, --c);
532 void
533 ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
535 r->_domain = d;
538 void
539 ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
541 r->_timeout.tv_sec = timeout.tv_sec;
542 r->_timeout.tv_usec = timeout.tv_usec;
545 void
546 ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
548 ldns_rdf **searchlist;
549 size_t list_count;
551 if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
552 return;
555 list_count = ldns_resolver_searchlist_count(r);
556 searchlist = ldns_resolver_searchlist(r);
558 searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
559 if (searchlist) {
560 r->_searchlist = searchlist;
562 searchlist[list_count] = ldns_rdf_clone(d);
563 ldns_resolver_set_searchlist_count(r, list_count + 1);
564 } /* no way to report mem err */
567 void
568 ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
570 LDNS_FREE(r->_tsig_keyname);
571 r->_tsig_keyname = strdup(tsig_keyname);
574 void
575 ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
577 LDNS_FREE(r->_tsig_algorithm);
578 r->_tsig_algorithm = strdup(tsig_algorithm);
581 void
582 ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
584 LDNS_FREE(r->_tsig_keydata);
585 r->_tsig_keydata = strdup(tsig_keydata);
588 void
589 ldns_resolver_set_random(ldns_resolver *r, bool b)
591 r->_random = b;
594 /* more sophisticated functions */
595 ldns_resolver *
596 ldns_resolver_new(void)
598 ldns_resolver *r;
600 r = LDNS_MALLOC(ldns_resolver);
601 if (!r) {
602 return NULL;
605 r->_searchlist = NULL;
606 r->_nameservers = NULL;
607 r->_rtt = NULL;
609 /* defaults are filled out */
610 ldns_resolver_set_searchlist_count(r, 0);
611 ldns_resolver_set_nameserver_count(r, 0);
612 ldns_resolver_set_usevc(r, 0);
613 ldns_resolver_set_port(r, LDNS_PORT);
614 ldns_resolver_set_domain(r, NULL);
615 ldns_resolver_set_defnames(r, false);
616 ldns_resolver_set_retry(r, 3);
617 ldns_resolver_set_retrans(r, 2);
618 ldns_resolver_set_fallback(r, true);
619 ldns_resolver_set_fail(r, false);
620 ldns_resolver_set_edns_udp_size(r, 0);
621 ldns_resolver_set_dnssec(r, false);
622 ldns_resolver_set_dnssec_cd(r, false);
623 ldns_resolver_set_dnssec_anchors(r, NULL);
624 ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
625 ldns_resolver_set_igntc(r, false);
626 ldns_resolver_set_recursive(r, false);
627 ldns_resolver_set_dnsrch(r, true);
629 /* randomize the nameserver to be queried
630 * when there are multiple
632 ldns_resolver_set_random(r, true);
634 ldns_resolver_set_debug(r, 0);
636 r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
637 r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
639 /* TODO: fd=0 is actually a valid socket (stdin),
640 replace with -1 */
641 r->_socket = 0;
642 r->_axfr_soa_count = 0;
643 r->_axfr_i = 0;
644 r->_cur_axfr_pkt = NULL;
646 r->_tsig_keyname = NULL;
647 r->_tsig_keydata = NULL;
648 r->_tsig_algorithm = NULL;
649 return r;
652 ldns_status
653 ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
655 return ldns_resolver_new_frm_fp_l(res, fp, NULL);
658 ldns_status
659 ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
661 ldns_resolver *r;
662 const char *keyword[LDNS_RESOLV_KEYWORDS];
663 char word[LDNS_MAX_LINELEN + 1];
664 int8_t expect;
665 uint8_t i;
666 ldns_rdf *tmp;
667 #ifdef HAVE_SSL
668 ldns_rr *tmp_rr;
669 #endif
670 ssize_t gtr, bgtr;
671 ldns_buffer *b;
672 int lnr = 0, oldline;
673 if(!line_nr) line_nr = &lnr;
675 /* do this better
676 * expect =
677 * 0: keyword
678 * 1: default domain dname
679 * 2: NS aaaa or a record
682 /* recognized keywords */
683 keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
684 keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
685 keyword[LDNS_RESOLV_SEARCH] = "search";
686 /* these two are read but not used atm TODO */
687 keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
688 keyword[LDNS_RESOLV_OPTIONS] = "options";
689 keyword[LDNS_RESOLV_ANCHOR] = "anchor";
690 expect = LDNS_RESOLV_KEYWORD;
692 r = ldns_resolver_new();
693 if (!r) {
694 return LDNS_STATUS_MEM_ERR;
697 gtr = 1;
698 word[0] = 0;
699 oldline = *line_nr;
700 expect = LDNS_RESOLV_KEYWORD;
701 while (gtr > 0) {
702 /* check comments */
703 if (word[0] == '#') {
704 word[0]='x';
705 if(oldline == *line_nr) {
706 /* skip until end of line */
707 int c;
708 do {
709 c = fgetc(fp);
710 } while(c != EOF && c != '\n');
711 if(c=='\n' && line_nr) (*line_nr)++;
713 /* and read next to prepare for further parsing */
714 oldline = *line_nr;
715 continue;
717 oldline = *line_nr;
718 switch(expect) {
719 case LDNS_RESOLV_KEYWORD:
720 /* keyword */
721 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
722 if (gtr != 0) {
723 if(word[0] == '#') continue;
724 for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
725 if (strcasecmp(keyword[i], word) == 0) {
726 /* chosen the keyword and
727 * expect values carefully
729 expect = i;
730 break;
733 /* no keyword recognized */
734 if (expect == LDNS_RESOLV_KEYWORD) {
735 /* skip line */
737 ldns_resolver_deep_free(r);
738 return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
742 break;
743 case LDNS_RESOLV_DEFDOMAIN:
744 /* default domain dname */
745 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
746 if (gtr == 0) {
747 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
749 if(word[0] == '#') {
750 expect = LDNS_RESOLV_KEYWORD;
751 continue;
753 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
754 if (!tmp) {
755 ldns_resolver_deep_free(r);
756 return LDNS_STATUS_SYNTAX_DNAME_ERR;
759 /* DOn't free, because we copy the pointer */
760 ldns_resolver_set_domain(r, tmp);
761 expect = LDNS_RESOLV_KEYWORD;
762 break;
763 case LDNS_RESOLV_NAMESERVER:
764 /* NS aaaa or a record */
765 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
766 if (gtr == 0) {
767 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
769 if(word[0] == '#') {
770 expect = LDNS_RESOLV_KEYWORD;
771 continue;
773 if(strchr(word, '%')) {
774 /* snip off interface labels,
775 * fe80::222:19ff:fe31:4222%eth0 */
776 strchr(word, '%')[0]=0;
778 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
779 if (!tmp) {
780 /* try ip4 */
781 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
783 /* could not parse it, exit */
784 if (!tmp) {
785 ldns_resolver_deep_free(r);
786 return LDNS_STATUS_SYNTAX_ERR;
788 (void)ldns_resolver_push_nameserver(r, tmp);
789 ldns_rdf_deep_free(tmp);
790 expect = LDNS_RESOLV_KEYWORD;
791 break;
792 case LDNS_RESOLV_SEARCH:
793 /* search list domain dname */
794 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
795 b = LDNS_MALLOC(ldns_buffer);
796 if(!b) {
797 ldns_resolver_deep_free(r);
798 return LDNS_STATUS_MEM_ERR;
801 ldns_buffer_new_frm_data(b, word, (size_t) gtr);
802 if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
803 LDNS_FREE(b);
804 ldns_resolver_deep_free(r);
805 return LDNS_STATUS_MEM_ERR;
807 bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
808 while (bgtr > 0) {
809 gtr -= bgtr;
810 if(word[0] == '#') {
811 expect = LDNS_RESOLV_KEYWORD;
812 break;
814 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
815 if (!tmp) {
816 ldns_resolver_deep_free(r);
817 ldns_buffer_free(b);
818 return LDNS_STATUS_SYNTAX_DNAME_ERR;
821 ldns_resolver_push_searchlist(r, tmp);
823 ldns_rdf_deep_free(tmp);
824 bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
825 (size_t) gtr + 1);
827 ldns_buffer_free(b);
828 if (expect != LDNS_RESOLV_KEYWORD) {
829 gtr = 1;
830 expect = LDNS_RESOLV_KEYWORD;
832 break;
833 case LDNS_RESOLV_SORTLIST:
834 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
835 /* sortlist not implemented atm */
836 expect = LDNS_RESOLV_KEYWORD;
837 break;
838 case LDNS_RESOLV_OPTIONS:
839 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
840 /* options not implemented atm */
841 expect = LDNS_RESOLV_KEYWORD;
842 break;
843 case LDNS_RESOLV_ANCHOR:
844 /* a file containing a DNSSEC trust anchor */
845 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
846 if (gtr == 0) {
847 ldns_resolver_deep_free(r);
848 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
850 if(word[0] == '#') {
851 expect = LDNS_RESOLV_KEYWORD;
852 continue;
855 #ifdef HAVE_SSL
856 tmp_rr = ldns_read_anchor_file(word);
857 (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
858 ldns_rr_free(tmp_rr);
859 #endif
860 expect = LDNS_RESOLV_KEYWORD;
861 break;
865 if (res) {
866 *res = r;
867 return LDNS_STATUS_OK;
868 } else {
869 ldns_resolver_deep_free(r);
870 return LDNS_STATUS_NULL;
874 ldns_status
875 ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
877 ldns_resolver *r;
878 FILE *fp;
879 ldns_status s;
881 if (!filename) {
882 fp = fopen(LDNS_RESOLV_CONF, "r");
884 } else {
885 fp = fopen(filename, "r");
887 if (!fp) {
888 return LDNS_STATUS_FILE_ERR;
891 s = ldns_resolver_new_frm_fp(&r, fp);
892 fclose(fp);
893 if (s == LDNS_STATUS_OK) {
894 if (res) {
895 *res = r;
896 return LDNS_STATUS_OK;
897 } else {
898 ldns_resolver_free(r);
899 return LDNS_STATUS_NULL;
902 return s;
905 void
906 ldns_resolver_free(ldns_resolver *res)
908 LDNS_FREE(res);
911 void
912 ldns_resolver_deep_free(ldns_resolver *res)
914 size_t i;
916 if (res) {
917 if (res->_searchlist) {
918 for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
919 ldns_rdf_deep_free(res->_searchlist[i]);
921 LDNS_FREE(res->_searchlist);
923 if (res->_nameservers) {
924 for (i = 0; i < res->_nameserver_count; i++) {
925 ldns_rdf_deep_free(res->_nameservers[i]);
927 LDNS_FREE(res->_nameservers);
929 if (ldns_resolver_domain(res)) {
930 ldns_rdf_deep_free(ldns_resolver_domain(res));
932 if (res->_tsig_keyname) {
933 LDNS_FREE(res->_tsig_keyname);
935 if (res->_tsig_keydata) {
936 LDNS_FREE(res->_tsig_keydata);
938 if (res->_tsig_algorithm) {
939 LDNS_FREE(res->_tsig_algorithm);
942 if (res->_cur_axfr_pkt) {
943 ldns_pkt_free(res->_cur_axfr_pkt);
946 if (res->_rtt) {
947 LDNS_FREE(res->_rtt);
949 if (res->_dnssec_anchors) {
950 ldns_rr_list_deep_free(res->_dnssec_anchors);
952 LDNS_FREE(res);
956 ldns_pkt *
957 ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name,
958 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
961 ldns_rdf *new_name;
962 ldns_rdf **search_list;
963 size_t i;
964 ldns_pkt *p;
966 if (ldns_dname_absolute(name)) {
967 /* query as-is */
968 return ldns_resolver_query(r, name, t, c, flags);
969 } else if (ldns_resolver_dnsrch(r)) {
970 search_list = ldns_resolver_searchlist(r);
971 for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
972 new_name = ldns_dname_cat_clone(name, search_list[i]);
974 p = ldns_resolver_query(r, new_name, t, c, flags);
975 ldns_rdf_free(new_name);
976 if (p) {
977 if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) {
978 return p;
979 } else {
980 ldns_pkt_free(p);
981 p = NULL;
986 return NULL;
989 ldns_pkt *
990 ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
991 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
993 ldns_rdf *newname;
994 ldns_pkt *pkt;
995 ldns_status status;
997 pkt = NULL;
999 if (!ldns_resolver_defnames(r)) {
1000 status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name,
1001 t, c, flags);
1002 if (status == LDNS_STATUS_OK) {
1003 return pkt;
1004 } else {
1005 if (pkt) {
1006 ldns_pkt_free(pkt);
1008 return NULL;
1012 if (!ldns_resolver_domain(r)) {
1013 /* _defnames is set, but the domain is not....?? */
1014 status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name,
1015 t, c, flags);
1016 if (status == LDNS_STATUS_OK) {
1017 return pkt;
1018 } else {
1019 if (pkt) {
1020 ldns_pkt_free(pkt);
1022 return NULL;
1026 newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r));
1027 if (!newname) {
1028 return NULL;
1031 (void)ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c,
1032 flags);
1034 ldns_rdf_free(newname);
1036 return pkt;
1039 static size_t *
1040 ldns_resolver_backup_rtt(ldns_resolver *r)
1042 size_t *new_rtt;
1043 size_t *old_rtt = ldns_resolver_rtt(r);
1045 if (old_rtt && ldns_resolver_nameserver_count(r)) {
1046 new_rtt = LDNS_XMALLOC(size_t
1047 , ldns_resolver_nameserver_count(r));
1048 memcpy(new_rtt, old_rtt, sizeof(size_t)
1049 * ldns_resolver_nameserver_count(r));
1050 ldns_resolver_set_rtt(r, new_rtt);
1051 return old_rtt;
1053 return NULL;
1056 static void
1057 ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
1059 size_t *cur_rtt = ldns_resolver_rtt(r);
1061 if (cur_rtt) {
1062 LDNS_FREE(cur_rtt);
1064 ldns_resolver_set_rtt(r, old_rtt);
1067 ldns_status
1068 ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1069 ldns_pkt *query_pkt)
1071 ldns_pkt *answer_pkt = NULL;
1072 ldns_status stat = LDNS_STATUS_OK;
1073 size_t *rtt;
1075 stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
1076 if (stat != LDNS_STATUS_OK) {
1077 if(answer_pkt) {
1078 ldns_pkt_free(answer_pkt);
1079 answer_pkt = NULL;
1081 } else {
1082 /* if tc=1 fall back to EDNS and/or TCP */
1083 /* check for tcp first (otherwise we don't care about tc=1) */
1084 if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
1085 if (ldns_pkt_tc(answer_pkt)) {
1086 /* was EDNS0 set? */
1087 if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
1088 ldns_pkt_set_edns_udp_size(query_pkt
1089 , 4096);
1090 ldns_pkt_free(answer_pkt);
1091 /* Nameservers should not become
1092 * unreachable because fragments are
1093 * dropped (network error). We might
1094 * still have success with TCP.
1095 * Therefore maintain reachability
1096 * statuses of the nameservers by
1097 * backup and restore the rtt list.
1099 rtt = ldns_resolver_backup_rtt(r);
1100 stat = ldns_send(&answer_pkt, r
1101 , query_pkt);
1102 ldns_resolver_restore_rtt(r, rtt);
1104 /* either way, if it is still truncated, use TCP */
1105 if (stat != LDNS_STATUS_OK ||
1106 ldns_pkt_tc(answer_pkt)) {
1107 ldns_resolver_set_usevc(r, true);
1108 ldns_pkt_free(answer_pkt);
1109 stat = ldns_send(&answer_pkt, r, query_pkt);
1110 ldns_resolver_set_usevc(r, false);
1116 if (answer) {
1117 *answer = answer_pkt;
1120 return stat;
1123 ldns_status
1124 ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
1125 const ldns_rdf *name, ldns_rr_type t,
1126 ldns_rr_class c, uint16_t flags)
1128 struct timeval now;
1130 /* prepare a question pkt from the parameters
1131 * and then send this */
1132 *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
1133 if (!*query_pkt) {
1134 return LDNS_STATUS_ERR;
1137 /* set DO bit if necessary */
1138 if (ldns_resolver_dnssec(r)) {
1139 if (ldns_resolver_edns_udp_size(r) == 0) {
1140 ldns_resolver_set_edns_udp_size(r, 4096);
1142 ldns_pkt_set_edns_do(*query_pkt, true);
1143 if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
1144 ldns_pkt_set_cd(*query_pkt, true);
1148 /* transfer the udp_edns_size from the resolver to the packet */
1149 if (ldns_resolver_edns_udp_size(r) != 0) {
1150 ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
1153 /* set the timestamp */
1154 now.tv_sec = time(NULL);
1155 now.tv_usec = 0;
1156 ldns_pkt_set_timestamp(*query_pkt, now);
1159 if (ldns_resolver_debug(r)) {
1160 ldns_pkt_print(stdout, *query_pkt);
1163 /* only set the id if it is not set yet */
1164 if (ldns_pkt_id(*query_pkt) == 0) {
1165 ldns_pkt_set_random_id(*query_pkt);
1168 return LDNS_STATUS_OK;
1172 ldns_status
1173 ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
1174 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1176 ldns_pkt *query_pkt;
1177 ldns_pkt *answer_pkt;
1178 ldns_status status;
1180 assert(r != NULL);
1181 assert(name != NULL);
1183 answer_pkt = NULL;
1185 /* do all the preprocessing here, then fire of an query to
1186 * the network */
1188 if (0 == t) {
1189 t= LDNS_RR_TYPE_A;
1191 if (0 == c) {
1192 c= LDNS_RR_CLASS_IN;
1194 if (0 == ldns_resolver_nameserver_count(r)) {
1195 return LDNS_STATUS_RES_NO_NS;
1197 if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1198 return LDNS_STATUS_RES_QUERY;
1201 status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1202 t, c, flags);
1203 if (status != LDNS_STATUS_OK) {
1204 return status;
1207 /* if tsig values are set, tsign it */
1208 /* TODO: make last 3 arguments optional too? maybe make complete
1209 rr instead of seperate values in resolver (and packet)
1210 Jelte
1211 should this go in pkt_prepare?
1213 if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
1214 #ifdef HAVE_SSL
1215 status = ldns_pkt_tsig_sign(query_pkt,
1216 ldns_resolver_tsig_keyname(r),
1217 ldns_resolver_tsig_keydata(r),
1218 300, ldns_resolver_tsig_algorithm(r), NULL);
1219 if (status != LDNS_STATUS_OK) {
1220 ldns_pkt_free(query_pkt);
1221 return LDNS_STATUS_CRYPTO_TSIG_ERR;
1223 #else
1224 ldns_pkt_free(query_pkt);
1225 return LDNS_STATUS_CRYPTO_TSIG_ERR;
1226 #endif /* HAVE_SSL */
1229 status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1230 ldns_pkt_free(query_pkt);
1232 /* allows answer to be NULL when not interested in return value */
1233 if (answer) {
1234 *answer = answer_pkt;
1236 return status;
1239 ldns_rr *
1240 ldns_axfr_next(ldns_resolver *resolver)
1242 ldns_rr *cur_rr;
1243 uint8_t *packet_wire;
1244 size_t packet_wire_size;
1245 ldns_lookup_table *rcode;
1246 ldns_status status;
1248 /* check if start() has been called */
1249 if (!resolver || resolver->_socket == 0) {
1250 return NULL;
1253 if (resolver->_cur_axfr_pkt) {
1254 if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
1255 ldns_pkt_free(resolver->_cur_axfr_pkt);
1256 resolver->_cur_axfr_pkt = NULL;
1257 return ldns_axfr_next(resolver);
1259 cur_rr = ldns_rr_clone(ldns_rr_list_rr(
1260 ldns_pkt_answer(resolver->_cur_axfr_pkt),
1261 resolver->_axfr_i));
1262 resolver->_axfr_i++;
1263 if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
1264 resolver->_axfr_soa_count++;
1265 if (resolver->_axfr_soa_count >= 2) {
1266 #ifndef USE_WINSOCK
1267 close(resolver->_socket);
1268 #else
1269 closesocket(resolver->_socket);
1270 #endif
1271 resolver->_socket = 0;
1272 ldns_pkt_free(resolver->_cur_axfr_pkt);
1273 resolver->_cur_axfr_pkt = NULL;
1276 return cur_rr;
1277 } else {
1278 packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size);
1279 if(!packet_wire)
1280 return NULL;
1282 status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1283 packet_wire_size);
1284 LDNS_FREE(packet_wire);
1286 resolver->_axfr_i = 0;
1287 if (status != LDNS_STATUS_OK) {
1288 /* TODO: make status return type of this function (...api change) */
1289 fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
1291 /* RoRi: we must now also close the socket, otherwise subsequent uses of the
1292 same resolver structure will fail because the link is still open or
1293 in an undefined state */
1294 #ifndef USE_WINSOCK
1295 close(resolver->_socket);
1296 #else
1297 closesocket(resolver->_socket);
1298 #endif
1299 resolver->_socket = 0;
1301 return NULL;
1302 } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
1303 rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt));
1304 if (rcode) {
1305 fprintf(stderr, "Error in AXFR: %s\n",
1306 rcode->name);
1307 } else {
1308 fprintf(stderr, "Error in AXFR: %d\n",
1309 (int) ldns_pkt_get_rcode(
1310 resolver->_cur_axfr_pkt));
1313 /* RoRi: we must now also close the socket, otherwise subsequent uses of the
1314 same resolver structure will fail because the link is still open or
1315 in an undefined state */
1316 #ifndef USE_WINSOCK
1317 close(resolver->_socket);
1318 #else
1319 closesocket(resolver->_socket);
1320 #endif
1321 resolver->_socket = 0;
1323 return NULL;
1324 } else {
1325 return ldns_axfr_next(resolver);
1332 bool
1333 ldns_axfr_complete(const ldns_resolver *res)
1335 /* complete when soa count is 2? */
1336 return res->_axfr_soa_count == 2;
1339 ldns_pkt *
1340 ldns_axfr_last_pkt(const ldns_resolver *res)
1342 return res->_cur_axfr_pkt;
1345 /* random isn't really that good */
1346 void
1347 ldns_resolver_nameservers_randomize(ldns_resolver *r)
1349 uint16_t i, j;
1350 ldns_rdf **ns, *tmpns;
1351 size_t *rtt, tmprtt;
1353 /* should I check for ldns_resolver_random?? */
1354 assert(r != NULL);
1356 ns = ldns_resolver_nameservers(r);
1357 rtt = ldns_resolver_rtt(r);
1358 for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
1359 j = ldns_get_random() % ldns_resolver_nameserver_count(r);
1360 tmpns = ns[i];
1361 ns[i] = ns[j];
1362 ns[j] = tmpns;
1363 tmprtt = rtt[i];
1364 rtt[i] = rtt[j];
1365 rtt[j] = tmprtt;
1367 ldns_resolver_set_nameservers(r, ns);