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