xref: /freebsd/contrib/ldns/resolver.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
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 = 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;
781 
782 	if(!fp) {
783 		myfp = fopen(LDNS_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 
804 	r = ldns_resolver_new();
805 	if (!r) {
806 		if(!fp) fclose(myfp);
807 		return LDNS_STATUS_MEM_ERR;
808 	}
809 
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)++;
825                         }
826 			/* and read next to prepare for further parsing */
827                         oldline = *line_nr;
828 			continue;
829 		}
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
841 	        					 */
842 							expect = i;
843 							break;
844 						}
845 					}
846 					/* no keyword recognized */
847 					if (expect == LDNS_RESOLV_KEYWORD) {
848 						/* skip line */
849 						/*
850 						ldns_resolver_deep_free(r);
851 						if(!fp) fclose(myfp);
852 						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
853 						*/
854 					}
855 				}
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;
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 					if(!fp) fclose(myfp);
872 					ldns_resolver_deep_free(r);
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 					ldns_resolver_deep_free(r);
886 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
887 				}
888                                 if(word[0] == '#') {
889                                         expect = LDNS_RESOLV_KEYWORD;
890                                         continue;
891                                 }
892                                 if(strchr(word, '%')) {
893                                         /* snip off interface labels,
894                                          * fe80::222:19ff:fe31:4222%eth0 */
895                                         strchr(word, '%')[0]=0;
896                                 }
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);
901 				}
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;
907 				}
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;
920 				}
921 
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;
928 				}
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;
935                                         }
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;
942 					}
943 
944 					ldns_resolver_push_searchlist(r, tmp);
945 
946 					ldns_rdf_deep_free(tmp);
947 					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
948 					    (size_t) gtr + 1);
949 				}
950 				ldns_buffer_free(b);
951 				if (expect != LDNS_RESOLV_KEYWORD) {
952 					gtr = 1;
953 					expect = LDNS_RESOLV_KEYWORD;
954 				}
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;
973 				}
974                                 if(word[0] == '#') {
975                                         expect = LDNS_RESOLV_KEYWORD;
976                                         continue;
977                                 }
978 
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;
986 		}
987 	}
988 
989 	if(!fp)
990 		fclose(myfp);
991 
992 	if (res) {
993 		*res = r;
994 		return LDNS_STATUS_OK;
995 	} else {
996 		ldns_resolver_deep_free(r);
997 		return LDNS_STATUS_NULL;
998 	}
999 }
1000 
1001 ldns_status
1002 ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
1003 {
1004 	ldns_resolver *r;
1005 	FILE *fp;
1006 	ldns_status s;
1007 
1008 	if (!filename) {
1009 		fp = fopen(LDNS_RESOLV_CONF, "r");
1010 
1011 	} else {
1012 		fp = fopen(filename, "r");
1013 	}
1014 	if (!fp) {
1015 		return LDNS_STATUS_FILE_ERR;
1016 	}
1017 
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;
1027 		}
1028 	}
1029 	return s;
1030 }
1031 
1032 void
1033 ldns_resolver_free(ldns_resolver *res)
1034 {
1035 	LDNS_FREE(res);
1036 }
1037 
1038 void
1039 ldns_resolver_deep_free(ldns_resolver *res)
1040 {
1041 	size_t i;
1042 
1043 	if (res) {
1044 		close_socket(res->_socket);
1045 
1046 		if (res->_searchlist) {
1047 			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
1048 				ldns_rdf_deep_free(res->_searchlist[i]);
1049 			}
1050 			LDNS_FREE(res->_searchlist);
1051 		}
1052 		if (res->_nameservers) {
1053 			for (i = 0; i < res->_nameserver_count; i++) {
1054 				ldns_rdf_deep_free(res->_nameservers[i]);
1055 			}
1056 			LDNS_FREE(res->_nameservers);
1057 		}
1058 		if (ldns_resolver_domain(res)) {
1059 			ldns_rdf_deep_free(ldns_resolver_domain(res));
1060 		}
1061 		if (res->_tsig_keyname) {
1062 			LDNS_FREE(res->_tsig_keyname);
1063 		}
1064 		if (res->_tsig_keydata) {
1065 			LDNS_FREE(res->_tsig_keydata);
1066 		}
1067 		if (res->_tsig_algorithm) {
1068 			LDNS_FREE(res->_tsig_algorithm);
1069 		}
1070 
1071 		if (res->_cur_axfr_pkt) {
1072 			ldns_pkt_free(res->_cur_axfr_pkt);
1073 		}
1074 
1075 		if (res->_rtt) {
1076 			LDNS_FREE(res->_rtt);
1077 		}
1078 		if (res->_dnssec_anchors) {
1079 			ldns_rr_list_deep_free(res->_dnssec_anchors);
1080 		}
1081 		LDNS_FREE(res);
1082 	}
1083 }
1084 
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)
1089 {
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 *)"" };
1095 
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]);
1108 			}
1109 
1110 			s = ldns_resolver_query_status(pkt, r,
1111 					new_name, t, c, flags);
1112 			ldns_rdf_deep_free(new_name);
1113 
1114 			if (pkt && *pkt) {
1115 				if (s == LDNS_STATUS_OK &&
1116 						ldns_pkt_get_rcode(*pkt) ==
1117 						LDNS_RCODE_NOERROR) {
1118 
1119 					return LDNS_STATUS_OK;
1120 				}
1121 				ldns_pkt_free(*pkt);
1122 				*pkt = NULL;
1123 			}
1124 		}
1125 	}
1126 	return s;
1127 }
1128 
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)
1132 {
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;
1138 	}
1139 	return pkt;
1140 }
1141 
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)
1146 {
1147 	ldns_rdf *newname;
1148 	ldns_status status;
1149 
1150 	if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
1151 		return ldns_resolver_send(pkt, r, name, t, c, flags);
1152 	}
1153 
1154 	newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
1155 	if (!newname) {
1156 		return LDNS_STATUS_MEM_ERR;
1157 	}
1158 	status = ldns_resolver_send(pkt, r, newname, t, c, flags);
1159 	ldns_rdf_free(newname);
1160 	return status;
1161 }
1162 
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)
1166 {
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;
1172 	}
1173 	return pkt;
1174 }
1175 
1176 static size_t *
1177 ldns_resolver_backup_rtt(ldns_resolver *r)
1178 {
1179 	size_t *new_rtt;
1180 	size_t *old_rtt = ldns_resolver_rtt(r);
1181 
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;
1190 	}
1191 	return NULL;
1192 }
1193 
1194 static void
1195 ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
1196 {
1197 	size_t *cur_rtt = ldns_resolver_rtt(r);
1198 
1199 	if (cur_rtt) {
1200 		LDNS_FREE(cur_rtt);
1201 	}
1202 	ldns_resolver_set_rtt(r, old_rtt);
1203 }
1204 
1205 ldns_status
1206 ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1207 				   ldns_pkt *query_pkt)
1208 {
1209 	ldns_pkt *answer_pkt = NULL;
1210 	ldns_status stat = LDNS_STATUS_OK;
1211 	size_t *rtt;
1212 
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;
1218 		}
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.
1237 					 */
1238 					rtt = ldns_resolver_backup_rtt(r);
1239 					stat = ldns_send(&answer_pkt, r
1240 							, query_pkt);
1241 					ldns_resolver_restore_rtt(r, rtt);
1242 				}
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);
1251 				}
1252 			}
1253 		}
1254 	}
1255 
1256 	if (answer && answer_pkt) {
1257 		*answer = answer_pkt;
1258 	}
1259 
1260 	return stat;
1261 }
1262 
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)
1267 {
1268 	struct timeval now;
1269 	ldns_rr* soa = NULL;
1270 
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();
1283 
1284 		if (!soa) {
1285 			return LDNS_STATUS_ERR;
1286 		}
1287 		owner_rdf = ldns_rdf_clone(name);
1288 		if (!owner_rdf) {
1289 			ldns_rr_free(soa);
1290 			return LDNS_STATUS_ERR;
1291 		}
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);
1329 
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);
1334 	}
1335 	if (!*query_pkt) {
1336 		ldns_rr_free(soa);
1337 		return LDNS_STATUS_ERR;
1338 	}
1339 
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);
1344 		}
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);
1348 		}
1349 	}
1350 
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));
1354 	}
1355 
1356 	/* set the timestamp */
1357 	now.tv_sec = time(NULL);
1358 	now.tv_usec = 0;
1359 	ldns_pkt_set_timestamp(*query_pkt, now);
1360 
1361 
1362 	if (ldns_resolver_debug(r)) {
1363 		ldns_pkt_print(stdout, *query_pkt);
1364 	}
1365 
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);
1369 	}
1370 
1371 	return LDNS_STATUS_OK;
1372 }
1373 
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)
1377 {
1378 	ldns_pkt *query_pkt;
1379 	ldns_pkt *answer_pkt;
1380 	ldns_status status;
1381 
1382 	assert(r != NULL);
1383 	assert(name != NULL);
1384 
1385 	answer_pkt = NULL;
1386 
1387 	/* do all the preprocessing here, then fire of an query to
1388 	 * the network */
1389 
1390 	if (0 == t) {
1391 		t= LDNS_RR_TYPE_A;
1392 	}
1393 	if (0 == c) {
1394 		c= LDNS_RR_CLASS_IN;
1395 	}
1396 	if (0 == ldns_resolver_nameserver_count(r)) {
1397 		return LDNS_STATUS_RES_NO_NS;
1398 	}
1399 	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1400 		return LDNS_STATUS_RES_QUERY;
1401 	}
1402 
1403 	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1404 	                                         t, c, flags);
1405 	if (status != LDNS_STATUS_OK) {
1406 		return status;
1407 	}
1408 
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?
1414 	*/
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;
1424 		}
1425 #else
1426 		ldns_pkt_free(query_pkt);
1427 	        return LDNS_STATUS_CRYPTO_TSIG_ERR;
1428 #endif /* HAVE_SSL */
1429 	}
1430 
1431 	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1432 	ldns_pkt_free(query_pkt);
1433 
1434 	/* allows answer to be NULL when not interested in return value */
1435 	if (answer) {
1436 		*answer = answer_pkt;
1437 	}
1438 	return status;
1439 }
1440 
1441 ldns_rr *
1442 ldns_axfr_next(ldns_resolver *resolver)
1443 {
1444 	ldns_rr *cur_rr;
1445 	uint8_t *packet_wire;
1446 	size_t packet_wire_size;
1447 	ldns_status status;
1448 
1449 	/* check if start() has been called */
1450 	if (!resolver || resolver->_socket == -1) {
1451 		return NULL;
1452 	}
1453 
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);
1459 		}
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) {
1467 
1468 				close_socket(resolver->_socket);
1469 
1470 				ldns_pkt_free(resolver->_cur_axfr_pkt);
1471 				resolver->_cur_axfr_pkt = NULL;
1472 			}
1473 		}
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;
1479 
1480 		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1481 				     packet_wire_size);
1482 		LDNS_FREE(packet_wire);
1483 
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
1490 
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 */
1494 
1495 			close_socket(resolver->_socket);
1496 
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));
1510 			}
1511 #endif
1512 
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 */
1516 
1517 			close_socket(resolver->_socket);
1518 
1519 			return NULL;
1520 		} else {
1521 			return ldns_axfr_next(resolver);
1522 		}
1523 
1524 	}
1525 
1526 }
1527 
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
1532  */
1533 void
1534 ldns_axfr_abort(ldns_resolver *resolver)
1535 {
1536 	/* Only abort if an actual AXFR is in progress */
1537 	if (resolver->_socket != -1)
1538 	{
1539 #ifndef USE_WINSOCK
1540 		close(resolver->_socket);
1541 #else
1542 		closesocket(resolver->_socket);
1543 #endif
1544 		resolver->_socket = -1;
1545 	}
1546 }
1547 
1548 bool
1549 ldns_axfr_complete(const ldns_resolver *res)
1550 {
1551 	/* complete when soa count is 2? */
1552 	return res->_axfr_soa_count == 2;
1553 }
1554 
1555 ldns_pkt *
1556 ldns_axfr_last_pkt(const ldns_resolver *res)
1557 {
1558 	return res->_cur_axfr_pkt;
1559 }
1560 
1561 void
1562 ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial)
1563 {
1564 	r->_serial = serial;
1565 }
1566 
1567 uint32_t
1568 ldns_resolver_get_ixfr_serial(const ldns_resolver *res)
1569 {
1570 	return res->_serial;
1571 }
1572 
1573 
1574 /* random isn't really that good */
1575 void
1576 ldns_resolver_nameservers_randomize(ldns_resolver *r)
1577 {
1578 	uint16_t i, j;
1579 	ldns_rdf **ns, *tmpns;
1580 	size_t *rtt, tmprtt;
1581 
1582 	/* should I check for ldns_resolver_random?? */
1583 	assert(r != NULL);
1584 
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;
1595 	}
1596 	ldns_resolver_set_nameservers(r, ns);
1597 }
1598 
1599