db238c372518568812c9dd459b5ce5168e159baf
[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 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