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