File Coverage

src/ldns/resolver.c
Criterion Covered Total %
statement 417 767 54.3
branch 107 326 32.8
condition n/a
subroutine n/a
pod n/a
total 524 1093 47.9


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