Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/ldns/drill/drill.c
39478 views
1
/*
2
* drill.c
3
* the main file of drill
4
* (c) 2005-2008 NLnet Labs
5
*
6
* See the file LICENSE for the license
7
*
8
*/
9
10
#include "drill.h"
11
#include <ldns/ldns.h>
12
13
#ifdef HAVE_SSL
14
#include <openssl/err.h>
15
#endif
16
17
/* query debug, 2 hex dumps */
18
int verbosity;
19
20
static int
21
is_ixfr_with_serial(const char* name, uint32_t *serial)
22
{
23
char* end;
24
if (strlen(name) > 5 &&
25
strncasecmp(name, "IXFR", 4) == 0 &&
26
name[4] == '=') {
27
*serial = (uint32_t) strtol((name+5), &end, 10);
28
return 1;
29
}
30
return 0;
31
}
32
33
static void
34
usage(FILE *stream, const char *progname)
35
{
36
fprintf(stream, " Usage: %s name [@server] [type] [class]\n", progname);
37
fprintf(stream, "\t<name> can be a domain name or an IP address (-x lookups)\n");
38
fprintf(stream, "\t<type> defaults to A\n");
39
fprintf(stream, "\t<class> defaults to IN\n");
40
fprintf(stream, "\n\targuments may be placed in random order\n");
41
fprintf(stream, "\n Options:\n");
42
fprintf(stream, "\t-D\t\tenable DNSSEC (DO bit)\n");
43
#ifdef HAVE_SSL
44
fprintf(stream, "\t-T\t\ttrace from the root down to <name>\n");
45
fprintf(stream, "\t-S\t\tchase signature(s) from <name> to a known key [*]\n");
46
#endif /*HAVE_SSL*/
47
fprintf(stream, "\t-I <address>\tsource address to query from\n");
48
fprintf(stream, "\t-V <number>\tverbosity (0-5)\n");
49
fprintf(stream, "\t-Q\t\tquiet mode (overrules -V)\n");
50
fprintf(stream, "\n");
51
fprintf(stream, "\t-f file\t\tread packet from file and send it\n");
52
fprintf(stream, "\t-i file\t\tread packet from file and print it\n");
53
fprintf(stream, "\t-w file\t\twrite answer packet to file\n");
54
fprintf(stream, "\t-q file\t\twrite query packet to file\n");
55
fprintf(stream, "\t-h\t\tshow this help\n");
56
fprintf(stream, "\t-v\t\tshow version\n");
57
fprintf(stream, "\n Query options:\n");
58
fprintf(stream, "\t-4\t\tstay on ip4\n");
59
fprintf(stream, "\t-6\t\tstay on ip6\n");
60
fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n");
61
fprintf(stream, "\t-b <bufsize>\tuse <bufsize> as the buffer size (defaults to 512 b)\n");
62
fprintf(stream, "\t-c <file>\tuse file for recursive nameserver configuration"
63
"\n\t\t\t(/etc/resolv.conf)\n");
64
fprintf(stream, "\t-k <file>\tspecify a file that contains a trusted DNSSEC key [**]\n");
65
fprintf(stream, "\t\t\tUsed to verify any signatures in the current answer.\n");
66
fprintf(stream, "\t\t\tWhen DNSSEC enabled tracing (-TD) or signature\n"
67
"\t\t\tchasing (-S) and no key files are given, keys are read\n"
68
"\t\t\tfrom: %s\n",
69
LDNS_TRUST_ANCHOR_FILE);
70
fprintf(stream, "\t-o <mnemonic>\tset flags to:"
71
"\n\t\t\t[QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n");
72
fprintf(stream, "\t\t\tlowercase: unset bit, uppercase: set bit\n");
73
fprintf(stream, "\t-p <port>\tuse <port> as remote port number\n");
74
fprintf(stream, "\t-s\t\tshow the DS RR for each key in a packet\n");
75
fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n");
76
fprintf(stream, "\t-x\t\tdo a reverse lookup\n");
77
fprintf(stream, "\twhen doing a secure trace:\n");
78
fprintf(stream, "\t-r <file>\tuse file as root servers hint file\n");
79
fprintf(stream, "\t-t\t\tsend the query with tcp (connected)\n");
80
fprintf(stream, "\t-d <domain>\tuse domain as the start point for the trace\n");
81
fprintf(stream, "\t-y <name:key[:algo]>\tspecify named base64 tsig key, and optional an\n\t\t\talgorithm (defaults to hmac-md5.sig-alg.reg.int)\n");
82
fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n");
83
fprintf(stream, "\n [*] = enables/implies DNSSEC\n");
84
fprintf(stream, " [**] = can be given more than once\n");
85
fprintf(stream, "\n [email protected] | http://www.nlnetlabs.nl/ldns/\n");
86
}
87
88
/**
89
* Prints the drill version to stderr
90
*/
91
static void
92
version(FILE *stream, const char *progname)
93
{
94
fprintf(stream, "%s version %s (ldns version %s)\n", progname, DRILL_VERSION, ldns_version());
95
fprintf(stream, "Written by NLnet Labs.\n");
96
fprintf(stream, "\nCopyright (c) 2004-2008 NLnet Labs.\n");
97
fprintf(stream, "Licensed under the revised BSD license.\n");
98
fprintf(stream, "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n");
99
fprintf(stream, "FOR A PARTICULAR PURPOSE.\n");
100
}
101
102
103
/**
104
* Main function of drill
105
* parse the arguments and prepare a query
106
*/
107
int
108
main(int argc, char *argv[])
109
{
110
ldns_resolver *res = NULL;
111
ldns_resolver *cmdline_res = NULL; /* only used to resolv @name names */
112
ldns_rr_list *cmdline_rr_list = NULL;
113
ldns_rdf *cmdline_dname = NULL;
114
ldns_rdf *qname;
115
ldns_pkt *pkt;
116
ldns_pkt *qpkt;
117
char *serv;
118
char *src = NULL;
119
const char *name;
120
char *progname;
121
char *query_file = NULL;
122
char *answer_file = NULL;
123
ldns_buffer *query_buffer = NULL;
124
ldns_rdf *serv_rdf;
125
ldns_rdf *src_rdf = NULL;
126
ldns_rr_type type;
127
ldns_rr_class clas;
128
#if 0
129
ldns_pkt_opcode opcode = LDNS_PACKET_QUERY;
130
#endif
131
int i, c;
132
int int_type;
133
int int_clas;
134
int PURPOSE;
135
char *tsig_name = NULL;
136
char *tsig_data = NULL;
137
char *tsig_algorithm = NULL;
138
size_t tsig_separator;
139
size_t tsig_separator2;
140
ldns_rr *axfr_rr;
141
ldns_status status;
142
char *type_str;
143
uint32_t serial = 0;
144
/* list of keys used in dnssec operations */
145
ldns_rr_list *key_list = ldns_rr_list_new();
146
/* what key verify the current answer */
147
ldns_rr_list *key_verified;
148
149
/* resolver options */
150
uint16_t qflags;
151
uint16_t qbuf;
152
uint16_t qport;
153
uint8_t qfamily;
154
bool qdnssec;
155
bool qfallback;
156
bool qds;
157
bool qusevc;
158
bool qrandom;
159
bool drill_reverse = false;
160
161
char *resolv_conf_file = NULL;
162
163
ldns_rdf *trace_start_name = NULL;
164
165
int result = 0;
166
167
uint8_t s6addr[16];
168
char ip6_arpa_str[74];
169
uint8_t s4addr[4];
170
char in_addr_arpa_str[40];
171
172
#ifdef USE_WINSOCK
173
int r;
174
WSADATA wsa_data;
175
#endif
176
ldns_output_format_storage fmt_storage;
177
ldns_output_format* fmt = ldns_output_format_init(&fmt_storage);
178
179
int_type = -1; serv = NULL; type = 0;
180
int_clas = -1; name = NULL; clas = 0;
181
qname = NULL; src = NULL;
182
progname = strdup(argv[0]);
183
184
#ifdef USE_WINSOCK
185
r = WSAStartup(MAKEWORD(2,2), &wsa_data);
186
if(r != 0) {
187
printf("Failed WSAStartup: %d\n", r);
188
result = EXIT_FAILURE;
189
goto exit;
190
}
191
#endif /* USE_WINSOCK */
192
193
194
PURPOSE = DRILL_QUERY;
195
qflags = LDNS_RD;
196
qport = LDNS_PORT;
197
verbosity = 2;
198
qdnssec = false;
199
qfamily = LDNS_RESOLV_INETANY;
200
qfallback = false;
201
qds = false;
202
qbuf = 0;
203
qusevc = false;
204
qrandom = true;
205
key_verified = NULL;
206
ldns_edns_option_list* edns_list = NULL;
207
208
ldns_init_random(NULL, 0);
209
210
/* string from orig drill: "i:w:I46Sk:TNp:b:DsvhVcuaq:f:xr" */
211
/* global first, query opt next, option with parm's last
212
* and sorted */ /* "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */
213
214
while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:I:k:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) {
215
switch(c) {
216
/* global options */
217
case '4':
218
qfamily = LDNS_RESOLV_INET;
219
break;
220
case '6':
221
qfamily = LDNS_RESOLV_INET6;
222
break;
223
case 'D':
224
qdnssec = true;
225
break;
226
case 'I':
227
src = optarg;
228
break;
229
case 'T':
230
if (PURPOSE == DRILL_CHASE) {
231
fprintf(stderr, "-T and -S cannot be used at the same time.\n");
232
exit(EXIT_FAILURE);
233
}
234
PURPOSE = DRILL_TRACE;
235
break;
236
#ifdef HAVE_SSL
237
case 'S':
238
if (PURPOSE == DRILL_TRACE) {
239
fprintf(stderr, "-T and -S cannot be used at the same time.\n");
240
exit(EXIT_FAILURE);
241
}
242
PURPOSE = DRILL_CHASE;
243
break;
244
#endif /* HAVE_SSL */
245
case 'V':
246
if (strtok(optarg, "0123456789") != NULL) {
247
fprintf(stderr, "-V expects an number as an argument.\n");
248
exit(EXIT_FAILURE);
249
}
250
verbosity = atoi(optarg);
251
break;
252
case 'Q':
253
fmt->flags |= LDNS_FMT_SHORT;
254
verbosity = -1;
255
break;
256
case 'f':
257
query_file = optarg;
258
break;
259
case 'i':
260
answer_file = optarg;
261
PURPOSE = DRILL_AFROMFILE;
262
break;
263
case 'w':
264
answer_file = optarg;
265
break;
266
case 'q':
267
query_file = optarg;
268
PURPOSE = DRILL_QTOFILE;
269
break;
270
case 'r':
271
if (global_dns_root) {
272
fprintf(stderr, "There was already a series of root servers set\n");
273
exit(EXIT_FAILURE);
274
}
275
global_dns_root = read_root_hints(optarg);
276
if (!global_dns_root) {
277
fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg);
278
exit(EXIT_FAILURE);
279
}
280
break;
281
/* query options */
282
case 'a':
283
qfallback = true;
284
break;
285
case 'b':
286
qbuf = (uint16_t)atoi(optarg);
287
if (qbuf == 0) {
288
error("%s", "<bufsize> could not be converted");
289
}
290
break;
291
case 'c':
292
resolv_conf_file = optarg;
293
break;
294
case 't':
295
qusevc = true;
296
break;
297
case 'k':
298
status = read_key_file(optarg,
299
key_list, false);
300
if (status != LDNS_STATUS_OK) {
301
error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status));
302
}
303
qdnssec = true; /* enable that too */
304
break;
305
case 'o':
306
/* only looks at the first hit: capital=ON, lowercase=OFF*/
307
if (strstr(optarg, "QR")) {
308
DRILL_ON(qflags, LDNS_QR);
309
}
310
if (strstr(optarg, "qr")) {
311
DRILL_OFF(qflags, LDNS_QR);
312
}
313
if (strstr(optarg, "AA")) {
314
DRILL_ON(qflags, LDNS_AA);
315
}
316
if (strstr(optarg, "aa")) {
317
DRILL_OFF(qflags, LDNS_AA);
318
}
319
if (strstr(optarg, "TC")) {
320
DRILL_ON(qflags, LDNS_TC);
321
}
322
if (strstr(optarg, "tc")) {
323
DRILL_OFF(qflags, LDNS_TC);
324
}
325
if (strstr(optarg, "RD")) {
326
DRILL_ON(qflags, LDNS_RD);
327
}
328
if (strstr(optarg, "rd")) {
329
DRILL_OFF(qflags, LDNS_RD);
330
}
331
if (strstr(optarg, "CD")) {
332
DRILL_ON(qflags, LDNS_CD);
333
}
334
if (strstr(optarg, "cd")) {
335
DRILL_OFF(qflags, LDNS_CD);
336
}
337
if (strstr(optarg, "RA")) {
338
DRILL_ON(qflags, LDNS_RA);
339
}
340
if (strstr(optarg, "ra")) {
341
DRILL_OFF(qflags, LDNS_RA);
342
}
343
if (strstr(optarg, "AD")) {
344
DRILL_ON(qflags, LDNS_AD);
345
}
346
if (strstr(optarg, "ad")) {
347
DRILL_OFF(qflags, LDNS_AD);
348
}
349
break;
350
case 'p':
351
qport = (uint16_t)atoi(optarg);
352
if (qport == 0) {
353
error("%s", "<port> could not be converted");
354
}
355
break;
356
case 's':
357
qds = true;
358
break;
359
case 'u':
360
qusevc = false;
361
break;
362
case 'v':
363
version(stdout, progname);
364
result = EXIT_SUCCESS;
365
goto exit;
366
case 'x':
367
drill_reverse = true;
368
break;
369
case 'y':
370
#ifdef HAVE_SSL
371
if (strchr(optarg, ':')) {
372
tsig_separator = (size_t) (strchr(optarg, ':') - optarg);
373
if (tsig_algorithm) {
374
free(tsig_algorithm);
375
tsig_algorithm = NULL;
376
}
377
if (strchr(optarg + tsig_separator + 1, ':')) {
378
tsig_separator2 = (size_t) (strchr(optarg + tsig_separator + 1, ':') - optarg);
379
tsig_algorithm = xmalloc(strlen(optarg) - tsig_separator2);
380
strncpy(tsig_algorithm, optarg + tsig_separator2 + 1, strlen(optarg) - tsig_separator2);
381
tsig_algorithm[strlen(optarg) - tsig_separator2 - 1] = '\0';
382
} else {
383
tsig_separator2 = strlen(optarg);
384
tsig_algorithm = strdup("hmac-md5.sig-alg.reg.int");
385
}
386
tsig_name = xmalloc(tsig_separator + 1);
387
tsig_data = xmalloc(tsig_separator2 - tsig_separator);
388
strncpy(tsig_name, optarg, tsig_separator);
389
strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1);
390
/* strncpy does not append \0 if source is longer than n */
391
tsig_name[tsig_separator] = '\0';
392
tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0';
393
}
394
#else
395
fprintf(stderr, "TSIG requested, but SSL is not supported\n");
396
result = EXIT_FAILURE;
397
goto exit;
398
#endif /* HAVE_SSL */
399
break;
400
case 'z':
401
qrandom = false;
402
break;
403
case 'd':
404
trace_start_name = ldns_dname_new_frm_str(optarg);
405
if (!trace_start_name) {
406
fprintf(stderr, "Unable to parse argument for -%c\n", c);
407
result = EXIT_FAILURE;
408
goto exit;
409
}
410
break;
411
case 'h':
412
version(stdout, progname);
413
usage(stdout, progname);
414
result = EXIT_SUCCESS;
415
goto exit;
416
break;
417
default:
418
fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c);
419
result = EXIT_FAILURE;
420
goto exit;
421
}
422
}
423
argc -= optind;
424
argv += optind;
425
426
if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) &&
427
ldns_rr_list_rr_count(key_list) == 0) {
428
429
(void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true);
430
}
431
if (ldns_rr_list_rr_count(key_list) > 0) {
432
printf(";; Number of trusted keys: %d\n",
433
(int) ldns_rr_list_rr_count(key_list));
434
}
435
/* do a secure trace when requested */
436
if (PURPOSE == DRILL_TRACE && qdnssec) {
437
#ifdef HAVE_SSL
438
if (ldns_rr_list_rr_count(key_list) == 0) {
439
warning("%s", "No trusted keys were given. Will not be able to verify authenticity!");
440
}
441
PURPOSE = DRILL_SECTRACE;
442
#else
443
fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n");
444
exit(1);
445
#endif /* HAVE_SSL */
446
}
447
448
/* parse the arguments, with multiple arguments, the last argument
449
* found is used */
450
for(i = 0; i < argc; i++) {
451
452
/* if ^@ then it's a server */
453
if (argv[i][0] == '@') {
454
if (strlen(argv[i]) == 1) {
455
warning("%s", "No nameserver given");
456
exit(EXIT_FAILURE);
457
}
458
serv = argv[i] + 1;
459
continue;
460
}
461
/* if ^+ then it's an EDNS option */
462
if (argv[i][0] == '+') {
463
if (!strcmp(argv[i]+1, "nsid")) {
464
ldns_edns_option *edns;
465
edns_list = ldns_edns_option_list_new();
466
467
/* create NSID EDNS*/
468
edns = ldns_edns_new_from_data(LDNS_EDNS_NSID, 0, NULL);
469
470
if (edns_list == NULL || edns == NULL) {
471
error("EDNS option could not be allocated");
472
break;
473
}
474
475
if (!(ldns_edns_option_list_push(edns_list, edns))) {
476
error("EDNS option NSID could not be attached");
477
break;
478
}
479
continue;
480
}
481
else {
482
error("Unsupported argument after '+'");
483
break;
484
}
485
}
486
/* if has a dot, it's a name */
487
if (strchr(argv[i], '.')) {
488
name = argv[i];
489
continue;
490
}
491
/* if it matches a type, it's a type */
492
if (int_type == -1) {
493
type = ldns_get_rr_type_by_name(argv[i]);
494
if (type != 0) {
495
int_type = 0;
496
continue;
497
} else if (is_ixfr_with_serial(argv[i], &serial)) {
498
type = LDNS_RR_TYPE_IXFR;
499
int_type = 0;
500
continue;
501
}
502
}
503
/* if it matches a class, it's a class */
504
if (int_clas == -1) {
505
clas = ldns_get_rr_class_by_name(argv[i]);
506
if (clas != 0) {
507
int_clas = 0;
508
continue;
509
}
510
}
511
/* it all fails assume it's a name */
512
name = argv[i];
513
}
514
/* act like dig and use for . NS */
515
if (!name) {
516
name = ".";
517
int_type = 0;
518
type = LDNS_RR_TYPE_NS;
519
}
520
521
/* defaults if not given */
522
if (int_clas == -1) {
523
clas = LDNS_RR_CLASS_IN;
524
}
525
if (int_type == -1) {
526
if (!drill_reverse) {
527
type = LDNS_RR_TYPE_A;
528
} else {
529
type = LDNS_RR_TYPE_PTR;
530
}
531
}
532
if (!drill_reverse)
533
; /* pass */
534
else if (strchr(name, ':')) { /* ipv4 or ipv6 addr? */
535
if (!inet_pton(AF_INET6, name, &s6addr)) {
536
error("Syntax error: cannot parse IPv6 address\n");
537
}
538
(void) snprintf(ip6_arpa_str, sizeof(ip6_arpa_str),
539
"%x.%x.%x.%x.%x.%x.%x.%x."
540
"%x.%x.%x.%x.%x.%x.%x.%x."
541
"%x.%x.%x.%x.%x.%x.%x.%x."
542
"%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
543
(unsigned int)(s6addr[15] & 0x0F),
544
(unsigned int)(s6addr[15] >> 4),
545
(unsigned int)(s6addr[14] & 0x0F),
546
(unsigned int)(s6addr[14] >> 4),
547
(unsigned int)(s6addr[13] & 0x0F),
548
(unsigned int)(s6addr[13] >> 4),
549
(unsigned int)(s6addr[12] & 0x0F),
550
(unsigned int)(s6addr[12] >> 4),
551
(unsigned int)(s6addr[11] & 0x0F),
552
(unsigned int)(s6addr[11] >> 4),
553
(unsigned int)(s6addr[10] & 0x0F),
554
(unsigned int)(s6addr[10] >> 4),
555
(unsigned int)(s6addr[9] & 0x0F),
556
(unsigned int)(s6addr[9] >> 4),
557
(unsigned int)(s6addr[8] & 0x0F),
558
(unsigned int)(s6addr[8] >> 4),
559
(unsigned int)(s6addr[7] & 0x0F),
560
(unsigned int)(s6addr[7] >> 4),
561
(unsigned int)(s6addr[6] & 0x0F),
562
(unsigned int)(s6addr[6] >> 4),
563
(unsigned int)(s6addr[5] & 0x0F),
564
(unsigned int)(s6addr[5] >> 4),
565
(unsigned int)(s6addr[4] & 0x0F),
566
(unsigned int)(s6addr[4] >> 4),
567
(unsigned int)(s6addr[3] & 0x0F),
568
(unsigned int)(s6addr[3] >> 4),
569
(unsigned int)(s6addr[2] & 0x0F),
570
(unsigned int)(s6addr[2] >> 4),
571
(unsigned int)(s6addr[1] & 0x0F),
572
(unsigned int)(s6addr[1] >> 4),
573
(unsigned int)(s6addr[0] & 0x0F),
574
(unsigned int)(s6addr[0] >> 4));
575
name = ip6_arpa_str;
576
577
} else if (!inet_pton(AF_INET, name, &s4addr)) {
578
error("Syntax error: cannot parse IPv4 address\n");
579
580
} else {
581
(void) snprintf(in_addr_arpa_str, sizeof(in_addr_arpa_str),
582
"%d.%d.%d.%d.in-addr.arpa.", (int)s4addr[3],
583
(int)s4addr[2], (int)s4addr[1], (int)s4addr[0]);
584
name = in_addr_arpa_str;
585
}
586
587
if (src) {
588
src_rdf = ldns_rdf_new_addr_frm_str(src);
589
if(!src_rdf) {
590
fprintf(stderr, "-I must be a valid IP[v6] address.\n");
591
exit(EXIT_FAILURE);
592
}
593
if (ldns_rdf_size(src_rdf) == 4) {
594
qfamily = LDNS_RESOLV_INET;
595
596
} else if (ldns_rdf_size(src_rdf) == 16) {
597
qfamily = LDNS_RESOLV_INET6;
598
}
599
}
600
601
/* set the nameserver to use */
602
if (!serv) {
603
/* no server given -- make a resolver from /etc/resolv.conf */
604
status = ldns_resolver_new_frm_file(&res, resolv_conf_file);
605
if (status != LDNS_STATUS_OK) {
606
warning("Could not create a resolver structure: %s (%s)\n"
607
"Try drill @localhost if you have a resolver running on your machine.",
608
ldns_get_errorstr_by_id(status), resolv_conf_file);
609
result = EXIT_FAILURE;
610
goto exit;
611
}
612
} else {
613
res = ldns_resolver_new();
614
if (!res || strlen(serv) <= 0) {
615
warning("Could not create a resolver structure");
616
result = EXIT_FAILURE;
617
goto exit;
618
}
619
/* add the nameserver */
620
serv_rdf = ldns_rdf_new_addr_frm_str(serv);
621
if (!serv_rdf) {
622
/* try to resolv the name if possible */
623
status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file);
624
625
if (status != LDNS_STATUS_OK) {
626
error("%s", "@server ip could not be converted");
627
}
628
ldns_resolver_set_dnssec(cmdline_res, qdnssec);
629
ldns_resolver_set_ip6(cmdline_res, qfamily);
630
ldns_resolver_set_fallback(cmdline_res, qfallback);
631
ldns_resolver_set_usevc(cmdline_res, qusevc);
632
ldns_resolver_set_source(cmdline_res, src_rdf);
633
634
cmdline_dname = ldns_dname_new_frm_str(serv);
635
636
cmdline_rr_list = ldns_get_rr_list_addr_by_name(
637
cmdline_res,
638
cmdline_dname,
639
LDNS_RR_CLASS_IN,
640
qflags);
641
ldns_rdf_deep_free(cmdline_dname);
642
if (!cmdline_rr_list) {
643
/* This error msg is not always accurate */
644
error("%s `%s\'", "could not find any address for the name:", serv);
645
} else {
646
if (ldns_resolver_push_nameserver_rr_list(
647
res,
648
cmdline_rr_list
649
) != LDNS_STATUS_OK) {
650
error("%s", "pushing nameserver");
651
}
652
}
653
} else {
654
if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) {
655
error("%s", "pushing nameserver");
656
} else {
657
ldns_rdf_deep_free(serv_rdf);
658
}
659
}
660
}
661
/* set the resolver options */
662
ldns_resolver_set_ixfr_serial(res, serial);
663
ldns_resolver_set_port(res, qport);
664
ldns_resolver_set_source(res, src_rdf);
665
if (verbosity >= 5) {
666
ldns_resolver_set_debug(res, true);
667
} else {
668
ldns_resolver_set_debug(res, false);
669
}
670
ldns_resolver_set_dnssec(res, qdnssec);
671
/* ldns_resolver_set_dnssec_cd(res, qdnssec);*/
672
ldns_resolver_set_ip6(res, qfamily);
673
ldns_resolver_set_fallback(res, qfallback);
674
ldns_resolver_set_usevc(res, qusevc);
675
ldns_resolver_set_random(res, qrandom);
676
if (qbuf != 0) {
677
ldns_resolver_set_edns_udp_size(res, qbuf);
678
}
679
680
if (!name &&
681
PURPOSE != DRILL_AFROMFILE &&
682
!query_file
683
) {
684
usage(stdout, progname);
685
result = EXIT_FAILURE;
686
goto exit;
687
}
688
689
if (tsig_name && tsig_data) {
690
/* With dig TSIG keys are also specified with -y,
691
* but format with drill is: -y <name:key[:algo]>
692
* and with dig: -y [hmac:]name:key
693
*
694
* When we detect an unknown tsig algorithm in algo,
695
* but a known algorithm in name, we cane assume dig
696
* order was used.
697
*
698
* Following if statement is to anticipate and correct dig order
699
*/
700
if ( strcasecmp(tsig_algorithm, "hmac-md5.sig-alg.reg.int")
701
&& strcasecmp(tsig_algorithm, "hmac-md5")
702
&& strcasecmp(tsig_algorithm, "hmac-sha1")
703
&& strcasecmp(tsig_algorithm, "hmac-sha256")
704
&& (
705
strcasecmp(tsig_name, "hmac-md5.sig-alg.reg.int") == 0
706
|| strcasecmp(tsig_name, "hmac-md5") == 0
707
|| strcasecmp(tsig_name, "hmac-sha1") == 0
708
|| strcasecmp(tsig_name, "hmac-sha256") == 0
709
)) {
710
711
/* Roll options */
712
char *tmp_tsig_algorithm = tsig_name;
713
tsig_name = tsig_data;
714
tsig_data = tsig_algorithm;
715
tsig_algorithm = tmp_tsig_algorithm;
716
}
717
718
if (strcasecmp(tsig_algorithm, "hmac-md5") == 0) {
719
free(tsig_algorithm);
720
tsig_algorithm = strdup("hmac-md5.sig-alg.reg.int");
721
}
722
723
ldns_resolver_set_tsig_keyname(res, tsig_name);
724
ldns_resolver_set_tsig_keydata(res, tsig_data);
725
ldns_resolver_set_tsig_algorithm(res, tsig_algorithm);
726
}
727
728
/* main switching part of drill */
729
switch(PURPOSE) {
730
case DRILL_TRACE:
731
/* do a trace from the root down */
732
if (!global_dns_root) {
733
init_root();
734
}
735
qname = ldns_dname_new_frm_str(name);
736
if (!qname) {
737
error("%s", "parsing query name");
738
}
739
/* don't care about return packet */
740
do_trace(res, qname, type, clas);
741
clear_root();
742
break;
743
case DRILL_SECTRACE:
744
/* do a secure trace from the root down */
745
if (!global_dns_root) {
746
init_root();
747
}
748
qname = ldns_dname_new_frm_str(name);
749
if (!qname) {
750
error("%s", "making qname");
751
}
752
/* don't care about return packet */
753
#ifdef HAVE_SSL
754
result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name);
755
#endif /* HAVE_SSL */
756
clear_root();
757
break;
758
case DRILL_CHASE:
759
qname = ldns_dname_new_frm_str(name);
760
if (!qname) {
761
error("%s", "making qname");
762
}
763
764
ldns_resolver_set_dnssec(res, true);
765
ldns_resolver_set_dnssec_cd(res, true);
766
/* set dnssec implies udp_size of 4096 */
767
ldns_resolver_set_edns_udp_size(res, 4096);
768
pkt = NULL;
769
status = ldns_resolver_query_status(
770
&pkt, res, qname, type, clas, qflags);
771
if (status != LDNS_STATUS_OK) {
772
error("error sending query: %s",
773
ldns_get_errorstr_by_id(status));
774
}
775
if (!pkt) {
776
if (status == LDNS_STATUS_OK) {
777
error("%s", "error pkt sending");
778
}
779
result = EXIT_FAILURE;
780
} else {
781
if (verbosity >= 3) {
782
ldns_pkt_print(stdout, pkt);
783
}
784
785
if (!ldns_pkt_answer(pkt)) {
786
mesg("No answer in packet");
787
} else {
788
#ifdef HAVE_SSL
789
ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list));
790
result = do_chase(res, qname, type,
791
clas, key_list,
792
pkt, qflags, NULL);
793
if (result == LDNS_STATUS_OK) {
794
if (verbosity != -1) {
795
mesg("Chase successful");
796
}
797
result = 0;
798
} else {
799
if (verbosity != -1) {
800
mesg("Chase failed.");
801
}
802
}
803
#endif /* HAVE_SSL */
804
}
805
ldns_pkt_free(pkt);
806
}
807
break;
808
case DRILL_AFROMFILE:
809
pkt = read_hex_pkt(answer_file);
810
if (pkt) {
811
if (verbosity != -1) {
812
ldns_pkt_print(stdout, pkt);
813
}
814
ldns_pkt_free(pkt);
815
}
816
817
break;
818
case DRILL_QTOFILE:
819
qname = ldns_dname_new_frm_str(name);
820
if (!qname) {
821
error("%s", "making qname");
822
}
823
status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags);
824
if(status != LDNS_STATUS_OK) {
825
error("%s", "making query: %s",
826
ldns_get_errorstr_by_id(status));
827
}
828
dump_hex(qpkt, query_file);
829
ldns_pkt_free(qpkt);
830
break;
831
case DRILL_NSEC:
832
break;
833
case DRILL_QUERY:
834
default:
835
if (query_file) {
836
/* this old way, the query packet needed
837
to be parseable, but we want to be able
838
to send mangled packets, so we need
839
to do it directly */
840
#if 0
841
qpkt = read_hex_pkt(query_file);
842
if (qpkt) {
843
status = ldns_resolver_send_pkt(&pkt, res, qpkt);
844
if (status != LDNS_STATUS_OK) {
845
printf("Error: %s\n", ldns_get_errorstr_by_id(status));
846
exit(1);
847
}
848
} else {
849
/* qpkt was bogus, reset pkt */
850
pkt = NULL;
851
}
852
#endif
853
query_buffer = read_hex_buffer(query_file);
854
if (query_buffer) {
855
status = ldns_send_buffer(&pkt, res, query_buffer, NULL);
856
ldns_buffer_free(query_buffer);
857
if (status != LDNS_STATUS_OK) {
858
printf("Error: %s\n", ldns_get_errorstr_by_id(status));
859
exit(1);
860
}
861
} else {
862
printf("NO BUFFER\n");
863
pkt = NULL;
864
}
865
} else {
866
qname = ldns_dname_new_frm_str(name);
867
if (!qname) {
868
error("%s", "error in making qname");
869
}
870
871
if (type == LDNS_RR_TYPE_AXFR) {
872
status = ldns_axfr_start(res, qname, clas);
873
if(status != LDNS_STATUS_OK) {
874
error("Error starting axfr: %s",
875
ldns_get_errorstr_by_id(status));
876
}
877
axfr_rr = ldns_axfr_next(res);
878
if(!axfr_rr) {
879
fprintf(stderr, "AXFR failed.\n");
880
ldns_pkt_print(stdout,
881
ldns_axfr_last_pkt(res));
882
goto exit;
883
}
884
while (axfr_rr) {
885
if (verbosity != -1) {
886
ldns_rr_print(stdout, axfr_rr);
887
}
888
ldns_rr_free(axfr_rr);
889
axfr_rr = ldns_axfr_next(res);
890
}
891
892
goto exit;
893
} else {
894
/* create a packet and set the RD flag on it */
895
pkt = NULL;
896
897
status = ldns_resolver_prepare_query_pkt(&qpkt,
898
res, qname, type, clas, qflags);
899
if(status != LDNS_STATUS_OK) {
900
error("%s", "making query: %s",
901
ldns_get_errorstr_by_id(status));
902
}
903
904
if (edns_list) {
905
/* attach the structed EDNS options */
906
ldns_pkt_set_edns_option_list(qpkt, edns_list);
907
}
908
909
status = ldns_resolver_send_pkt(&pkt, res, qpkt);
910
ldns_pkt_free(qpkt);
911
912
if (status != LDNS_STATUS_OK) {
913
error("error sending query: %s"
914
, ldns_get_errorstr_by_id(
915
status));
916
}
917
}
918
}
919
920
/* now handling the response message/packet */
921
if (!pkt) {
922
mesg("No packet received");
923
result = EXIT_FAILURE;
924
} else {
925
ldns_pkt_print_fmt(stdout, fmt, pkt);
926
if (verbosity != -1) {
927
if (ldns_pkt_tc(pkt)) {
928
fprintf(stdout,
929
"\n;; WARNING: The answer packet was truncated; you might want to\n");
930
fprintf(stdout,
931
";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n");
932
}
933
}
934
if (qds) {
935
if (verbosity != -1) {
936
print_ds_of_keys(pkt);
937
printf("\n");
938
}
939
}
940
941
if (ldns_rr_list_rr_count(key_list) > 0) {
942
/* -k's were given on the cmd line */
943
ldns_rr_list *rrset_verified;
944
uint16_t key_count;
945
946
rrset_verified = ldns_pkt_rr_list_by_name_and_type(
947
pkt, qname, type,
948
LDNS_SECTION_ANY_NOQUESTION);
949
950
if (type == LDNS_RR_TYPE_ANY) {
951
/* don't verify this */
952
break;
953
}
954
955
if (verbosity != -1) {
956
printf("; ");
957
ldns_rr_list_print(stdout, rrset_verified);
958
}
959
960
/* verify */
961
#ifdef HAVE_SSL
962
key_verified = ldns_rr_list_new();
963
result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified);
964
965
if (result == LDNS_STATUS_ERR) {
966
/* is the existence denied then? */
967
result = ldns_verify_denial(pkt, qname, type, NULL, NULL);
968
if (result == LDNS_STATUS_OK) {
969
if (verbosity != -1) {
970
printf("Existence denied for ");
971
ldns_rdf_print(stdout, qname);
972
type_str = ldns_rr_type2str(type);
973
printf("\t%s\n", type_str);
974
LDNS_FREE(type_str);
975
}
976
} else {
977
if (verbosity != -1) {
978
printf("Bad data; RR for name and "
979
"type not found or failed to "
980
"verify, and denial of "
981
"existence failed.\n");
982
}
983
}
984
} else if (result == LDNS_STATUS_OK) {
985
for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified);
986
key_count++) {
987
if (verbosity != -1) {
988
printf("; VALIDATED by id = %u, owner = ",
989
(unsigned int)ldns_calc_keytag(
990
ldns_rr_list_rr(key_verified, key_count)));
991
ldns_rdf_print(stdout, ldns_rr_owner(
992
ldns_rr_list_rr(key_list, key_count)));
993
printf("\n");
994
}
995
}
996
} else {
997
for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list);
998
key_count++) {
999
if (verbosity != -1) {
1000
printf("; %s for id = %u, owner = ",
1001
ldns_get_errorstr_by_id(result),
1002
(unsigned int)ldns_calc_keytag(
1003
ldns_rr_list_rr(key_list, key_count)));
1004
ldns_rdf_print(stdout, ldns_rr_owner(
1005
1006
ldns_rr_list_rr(key_list,
1007
key_count)));
1008
printf("\n");
1009
}
1010
}
1011
}
1012
ldns_rr_list_free(key_verified);
1013
#else
1014
(void) key_count;
1015
#endif /* HAVE_SSL */
1016
}
1017
if (answer_file) {
1018
dump_hex(pkt, answer_file);
1019
}
1020
ldns_pkt_free(pkt);
1021
}
1022
1023
break;
1024
}
1025
1026
exit:
1027
ldns_rdf_deep_free(qname);
1028
ldns_rdf_deep_free(src_rdf);
1029
ldns_resolver_deep_free(res);
1030
ldns_resolver_deep_free(cmdline_res);
1031
ldns_rr_list_deep_free(key_list);
1032
ldns_rr_list_deep_free(cmdline_rr_list);
1033
ldns_rdf_deep_free(trace_start_name);
1034
xfree(progname);
1035
xfree(tsig_name);
1036
xfree(tsig_data);
1037
xfree(tsig_algorithm);
1038
1039
#ifdef HAVE_SSL
1040
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(HAVE_LIBRESSL)
1041
#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
1042
CRYPTO_cleanup_all_ex_data ();
1043
#endif
1044
#ifdef HAVE_ERR_FREE_STRINGS
1045
ERR_free_strings ();
1046
#endif
1047
#ifdef HAVE_EVP_CLEANUP
1048
EVP_cleanup ();
1049
#endif
1050
#endif
1051
#endif
1052
#ifdef USE_WINSOCK
1053
WSACleanup();
1054
#endif
1055
1056
return result;
1057
}
1058
1059