acpi: Narrow workaround for broken interrupt settings
[dragonfly.git] / contrib / ldns / resolver.c
blobf9ec65a559665b3cbabd307e511b57eb9d05589d
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 ldns_rdf *
30 ldns_resolver_source(const ldns_resolver *r)
32 return r->_source;
35 uint16_t
36 ldns_resolver_edns_udp_size(const ldns_resolver *r)
38 return r->_edns_udp_size;
41 uint8_t
42 ldns_resolver_retry(const ldns_resolver *r)
44 return r->_retry;
47 uint8_t
48 ldns_resolver_retrans(const ldns_resolver *r)
50 return r->_retrans;
53 bool
54 ldns_resolver_fallback(const ldns_resolver *r)
56 return r->_fallback;
59 uint8_t
60 ldns_resolver_ip6(const ldns_resolver *r)
62 return r->_ip6;
65 bool
66 ldns_resolver_recursive(const ldns_resolver *r)
68 return r->_recursive;
71 bool
72 ldns_resolver_debug(const ldns_resolver *r)
74 return r->_debug;
77 bool
78 ldns_resolver_dnsrch(const ldns_resolver *r)
80 return r->_dnsrch;
83 bool
84 ldns_resolver_fail(const ldns_resolver *r)
86 return r->_fail;
89 bool
90 ldns_resolver_defnames(const ldns_resolver *r)
92 return r->_defnames;
95 ldns_rdf *
96 ldns_resolver_domain(const ldns_resolver *r)
98 return r->_domain;
101 ldns_rdf **
102 ldns_resolver_searchlist(const ldns_resolver *r)
104 return r->_searchlist;
107 ldns_rdf **
108 ldns_resolver_nameservers(const ldns_resolver *r)
110 return r->_nameservers;
113 size_t
114 ldns_resolver_nameserver_count(const ldns_resolver *r)
116 return r->_nameserver_count;
119 bool
120 ldns_resolver_dnssec(const ldns_resolver *r)
122 return r->_dnssec;
125 bool
126 ldns_resolver_dnssec_cd(const ldns_resolver *r)
128 return r->_dnssec_cd;
131 ldns_rr_list *
132 ldns_resolver_dnssec_anchors(const ldns_resolver *r)
134 return r->_dnssec_anchors;
137 bool
138 ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
140 size_t i;
141 bool result = false;
143 ldns_rr_list * trust_anchors;
144 ldns_rr * cur_rr;
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); }
157 result = true;
161 return result;
164 bool
165 ldns_resolver_igntc(const ldns_resolver *r)
167 return r->_igntc;
170 bool
171 ldns_resolver_usevc(const ldns_resolver *r)
173 return r->_usevc;
176 size_t *
177 ldns_resolver_rtt(const ldns_resolver *r)
179 return r->_rtt;
182 size_t
183 ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
185 size_t *rtt;
187 assert(r != NULL);
189 rtt = ldns_resolver_rtt(r);
191 if (pos >= ldns_resolver_nameserver_count(r)) {
192 /* error ?*/
193 return 0;
194 } else {
195 return rtt[pos];
200 struct timeval
201 ldns_resolver_timeout(const ldns_resolver *r)
203 return r->_timeout;
206 const char *
207 ldns_resolver_tsig_keyname(const ldns_resolver *r)
209 return r->_tsig_keyname;
212 const char *
213 ldns_resolver_tsig_algorithm(const ldns_resolver *r)
215 return r->_tsig_algorithm;
218 const char *
219 ldns_resolver_tsig_keydata(const ldns_resolver *r)
221 return r->_tsig_keydata;
224 bool
225 ldns_resolver_random(const ldns_resolver *r)
227 return r->_random;
230 size_t
231 ldns_resolver_searchlist_count(const ldns_resolver *r)
233 return r->_searchlist_count;
236 /* write */
237 void
238 ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
240 r->_port = p;
243 void
244 ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
246 r->_source = s;
249 ldns_rdf *
250 ldns_resolver_pop_nameserver(ldns_resolver *r)
252 ldns_rdf **nameservers;
253 ldns_rdf *pop;
254 size_t ns_count;
255 size_t *rtt;
257 assert(r != NULL);
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;
266 pop = nameservers[ns_count - 1];
268 if (ns_count == 1) {
269 LDNS_FREE(nameservers);
270 LDNS_FREE(rtt);
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));
279 ldns_resolver_set_nameservers(r, nameservers);
280 ldns_resolver_set_rtt(r, rtt);
282 /* decr the count */
283 ldns_resolver_dec_nameserver_count(r);
284 return pop;
287 ldns_status
288 ldns_resolver_push_nameserver(ldns_resolver *r, const ldns_rdf *n)
290 ldns_rdf **nameservers;
291 size_t ns_count;
292 size_t *rtt;
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 */
304 if (ns_count == 0) {
305 nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
306 } else {
307 nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
309 if(!nameservers)
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 */
316 if (ns_count == 0) {
317 rtt = LDNS_XMALLOC(size_t, 1);
318 } else {
319 rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
321 if(!rtt)
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;
334 ldns_status
335 ldns_resolver_push_nameserver_rr(ldns_resolver *r, const ldns_rr *rr)
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;
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;
350 ldns_status
351 ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, const ldns_rr_list *rrlist)
353 ldns_rr *rr;
354 ldns_status stat;
355 size_t i;
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;
366 return stat;
367 } else {
368 return LDNS_STATUS_ERR;
372 void
373 ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
375 r->_edns_udp_size = s;
378 void
379 ldns_resolver_set_recursive(ldns_resolver *r, bool re)
381 r->_recursive = re;
384 void
385 ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
387 r->_dnssec = d;
390 void
391 ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
393 r->_dnssec_cd = d;
396 void
397 ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
399 r->_dnssec_anchors = l;
402 ldns_status
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;
421 void
422 ldns_resolver_set_igntc(ldns_resolver *r, bool i)
424 r->_igntc = i;
427 void
428 ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
430 r->_usevc = vc;
433 void
434 ldns_resolver_set_debug(ldns_resolver *r, bool d)
436 r->_debug = d;
439 void
440 ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
442 r->_ip6 = ip6;
445 void
446 ldns_resolver_set_fail(ldns_resolver *r, bool f)
448 r->_fail =f;
451 static void
452 ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
454 r->_searchlist_count = c;
457 void
458 ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
460 r->_nameserver_count = c;
463 void
464 ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
466 r->_dnsrch = d;
469 void
470 ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
472 r->_retry = retry;
475 void
476 ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
478 r->_retrans = retrans;
481 void
482 ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
484 r->_fallback = fallback;
487 void
488 ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
490 r->_nameservers = n;
493 void
494 ldns_resolver_set_defnames(ldns_resolver *r, bool d)
496 r->_defnames = d;
499 void
500 ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
502 r->_rtt = rtt;
505 void
506 ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
508 size_t *rtt;
510 assert(r != NULL);
512 rtt = ldns_resolver_rtt(r);
514 if (pos >= ldns_resolver_nameserver_count(r)) {
515 /* error ?*/
516 } else {
517 rtt[pos] = value;
522 void
523 ldns_resolver_incr_nameserver_count(ldns_resolver *r)
525 size_t c;
527 c = ldns_resolver_nameserver_count(r);
528 ldns_resolver_set_nameserver_count(r, ++c);
531 void
532 ldns_resolver_dec_nameserver_count(ldns_resolver *r)
534 size_t c;
536 c = ldns_resolver_nameserver_count(r);
537 if (c == 0) {
538 return;
539 } else {
540 ldns_resolver_set_nameserver_count(r, --c);
544 void
545 ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
547 r->_domain = d;
550 void
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;
557 void
558 ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
560 ldns_rdf **searchlist;
561 size_t list_count;
563 if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
564 return;
567 list_count = ldns_resolver_searchlist_count(r);
568 searchlist = ldns_resolver_searchlist(r);
570 searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
571 if (searchlist) {
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 */
579 void
580 ldns_resolver_set_tsig_keyname(ldns_resolver *r, const char *tsig_keyname)
582 LDNS_FREE(r->_tsig_keyname);
583 r->_tsig_keyname = strdup(tsig_keyname);
586 void
587 ldns_resolver_set_tsig_algorithm(ldns_resolver *r, const char *tsig_algorithm)
589 LDNS_FREE(r->_tsig_algorithm);
590 r->_tsig_algorithm = strdup(tsig_algorithm);
593 void
594 ldns_resolver_set_tsig_keydata(ldns_resolver *r, const char *tsig_keydata)
596 LDNS_FREE(r->_tsig_keydata);
597 r->_tsig_keydata = strdup(tsig_keydata);
600 void
601 ldns_resolver_set_random(ldns_resolver *r, bool b)
603 r->_random = b;
606 /* more sophisticated functions */
607 ldns_resolver *
608 ldns_resolver_new(void)
610 ldns_resolver *r;
612 r = LDNS_MALLOC(ldns_resolver);
613 if (!r) {
614 return NULL;
617 r->_searchlist = NULL;
618 r->_nameservers = NULL;
619 r->_rtt = 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);
641 ldns_resolver_set_ixfr_serial(r, 0);
643 /* randomize the nameserver to be queried
644 * when there are multiple
646 ldns_resolver_set_random(r, true);
648 ldns_resolver_set_debug(r, 0);
650 r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
651 r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
653 r->_socket = -1;
654 r->_axfr_soa_count = 0;
655 r->_axfr_i = 0;
656 r->_cur_axfr_pkt = NULL;
658 r->_tsig_keyname = NULL;
659 r->_tsig_keydata = NULL;
660 r->_tsig_algorithm = NULL;
661 return r;
664 ldns_resolver *
665 ldns_resolver_clone(ldns_resolver *src)
667 ldns_resolver *dst;
668 size_t i;
670 assert(src != NULL);
672 if (!(dst = LDNS_MALLOC(ldns_resolver))) return NULL;
673 (void) memcpy(dst, src, sizeof(ldns_resolver));
675 if (dst->_searchlist_count == 0)
676 dst->_searchlist = NULL;
677 else {
678 if (!(dst->_searchlist =
679 LDNS_XMALLOC(ldns_rdf *, dst->_searchlist_count)))
680 goto error;
681 for (i = 0; i < dst->_searchlist_count; i++)
682 if (!(dst->_searchlist[i] =
683 ldns_rdf_clone(src->_searchlist[i]))) {
684 dst->_searchlist_count = i;
685 goto error_searchlist;
688 if (dst->_nameserver_count == 0) {
689 dst->_nameservers = NULL;
690 dst->_rtt = NULL;
691 } else {
692 if (!(dst->_nameservers =
693 LDNS_XMALLOC(ldns_rdf *, dst->_nameserver_count)))
694 goto error_searchlist;
695 for (i = 0; i < dst->_nameserver_count; i++)
696 if (!(dst->_nameservers[i] =
697 ldns_rdf_clone(src->_nameservers[i]))) {
698 dst->_nameserver_count = i;
699 goto error_nameservers;
701 if (!(dst->_rtt =
702 LDNS_XMALLOC(size_t, dst->_nameserver_count)))
703 goto error_nameservers;
704 (void) memcpy(dst->_rtt, src->_rtt,
705 sizeof(size_t) * dst->_nameserver_count);
707 if (dst->_domain && (!(dst->_domain = ldns_rdf_clone(src->_domain))))
708 goto error_rtt;
710 if (dst->_tsig_keyname &&
711 (!(dst->_tsig_keyname = strdup(src->_tsig_keyname))))
712 goto error_domain;
714 if (dst->_tsig_keydata &&
715 (!(dst->_tsig_keydata = strdup(src->_tsig_keydata))))
716 goto error_tsig_keyname;
718 if (dst->_tsig_algorithm &&
719 (!(dst->_tsig_algorithm = strdup(src->_tsig_algorithm))))
720 goto error_tsig_keydata;
722 if (dst->_cur_axfr_pkt &&
723 (!(dst->_cur_axfr_pkt = ldns_pkt_clone(src->_cur_axfr_pkt))))
724 goto error_tsig_algorithm;
726 if (dst->_dnssec_anchors &&
727 (!(dst->_dnssec_anchors=ldns_rr_list_clone(src->_dnssec_anchors))))
728 goto error_cur_axfr_pkt;
730 return dst;
732 error_cur_axfr_pkt:
733 ldns_pkt_free(dst->_cur_axfr_pkt);
734 error_tsig_algorithm:
735 LDNS_FREE(dst->_tsig_algorithm);
736 error_tsig_keydata:
737 LDNS_FREE(dst->_tsig_keydata);
738 error_tsig_keyname:
739 LDNS_FREE(dst->_tsig_keyname);
740 error_domain:
741 ldns_rdf_deep_free(dst->_domain);
742 error_rtt:
743 LDNS_FREE(dst->_rtt);
744 error_nameservers:
745 for (i = 0; i < dst->_nameserver_count; i++)
746 ldns_rdf_deep_free(dst->_nameservers[i]);
747 LDNS_FREE(dst->_nameservers);
748 error_searchlist:
749 for (i = 0; i < dst->_searchlist_count; i++)
750 ldns_rdf_deep_free(dst->_searchlist[i]);
751 LDNS_FREE(dst->_searchlist);
752 error:
753 LDNS_FREE(dst);
754 return NULL;
758 ldns_status
759 ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
761 return ldns_resolver_new_frm_fp_l(res, fp, NULL);
764 ldns_status
765 ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
767 ldns_resolver *r = NULL;
768 const char *keyword[LDNS_RESOLV_KEYWORDS];
769 char word[LDNS_MAX_LINELEN + 1];
770 int8_t expect;
771 uint8_t i;
772 ldns_rdf *tmp;
773 #ifdef HAVE_SSL
774 ldns_rr *tmp_rr;
775 #endif
776 ssize_t gtr, bgtr;
777 ldns_buffer *b;
778 int lnr = 0, oldline;
779 FILE* myfp = fp;
780 if(!line_nr) line_nr = &lnr;
782 if(!fp) {
783 myfp = fopen(LDNS_RESOLV_CONF, "r");
784 if(!myfp)
785 return LDNS_STATUS_FILE_ERR;
788 /* do this better
789 * expect =
790 * 0: keyword
791 * 1: default domain dname
792 * 2: NS aaaa or a record
795 /* recognized keywords */
796 keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
797 keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
798 keyword[LDNS_RESOLV_SEARCH] = "search";
799 /* these two are read but not used atm TODO */
800 keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
801 keyword[LDNS_RESOLV_OPTIONS] = "options";
802 keyword[LDNS_RESOLV_ANCHOR] = "anchor";
804 r = ldns_resolver_new();
805 if (!r) {
806 if(!fp) fclose(myfp);
807 return LDNS_STATUS_MEM_ERR;
810 gtr = 1;
811 word[0] = 0;
812 oldline = *line_nr;
813 expect = LDNS_RESOLV_KEYWORD;
814 while (gtr > 0) {
815 /* check comments */
816 if (word[0] == '#') {
817 word[0]='x';
818 if(oldline == *line_nr) {
819 /* skip until end of line */
820 int c;
821 do {
822 c = fgetc(myfp);
823 } while(c != EOF && c != '\n');
824 if(c=='\n') (*line_nr)++;
826 /* and read next to prepare for further parsing */
827 oldline = *line_nr;
828 continue;
830 oldline = *line_nr;
831 switch(expect) {
832 case LDNS_RESOLV_KEYWORD:
833 /* keyword */
834 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
835 if (gtr != 0) {
836 if(word[0] == '#') continue;
837 for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
838 if (strcasecmp(keyword[i], word) == 0) {
839 /* chosen the keyword and
840 * expect values carefully
842 expect = i;
843 break;
846 /* no keyword recognized */
847 if (expect == LDNS_RESOLV_KEYWORD) {
848 /* skip line */
850 ldns_resolver_deep_free(r);
851 if(!fp) fclose(myfp);
852 return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
856 break;
857 case LDNS_RESOLV_DEFDOMAIN:
858 /* default domain dname */
859 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
860 if (gtr == 0) {
861 if(!fp) fclose(myfp);
862 ldns_resolver_deep_free(r);
863 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
865 if(word[0] == '#') {
866 expect = LDNS_RESOLV_KEYWORD;
867 continue;
869 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
870 if (!tmp) {
871 if(!fp) fclose(myfp);
872 ldns_resolver_deep_free(r);
873 return LDNS_STATUS_SYNTAX_DNAME_ERR;
876 /* DOn't free, because we copy the pointer */
877 ldns_resolver_set_domain(r, tmp);
878 expect = LDNS_RESOLV_KEYWORD;
879 break;
880 case LDNS_RESOLV_NAMESERVER:
881 /* NS aaaa or a record */
882 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
883 if (gtr == 0) {
884 if(!fp) fclose(myfp);
885 ldns_resolver_deep_free(r);
886 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
888 if(word[0] == '#') {
889 expect = LDNS_RESOLV_KEYWORD;
890 continue;
892 if(strchr(word, '%')) {
893 /* snip off interface labels,
894 * fe80::222:19ff:fe31:4222%eth0 */
895 strchr(word, '%')[0]=0;
897 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
898 if (!tmp) {
899 /* try ip4 */
900 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
902 /* could not parse it, exit */
903 if (!tmp) {
904 ldns_resolver_deep_free(r);
905 if(!fp) fclose(myfp);
906 return LDNS_STATUS_SYNTAX_ERR;
908 (void)ldns_resolver_push_nameserver(r, tmp);
909 ldns_rdf_deep_free(tmp);
910 expect = LDNS_RESOLV_KEYWORD;
911 break;
912 case LDNS_RESOLV_SEARCH:
913 /* search list domain dname */
914 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
915 b = LDNS_MALLOC(ldns_buffer);
916 if(!b) {
917 ldns_resolver_deep_free(r);
918 if(!fp) fclose(myfp);
919 return LDNS_STATUS_MEM_ERR;
922 ldns_buffer_new_frm_data(b, word, (size_t) gtr);
923 if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
924 LDNS_FREE(b);
925 ldns_resolver_deep_free(r);
926 if(!fp) fclose(myfp);
927 return LDNS_STATUS_MEM_ERR;
929 bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
930 while (bgtr > 0) {
931 gtr -= bgtr;
932 if(word[0] == '#') {
933 expect = LDNS_RESOLV_KEYWORD;
934 break;
936 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
937 if (!tmp) {
938 ldns_resolver_deep_free(r);
939 ldns_buffer_free(b);
940 if(!fp) fclose(myfp);
941 return LDNS_STATUS_SYNTAX_DNAME_ERR;
944 ldns_resolver_push_searchlist(r, tmp);
946 ldns_rdf_deep_free(tmp);
947 bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
948 (size_t) gtr + 1);
950 ldns_buffer_free(b);
951 if (expect != LDNS_RESOLV_KEYWORD) {
952 gtr = 1;
953 expect = LDNS_RESOLV_KEYWORD;
955 break;
956 case LDNS_RESOLV_SORTLIST:
957 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
958 /* sortlist not implemented atm */
959 expect = LDNS_RESOLV_KEYWORD;
960 break;
961 case LDNS_RESOLV_OPTIONS:
962 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
963 /* options not implemented atm */
964 expect = LDNS_RESOLV_KEYWORD;
965 break;
966 case LDNS_RESOLV_ANCHOR:
967 /* a file containing a DNSSEC trust anchor */
968 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
969 if (gtr == 0) {
970 ldns_resolver_deep_free(r);
971 if(!fp) fclose(myfp);
972 return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
974 if(word[0] == '#') {
975 expect = LDNS_RESOLV_KEYWORD;
976 continue;
979 #ifdef HAVE_SSL
980 tmp_rr = ldns_read_anchor_file(word);
981 (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
982 ldns_rr_free(tmp_rr);
983 #endif
984 expect = LDNS_RESOLV_KEYWORD;
985 break;
989 if(!fp)
990 fclose(myfp);
992 if (res) {
993 *res = r;
994 return LDNS_STATUS_OK;
995 } else {
996 ldns_resolver_deep_free(r);
997 return LDNS_STATUS_NULL;
1001 ldns_status
1002 ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
1004 ldns_resolver *r;
1005 FILE *fp;
1006 ldns_status s;
1008 if (!filename) {
1009 fp = fopen(LDNS_RESOLV_CONF, "r");
1011 } else {
1012 fp = fopen(filename, "r");
1014 if (!fp) {
1015 return LDNS_STATUS_FILE_ERR;
1018 s = ldns_resolver_new_frm_fp(&r, fp);
1019 fclose(fp);
1020 if (s == LDNS_STATUS_OK) {
1021 if (res) {
1022 *res = r;
1023 return LDNS_STATUS_OK;
1024 } else {
1025 ldns_resolver_free(r);
1026 return LDNS_STATUS_NULL;
1029 return s;
1032 void
1033 ldns_resolver_free(ldns_resolver *res)
1035 LDNS_FREE(res);
1038 void
1039 ldns_resolver_deep_free(ldns_resolver *res)
1041 size_t i;
1043 if (res) {
1044 close_socket(res->_socket);
1046 if (res->_searchlist) {
1047 for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
1048 ldns_rdf_deep_free(res->_searchlist[i]);
1050 LDNS_FREE(res->_searchlist);
1052 if (res->_nameservers) {
1053 for (i = 0; i < res->_nameserver_count; i++) {
1054 ldns_rdf_deep_free(res->_nameservers[i]);
1056 LDNS_FREE(res->_nameservers);
1058 if (ldns_resolver_domain(res)) {
1059 ldns_rdf_deep_free(ldns_resolver_domain(res));
1061 if (res->_tsig_keyname) {
1062 LDNS_FREE(res->_tsig_keyname);
1064 if (res->_tsig_keydata) {
1065 LDNS_FREE(res->_tsig_keydata);
1067 if (res->_tsig_algorithm) {
1068 LDNS_FREE(res->_tsig_algorithm);
1071 if (res->_cur_axfr_pkt) {
1072 ldns_pkt_free(res->_cur_axfr_pkt);
1075 if (res->_rtt) {
1076 LDNS_FREE(res->_rtt);
1078 if (res->_dnssec_anchors) {
1079 ldns_rr_list_deep_free(res->_dnssec_anchors);
1081 LDNS_FREE(res);
1085 ldns_status
1086 ldns_resolver_search_status(ldns_pkt** pkt,
1087 ldns_resolver *r, const ldns_rdf *name,
1088 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1090 ldns_rdf *new_name;
1091 ldns_rdf **search_list;
1092 size_t i;
1093 ldns_status s = LDNS_STATUS_OK;
1094 ldns_rdf root_dname = { 1, LDNS_RDF_TYPE_DNAME, (void *)"" };
1096 if (ldns_dname_absolute(name)) {
1097 /* query as-is */
1098 return ldns_resolver_query_status(pkt, r, name, t, c, flags);
1099 } else if (ldns_resolver_dnsrch(r)) {
1100 search_list = ldns_resolver_searchlist(r);
1101 for (i = 0; i <= ldns_resolver_searchlist_count(r); i++) {
1102 if (i == ldns_resolver_searchlist_count(r)) {
1103 new_name = ldns_dname_cat_clone(name,
1104 &root_dname);
1105 } else {
1106 new_name = ldns_dname_cat_clone(name,
1107 search_list[i]);
1110 s = ldns_resolver_query_status(pkt, r,
1111 new_name, t, c, flags);
1112 ldns_rdf_deep_free(new_name);
1114 if (pkt && *pkt) {
1115 if (s == LDNS_STATUS_OK &&
1116 ldns_pkt_get_rcode(*pkt) ==
1117 LDNS_RCODE_NOERROR) {
1119 return LDNS_STATUS_OK;
1121 ldns_pkt_free(*pkt);
1122 *pkt = NULL;
1126 return s;
1129 ldns_pkt *
1130 ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name,
1131 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1133 ldns_pkt* pkt = NULL;
1134 if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
1135 name, t, c, flags) != LDNS_STATUS_OK) {
1136 ldns_pkt_free(pkt);
1137 return NULL;
1139 return pkt;
1142 ldns_status
1143 ldns_resolver_query_status(ldns_pkt** pkt,
1144 ldns_resolver *r, const ldns_rdf *name,
1145 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1147 ldns_rdf *newname;
1148 ldns_status status;
1150 if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
1151 return ldns_resolver_send(pkt, r, name, t, c, flags);
1154 newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
1155 if (!newname) {
1156 return LDNS_STATUS_MEM_ERR;
1158 status = ldns_resolver_send(pkt, r, newname, t, c, flags);
1159 ldns_rdf_free(newname);
1160 return status;
1163 ldns_pkt *
1164 ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
1165 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1167 ldns_pkt* pkt = NULL;
1168 if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
1169 name, t, c, flags) != LDNS_STATUS_OK) {
1170 ldns_pkt_free(pkt);
1171 return NULL;
1173 return pkt;
1176 static size_t *
1177 ldns_resolver_backup_rtt(ldns_resolver *r)
1179 size_t *new_rtt;
1180 size_t *old_rtt = ldns_resolver_rtt(r);
1182 if (old_rtt && ldns_resolver_nameserver_count(r)) {
1183 new_rtt = LDNS_XMALLOC(size_t
1184 , ldns_resolver_nameserver_count(r));
1185 if (!new_rtt) return NULL;
1186 memcpy(new_rtt, old_rtt, sizeof(size_t)
1187 * ldns_resolver_nameserver_count(r));
1188 ldns_resolver_set_rtt(r, new_rtt);
1189 return old_rtt;
1191 return NULL;
1194 static void
1195 ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
1197 size_t *cur_rtt = ldns_resolver_rtt(r);
1199 if (cur_rtt) {
1200 LDNS_FREE(cur_rtt);
1202 ldns_resolver_set_rtt(r, old_rtt);
1205 ldns_status
1206 ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1207 ldns_pkt *query_pkt)
1209 ldns_pkt *answer_pkt = NULL;
1210 ldns_status stat = LDNS_STATUS_OK;
1211 size_t *rtt;
1213 stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
1214 if (stat != LDNS_STATUS_OK) {
1215 if(answer_pkt) {
1216 ldns_pkt_free(answer_pkt);
1217 answer_pkt = NULL;
1219 } else {
1220 /* if tc=1 fall back to EDNS and/or TCP */
1221 /* check for tcp first (otherwise we don't care about tc=1) */
1222 if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
1223 if (ldns_pkt_tc(answer_pkt)) {
1224 /* was EDNS0 set? */
1225 if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
1226 ldns_pkt_set_edns_udp_size(query_pkt
1227 , 4096);
1228 ldns_pkt_free(answer_pkt);
1229 answer_pkt = NULL;
1230 /* Nameservers should not become
1231 * unreachable because fragments are
1232 * dropped (network error). We might
1233 * still have success with TCP.
1234 * Therefore maintain reachability
1235 * statuses of the nameservers by
1236 * backup and restore the rtt list.
1238 rtt = ldns_resolver_backup_rtt(r);
1239 stat = ldns_send(&answer_pkt, r
1240 , query_pkt);
1241 ldns_resolver_restore_rtt(r, rtt);
1243 /* either way, if it is still truncated, use TCP */
1244 if (stat != LDNS_STATUS_OK ||
1245 ldns_pkt_tc(answer_pkt)) {
1246 ldns_resolver_set_usevc(r, true);
1247 ldns_pkt_free(answer_pkt);
1248 answer_pkt = NULL;
1249 stat = ldns_send(&answer_pkt, r, query_pkt);
1250 ldns_resolver_set_usevc(r, false);
1256 if (answer && answer_pkt) {
1257 *answer = answer_pkt;
1260 return stat;
1263 ldns_status
1264 ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
1265 const ldns_rdf *name, ldns_rr_type t,
1266 ldns_rr_class c, uint16_t flags)
1268 struct timeval now;
1269 ldns_rr* soa = NULL;
1271 /* prepare a question pkt from the parameters
1272 * and then send this */
1273 if (t == LDNS_RR_TYPE_IXFR) {
1274 ldns_rdf *owner_rdf;
1275 ldns_rdf *mname_rdf;
1276 ldns_rdf *rname_rdf;
1277 ldns_rdf *serial_rdf;
1278 ldns_rdf *refresh_rdf;
1279 ldns_rdf *retry_rdf;
1280 ldns_rdf *expire_rdf;
1281 ldns_rdf *minimum_rdf;
1282 soa = ldns_rr_new();
1284 if (!soa) {
1285 return LDNS_STATUS_ERR;
1287 owner_rdf = ldns_rdf_clone(name);
1288 if (!owner_rdf) {
1289 ldns_rr_free(soa);
1290 return LDNS_STATUS_ERR;
1292 ldns_rr_set_owner(soa, owner_rdf);
1293 ldns_rr_set_type(soa, LDNS_RR_TYPE_SOA);
1294 ldns_rr_set_class(soa, c);
1295 ldns_rr_set_question(soa, false);
1296 if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
1297 ldns_rr_free(soa);
1298 return LDNS_STATUS_ERR;
1299 } else ldns_rr_push_rdf(soa, mname_rdf);
1300 if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
1301 ldns_rr_free(soa);
1302 return LDNS_STATUS_ERR;
1303 } else ldns_rr_push_rdf(soa, rname_rdf);
1304 serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, ldns_resolver_get_ixfr_serial(r));
1305 if (!serial_rdf) {
1306 ldns_rr_free(soa);
1307 return LDNS_STATUS_ERR;
1308 } else ldns_rr_push_rdf(soa, serial_rdf);
1309 refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1310 if (!refresh_rdf) {
1311 ldns_rr_free(soa);
1312 return LDNS_STATUS_ERR;
1313 } else ldns_rr_push_rdf(soa, refresh_rdf);
1314 retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1315 if (!retry_rdf) {
1316 ldns_rr_free(soa);
1317 return LDNS_STATUS_ERR;
1318 } else ldns_rr_push_rdf(soa, retry_rdf);
1319 expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1320 if (!expire_rdf) {
1321 ldns_rr_free(soa);
1322 return LDNS_STATUS_ERR;
1323 } else ldns_rr_push_rdf(soa, expire_rdf);
1324 minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1325 if (!minimum_rdf) {
1326 ldns_rr_free(soa);
1327 return LDNS_STATUS_ERR;
1328 } else ldns_rr_push_rdf(soa, minimum_rdf);
1330 *query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name),
1331 c, flags, soa);
1332 } else {
1333 *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
1335 if (!*query_pkt) {
1336 ldns_rr_free(soa);
1337 return LDNS_STATUS_ERR;
1340 /* set DO bit if necessary */
1341 if (ldns_resolver_dnssec(r)) {
1342 if (ldns_resolver_edns_udp_size(r) == 0) {
1343 ldns_resolver_set_edns_udp_size(r, 4096);
1345 ldns_pkt_set_edns_do(*query_pkt, true);
1346 if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
1347 ldns_pkt_set_cd(*query_pkt, true);
1351 /* transfer the udp_edns_size from the resolver to the packet */
1352 if (ldns_resolver_edns_udp_size(r) != 0) {
1353 ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
1356 /* set the timestamp */
1357 now.tv_sec = time(NULL);
1358 now.tv_usec = 0;
1359 ldns_pkt_set_timestamp(*query_pkt, now);
1362 if (ldns_resolver_debug(r)) {
1363 ldns_pkt_print(stdout, *query_pkt);
1366 /* only set the id if it is not set yet */
1367 if (ldns_pkt_id(*query_pkt) == 0) {
1368 ldns_pkt_set_random_id(*query_pkt);
1371 return LDNS_STATUS_OK;
1374 ldns_status
1375 ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
1376 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1378 ldns_pkt *query_pkt;
1379 ldns_pkt *answer_pkt;
1380 ldns_status status;
1382 assert(r != NULL);
1383 assert(name != NULL);
1385 answer_pkt = NULL;
1387 /* do all the preprocessing here, then fire of an query to
1388 * the network */
1390 if (0 == t) {
1391 t= LDNS_RR_TYPE_A;
1393 if (0 == c) {
1394 c= LDNS_RR_CLASS_IN;
1396 if (0 == ldns_resolver_nameserver_count(r)) {
1397 return LDNS_STATUS_RES_NO_NS;
1399 if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1400 return LDNS_STATUS_RES_QUERY;
1403 status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1404 t, c, flags);
1405 if (status != LDNS_STATUS_OK) {
1406 return status;
1409 /* if tsig values are set, tsign it */
1410 /* TODO: make last 3 arguments optional too? maybe make complete
1411 rr instead of separate values in resolver (and packet)
1412 Jelte
1413 should this go in pkt_prepare?
1415 if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
1416 #ifdef HAVE_SSL
1417 status = ldns_pkt_tsig_sign(query_pkt,
1418 ldns_resolver_tsig_keyname(r),
1419 ldns_resolver_tsig_keydata(r),
1420 300, ldns_resolver_tsig_algorithm(r), NULL);
1421 if (status != LDNS_STATUS_OK) {
1422 ldns_pkt_free(query_pkt);
1423 return LDNS_STATUS_CRYPTO_TSIG_ERR;
1425 #else
1426 ldns_pkt_free(query_pkt);
1427 return LDNS_STATUS_CRYPTO_TSIG_ERR;
1428 #endif /* HAVE_SSL */
1431 status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1432 ldns_pkt_free(query_pkt);
1434 /* allows answer to be NULL when not interested in return value */
1435 if (answer) {
1436 *answer = answer_pkt;
1438 return status;
1441 ldns_rr *
1442 ldns_axfr_next(ldns_resolver *resolver)
1444 ldns_rr *cur_rr;
1445 uint8_t *packet_wire;
1446 size_t packet_wire_size;
1447 ldns_status status;
1449 /* check if start() has been called */
1450 if (!resolver || resolver->_socket == -1) {
1451 return NULL;
1454 if (resolver->_cur_axfr_pkt) {
1455 if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
1456 ldns_pkt_free(resolver->_cur_axfr_pkt);
1457 resolver->_cur_axfr_pkt = NULL;
1458 return ldns_axfr_next(resolver);
1460 cur_rr = ldns_rr_clone(ldns_rr_list_rr(
1461 ldns_pkt_answer(resolver->_cur_axfr_pkt),
1462 resolver->_axfr_i));
1463 resolver->_axfr_i++;
1464 if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
1465 resolver->_axfr_soa_count++;
1466 if (resolver->_axfr_soa_count >= 2) {
1468 close_socket(resolver->_socket);
1470 ldns_pkt_free(resolver->_cur_axfr_pkt);
1471 resolver->_cur_axfr_pkt = NULL;
1474 return cur_rr;
1475 } else {
1476 packet_wire = ldns_tcp_read_wire_timeout(resolver->_socket, &packet_wire_size, resolver->_timeout);
1477 if(!packet_wire)
1478 return NULL;
1480 status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1481 packet_wire_size);
1482 LDNS_FREE(packet_wire);
1484 resolver->_axfr_i = 0;
1485 if (status != LDNS_STATUS_OK) {
1486 /* TODO: make status return type of this function (...api change) */
1487 #ifdef STDERR_MSGS
1488 fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
1489 #endif
1491 /* we must now also close the socket, otherwise subsequent uses of the
1492 same resolver structure will fail because the link is still open or
1493 in an undefined state */
1495 close_socket(resolver->_socket);
1497 return NULL;
1498 } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
1499 #ifdef STDERR_MSGS
1500 ldns_lookup_table *rcode = ldns_lookup_by_id(
1501 ldns_rcodes,(int) ldns_pkt_get_rcode(
1502 resolver->_cur_axfr_pkt));
1503 if (rcode) {
1504 fprintf(stderr, "Error in AXFR: %s\n",
1505 rcode->name);
1506 } else {
1507 fprintf(stderr, "Error in AXFR: %d\n",
1508 (int) ldns_pkt_get_rcode(
1509 resolver->_cur_axfr_pkt));
1511 #endif
1513 /* we must now also close the socket, otherwise subsequent uses of the
1514 same resolver structure will fail because the link is still open or
1515 in an undefined state */
1517 close_socket(resolver->_socket);
1519 return NULL;
1520 } else {
1521 return ldns_axfr_next(resolver);
1528 /* this function is needed to abort a transfer that is in progress;
1529 * without it an aborted transfer will lead to the AXFR code in the
1530 * library staying in an indetermined state because the socket for the
1531 * AXFR is never closed
1533 void
1534 ldns_axfr_abort(ldns_resolver *resolver)
1536 /* Only abort if an actual AXFR is in progress */
1537 if (resolver->_socket != -1)
1539 #ifndef USE_WINSOCK
1540 close(resolver->_socket);
1541 #else
1542 closesocket(resolver->_socket);
1543 #endif
1544 resolver->_socket = -1;
1548 bool
1549 ldns_axfr_complete(const ldns_resolver *res)
1551 /* complete when soa count is 2? */
1552 return res->_axfr_soa_count == 2;
1555 ldns_pkt *
1556 ldns_axfr_last_pkt(const ldns_resolver *res)
1558 return res->_cur_axfr_pkt;
1561 void
1562 ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial)
1564 r->_serial = serial;
1567 uint32_t
1568 ldns_resolver_get_ixfr_serial(const ldns_resolver *res)
1570 return res->_serial;
1574 /* random isn't really that good */
1575 void
1576 ldns_resolver_nameservers_randomize(ldns_resolver *r)
1578 uint16_t i, j;
1579 ldns_rdf **ns, *tmpns;
1580 size_t *rtt, tmprtt;
1582 /* should I check for ldns_resolver_random?? */
1583 assert(r != NULL);
1585 ns = ldns_resolver_nameservers(r);
1586 rtt = ldns_resolver_rtt(r);
1587 for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
1588 j = ldns_get_random() % ldns_resolver_nameserver_count(r);
1589 tmpns = ns[i];
1590 ns[i] = ns[j];
1591 ns[j] = tmpns;
1592 tmprtt = rtt[i];
1593 rtt[i] = rtt[j];
1594 rtt[j] = tmprtt;
1596 ldns_resolver_set_nameservers(r, ns);