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>
18 /* Access function for reading
19 * and setting the different Resolver
24 ldns_resolver_port(const ldns_resolver *r)
30 ldns_resolver_source(const ldns_resolver *r)
36 ldns_resolver_edns_udp_size(const ldns_resolver *r)
38 return r->_edns_udp_size;
42 ldns_resolver_retry(const ldns_resolver *r)
48 ldns_resolver_retrans(const ldns_resolver *r)
54 ldns_resolver_fallback(const ldns_resolver *r)
60 ldns_resolver_ip6(const ldns_resolver *r)
66 ldns_resolver_recursive(const ldns_resolver *r)
72 ldns_resolver_debug(const ldns_resolver *r)
78 ldns_resolver_dnsrch(const ldns_resolver *r)
84 ldns_resolver_fail(const ldns_resolver *r)
90 ldns_resolver_defnames(const ldns_resolver *r)
96 ldns_resolver_domain(const ldns_resolver *r)
102 ldns_resolver_searchlist(const ldns_resolver *r)
104 return r->_searchlist;
108 ldns_resolver_nameservers(const ldns_resolver *r)
110 return r->_nameservers;
114 ldns_resolver_nameserver_count(const ldns_resolver *r)
116 return r->_nameserver_count;
120 ldns_resolver_dnssec(const ldns_resolver *r)
126 ldns_resolver_dnssec_cd(const ldns_resolver *r)
128 return r->_dnssec_cd;
132 ldns_resolver_dnssec_anchors(const ldns_resolver *r)
134 return r->_dnssec_anchors;
138 ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
143 ldns_rr_list * trust_anchors;
146 if (!r || !keys) { return false; }
148 trust_anchors = ldns_resolver_dnssec_anchors(r);
150 if (!trust_anchors) { return false; }
152 for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
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); }
165 ldns_resolver_igntc(const ldns_resolver *r)
171 ldns_resolver_usevc(const ldns_resolver *r)
177 ldns_resolver_rtt(const ldns_resolver *r)
183 ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
189 rtt = ldns_resolver_rtt(r);
191 if (pos >= ldns_resolver_nameserver_count(r)) {
201 ldns_resolver_timeout(const ldns_resolver *r)
207 ldns_resolver_tsig_keyname(const ldns_resolver *r)
209 return r->_tsig_keyname;
213 ldns_resolver_tsig_algorithm(const ldns_resolver *r)
215 return r->_tsig_algorithm;
219 ldns_resolver_tsig_keydata(const ldns_resolver *r)
221 return r->_tsig_keydata;
225 ldns_resolver_random(const ldns_resolver *r)
231 ldns_resolver_searchlist_count(const ldns_resolver *r)
233 return r->_searchlist_count;
238 ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
244 ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
250 ldns_resolver_pop_nameserver(ldns_resolver *r)
252 ldns_rdf **nameservers;
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) {
266 pop = nameservers[ns_count - 1];
269 LDNS_FREE(nameservers);
272 ldns_resolver_set_nameservers(r, NULL);
273 ldns_resolver_set_rtt(r, NULL);
275 nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *,
277 rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
279 ldns_resolver_set_nameservers(r, nameservers);
280 ldns_resolver_set_rtt(r, rtt);
283 ldns_resolver_dec_nameserver_count(r);
288 ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
290 ldns_rdf **nameservers;
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;
299 ns_count = ldns_resolver_nameserver_count(r);
300 nameservers = ldns_resolver_nameservers(r);
301 rtt = ldns_resolver_rtt(r);
303 /* make room for the next one */
305 nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
307 nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
310 return LDNS_STATUS_MEM_ERR;
312 /* set the new value in the resolver */
313 ldns_resolver_set_nameservers(r, nameservers);
315 /* don't forget the rtt */
317 rtt = LDNS_XMALLOC(size_t, 1);
319 rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
322 return LDNS_STATUS_MEM_ERR;
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;
335 ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
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;
342 address = ldns_rr_rdf(rr, 0); /* extract the ip number */
344 return ldns_resolver_push_nameserver(r, address);
346 return LDNS_STATUS_ERR;
351 ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
357 stat = LDNS_STATUS_OK;
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;
368 return LDNS_STATUS_ERR;
373 ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
375 r->_edns_udp_size = s;
379 ldns_resolver_set_recursive(ldns_resolver *r, bool re)
385 ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
391 ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
397 ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
399 r->_dnssec_anchors = l;
403 ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
405 ldns_rr_list * trust_anchors;
407 if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
408 ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
410 return LDNS_STATUS_ERR;
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);
418 return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
422 ldns_resolver_set_igntc(ldns_resolver *r, bool i)
428 ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
434 ldns_resolver_set_debug(ldns_resolver *r, bool d)
440 ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
446 ldns_resolver_set_fail(ldns_resolver *r, bool f)
452 ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
454 r->_searchlist_count = c;
458 ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
460 r->_nameserver_count = c;
464 ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
470 ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
476 ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
478 r->_retrans = retrans;
482 ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
484 r->_fallback = fallback;
488 ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
494 ldns_resolver_set_defnames(ldns_resolver *r, bool d)
500 ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
506 ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
512 rtt = ldns_resolver_rtt(r);
514 if (pos >= ldns_resolver_nameserver_count(r)) {
523 ldns_resolver_incr_nameserver_count(ldns_resolver *r)
527 c = ldns_resolver_nameserver_count(r);
528 ldns_resolver_set_nameserver_count(r, ++c);
532 ldns_resolver_dec_nameserver_count(ldns_resolver *r)
536 c = ldns_resolver_nameserver_count(r);
540 ldns_resolver_set_nameserver_count(r, --c);
545 ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
551 ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
553 r->_timeout.tv_sec = timeout.tv_sec;
554 r->_timeout.tv_usec = timeout.tv_usec;
558 ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
560 ldns_rdf **searchlist;
563 if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
567 list_count = ldns_resolver_searchlist_count(r);
568 searchlist = ldns_resolver_searchlist(r);
570 searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
572 r->_searchlist = searchlist;
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 */
580 ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
582 LDNS_FREE(r->_tsig_keyname);
583 r->_tsig_keyname = strdup(tsig_keyname);
587 ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
589 LDNS_FREE(r->_tsig_algorithm);
590 r->_tsig_algorithm = strdup(tsig_algorithm);
594 ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
596 LDNS_FREE(r->_tsig_keydata);
597 r->_tsig_keydata = strdup(tsig_keydata);
601 ldns_resolver_set_random(ldns_resolver *r, bool b)
606 /* more sophisticated functions */
608 ldns_resolver_new(void)
612 r = LDNS_MALLOC(ldns_resolver);
617 r->_searchlist = NULL;
618 r->_nameservers = NULL;
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);
642 /* randomize the nameserver to be queried
643 * when there are multiple
645 ldns_resolver_set_random(r, true);
647 ldns_resolver_set_debug(r, 0);
649 r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
650 r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
652 /* TODO: fd=0 is actually a valid socket (stdin),
655 r->_axfr_soa_count = 0;
657 r->_cur_axfr_pkt = NULL;
659 r->_tsig_keyname = NULL;
660 r->_tsig_keydata = NULL;
661 r->_tsig_algorithm = NULL;
666 ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
668 return ldns_resolver_new_frm_fp_l(res, fp, NULL);
672 ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
675 const char *keyword[LDNS_RESOLV_KEYWORDS];
676 char word[LDNS_MAX_LINELEN + 1];
685 int lnr = 0, oldline;
687 if(!line_nr) line_nr = &lnr;
690 myfp = fopen("/etc/resolv.conf", "r");
692 return LDNS_STATUS_FILE_ERR;
698 * 1: default domain dname
699 * 2: NS aaaa or a record
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;
712 r = ldns_resolver_new();
714 if(!fp) fclose(myfp);
715 return LDNS_STATUS_MEM_ERR;
721 expect = LDNS_RESOLV_KEYWORD;
724 if (word[0] == '#') {
726 if(oldline == *line_nr) {
727 /* skip until end of line */
731 } while(c != EOF && c != '\n');
732 if(c=='\n') (*line_nr)++;
734 /* and read next to prepare for further parsing */
740 case LDNS_RESOLV_KEYWORD:
742 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
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
754 /* no keyword recognized */
755 if (expect == LDNS_RESOLV_KEYWORD) {
758 ldns_resolver_deep_free(r);
759 if(!fp) fclose(myfp);
760 return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
765 case LDNS_RESOLV_DEFDOMAIN:
766 /* default domain dname */
767 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
769 if(!fp) fclose(myfp);
770 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
773 expect = LDNS_RESOLV_KEYWORD;
776 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
778 ldns_resolver_deep_free(r);
779 if(!fp) fclose(myfp);
780 return LDNS_STATUS_SYNTAX_DNAME_ERR;
783 /* DOn't free, because we copy the pointer */
784 ldns_resolver_set_domain(r, tmp);
785 expect = LDNS_RESOLV_KEYWORD;
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);
791 if(!fp) fclose(myfp);
792 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
795 expect = LDNS_RESOLV_KEYWORD;
798 if(strchr(word, '%')) {
799 /* snip off interface labels,
800 * fe80::222:19ff:fe31:4222%eth0 */
801 strchr(word, '%')[0]=0;
803 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
806 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
808 /* could not parse it, exit */
810 ldns_resolver_deep_free(r);
811 if(!fp) fclose(myfp);
812 return LDNS_STATUS_SYNTAX_ERR;
814 (void)ldns_resolver_push_nameserver(r, tmp);
815 ldns_rdf_deep_free(tmp);
816 expect = LDNS_RESOLV_KEYWORD;
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);
823 ldns_resolver_deep_free(r);
824 if(!fp) fclose(myfp);
825 return LDNS_STATUS_MEM_ERR;
828 ldns_buffer_new_frm_data(b, word, (size_t) gtr);
829 if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
831 ldns_resolver_deep_free(r);
832 if(!fp) fclose(myfp);
833 return LDNS_STATUS_MEM_ERR;
835 bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
839 expect = LDNS_RESOLV_KEYWORD;
842 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
844 ldns_resolver_deep_free(r);
846 if(!fp) fclose(myfp);
847 return LDNS_STATUS_SYNTAX_DNAME_ERR;
850 ldns_resolver_push_searchlist(r, tmp);
852 ldns_rdf_deep_free(tmp);
853 bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
857 if (expect != LDNS_RESOLV_KEYWORD) {
859 expect = LDNS_RESOLV_KEYWORD;
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;
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;
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);
876 ldns_resolver_deep_free(r);
877 if(!fp) fclose(myfp);
878 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
881 expect = LDNS_RESOLV_KEYWORD;
886 tmp_rr = ldns_read_anchor_file(word);
887 (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
888 ldns_rr_free(tmp_rr);
890 expect = LDNS_RESOLV_KEYWORD;
900 return LDNS_STATUS_OK;
902 ldns_resolver_deep_free(r);
903 return LDNS_STATUS_NULL;
908 ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
915 fp = fopen(LDNS_RESOLV_CONF, "r");
918 fp = fopen(filename, "r");
921 return LDNS_STATUS_FILE_ERR;
924 s = ldns_resolver_new_frm_fp(&r, fp);
926 if (s == LDNS_STATUS_OK) {
929 return LDNS_STATUS_OK;
931 ldns_resolver_free(r);
932 return LDNS_STATUS_NULL;
939 ldns_resolver_free(ldns_resolver *res)
945 ldns_resolver_deep_free(ldns_resolver *res)
950 if (res->_searchlist) {
951 for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
952 ldns_rdf_deep_free(res->_searchlist[i]);
954 LDNS_FREE(res->_searchlist);
956 if (res->_nameservers) {
957 for (i = 0; i < res->_nameserver_count; i++) {
958 ldns_rdf_deep_free(res->_nameservers[i]);
960 LDNS_FREE(res->_nameservers);
962 if (ldns_resolver_domain(res)) {
963 ldns_rdf_deep_free(ldns_resolver_domain(res));
965 if (res->_tsig_keyname) {
966 LDNS_FREE(res->_tsig_keyname);
968 if (res->_tsig_keydata) {
969 LDNS_FREE(res->_tsig_keydata);
971 if (res->_tsig_algorithm) {
972 LDNS_FREE(res->_tsig_algorithm);
975 if (res->_cur_axfr_pkt) {
976 ldns_pkt_free(res->_cur_axfr_pkt);
980 LDNS_FREE(res->_rtt);
982 if (res->_dnssec_anchors) {
983 ldns_rr_list_deep_free(res->_dnssec_anchors);
990 ldns_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)
995 ldns_rdf **search_list;
997 ldns_status s = LDNS_STATUS_OK;
999 if (ldns_dname_absolute(name)) {
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]);
1007 s = ldns_resolver_query_status(pkt, r,
1008 new_name, t, c, flags);
1009 ldns_rdf_free(new_name);
1011 if (s == LDNS_STATUS_OK && *pkt &&
1012 ldns_pkt_get_rcode(*pkt) ==
1013 LDNS_RCODE_NOERROR) {
1014 return LDNS_STATUS_OK;
1016 ldns_pkt_free(*pkt);
1024 ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name,
1025 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1027 ldns_pkt* pkt = NULL;
1028 if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
1029 name, t, c, flags) != LDNS_STATUS_OK) {
1036 ldns_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)
1043 if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
1044 return ldns_resolver_send(pkt, r, name, t, c, flags);
1047 newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
1049 return LDNS_STATUS_MEM_ERR;
1051 status = ldns_resolver_send(pkt, r, newname, t, c, flags);
1052 ldns_rdf_free(newname);
1057 ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
1058 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1060 ldns_pkt* pkt = NULL;
1061 if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
1062 name, t, c, flags) != LDNS_STATUS_OK) {
1069 ldns_resolver_backup_rtt(ldns_resolver *r)
1072 size_t *old_rtt = ldns_resolver_rtt(r);
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);
1086 ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
1088 size_t *cur_rtt = ldns_resolver_rtt(r);
1093 ldns_resolver_set_rtt(r, old_rtt);
1097 ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1098 ldns_pkt *query_pkt)
1100 ldns_pkt *answer_pkt = NULL;
1101 ldns_status stat = LDNS_STATUS_OK;
1104 stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
1105 if (stat != LDNS_STATUS_OK) {
1107 ldns_pkt_free(answer_pkt);
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
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.
1128 rtt = ldns_resolver_backup_rtt(r);
1129 stat = ldns_send(&answer_pkt, r
1131 ldns_resolver_restore_rtt(r, rtt);
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);
1146 *answer = answer_pkt;
1153 ldns_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)
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),
1165 *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
1168 return LDNS_STATUS_ERR;
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);
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);
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));
1187 /* set the timestamp */
1188 now.tv_sec = time(NULL);
1190 ldns_pkt_set_timestamp(*query_pkt, now);
1193 if (ldns_resolver_debug(r)) {
1194 ldns_pkt_print(stdout, *query_pkt);
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);
1202 return LDNS_STATUS_OK;
1207 ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
1208 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1210 ldns_pkt *query_pkt;
1211 ldns_pkt *answer_pkt;
1215 assert(name != NULL);
1219 /* do all the preprocessing here, then fire of an query to
1226 c= LDNS_RR_CLASS_IN;
1228 if (0 == ldns_resolver_nameserver_count(r)) {
1229 return LDNS_STATUS_RES_NO_NS;
1231 if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1232 return LDNS_STATUS_RES_QUERY;
1235 status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1237 if (status != LDNS_STATUS_OK) {
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)
1245 should this go in pkt_prepare?
1247 if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
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;
1258 ldns_pkt_free(query_pkt);
1259 return LDNS_STATUS_CRYPTO_TSIG_ERR;
1260 #endif /* HAVE_SSL */
1263 status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1264 ldns_pkt_free(query_pkt);
1266 /* allows answer to be NULL when not interested in return value */
1268 *answer = answer_pkt;
1274 ldns_axfr_next(ldns_resolver *resolver)
1277 uint8_t *packet_wire;
1278 size_t packet_wire_size;
1279 ldns_lookup_table *rcode;
1282 /* check if start() has been called */
1283 if (!resolver || resolver->_socket == 0) {
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);
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) {
1301 close(resolver->_socket);
1303 closesocket(resolver->_socket);
1305 resolver->_socket = 0;
1306 ldns_pkt_free(resolver->_cur_axfr_pkt);
1307 resolver->_cur_axfr_pkt = NULL;
1312 packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size);
1316 status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1318 LDNS_FREE(packet_wire);
1320 resolver->_axfr_i = 0;
1321 if (status != LDNS_STATUS_OK) {
1322 /* TODO: make status return type of this function (...api change) */
1324 fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
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 */
1331 close(resolver->_socket);
1333 closesocket(resolver->_socket);
1335 resolver->_socket = 0;
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));
1342 fprintf(stderr, "Error in AXFR: %s\n",
1345 fprintf(stderr, "Error in AXFR: %d\n",
1346 (int) ldns_pkt_get_rcode(
1347 resolver->_cur_axfr_pkt));
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 */
1355 close(resolver->_socket);
1357 closesocket(resolver->_socket);
1359 resolver->_socket = 0;
1363 return ldns_axfr_next(resolver);
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
1376 ldns_axfr_abort(ldns_resolver *resolver)
1378 /* Only abort if an actual AXFR is in progress */
1379 if (resolver->_socket != 0)
1382 close(resolver->_socket);
1384 closesocket(resolver->_socket);
1386 resolver->_socket = 0;
1391 ldns_axfr_complete(const ldns_resolver *res)
1393 /* complete when soa count is 2? */
1394 return res->_axfr_soa_count == 2;
1398 ldns_axfr_last_pkt(const ldns_resolver *res)
1400 return res->_cur_axfr_pkt;
1403 /* random isn't really that good */
1405 ldns_resolver_nameservers_randomize(ldns_resolver *r)
1408 ldns_rdf **ns, *tmpns;
1409 size_t *rtt, tmprtt;
1411 /* should I check for ldns_resolver_random?? */
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);
1425 ldns_resolver_set_nameservers(r, ns);