]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ldns-host/ldns-host.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ldns-host / ldns-host.c
1 /*-
2  * (c) Magerya Vitaly
3  *
4  * Copying and distribution of this file, with or without modification,
5  * are permitted in any medium without royalty provided the copyright
6  * notice and this notice are preserved. This file is offered as-is,
7  * without any warranty.
8  */
9
10 #include <netinet/in.h>
11
12 #include <limits.h>
13 #include <netdb.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17
18 #include <ldns/ldns.h>
19
20 /* General utilities.
21  */
22
23 static char *progname;
24
25 #define countof(array) (sizeof(array)/sizeof(*(array)))
26
27 static void
28 die(int code, const char *fmt, ...) {
29     va_list args;
30
31     va_start(args, fmt);
32     fprintf(stderr, "%s: ", progname);
33     vfprintf(stderr, fmt, args);
34     fprintf(stderr, "\n");
35     va_end(args);
36     exit(code);
37 }
38
39 static int
40 ndots(const char *name) {
41     int n;
42
43     for (n = 0; (name = strchr(name, '.')); n++, name++);
44     return n;
45 }
46
47 /* General LDNS-specific utilities.
48  */
49
50 static ldns_status
51 ldns_resolver_new_default(ldns_resolver **res) {
52     if (ldns_resolver_new_frm_file(res, NULL) == LDNS_STATUS_OK ||
53         (*res = ldns_resolver_new()) != NULL)
54         return LDNS_STATUS_OK;
55     return LDNS_STATUS_MEM_ERR;
56 }
57
58 static ldns_status
59 ldns_resolver_push_default_servers(ldns_resolver *res) {
60     ldns_status status;
61     ldns_rdf *addr;
62
63     if ((status = ldns_str2rdf_a(&addr, "127.0.0.1")) != LDNS_STATUS_OK ||
64         (status = ldns_resolver_push_nameserver(res, addr)) != LDNS_STATUS_OK)
65         return ldns_rdf_deep_free(addr), status;
66     ldns_rdf_deep_free(addr);
67     if ((status = ldns_str2rdf_aaaa(&addr, "::1")) != LDNS_STATUS_OK ||
68         (status = ldns_resolver_push_nameserver(res, addr)) != LDNS_STATUS_OK)
69         return ldns_rdf_deep_free(addr), status;
70     ldns_rdf_deep_free(addr);
71     return LDNS_STATUS_OK;
72 }
73
74 static ldns_rdf *
75 ldns_rdf_new_addr_frm_str(const char *str) {
76     ldns_rdf *addr;
77
78     if ((addr = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, str)) == NULL)
79         addr = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, str);
80     return addr;
81 }
82
83 static void
84 ldns_resolver_remove_nameservers(ldns_resolver *res) {
85     while (ldns_resolver_nameserver_count(res) > 0)
86         ldns_rdf_deep_free(ldns_resolver_pop_nameserver(res));
87 }
88
89 static ldns_rdf *
90 ldns_rdf_reverse_a(ldns_rdf *addr, const char *base) {
91     char *buf;
92     int i, len;
93
94     len = strlen(base);
95     buf = alloca(LDNS_IP4ADDRLEN*4 + len + 1);
96     for (len = i = 0; i < LDNS_IP4ADDRLEN; i++)
97         len += sprintf(&buf[len], "%d.",
98             (int)ldns_rdf_data(addr)[LDNS_IP4ADDRLEN - i - 1]);
99     sprintf(&buf[len], "%s", base);
100     return ldns_dname_new_frm_str(buf);
101 }
102
103 static ldns_rdf *
104 ldns_rdf_reverse_aaaa(ldns_rdf *addr, const char *base) {
105     char *buf;
106     int i, len;
107
108     len = strlen(base);
109     buf = alloca(LDNS_IP6ADDRLEN*4 + len + 1);
110     for (i = 0; i < LDNS_IP6ADDRLEN; i++) {
111         uint8_t byte = ldns_rdf_data(addr)[LDNS_IP6ADDRLEN - i - 1];
112         sprintf(&buf[i*4], "%x.%x.", byte & 0x0F, byte >> 4);
113     }
114     sprintf(&buf[LDNS_IP6ADDRLEN*4], "%s", base);
115     return ldns_dname_new_frm_str(buf);
116 }
117
118 static ldns_status
119 ldns_pkt_push_rr_soa(ldns_pkt *pkt, ldns_pkt_section sec,
120     const ldns_rdf *name, ldns_rr_class c, uint32_t serial) {
121     ldns_rdf *rdf;
122     ldns_rr *rr;
123     uint32_t n;
124
125     if ((rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_SOA)) == NULL)
126         return LDNS_STATUS_MEM_ERR;
127     ldns_rr_set_class(rr, c);
128     ldns_rr_set_owner(rr, ldns_rdf_clone(name));
129     ldns_rr_set_ttl(rr, 0);
130
131     n = 0;
132     if ((rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, &n)) == NULL)
133         goto memerr;
134     ldns_rr_set_rdf(rr, rdf, 0);
135     ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), 1);
136
137     n = htonl(serial);
138     if ((rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT32, 4, &n)) == NULL)
139         goto memerr;
140     ldns_rr_set_rdf(rr, rdf, 2);
141
142     n = 0;
143     if ((rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_PERIOD, 4, &n)) == NULL)
144         goto memerr;
145     ldns_rr_set_rdf(rr, rdf, 3);
146     ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), 4);
147     ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), 5);
148     ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), 6);
149
150     if (ldns_rr_rdf(rr, 1) == NULL || ldns_rr_rdf(rr, 4) == NULL ||
151         ldns_rr_rdf(rr, 5) == NULL || ldns_rr_rdf(rr, 6) == NULL ||
152         !ldns_pkt_push_rr(pkt, sec, rr))
153         goto memerr;
154     return LDNS_STATUS_OK;
155
156 memerr:
157     ldns_rr_free(rr);
158     return LDNS_STATUS_MEM_ERR;
159 }
160
161 static ldns_status
162 ldns_resolver_send_to(ldns_pkt **answer, ldns_resolver *res,
163     const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c,
164     uint16_t flags, uint32_t ixfr_serial, int nameserver) {
165     ldns_status status;
166     ldns_pkt *qpkt;
167
168     int nscnt = ldns_resolver_nameserver_count(res);
169     ldns_rdf **ns = ldns_resolver_nameservers(res);
170     size_t *rtt = ldns_resolver_rtt(res);
171
172     ldns_resolver_set_nameservers(res, &ns[nameserver]);
173     ldns_resolver_set_rtt(res, &rtt[nameserver]);
174     ldns_resolver_set_nameserver_count(res, 1);
175
176     status = ldns_resolver_prepare_query_pkt(&qpkt, res, name, t, c, flags);
177     if (status == LDNS_STATUS_OK && t == LDNS_RR_TYPE_IXFR)
178         status = ldns_pkt_push_rr_soa(qpkt,
179             LDNS_SECTION_AUTHORITY, name, c, ixfr_serial);
180     if (status == LDNS_STATUS_OK)
181         status = ldns_resolver_send_pkt(answer, res, qpkt);
182     ldns_pkt_free(qpkt);
183
184     ldns_resolver_set_nameservers(res, ns);
185     ldns_resolver_set_rtt(res, rtt);
186     ldns_resolver_set_nameserver_count(res, nscnt);
187     return status;
188 }
189
190 static void
191 ldns_pkt_filter_answer(ldns_pkt *pkt, ldns_rr_type type) {
192     int i, j, cnt;
193     ldns_rr_list *rrlist;
194     ldns_rr *rr;
195     ldns_rr_type rrtype;
196
197     rrlist = ldns_pkt_answer(pkt);
198     cnt = ldns_rr_list_rr_count(rrlist);
199     for (i = j = 0; i < cnt; i++) {
200         rr = ldns_rr_list_rr(rrlist, i);
201         rrtype = ldns_rr_get_type(rr);
202         if (type == LDNS_RR_TYPE_ANY ||
203             type == rrtype ||
204             (type == LDNS_RR_TYPE_AXFR &&
205                 (rrtype == LDNS_RR_TYPE_A ||
206                     rrtype == LDNS_RR_TYPE_AAAA ||
207                     rrtype == LDNS_RR_TYPE_NS ||
208                     rrtype == LDNS_RR_TYPE_PTR)))
209             ldns_rr_list_set_rr(rrlist, rr, j++);
210     }
211     ldns_rr_list_set_rr_count(rrlist, j);
212 }
213
214 /* Packet content printing.
215  */
216
217 static struct {
218     ldns_rr_type type;
219     const char *text;
220 } rr_types[] = {
221     {LDNS_RR_TYPE_A,        "has address"},
222     {LDNS_RR_TYPE_NS,       "name server"},
223     {LDNS_RR_TYPE_CNAME,    "is an alias for"},
224     {LDNS_RR_TYPE_WKS,      "has well known services"},
225     {LDNS_RR_TYPE_PTR,      "domain name pointer"},
226     {LDNS_RR_TYPE_HINFO,    "host information"},
227     {LDNS_RR_TYPE_MX,       "mail is handled by"},
228     {LDNS_RR_TYPE_TXT,      "descriptive text"},
229     {LDNS_RR_TYPE_X25,      "x25 address"},
230     {LDNS_RR_TYPE_ISDN,     "ISDN address"},
231     {LDNS_RR_TYPE_SIG,      "has signature"},
232     {LDNS_RR_TYPE_KEY,      "has key"},
233     {LDNS_RR_TYPE_AAAA,     "has IPv6 address"},
234     {LDNS_RR_TYPE_LOC,      "location"},
235 };
236
237 static void
238 print_opcode(ldns_pkt_opcode opcode) {
239     ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode);
240
241     if (lt && lt->name)
242         printf("%s", lt->name);
243     else
244         printf("RESERVED%d", opcode);
245 }
246
247 static void
248 print_rcode(uint8_t rcode) {
249     ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode);
250
251     if (lt && lt->name)
252         printf("%s", lt->name);
253     else
254         printf("RESERVED%d", rcode);
255 }
256
257 static int
258 print_rr_type(ldns_rr_type type) {
259     char *str;
260     int n;
261     
262     str = ldns_rr_type2str(type);
263     n = printf("%s", str);
264     free(str);
265     return n;
266 }
267
268 static int
269 print_rr_class(ldns_rr_class cls) {
270     char *str;
271     int n;
272
273     str = ldns_rr_class2str(cls);
274     n = printf("%s", str);
275     free(str);
276     return n;
277 }
278
279 static int
280 print_rdf(ldns_rdf *rdf) {
281     char *str;
282     int n;
283
284     str = ldns_rdf2str(rdf);
285     n = printf("%s", str);
286     free(str);
287     return n;
288 }
289
290 static int
291 print_rdf_nodot(ldns_rdf *rdf) {
292     char *str;
293     int len, n;
294
295     str = ldns_rdf2str(rdf);
296     len = strlen(str);
297     n = printf("%.*s", str[len-1] == '.' ? len-1 : len, str);
298     free(str);
299     return n;
300 }
301
302 static int
303 print_padding(int fromcol, int tocol) {
304     int col = fromcol, nextcol = fromcol + 8 - fromcol%8;
305
306     if (fromcol + 1 > tocol) tocol = fromcol + 1;
307     for (; nextcol <= tocol; col = nextcol, nextcol += 8)
308         printf("\t");
309     for (; col < tocol; col++)
310         printf(" ");
311     return col - fromcol;
312 }
313
314 static void
315 print_rr_verbose(ldns_rr *rr) {
316     bool isq = ldns_rr_is_question(rr);
317     int rdcnt = ldns_rr_rd_count(rr);
318     int i, n;
319
320     /* bind9-host does not count the initial ';' here */
321     n = isq ? printf(";") : 0;
322     n = print_rdf(ldns_rr_owner(rr));
323     if (!isq) {
324         n += print_padding(n, 24);
325         n += printf("%d", ldns_rr_ttl(rr));
326     }
327     n += print_padding(n, 32);
328     n += print_rr_class(ldns_rr_get_class(rr));
329     n += print_padding(n, 40);
330     n += print_rr_type(ldns_rr_get_type(rr));
331     for (i = 0; i < rdcnt; i++) {
332         if (i == 0) print_padding(n, 48);
333         else printf(" ");
334         print_rdf(ldns_rr_rdf(rr, i));
335     }
336     printf("\n");
337 }
338
339 static void
340 print_pkt_section_verbose(const char *name, ldns_rr_list *rrlist) {
341     int i, cnt = ldns_rr_list_rr_count(rrlist);
342
343     if (cnt == 0)
344         return;
345     printf(";; %s SECTION:\n", name);
346     for (i = 0; i < cnt; i++)
347         print_rr_verbose(ldns_rr_list_rr(rrlist, i));
348     printf("\n");
349 }
350
351 static void
352 print_pkt_verbose(ldns_pkt *pkt) {
353     int got_flags = 0;
354
355     printf(";; ->>HEADER<<- opcode: ");
356     print_opcode(ldns_pkt_get_opcode(pkt));
357     printf(", status: ");
358     print_rcode(ldns_pkt_get_rcode(pkt));
359     printf(", id: %u\n", ldns_pkt_id(pkt));
360     printf(";; flags:");
361     if (ldns_pkt_qr(pkt)) printf(" qr"), got_flags = 1;
362     if (ldns_pkt_aa(pkt)) printf(" aa"), got_flags = 1;
363     if (ldns_pkt_tc(pkt)) printf(" tc"), got_flags = 1;
364     if (ldns_pkt_rd(pkt)) printf(" rd"), got_flags = 1;
365     if (ldns_pkt_ra(pkt)) printf(" ra"), got_flags = 1;
366     if (ldns_pkt_ad(pkt)) printf(" ad"), got_flags = 1;
367     if (ldns_pkt_cd(pkt)) printf(" cd"), got_flags = 1;
368     if (!got_flags) printf(" ");
369     printf("; QUERY: %u, ANSWER: %u, AUTHORITY: %u, ADDITIONAL: %u\n",
370         ldns_pkt_qdcount(pkt), ldns_pkt_ancount(pkt),
371         ldns_pkt_nscount(pkt), ldns_pkt_arcount(pkt));
372     if (ldns_pkt_edns(pkt))
373         printf(";; EDNS: version: %u, udp=%u\n",
374             ldns_pkt_edns_version(pkt), ldns_pkt_edns_udp_size(pkt));
375     printf("\n");
376     print_pkt_section_verbose("QUESTION", ldns_pkt_question(pkt));
377     print_pkt_section_verbose("ANSWER", ldns_pkt_answer(pkt));
378     print_pkt_section_verbose("AUTHORITY", ldns_pkt_authority(pkt));
379     print_pkt_section_verbose("ADDITIONAL", ldns_pkt_additional(pkt));
380 }
381
382 static void
383 print_rr_short(ldns_rr *rr) {
384     ldns_rr_type type = ldns_rr_get_type(rr);
385     size_t i, rdcnt = ldns_rr_rd_count(rr);
386
387     print_rdf_nodot(ldns_rr_owner(rr));
388     printf(" ");
389     for (i = 0; i < countof(rr_types); i++) {
390         if (rr_types[i].type == type) {
391             printf("%s", rr_types[i].text);
392             goto found;
393         }
394     }
395
396     printf("has ");
397     print_rr_type(type);
398     printf(" record");
399
400 found:
401     for (i = 0; i < rdcnt; i++) {
402         printf(" ");
403         print_rdf(ldns_rr_rdf(rr, i));
404     }
405     printf("\n");
406 }
407
408 static void
409 print_pkt_short(ldns_pkt *pkt, bool print_rr_server) {
410     ldns_rr_list *rrlist = ldns_pkt_answer(pkt);
411     size_t i;
412
413     for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
414         if (print_rr_server) {
415             printf("Nameserver ");
416             print_rdf(ldns_pkt_answerfrom(pkt));
417             printf(":\n\t");
418         }
419         print_rr_short(ldns_rr_list_rr(rrlist, i));
420     }
421 }
422
423 static void
424 print_received_line(ldns_resolver *res, ldns_pkt *pkt) {
425     char *from = ldns_rdf2str(ldns_pkt_answerfrom(pkt));
426
427     printf("Received %zu bytes from %s#%d in %d ms\n",
428             ldns_pkt_size(pkt), from, ldns_resolver_port(res),
429             ldns_pkt_querytime(pkt));
430     free(from);
431 }
432
433 /* Main program.
434  *
435  * Note that no memory is freed below this line by intention.
436  */
437
438 #define DEFAULT_TCP_TIMEOUT 10
439 #define DEFAULT_UDP_TIMEOUT 5
440
441 enum operation_mode { M_AXFR, M_DEFAULT_Q, M_SINGLE_Q, M_SOA };
442
443 static enum operation_mode o_mode = M_DEFAULT_Q;
444 static bool o_ignore_servfail = true;
445 static bool o_ip6_int = false;
446 static bool o_print_pkt_server = false;
447 static bool o_print_rr_server = false;
448 static bool o_recursive = true;
449 static bool o_tcp = false;
450 static bool o_verbose = false;
451 static char *o_name = NULL;
452 static char *o_server = NULL;
453 static int o_ipversion = LDNS_RESOLV_INETANY;
454 static int o_ndots = 1;
455 static int o_retries = 1;
456 static ldns_rr_class o_rrclass = LDNS_RR_CLASS_IN;
457 static ldns_rr_type o_rrtype = LDNS_RR_TYPE_A;
458 static time_t o_timeout = 0;
459 static uint32_t o_ixfr_serial = 0;
460
461 static void
462 usage(void) {
463     fputs(
464     "Usage: host [-aCdilrsTvw46] [-c class] [-N ndots] [-R number]\n"
465     "            [-t type] [-W wait] name [server]\n"
466     "\t-a same as -v -t ANY\n"
467     "\t-C query SOA records from all authoritative name servers\n"
468     "\t-c use this query class (IN, CH, HS, etc)\n"
469     "\t-d produce verbose output, same as -v\n"
470     "\t-i use IP6.INT for IPv6 reverse lookups\n"
471     "\t-l list records in a zone via AXFR\n"
472     "\t-N consider names with at least this many dots as absolute\n"
473     "\t-R retry UDP queries this many times\n"
474     "\t-r disable recursive query\n"
475     "\t-s do not ignore SERVFAIL responses\n"
476     "\t-T send query via TCP\n"
477     "\t-t use this query type (A, AAAA, MX, etc)\n"
478     "\t-v produce verbose output\n"
479     "\t-w wait forever for a server reply\n"
480     "\t-W wait this many seconds for a reply\n"
481     "\t-4 use IPv4 only\n"
482     "\t-6 use IPv6 only\n",
483     stderr);
484     exit(1);
485 }
486
487 static void
488 parse_args(int argc, char *argv[]) {
489     int ch;
490
491     progname = argv[0];
492     while ((ch = getopt(argc, argv, "aCdilrsTvw46c:N:R:t:W:")) != -1) {
493         switch (ch) {
494         case 'a':
495             if (o_mode != M_AXFR)
496                 o_mode = M_SINGLE_Q;
497             o_rrtype = LDNS_RR_TYPE_ANY;
498             o_verbose = true;
499             break;
500         case 'C':
501             o_mode = M_SOA;
502             o_print_rr_server = true;
503             o_rrclass = LDNS_RR_CLASS_IN;
504             o_rrtype = LDNS_RR_TYPE_NS;
505             break;
506         case 'c':
507             /* bind9-host sets o_mode to M_SINGLE_Q here */
508             o_rrclass = ldns_get_rr_class_by_name(optarg);
509             if (o_rrclass <= 0)
510                 die(2, "invalid class: %s\n", optarg);
511             break;
512         case 'd': o_verbose = true; break;
513         case 'i': o_ip6_int = true; break;
514         case 'l':
515             o_mode = M_AXFR;
516             o_rrtype = LDNS_RR_TYPE_AXFR;
517             o_tcp = true;
518             break;
519         case 'N':
520             o_ndots = atoi(optarg);
521             if (o_ndots < 0) o_ndots = 0;
522             break;
523         case 'n':
524             /* bind9-host accepts and ignores this option */
525             break;
526         case 'r': o_recursive = 0; break;
527         case 'R':
528             o_retries = atoi(optarg);
529             if (o_retries <= 0) o_retries = 1;
530             if (o_retries > 255) o_retries = 255;
531             break;
532         case 's': o_ignore_servfail = false; break;
533         case 'T': o_tcp = true; break;
534         case 't':
535             if (o_mode != M_AXFR)
536                 o_mode = M_SINGLE_Q;
537             if (strncasecmp(optarg, "ixfr=", 5) == 0) {
538                 o_rrtype = LDNS_RR_TYPE_IXFR;
539                 o_ixfr_serial = atol(optarg + 5);
540             } else {
541                 o_rrtype = ldns_get_rr_type_by_name(optarg);
542                 if (o_rrtype <= 0)
543                     die(2, "invalid type: %s\n", optarg);
544             }
545             if (o_rrtype == LDNS_RR_TYPE_AXFR || o_rrtype == LDNS_RR_TYPE_IXFR)
546                 o_tcp = true;
547             if (o_rrtype == LDNS_RR_TYPE_AXFR) {
548                 o_mode = M_AXFR;
549                 o_rrtype = LDNS_RR_TYPE_ANY;
550                 o_verbose = true;
551             }
552             break;
553         case 'v': o_verbose = true; break;
554         case 'w':
555               o_timeout = (time_t)INT_MAX;
556               break;
557         case 'W':
558             o_timeout = atol(optarg);
559             if (o_timeout <= 0) o_timeout = 1;
560             break;
561         case '4': o_ipversion = LDNS_RESOLV_INET; break;
562         case '6': o_ipversion = LDNS_RESOLV_INET6; break;
563         default:
564             usage();
565         }
566     }
567     argc -= optind;
568     argv += optind;
569     /* bind9-host ignores arguments after the 2-nd one */
570     if (argc < 1)
571         usage();
572     o_name = argv[0];
573     if (argc > 1) {
574         o_server = argv[1];
575         o_print_pkt_server = true;
576     }
577 }
578
579 static ldns_rdf*
580 safe_str2rdf_dname(const char *name) {
581     ldns_rdf *dname;
582     ldns_status status;
583
584     if ((status = ldns_str2rdf_dname(&dname, name)) != LDNS_STATUS_OK) {
585         die(1, "'%s' is not a legal name (%s)",
586             name, ldns_get_errorstr_by_id(status));
587     }
588     return dname;
589 }
590
591 static ldns_rdf*
592 safe_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) {
593     ldns_rdf *result = ldns_dname_cat_clone(rd1, rd2);
594
595     if (!result)
596         die(1, "not enought memory for a domain name");
597     /* Why doesn't ldns_dname_cat_clone check this condition? */
598     if (ldns_rdf_size(result) > LDNS_MAX_DOMAINLEN)
599         die(1, "'%s' is not a legal name (%s)\n", ldns_rdf2str(result),
600             ldns_get_errorstr_by_id(LDNS_STATUS_DOMAINNAME_OVERFLOW));
601     return result;
602 }
603
604 static bool
605 query(ldns_resolver *res, ldns_rdf *domain, ldns_pkt **pkt) {
606     ldns_status status;
607     ldns_pkt_rcode rcode;
608     int i, cnt;
609
610     if (o_verbose) {
611         printf("Trying \"");
612         print_rdf_nodot(domain);
613         printf("\"\n");
614     }
615     for (cnt = ldns_resolver_nameserver_count(res), i = 0; i < cnt; i++) {
616         status = ldns_resolver_send_to(pkt, res, domain, o_rrtype,
617             o_rrclass, o_recursive ? LDNS_RD : 0, o_ixfr_serial, i);
618         if (status != LDNS_STATUS_OK) {
619             *pkt = NULL;
620             continue;
621         }
622         if (ldns_pkt_tc(*pkt) && !ldns_resolver_usevc(res)) {
623             if (o_verbose)
624                 printf(";; Truncated, retrying in TCP mode.\n");
625             ldns_resolver_set_usevc(res, true);
626             status = ldns_resolver_send_to(pkt, res, domain, o_rrtype,
627                 o_rrclass, o_recursive ? LDNS_RD : 0, o_ixfr_serial, i);
628             ldns_resolver_set_usevc(res, false);
629             if (status != LDNS_STATUS_OK)
630                 continue;
631         }
632         rcode = ldns_pkt_get_rcode(*pkt);
633         if (o_ignore_servfail && rcode == LDNS_RCODE_SERVFAIL && cnt > 1)
634             continue;
635         return rcode == LDNS_RCODE_NOERROR;
636     }
637     if (*pkt == NULL) {
638         printf(";; connection timed out; no servers could be reached\n");
639         exit(1);
640     }
641     return false;
642 }
643
644 static ldns_rdf *
645 search(ldns_resolver *res, ldns_rdf *domain, ldns_pkt **pkt, bool absolute) {
646     ldns_rdf *dname, **searchlist;
647     int i, n;
648
649     if (absolute && query(res, domain, pkt))
650         return domain;
651
652     if ((dname = ldns_resolver_domain(res)) != NULL) {
653         dname = safe_dname_cat_clone(domain, dname);
654         if (query(res, dname, pkt))
655             return dname;
656     }
657
658     searchlist = ldns_resolver_searchlist(res);
659     n = ldns_resolver_searchlist_count(res);
660     for (i = 0; i < n; i++) {
661         dname = safe_dname_cat_clone(domain, searchlist[i]);
662         if (query(res, dname, pkt))
663             return dname;
664     }
665
666     if (!absolute && query(res, domain, pkt))
667         return domain;
668
669     return NULL;
670 }
671
672 static void
673 report(ldns_resolver *res, ldns_rdf *domain, ldns_pkt *pkt) {
674     ldns_pkt_rcode rcode;
675
676     if (o_print_pkt_server) {
677         printf("Using domain server:\nName: %s\nAddress: ", o_server);
678         print_rdf(ldns_pkt_answerfrom(pkt));
679         printf("#%d\nAliases: \n\n", ldns_resolver_port(res));
680         o_print_pkt_server = false;
681     }
682     rcode = ldns_pkt_get_rcode(pkt);
683     if (rcode != LDNS_RCODE_NOERROR) {
684         printf("Host ");
685         print_rdf_nodot(domain);
686         printf(" not found: %d(", rcode);
687         print_rcode(rcode);
688         printf(")\n");
689     } else {
690         if (o_verbose) {
691             print_pkt_verbose(pkt);
692         } else {
693             print_pkt_short(pkt, o_print_rr_server);
694             if (o_mode != M_DEFAULT_Q &&
695                 ldns_rr_list_rr_count(ldns_pkt_answer(pkt)) == 0) {
696                 print_rdf_nodot(domain);
697                 printf(" has no ");
698                 print_rr_type(o_rrtype);
699                 printf(" record\n");
700             }
701         }
702     }
703     if (o_verbose)
704         print_received_line(res, pkt);
705 }
706
707 static bool
708 doquery(ldns_resolver *res, ldns_rdf *domain) {
709     ldns_pkt *pkt;
710     bool q;
711
712     q = query(res, domain, &pkt);
713     report(res, domain, pkt);
714     return q;
715 }
716
717 static bool
718 doquery_filtered(ldns_resolver *res, ldns_rdf *domain) {
719     ldns_pkt *pkt;
720     bool q;
721
722     q = query(res, domain, &pkt);
723     ldns_pkt_filter_answer(pkt, o_rrtype);
724     report(res, domain, pkt);
725     return q;
726 }
727
728 static bool
729 dosearch(ldns_resolver *res, ldns_rdf *domain, bool absolute) {
730     ldns_pkt *pkt;
731     ldns_rdf *dname;
732
733     dname = search(res, domain, &pkt, absolute);
734     report(res, dname != NULL ? dname : domain, pkt);
735     return o_mode != M_DEFAULT_Q ? (dname != NULL) :
736         (dname != NULL) &&
737         (o_rrtype = LDNS_RR_TYPE_AAAA, doquery_filtered(res, dname)) &&
738         (o_rrtype = LDNS_RR_TYPE_MX, doquery_filtered(res, dname));
739 }
740
741 static bool
742 doaxfr(ldns_resolver *res, ldns_rdf *domain, bool absolute) {
743     ldns_pkt *pkt;
744     ldns_rdf *dname;
745     ldns_rr_type rrtype;
746
747     rrtype = o_rrtype;
748     o_rrtype = LDNS_RR_TYPE_AXFR;
749     dname = search(res, domain, &pkt, absolute);
750     ldns_pkt_filter_answer(pkt, rrtype);
751     report(res, dname != NULL ? dname : domain, pkt);
752     return dname != NULL;
753 }
754
755 static bool
756 dosoa(ldns_resolver *res, ldns_rdf *domain, bool absolute) {
757     ldns_rr_list *answer, **nsaddrs;
758     ldns_rdf *dname, *addr;
759     ldns_pkt *pkt;
760     ldns_rr *rr;
761     size_t i, j, n, cnt;
762
763     if ((dname = search(res, domain, &pkt, absolute)) == NULL)
764         return false;
765
766     answer = ldns_pkt_answer(pkt);
767     cnt = ldns_rr_list_rr_count(answer);
768     nsaddrs = alloca(cnt*sizeof(*nsaddrs));
769     for (n = 0, i = 0; i < cnt; i++)
770         if ((addr = ldns_rr_ns_nsdname(ldns_rr_list_rr(answer, i))) != NULL)
771             nsaddrs[n++] = ldns_get_rr_list_addr_by_name(res, 
772                 addr, LDNS_RR_CLASS_IN, 0); 
773
774     o_print_pkt_server = false;
775     o_recursive = false;
776     o_rrtype = LDNS_RR_TYPE_SOA;
777     for (i = 0; i < n; i++) {
778         cnt = ldns_rr_list_rr_count(nsaddrs[i]);
779         for (j = 0; j < cnt; j++) {
780             ldns_resolver_remove_nameservers(res);
781             rr = ldns_rr_list_rr(nsaddrs[i], j);
782             if ((ldns_resolver_ip6(res) == LDNS_RESOLV_INET &&
783                     ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) ||
784                 (ldns_resolver_ip6(res) == LDNS_RESOLV_INET6 &&
785                     ldns_rr_get_type(rr) == LDNS_RR_TYPE_A))
786                 continue;
787             if (ldns_resolver_push_nameserver_rr(res, rr) == LDNS_STATUS_OK)
788                 /* bind9-host queries for domain, not dname here */
789                 doquery(res, dname);
790         }
791     }
792     return 0;
793 }
794
795 static void
796 resolver_set_nameserver_hostname(ldns_resolver *res, const char *server) {
797     struct addrinfo hints, *ailist, *ai;
798     ldns_status status;
799     ldns_rdf *rdf;
800     int err;
801
802     memset(&hints, 0, sizeof hints);
803     switch (ldns_resolver_ip6(res)) {
804     case LDNS_RESOLV_INET: hints.ai_family = PF_INET; break;
805     case LDNS_RESOLV_INET6: hints.ai_family = PF_INET6; break;
806     default: hints.ai_family = PF_UNSPEC; break;
807     }
808     hints.ai_socktype = SOCK_STREAM;
809     do err = getaddrinfo(server, NULL, &hints, &ailist);
810     while (err == EAI_AGAIN);
811     if (err != 0)
812         die(1, "couldn't get address for '%s': %s", server, gai_strerror(err));
813     for (ai = ailist; ai != NULL; ai = ai->ai_next) {
814         if ((rdf = ldns_sockaddr_storage2rdf((void*)ai->ai_addr, NULL)) == NULL)
815             die(1, "couldn't allocate an rdf: %s",
816                 ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR));
817         status = ldns_resolver_push_nameserver(res, rdf);
818         if (status != LDNS_STATUS_OK)
819             die(1, "couldn't push a nameserver address: %s",
820                 ldns_get_errorstr_by_id(status));
821     }
822 }
823
824 static void
825 resolver_set_nameserver_str(ldns_resolver *res, const char *server) {
826     ldns_rdf *addr;
827
828     ldns_resolver_remove_nameservers(res);
829     addr = ldns_rdf_new_addr_frm_str(server);
830     if (addr) {
831         if (ldns_resolver_push_nameserver(res, addr) != LDNS_STATUS_OK)
832             die(1, "couldn't push a nameserver address");
833     } else
834         resolver_set_nameserver_hostname(res, server);
835 }
836
837 int
838 main(int argc, char *argv[]) {
839     ldns_rdf *addr, *dname;
840     ldns_resolver *res;
841     ldns_status status;
842     struct timeval restimeout;
843
844     parse_args(argc, argv);
845
846     status = ldns_resolver_new_default(&res);
847     if (status != LDNS_STATUS_OK)
848         die(1, "error creating resolver: %s", ldns_get_errorstr_by_id(status));
849     if (ldns_resolver_nameserver_count(res) == 0)
850         ldns_resolver_push_default_servers(res);
851
852     ldns_resolver_set_usevc(res, o_tcp);
853     restimeout.tv_sec = o_timeout > 0 ? o_timeout :
854         o_tcp ? DEFAULT_TCP_TIMEOUT : DEFAULT_UDP_TIMEOUT;
855     restimeout.tv_usec = 0;
856     ldns_resolver_set_timeout(res, restimeout);
857     ldns_resolver_set_retry(res, o_retries+1);
858     ldns_resolver_set_ip6(res, o_ipversion);
859     ldns_resolver_set_defnames(res, false);
860     ldns_resolver_set_fallback(res, false);
861
862     if (o_server)
863         resolver_set_nameserver_str(res, o_server);
864
865     if (ldns_str2rdf_a(&addr, o_name) == LDNS_STATUS_OK) {
866         dname = ldns_rdf_reverse_a(addr, "in-addr.arpa");
867         if (dname == NULL)
868             die(1, "can't reverse '%s': %s", o_name,
869                 ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR));
870         o_mode = M_SINGLE_Q;
871         o_rrtype = LDNS_RR_TYPE_PTR;
872         return !doquery(res, dname);
873     } else if (ldns_str2rdf_aaaa(&addr, o_name) == LDNS_STATUS_OK) {
874         dname = ldns_rdf_reverse_aaaa(addr, o_ip6_int ? "ip6.int" : "ip6.arpa");
875         if (dname == NULL)
876             die(1, "can't reverse '%s': %s", o_name,
877                 ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR));
878         o_mode = M_SINGLE_Q;
879         o_rrtype = LDNS_RR_TYPE_PTR;
880         return !doquery(res, dname);
881     }
882     return !(o_mode == M_SOA ? dosoa : o_mode == M_AXFR ? doaxfr : dosearch)
883         (res, safe_str2rdf_dname(o_name), ndots(o_name) >= o_ndots);
884 }