xref: /dragonfly/contrib/ldns/resolver.c (revision fcf53d9b)
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 uint16_t
30 ldns_resolver_edns_udp_size(const ldns_resolver *r)
31 {
32 	        return r->_edns_udp_size;
33 }
34 
35 uint8_t
36 ldns_resolver_retry(const ldns_resolver *r)
37 {
38 	return r->_retry;
39 }
40 
41 uint8_t
42 ldns_resolver_retrans(const ldns_resolver *r)
43 {
44 	return r->_retrans;
45 }
46 
47 bool
48 ldns_resolver_fallback(const ldns_resolver *r)
49 {
50 	return r->_fallback;
51 }
52 
53 uint8_t
54 ldns_resolver_ip6(const ldns_resolver *r)
55 {
56 	return r->_ip6;
57 }
58 
59 bool
60 ldns_resolver_recursive(const ldns_resolver *r)
61 {
62 	return r->_recursive;
63 }
64 
65 bool
66 ldns_resolver_debug(const ldns_resolver *r)
67 {
68 	return r->_debug;
69 }
70 
71 bool
72 ldns_resolver_dnsrch(const ldns_resolver *r)
73 {
74 	return r->_dnsrch;
75 }
76 
77 bool
78 ldns_resolver_fail(const ldns_resolver *r)
79 {
80 	return r->_fail;
81 }
82 
83 bool
84 ldns_resolver_defnames(const ldns_resolver *r)
85 {
86 	return r->_defnames;
87 }
88 
89 ldns_rdf *
90 ldns_resolver_domain(const ldns_resolver *r)
91 {
92 	return r->_domain;
93 }
94 
95 ldns_rdf **
96 ldns_resolver_searchlist(const ldns_resolver *r)
97 {
98 	return r->_searchlist;
99 }
100 
101 ldns_rdf **
102 ldns_resolver_nameservers(const ldns_resolver *r)
103 {
104 	return r->_nameservers;
105 }
106 
107 size_t
108 ldns_resolver_nameserver_count(const ldns_resolver *r)
109 {
110 	return r->_nameserver_count;
111 }
112 
113 bool
114 ldns_resolver_dnssec(const ldns_resolver *r)
115 {
116 	return r->_dnssec;
117 }
118 
119 bool
120 ldns_resolver_dnssec_cd(const ldns_resolver *r)
121 {
122 	return r->_dnssec_cd;
123 }
124 
125 ldns_rr_list *
126 ldns_resolver_dnssec_anchors(const ldns_resolver *r)
127 {
128     return r->_dnssec_anchors;
129 }
130 
131 bool
132 ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
133 {
134   size_t i;
135   bool result = false;
136 
137   ldns_rr_list * trust_anchors;
138   ldns_rr * cur_rr;
139 
140   if (!r || !keys) { return false; }
141 
142   trust_anchors = ldns_resolver_dnssec_anchors(r);
143 
144   if (!trust_anchors) { return false; }
145 
146   for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
147 
148     cur_rr = ldns_rr_list_rr(keys, i);
149     if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
150       if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
151       result = true;
152     }
153   }
154 
155   return result;
156 }
157 
158 bool
159 ldns_resolver_igntc(const ldns_resolver *r)
160 {
161 	return r->_igntc;
162 }
163 
164 bool
165 ldns_resolver_usevc(const ldns_resolver *r)
166 {
167 	return r->_usevc;
168 }
169 
170 size_t *
171 ldns_resolver_rtt(const ldns_resolver *r)
172 {
173 	return r->_rtt;
174 }
175 
176 size_t
177 ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
178 {
179 	size_t *rtt;
180 
181 	assert(r != NULL);
182 
183 	rtt = ldns_resolver_rtt(r);
184 
185 	if (pos >= ldns_resolver_nameserver_count(r)) {
186 		/* error ?*/
187 		return 0;
188 	} else {
189 		return rtt[pos];
190 	}
191 
192 }
193 
194 struct timeval
195 ldns_resolver_timeout(const ldns_resolver *r)
196 {
197 	return r->_timeout;
198 }
199 
200 char *
201 ldns_resolver_tsig_keyname(const ldns_resolver *r)
202 {
203 	return r->_tsig_keyname;
204 }
205 
206 char *
207 ldns_resolver_tsig_algorithm(const ldns_resolver *r)
208 {
209 	return r->_tsig_algorithm;
210 }
211 
212 char *
213 ldns_resolver_tsig_keydata(const ldns_resolver *r)
214 {
215 	return r->_tsig_keydata;
216 }
217 
218 bool
219 ldns_resolver_random(const ldns_resolver *r)
220 {
221 	return r->_random;
222 }
223 
224 size_t
225 ldns_resolver_searchlist_count(const ldns_resolver *r)
226 {
227 	return r->_searchlist_count;
228 }
229 
230 /* write */
231 void
232 ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
233 {
234 	r->_port = p;
235 }
236 
237 ldns_rdf *
238 ldns_resolver_pop_nameserver(ldns_resolver *r)
239 {
240 	ldns_rdf **nameservers;
241 	ldns_rdf *pop;
242 	size_t ns_count;
243 	size_t *rtt;
244 
245 	assert(r != NULL);
246 
247 	ns_count = ldns_resolver_nameserver_count(r);
248 	nameservers = ldns_resolver_nameservers(r);
249 	rtt = ldns_resolver_rtt(r);
250 	if (ns_count == 0 || !nameservers) {
251 		return NULL;
252 	}
253 
254 	pop = nameservers[ns_count - 1];
255 
256 	nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count - 1));
257 	rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
258 
259 	ldns_resolver_set_nameservers(r, nameservers);
260 	ldns_resolver_set_rtt(r, rtt);
261 	/* decr the count */
262 	ldns_resolver_dec_nameserver_count(r);
263 	return pop;
264 }
265 
266 ldns_status
267 ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
268 {
269 	ldns_rdf **nameservers;
270 	size_t ns_count;
271 	size_t *rtt;
272 
273 	if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
274 			ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
275 		return LDNS_STATUS_ERR;
276 	}
277 
278 	ns_count = ldns_resolver_nameserver_count(r);
279 	nameservers = ldns_resolver_nameservers(r);
280 	rtt = ldns_resolver_rtt(r);
281 
282 	/* make room for the next one */
283 	nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
284 	/* don't forget the rtt */
285 	rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
286 
287 	/* set the new value in the resolver */
288 	ldns_resolver_set_nameservers(r, nameservers);
289 
290 	/* slide n in its slot. */
291 	/* we clone it here, because then we can free the original
292 	 * rr's where it stood */
293 	nameservers[ns_count] = ldns_rdf_clone(n);
294 	rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
295 	ldns_resolver_incr_nameserver_count(r);
296 	ldns_resolver_set_rtt(r, rtt);
297 	return LDNS_STATUS_OK;
298 }
299 
300 ldns_status
301 ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
302 {
303 	ldns_rdf *address;
304 	if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
305 			ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
306 		return LDNS_STATUS_ERR;
307 	}
308 	address = ldns_rr_rdf(rr, 0); /* extract the ip number */
309 	if (address) {
310 		return ldns_resolver_push_nameserver(r, address);
311 	} else {
312 		return LDNS_STATUS_ERR;
313 	}
314 }
315 
316 ldns_status
317 ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
318 {
319 	ldns_rr *rr;
320 	ldns_status stat;
321 	size_t i;
322 
323 	stat = LDNS_STATUS_OK;
324 	if (rrlist) {
325 		for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
326 			rr = ldns_rr_list_rr(rrlist, i);
327 			if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
328 				stat = LDNS_STATUS_ERR;
329 			}
330 		}
331 		return stat;
332 	} else {
333 		return LDNS_STATUS_ERR;
334 	}
335 }
336 
337 void
338 ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
339 {
340 	        r->_edns_udp_size = s;
341 }
342 
343 void
344 ldns_resolver_set_recursive(ldns_resolver *r, bool re)
345 {
346 	r->_recursive = re;
347 }
348 
349 void
350 ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
351 {
352 	r->_dnssec = d;
353 }
354 
355 void
356 ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
357 {
358 	r->_dnssec_cd = d;
359 }
360 
361 void
362 ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
363 {
364   r->_dnssec_anchors = l;
365 }
366 
367 ldns_status
368 ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
369 {
370   ldns_rr_list * trust_anchors;
371 
372   if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY)) {
373     return LDNS_STATUS_ERR;
374   }
375 
376   if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
377     trust_anchors = ldns_rr_list_new();
378     ldns_resolver_set_dnssec_anchors(r, trust_anchors);
379   }
380 
381   return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
382 }
383 
384 void
385 ldns_resolver_set_igntc(ldns_resolver *r, bool i)
386 {
387 	r->_igntc = i;
388 }
389 
390 void
391 ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
392 {
393 	r->_usevc = vc;
394 }
395 
396 void
397 ldns_resolver_set_debug(ldns_resolver *r, bool d)
398 {
399 	r->_debug = d;
400 }
401 
402 void
403 ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
404 {
405 	r->_ip6 = ip6;
406 }
407 
408 void
409 ldns_resolver_set_fail(ldns_resolver *r, bool f)
410 {
411 	r->_fail =f;
412 }
413 
414 void
415 ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
416 {
417 	r->_searchlist_count = c;
418 }
419 
420 void
421 ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
422 {
423 	r->_nameserver_count = c;
424 }
425 
426 void
427 ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
428 {
429 	r->_dnsrch = d;
430 }
431 
432 void
433 ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
434 {
435 	r->_retry = retry;
436 }
437 
438 void
439 ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
440 {
441 	r->_retrans = retrans;
442 }
443 
444 void
445 ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
446 {
447 	r->_fallback = fallback;
448 }
449 
450 void
451 ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
452 {
453 	r->_nameservers = n;
454 }
455 
456 void
457 ldns_resolver_set_defnames(ldns_resolver *r, bool d)
458 {
459 	r->_defnames = d;
460 }
461 
462 void
463 ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
464 {
465 	r->_rtt = rtt;
466 }
467 
468 void
469 ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
470 {
471 	size_t *rtt;
472 
473 	assert(r != NULL);
474 
475 	rtt = ldns_resolver_rtt(r);
476 
477 	if (pos >= ldns_resolver_nameserver_count(r)) {
478 		/* error ?*/
479 	} else {
480 		rtt[pos] = value;
481 	}
482 
483 }
484 
485 void
486 ldns_resolver_incr_nameserver_count(ldns_resolver *r)
487 {
488 	size_t c;
489 
490 	c = ldns_resolver_nameserver_count(r);
491 	ldns_resolver_set_nameserver_count(r, ++c);
492 }
493 
494 void
495 ldns_resolver_dec_nameserver_count(ldns_resolver *r)
496 {
497 	size_t c;
498 
499 	c = ldns_resolver_nameserver_count(r);
500 	if (c == 0) {
501 		return;
502 	} else {
503 		ldns_resolver_set_nameserver_count(r, --c);
504 	}
505 }
506 
507 void
508 ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
509 {
510 	r->_domain = d;
511 }
512 
513 void
514 ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
515 {
516 	r->_timeout.tv_sec = timeout.tv_sec;
517 	r->_timeout.tv_usec = timeout.tv_usec;
518 }
519 
520 void
521 ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
522 {
523 	ldns_rdf **searchlist;
524 	size_t list_count;
525 
526 	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
527 		return;
528 	}
529 
530 	list_count = ldns_resolver_searchlist_count(r);
531 	searchlist = ldns_resolver_searchlist(r);
532 
533 	searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
534 	if (searchlist) {
535 		r->_searchlist = searchlist;
536 
537 		searchlist[list_count] = ldns_rdf_clone(d);
538 		ldns_resolver_set_searchlist_count(r, list_count + 1);
539 	}
540 }
541 
542 void
543 ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
544 {
545 	LDNS_FREE(r->_tsig_keyname);
546 	r->_tsig_keyname = strdup(tsig_keyname);
547 }
548 
549 void
550 ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
551 {
552 	LDNS_FREE(r->_tsig_algorithm);
553 	r->_tsig_algorithm = strdup(tsig_algorithm);
554 }
555 
556 void
557 ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
558 {
559 	LDNS_FREE(r->_tsig_keydata);
560 	r->_tsig_keydata = strdup(tsig_keydata);
561 }
562 
563 void
564 ldns_resolver_set_random(ldns_resolver *r, bool b)
565 {
566 	r->_random = b;
567 }
568 
569 /* more sophisticated functions */
570 ldns_resolver *
571 ldns_resolver_new(void)
572 {
573 	ldns_resolver *r;
574 
575 	r = LDNS_MALLOC(ldns_resolver);
576 	if (!r) {
577 		return NULL;
578 	}
579 
580 	r->_searchlist = NULL;
581 	r->_nameservers = NULL;
582 	r->_rtt = NULL;
583 
584 	/* defaults are filled out */
585 	ldns_resolver_set_searchlist_count(r, 0);
586 	ldns_resolver_set_nameserver_count(r, 0);
587 	ldns_resolver_set_usevc(r, 0);
588 	ldns_resolver_set_port(r, LDNS_PORT);
589 	ldns_resolver_set_domain(r, NULL);
590 	ldns_resolver_set_defnames(r, false);
591 	ldns_resolver_set_retry(r, 3);
592 	ldns_resolver_set_retrans(r, 2);
593 	ldns_resolver_set_fallback(r, true);
594 	ldns_resolver_set_fail(r, false);
595 	ldns_resolver_set_edns_udp_size(r, 0);
596 	ldns_resolver_set_dnssec(r, false);
597 	ldns_resolver_set_dnssec_cd(r, false);
598 	ldns_resolver_set_dnssec_anchors(r, NULL);
599 	ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
600 	ldns_resolver_set_igntc(r, false);
601 	ldns_resolver_set_recursive(r, false);
602 	ldns_resolver_set_dnsrch(r, true);
603 
604 	/* randomize the nameserver to be queried
605 	 * when there are multiple
606 	 */
607 	ldns_resolver_set_random(r, true);
608 
609 	ldns_resolver_set_debug(r, 0);
610 
611 	r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
612 	r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
613 
614 	/* TODO: fd=0 is actually a valid socket (stdin),
615            replace with -1 */
616 	r->_socket = 0;
617 	r->_axfr_soa_count = 0;
618 	r->_axfr_i = 0;
619 	r->_cur_axfr_pkt = NULL;
620 
621 	r->_tsig_keyname = NULL;
622 	r->_tsig_keydata = NULL;
623 	r->_tsig_algorithm = NULL;
624 	return r;
625 }
626 
627 ldns_status
628 ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
629 {
630 	return ldns_resolver_new_frm_fp_l(res, fp, NULL);
631 }
632 
633 ldns_status
634 ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
635 {
636 	ldns_resolver *r;
637 	const char *keyword[LDNS_RESOLV_KEYWORDS];
638 	char word[LDNS_MAX_LINELEN + 1];
639 	int8_t expect;
640 	uint8_t i;
641 	ldns_rdf *tmp;
642 #ifdef HAVE_SSL
643 	ldns_rr *tmp_rr;
644 #endif
645 	ssize_t gtr, bgtr;
646 	ldns_buffer *b;
647         int lnr = 0, oldline;
648         if(!line_nr) line_nr = &lnr;
649 
650 	/* do this better
651 	 * expect =
652 	 * 0: keyword
653 	 * 1: default domain dname
654 	 * 2: NS aaaa or a record
655 	 */
656 
657 	/* recognized keywords */
658 	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
659 	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
660 	keyword[LDNS_RESOLV_SEARCH] = "search";
661 	/* these two are read but not used atm TODO */
662 	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
663 	keyword[LDNS_RESOLV_OPTIONS] = "options";
664 	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
665 	expect = LDNS_RESOLV_KEYWORD;
666 
667 	r = ldns_resolver_new();
668 	if (!r) {
669 		return LDNS_STATUS_MEM_ERR;
670 	}
671 
672 	gtr = 1;
673 	word[0] = 0;
674         oldline = *line_nr;
675         expect = LDNS_RESOLV_KEYWORD;
676 	while (gtr > 0) {
677 		/* check comments */
678 		if (word[0] == '#') {
679                         word[0]='x';
680                         if(oldline == *line_nr) {
681                                 /* skip until end of line */
682                                 int c;
683                                 do {
684                                         c = fgetc(fp);
685                                 } while(c != EOF && c != '\n');
686                                 if(c=='\n' && line_nr) (*line_nr)++;
687                         }
688 			/* and read next to prepare for further parsing */
689                         oldline = *line_nr;
690 			continue;
691 		}
692                 oldline = *line_nr;
693 		switch(expect) {
694 			case LDNS_RESOLV_KEYWORD:
695 				/* keyword */
696 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
697 				if (gtr != 0) {
698                                         if(word[0] == '#') continue;
699 					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
700 						if (strcasecmp(keyword[i], word) == 0) {
701 							/* chosen the keyword and
702 							 * expect values carefully
703 	        					 */
704 							expect = i;
705 							break;
706 						}
707 					}
708 					/* no keyword recognized */
709 					if (expect == LDNS_RESOLV_KEYWORD) {
710 						/* skip line */
711 						/*
712 						ldns_resolver_deep_free(r);
713 						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
714 						*/
715 					}
716 				}
717 				break;
718 			case LDNS_RESOLV_DEFDOMAIN:
719 				/* default domain dname */
720 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
721 				if (gtr == 0) {
722 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
723 				}
724                                 if(word[0] == '#') {
725                                         expect = LDNS_RESOLV_KEYWORD;
726                                         continue;
727                                 }
728 				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
729 				if (!tmp) {
730 					ldns_resolver_deep_free(r);
731 					return LDNS_STATUS_SYNTAX_DNAME_ERR;
732 				}
733 
734 				/* DOn't free, because we copy the pointer */
735 				ldns_resolver_set_domain(r, tmp);
736 				expect = LDNS_RESOLV_KEYWORD;
737 				break;
738 			case LDNS_RESOLV_NAMESERVER:
739 				/* NS aaaa or a record */
740 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
741 				if (gtr == 0) {
742 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
743 				}
744                                 if(word[0] == '#') {
745                                         expect = LDNS_RESOLV_KEYWORD;
746                                         continue;
747                                 }
748                                 if(strchr(word, '%')) {
749                                         /* snip off interface labels,
750                                          * fe80::222:19ff:fe31:4222%eth0 */
751                                         strchr(word, '%')[0]=0;
752                                 }
753 				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
754 				if (!tmp) {
755 					/* try ip4 */
756 					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
757 				}
758 				/* could not parse it, exit */
759 				if (!tmp) {
760 					ldns_resolver_deep_free(r);
761 					return LDNS_STATUS_SYNTAX_ERR;
762 				}
763 				(void)ldns_resolver_push_nameserver(r, tmp);
764 				ldns_rdf_deep_free(tmp);
765 				expect = LDNS_RESOLV_KEYWORD;
766 				break;
767 			case LDNS_RESOLV_SEARCH:
768 				/* search list domain dname */
769 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
770 				b = LDNS_MALLOC(ldns_buffer);
771 				if(!b) {
772 					ldns_resolver_deep_free(r);
773 					return LDNS_STATUS_MEM_ERR;
774 				}
775 
776 				ldns_buffer_new_frm_data(b, word, (size_t) gtr);
777 				if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
778 					LDNS_FREE(b);
779 					ldns_resolver_deep_free(r);
780 					return LDNS_STATUS_MEM_ERR;
781 				}
782 				bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
783 				while (bgtr > 0) {
784 					gtr -= bgtr;
785                                         if(word[0] == '#') {
786                                                 expect = LDNS_RESOLV_KEYWORD;
787 						ldns_buffer_free(b);
788                                                 continue;
789                                         }
790 					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
791 					if (!tmp) {
792 						ldns_resolver_deep_free(r);
793 						ldns_buffer_free(b);
794 						return LDNS_STATUS_SYNTAX_DNAME_ERR;
795 					}
796 
797 					ldns_resolver_push_searchlist(r, tmp);
798 
799 					ldns_rdf_deep_free(tmp);
800 					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
801 					    (size_t) gtr + 1);
802 				}
803 				ldns_buffer_free(b);
804 				gtr = 1;
805 				expect = LDNS_RESOLV_KEYWORD;
806 				break;
807 			case LDNS_RESOLV_SORTLIST:
808 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
809 				/* sortlist not implemented atm */
810 				expect = LDNS_RESOLV_KEYWORD;
811 				break;
812 			case LDNS_RESOLV_OPTIONS:
813 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
814 				/* options not implemented atm */
815 				expect = LDNS_RESOLV_KEYWORD;
816 				break;
817 			case LDNS_RESOLV_ANCHOR:
818 				/* a file containing a DNSSEC trust anchor */
819 				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
820 				if (gtr == 0) {
821 					ldns_resolver_deep_free(r);
822 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
823 				}
824                                 if(word[0] == '#') {
825                                         expect = LDNS_RESOLV_KEYWORD;
826                                         continue;
827                                 }
828 
829 #ifdef HAVE_SSL
830 				tmp_rr = ldns_read_anchor_file(word);
831 				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
832 				ldns_rr_free(tmp_rr);
833 #endif
834 				expect = LDNS_RESOLV_KEYWORD;
835 				break;
836 		}
837 	}
838 
839 	if (res) {
840 		*res = r;
841 		return LDNS_STATUS_OK;
842 	} else {
843 		ldns_resolver_deep_free(r);
844 		return LDNS_STATUS_NULL;
845 	}
846 }
847 
848 ldns_status
849 ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
850 {
851 	ldns_resolver *r;
852 	FILE *fp;
853 	ldns_status s;
854 
855 	if (!filename) {
856 		fp = fopen(LDNS_RESOLV_CONF, "r");
857 
858 	} else {
859 		fp = fopen(filename, "r");
860 	}
861 	if (!fp) {
862 		return LDNS_STATUS_FILE_ERR;
863 	}
864 
865 	s = ldns_resolver_new_frm_fp(&r, fp);
866 	fclose(fp);
867 	if (s == LDNS_STATUS_OK) {
868 		if (res) {
869 			*res = r;
870 			return LDNS_STATUS_OK;
871 		} else  {
872 			return LDNS_STATUS_NULL;
873 		}
874 	}
875 	return s;
876 }
877 
878 void
879 ldns_resolver_free(ldns_resolver *res)
880 {
881 	LDNS_FREE(res);
882 }
883 
884 void
885 ldns_resolver_deep_free(ldns_resolver *res)
886 {
887 	size_t i;
888 
889 	if (res) {
890 		if (res->_searchlist) {
891 			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
892 				ldns_rdf_deep_free(res->_searchlist[i]);
893 			}
894 			LDNS_FREE(res->_searchlist);
895 		}
896 		if (res->_nameservers) {
897 			for (i = 0; i < res->_nameserver_count; i++) {
898 				ldns_rdf_deep_free(res->_nameservers[i]);
899 			}
900 			LDNS_FREE(res->_nameservers);
901 		}
902 		if (ldns_resolver_domain(res)) {
903 			ldns_rdf_deep_free(ldns_resolver_domain(res));
904 		}
905 		if (res->_tsig_keyname) {
906 			LDNS_FREE(res->_tsig_keyname);
907 		}
908 		if (res->_tsig_keydata) {
909 			LDNS_FREE(res->_tsig_keydata);
910 		}
911 		if (res->_tsig_algorithm) {
912 			LDNS_FREE(res->_tsig_algorithm);
913 		}
914 
915 		if (res->_cur_axfr_pkt) {
916 			ldns_pkt_free(res->_cur_axfr_pkt);
917 		}
918 
919 		if (res->_rtt) {
920 			LDNS_FREE(res->_rtt);
921 		}
922 		if (res->_dnssec_anchors) {
923 			ldns_rr_list_deep_free(res->_dnssec_anchors);
924 		}
925 		LDNS_FREE(res);
926 	}
927 }
928 
929 ldns_pkt *
930 ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
931 	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
932 {
933 
934 	char *str_dname;
935 	ldns_rdf *new_name;
936 	ldns_rdf **search_list;
937 	size_t i;
938 	ldns_pkt *p;
939 
940 	str_dname = ldns_rdf2str(name);
941 
942 	if (ldns_dname_str_absolute(str_dname)) {
943 		/* query as-is */
944 		return ldns_resolver_query(r, name, t, c, flags);
945 	} else if (ldns_resolver_dnsrch(r)) {
946 		search_list = ldns_resolver_searchlist(r);
947 		for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
948 			new_name = ldns_dname_cat_clone(name, search_list[i]);
949 
950 			p = ldns_resolver_query(r, new_name, t, c, flags);
951 			ldns_rdf_free(new_name);
952 			if (p) {
953 				if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) {
954 					return p;
955 				} else {
956 					ldns_pkt_free(p);
957 					p = NULL;
958 				}
959 			}
960 		}
961 	}
962 	return NULL;
963 }
964 
965 ldns_pkt *
966 ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
967 	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
968 {
969 	ldns_rdf *newname;
970 	ldns_pkt *pkt;
971 	ldns_status status;
972 
973 	pkt = NULL;
974 
975 	if (!ldns_resolver_defnames(r)) {
976 		status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name,
977 				t, c, flags);
978 		if (status == LDNS_STATUS_OK) {
979 			return pkt;
980 		} else {
981 			if (pkt) {
982 				ldns_pkt_free(pkt);
983 			}
984 			return NULL;
985 		}
986 	}
987 
988 	if (!ldns_resolver_domain(r)) {
989 		/* _defnames is set, but the domain is not....?? */
990 		status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name,
991 				t, c, flags);
992 		if (status == LDNS_STATUS_OK) {
993 			return pkt;
994 		} else {
995 			if (pkt) {
996 				ldns_pkt_free(pkt);
997 			}
998 			return NULL;
999 		}
1000 	}
1001 
1002 	newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r));
1003 	if (!newname) {
1004 		if (pkt) {
1005 			ldns_pkt_free(pkt);
1006 		}
1007 		return NULL;
1008 	}
1009 
1010 	(void)ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c,
1011 			flags);
1012 
1013 	ldns_rdf_free(newname);
1014 
1015 	return pkt;
1016 }
1017 
1018 ldns_status
1019 ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
1020 				   ldns_pkt *query_pkt)
1021 {
1022 	ldns_pkt *answer_pkt = NULL;
1023 	ldns_status stat = LDNS_STATUS_OK;
1024 
1025 	stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
1026 	if (stat != LDNS_STATUS_OK) {
1027 		if(answer_pkt) {
1028 			ldns_pkt_free(answer_pkt);
1029 			answer_pkt = NULL;
1030 		}
1031 	} else {
1032 		/* if tc=1 fall back to EDNS and/or TCP */
1033 		/* check for tcp first (otherwise we don't care about tc=1) */
1034 		if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
1035 			if (ldns_pkt_tc(answer_pkt)) {
1036 				/* was EDNS0 set? */
1037 				if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
1038 					ldns_pkt_set_edns_udp_size(query_pkt, 4096);
1039 					ldns_pkt_free(answer_pkt);
1040 					stat = ldns_send(&answer_pkt, r, query_pkt);
1041 				}
1042 				/* either way, if it is still truncated, use TCP */
1043 				if (stat != LDNS_STATUS_OK ||
1044 				    ldns_pkt_tc(answer_pkt)) {
1045 					ldns_resolver_set_usevc(r, true);
1046 					ldns_pkt_free(answer_pkt);
1047 					stat = ldns_send(&answer_pkt, r, query_pkt);
1048 					ldns_resolver_set_usevc(r, false);
1049 				}
1050 			}
1051 		}
1052 	}
1053 
1054 	if (answer) {
1055 		*answer = answer_pkt;
1056 	}
1057 
1058 	return stat;
1059 }
1060 
1061 ldns_status
1062 ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
1063                                 const ldns_rdf *name, ldns_rr_type t,
1064                                 ldns_rr_class c, uint16_t flags)
1065 {
1066 	/* prepare a question pkt from the parameters
1067 	 * and then send this */
1068 	*query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
1069 	if (!*query_pkt) {
1070 		return LDNS_STATUS_ERR;
1071 	}
1072 
1073 	/* set DO bit if necessary */
1074 	if (ldns_resolver_dnssec(r)) {
1075 		if (ldns_resolver_edns_udp_size(r) == 0) {
1076 			ldns_resolver_set_edns_udp_size(r, 4096);
1077 		}
1078 		ldns_pkt_set_edns_do(*query_pkt, true);
1079 		if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
1080 			ldns_pkt_set_cd(*query_pkt, true);
1081 		}
1082 	}
1083 
1084 	/* transfer the udp_edns_size from the resolver to the packet */
1085 	if (ldns_resolver_edns_udp_size(r) != 0) {
1086 		ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
1087 	}
1088 
1089 	if (ldns_resolver_debug(r)) {
1090 		ldns_pkt_print(stdout, *query_pkt);
1091 	}
1092 
1093 	/* only set the id if it is not set yet */
1094 	if (ldns_pkt_id(*query_pkt) == 0) {
1095 		ldns_pkt_set_random_id(*query_pkt);
1096 	}
1097 
1098 	return LDNS_STATUS_OK;
1099 }
1100 
1101 
1102 ldns_status
1103 ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
1104 		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1105 {
1106 	ldns_pkt *query_pkt;
1107 	ldns_pkt *answer_pkt;
1108 	ldns_status status;
1109 
1110 	assert(r != NULL);
1111 	assert(name != NULL);
1112 
1113 	answer_pkt = NULL;
1114 
1115 	/* do all the preprocessing here, then fire of an query to
1116 	 * the network */
1117 
1118 	if (0 == t) {
1119 		t= LDNS_RR_TYPE_A;
1120 	}
1121 	if (0 == c) {
1122 		c= LDNS_RR_CLASS_IN;
1123 	}
1124 	if (0 == ldns_resolver_nameserver_count(r)) {
1125 		return LDNS_STATUS_RES_NO_NS;
1126 	}
1127 	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
1128 		return LDNS_STATUS_RES_QUERY;
1129 	}
1130 
1131 	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
1132 	                                         t, c, flags);
1133 	if (status != LDNS_STATUS_OK) {
1134 		return status;
1135 	}
1136 
1137 	/* if tsig values are set, tsign it */
1138 	/* TODO: make last 3 arguments optional too? maybe make complete
1139 	         rr instead of seperate values in resolver (and packet)
1140 	  Jelte
1141 	  should this go in pkt_prepare?
1142 	*/
1143 #ifdef HAVE_SSL
1144 	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
1145 		status = ldns_pkt_tsig_sign(query_pkt,
1146 		                            ldns_resolver_tsig_keyname(r),
1147 		                            ldns_resolver_tsig_keydata(r),
1148 		                            300, ldns_resolver_tsig_algorithm(r), NULL);
1149 		if (status != LDNS_STATUS_OK) {
1150 			return LDNS_STATUS_CRYPTO_TSIG_ERR;
1151 		}
1152 	}
1153 #else
1154 	return LDNS_STATUS_CRYPTO_TSIG_ERR;
1155 #endif /* HAVE_SSL */
1156 
1157 	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
1158 	ldns_pkt_free(query_pkt);
1159 
1160 	/* allows answer to be NULL when not interested in return value */
1161 	if (answer) {
1162 		*answer = answer_pkt;
1163 	}
1164 	return status;
1165 }
1166 
1167 ldns_rr *
1168 ldns_axfr_next(ldns_resolver *resolver)
1169 {
1170 	ldns_rr *cur_rr;
1171 	uint8_t *packet_wire;
1172 	size_t packet_wire_size;
1173 	ldns_lookup_table *rcode;
1174 	ldns_status status;
1175 
1176 	/* check if start() has been called */
1177 	if (!resolver || resolver->_socket == 0) {
1178 		return NULL;
1179 	}
1180 
1181 	if (resolver->_cur_axfr_pkt) {
1182 		if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
1183 			ldns_pkt_free(resolver->_cur_axfr_pkt);
1184 			resolver->_cur_axfr_pkt = NULL;
1185 			return ldns_axfr_next(resolver);
1186 		}
1187 		cur_rr = ldns_rr_clone(ldns_rr_list_rr(
1188 					ldns_pkt_answer(resolver->_cur_axfr_pkt),
1189 					resolver->_axfr_i));
1190 		resolver->_axfr_i++;
1191 		if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
1192 			resolver->_axfr_soa_count++;
1193 			if (resolver->_axfr_soa_count >= 2) {
1194 #ifndef USE_WINSOCK
1195 				close(resolver->_socket);
1196 #else
1197 				closesocket(resolver->_socket);
1198 #endif
1199 				resolver->_socket = 0;
1200 				ldns_pkt_free(resolver->_cur_axfr_pkt);
1201 				resolver->_cur_axfr_pkt = NULL;
1202 			}
1203 		}
1204 		return cur_rr;
1205 	} else {
1206 		packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size);
1207 		if(!packet_wire)
1208 			return NULL;
1209 
1210 		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
1211 				     packet_wire_size);
1212 		free(packet_wire);
1213 
1214 		resolver->_axfr_i = 0;
1215 		if (status != LDNS_STATUS_OK) {
1216 			/* TODO: make status return type of this function (...api change) */
1217 			fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
1218 
1219 			/* RoRi: we must now also close the socket, otherwise subsequent uses of the
1220 			   same resolver structure will fail because the link is still open or
1221 			   in an undefined state */
1222 #ifndef USE_WINSOCK
1223 			close(resolver->_socket);
1224 #else
1225 			closesocket(resolver->_socket);
1226 #endif
1227 			resolver->_socket = 0;
1228 
1229 			return NULL;
1230 		} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
1231 			rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt));
1232 			fprintf(stderr, "Error in AXFR: %s\n", rcode->name);
1233 
1234 			/* RoRi: we must now also close the socket, otherwise subsequent uses of the
1235 			   same resolver structure will fail because the link is still open or
1236 			   in an undefined state */
1237 #ifndef USE_WINSOCK
1238 			close(resolver->_socket);
1239 #else
1240 			closesocket(resolver->_socket);
1241 #endif
1242 			resolver->_socket = 0;
1243 
1244 			return NULL;
1245 		} else {
1246 			return ldns_axfr_next(resolver);
1247 		}
1248 
1249 	}
1250 
1251 }
1252 
1253 bool
1254 ldns_axfr_complete(const ldns_resolver *res)
1255 {
1256 	/* complete when soa count is 2? */
1257 	return res->_axfr_soa_count == 2;
1258 }
1259 
1260 ldns_pkt *
1261 ldns_axfr_last_pkt(const ldns_resolver *res)
1262 {
1263 	return res->_cur_axfr_pkt;
1264 }
1265 
1266 /* random isn't really that good */
1267 void
1268 ldns_resolver_nameservers_randomize(ldns_resolver *r)
1269 {
1270 	uint16_t i, j;
1271 	ldns_rdf **ns, *tmp;
1272 
1273 	/* should I check for ldns_resolver_random?? */
1274 	assert(r != NULL);
1275 
1276 	ns = ldns_resolver_nameservers(r);
1277 	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
1278 		j = ldns_get_random() % ldns_resolver_nameserver_count(r);
1279 		tmp = ns[i];
1280 		ns[i] = ns[j];
1281 		ns[j] = tmp;
1282 	}
1283 	ldns_resolver_set_nameservers(r, ns);
1284 }
1285 
1286