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