C 11
Ldns-host.c Guest on 4th October 2020 12:27:24 AM
  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. }

Paste is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.