1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer * drill.c
3825eb42bSJan Lentfer * the main file of drill
4825eb42bSJan Lentfer * (c) 2005-2008 NLnet Labs
5825eb42bSJan Lentfer *
6825eb42bSJan Lentfer * See the file LICENSE for the license
7825eb42bSJan Lentfer *
8825eb42bSJan Lentfer */
9825eb42bSJan Lentfer
10825eb42bSJan Lentfer #include "drill.h"
11825eb42bSJan Lentfer #include <ldns/ldns.h>
12825eb42bSJan Lentfer
13825eb42bSJan Lentfer #ifdef HAVE_SSL
14825eb42bSJan Lentfer #include <openssl/err.h>
15825eb42bSJan Lentfer #endif
16825eb42bSJan Lentfer
17825eb42bSJan Lentfer /* query debug, 2 hex dumps */
18825eb42bSJan Lentfer int verbosity;
19825eb42bSJan Lentfer
205340022aSzrj static int
is_ixfr_with_serial(const char * name,uint32_t * serial)215340022aSzrj is_ixfr_with_serial(const char* name, uint32_t *serial)
225340022aSzrj {
235340022aSzrj char* end;
245340022aSzrj if (strlen(name) > 5 &&
255340022aSzrj strncasecmp(name, "IXFR", 4) == 0 &&
265340022aSzrj name[4] == '=') {
275340022aSzrj *serial = (uint32_t) strtol((name+5), &end, 10);
285340022aSzrj return 1;
295340022aSzrj }
305340022aSzrj return 0;
315340022aSzrj }
325340022aSzrj
33825eb42bSJan Lentfer static void
usage(FILE * stream,const char * progname)34825eb42bSJan Lentfer usage(FILE *stream, const char *progname)
35825eb42bSJan Lentfer {
36825eb42bSJan Lentfer fprintf(stream, " Usage: %s name [@server] [type] [class]\n", progname);
37825eb42bSJan Lentfer fprintf(stream, "\t<name> can be a domain name or an IP address (-x lookups)\n");
38825eb42bSJan Lentfer fprintf(stream, "\t<type> defaults to A\n");
39825eb42bSJan Lentfer fprintf(stream, "\t<class> defaults to IN\n");
40825eb42bSJan Lentfer fprintf(stream, "\n\targuments may be placed in random order\n");
41825eb42bSJan Lentfer fprintf(stream, "\n Options:\n");
42825eb42bSJan Lentfer fprintf(stream, "\t-D\t\tenable DNSSEC (DO bit)\n");
43825eb42bSJan Lentfer #ifdef HAVE_SSL
44825eb42bSJan Lentfer fprintf(stream, "\t-T\t\ttrace from the root down to <name>\n");
455340022aSzrj fprintf(stream, "\t-S\t\tchase signature(s) from <name> to a known key [*]\n");
46825eb42bSJan Lentfer #endif /*HAVE_SSL*/
475340022aSzrj fprintf(stream, "\t-I <address>\tsource address to query from\n");
48825eb42bSJan Lentfer fprintf(stream, "\t-V <number>\tverbosity (0-5)\n");
49825eb42bSJan Lentfer fprintf(stream, "\t-Q\t\tquiet mode (overrules -V)\n");
50825eb42bSJan Lentfer fprintf(stream, "\n");
51825eb42bSJan Lentfer fprintf(stream, "\t-f file\t\tread packet from file and send it\n");
52825eb42bSJan Lentfer fprintf(stream, "\t-i file\t\tread packet from file and print it\n");
53825eb42bSJan Lentfer fprintf(stream, "\t-w file\t\twrite answer packet to file\n");
54825eb42bSJan Lentfer fprintf(stream, "\t-q file\t\twrite query packet to file\n");
55825eb42bSJan Lentfer fprintf(stream, "\t-h\t\tshow this help\n");
56825eb42bSJan Lentfer fprintf(stream, "\t-v\t\tshow version\n");
57825eb42bSJan Lentfer fprintf(stream, "\n Query options:\n");
58825eb42bSJan Lentfer fprintf(stream, "\t-4\t\tstay on ip4\n");
59825eb42bSJan Lentfer fprintf(stream, "\t-6\t\tstay on ip6\n");
60825eb42bSJan Lentfer fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n");
61825eb42bSJan Lentfer fprintf(stream, "\t-b <bufsize>\tuse <bufsize> as the buffer size (defaults to 512 b)\n");
62*ee791febSAntonio Huete Jimenez fprintf(stream, "\t-c <file>\tuse file for recursive nameserver configuration"
63d1b2b5caSJohn Marino "\n\t\t\t(/etc/resolv.conf)\n");
64d1b2b5caSJohn Marino fprintf(stream, "\t-k <file>\tspecify a file that contains a trusted DNSSEC key [**]\n");
65d1b2b5caSJohn Marino fprintf(stream, "\t\t\tUsed to verify any signatures in the current answer.\n");
66d1b2b5caSJohn Marino fprintf(stream, "\t\t\tWhen DNSSEC enabled tracing (-TD) or signature\n"
67d1b2b5caSJohn Marino "\t\t\tchasing (-S) and no key files are given, keys are read\n"
68d1b2b5caSJohn Marino "\t\t\tfrom: %s\n",
69d1b2b5caSJohn Marino LDNS_TRUST_ANCHOR_FILE);
70d1b2b5caSJohn Marino fprintf(stream, "\t-o <mnemonic>\tset flags to:"
71d1b2b5caSJohn Marino "\n\t\t\t[QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n");
72825eb42bSJan Lentfer fprintf(stream, "\t\t\tlowercase: unset bit, uppercase: set bit\n");
73825eb42bSJan Lentfer fprintf(stream, "\t-p <port>\tuse <port> as remote port number\n");
74825eb42bSJan Lentfer fprintf(stream, "\t-s\t\tshow the DS RR for each key in a packet\n");
75825eb42bSJan Lentfer fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n");
76825eb42bSJan Lentfer fprintf(stream, "\t-x\t\tdo a reverse lookup\n");
77825eb42bSJan Lentfer fprintf(stream, "\twhen doing a secure trace:\n");
78d1b2b5caSJohn Marino fprintf(stream, "\t-r <file>\tuse file as root servers hint file\n");
79825eb42bSJan Lentfer fprintf(stream, "\t-t\t\tsend the query with tcp (connected)\n");
80d1b2b5caSJohn Marino fprintf(stream, "\t-d <domain>\tuse domain as the start point for the trace\n");
81825eb42bSJan Lentfer 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");
82825eb42bSJan Lentfer fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n");
83825eb42bSJan Lentfer fprintf(stream, "\n [*] = enables/implies DNSSEC\n");
84825eb42bSJan Lentfer fprintf(stream, " [**] = can be given more than once\n");
85825eb42bSJan Lentfer fprintf(stream, "\n ldns-team@nlnetlabs.nl | http://www.nlnetlabs.nl/ldns/\n");
86825eb42bSJan Lentfer }
87825eb42bSJan Lentfer
88825eb42bSJan Lentfer /**
89825eb42bSJan Lentfer * Prints the drill version to stderr
90825eb42bSJan Lentfer */
91825eb42bSJan Lentfer static void
version(FILE * stream,const char * progname)92825eb42bSJan Lentfer version(FILE *stream, const char *progname)
93825eb42bSJan Lentfer {
94825eb42bSJan Lentfer fprintf(stream, "%s version %s (ldns version %s)\n", progname, DRILL_VERSION, ldns_version());
95825eb42bSJan Lentfer fprintf(stream, "Written by NLnet Labs.\n");
96825eb42bSJan Lentfer fprintf(stream, "\nCopyright (c) 2004-2008 NLnet Labs.\n");
97825eb42bSJan Lentfer fprintf(stream, "Licensed under the revised BSD license.\n");
98825eb42bSJan Lentfer fprintf(stream, "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n");
99825eb42bSJan Lentfer fprintf(stream, "FOR A PARTICULAR PURPOSE.\n");
100825eb42bSJan Lentfer }
101825eb42bSJan Lentfer
102825eb42bSJan Lentfer
103825eb42bSJan Lentfer /**
104825eb42bSJan Lentfer * Main function of drill
105825eb42bSJan Lentfer * parse the arguments and prepare a query
106825eb42bSJan Lentfer */
107825eb42bSJan Lentfer int
main(int argc,char * argv[])108825eb42bSJan Lentfer main(int argc, char *argv[])
109825eb42bSJan Lentfer {
110825eb42bSJan Lentfer ldns_resolver *res = NULL;
111825eb42bSJan Lentfer ldns_resolver *cmdline_res = NULL; /* only used to resolv @name names */
112825eb42bSJan Lentfer ldns_rr_list *cmdline_rr_list = NULL;
113825eb42bSJan Lentfer ldns_rdf *cmdline_dname = NULL;
114819dec71SDaniel Fojt ldns_rdf *qname;
115825eb42bSJan Lentfer ldns_pkt *pkt;
116825eb42bSJan Lentfer ldns_pkt *qpkt;
117825eb42bSJan Lentfer char *serv;
1185340022aSzrj char *src = NULL;
119d1b2b5caSJohn Marino const char *name;
120825eb42bSJan Lentfer char *progname;
121825eb42bSJan Lentfer char *query_file = NULL;
122825eb42bSJan Lentfer char *answer_file = NULL;
123825eb42bSJan Lentfer ldns_buffer *query_buffer = NULL;
124825eb42bSJan Lentfer ldns_rdf *serv_rdf;
1255340022aSzrj ldns_rdf *src_rdf = NULL;
126825eb42bSJan Lentfer ldns_rr_type type;
127825eb42bSJan Lentfer ldns_rr_class clas;
128825eb42bSJan Lentfer #if 0
129825eb42bSJan Lentfer ldns_pkt_opcode opcode = LDNS_PACKET_QUERY;
130825eb42bSJan Lentfer #endif
131825eb42bSJan Lentfer int i, c;
132825eb42bSJan Lentfer int int_type;
133825eb42bSJan Lentfer int int_clas;
134825eb42bSJan Lentfer int PURPOSE;
135825eb42bSJan Lentfer char *tsig_name = NULL;
136825eb42bSJan Lentfer char *tsig_data = NULL;
137825eb42bSJan Lentfer char *tsig_algorithm = NULL;
138825eb42bSJan Lentfer size_t tsig_separator;
139825eb42bSJan Lentfer size_t tsig_separator2;
140825eb42bSJan Lentfer ldns_rr *axfr_rr;
141825eb42bSJan Lentfer ldns_status status;
142825eb42bSJan Lentfer char *type_str;
1435340022aSzrj uint32_t serial = 0;
144825eb42bSJan Lentfer /* list of keys used in dnssec operations */
145825eb42bSJan Lentfer ldns_rr_list *key_list = ldns_rr_list_new();
146825eb42bSJan Lentfer /* what key verify the current answer */
147825eb42bSJan Lentfer ldns_rr_list *key_verified;
148825eb42bSJan Lentfer
149825eb42bSJan Lentfer /* resolver options */
150825eb42bSJan Lentfer uint16_t qflags;
151825eb42bSJan Lentfer uint16_t qbuf;
152825eb42bSJan Lentfer uint16_t qport;
153825eb42bSJan Lentfer uint8_t qfamily;
154825eb42bSJan Lentfer bool qdnssec;
155825eb42bSJan Lentfer bool qfallback;
156825eb42bSJan Lentfer bool qds;
157825eb42bSJan Lentfer bool qusevc;
158825eb42bSJan Lentfer bool qrandom;
159819dec71SDaniel Fojt bool drill_reverse = false;
160825eb42bSJan Lentfer
161825eb42bSJan Lentfer char *resolv_conf_file = NULL;
162825eb42bSJan Lentfer
163825eb42bSJan Lentfer ldns_rdf *trace_start_name = NULL;
164825eb42bSJan Lentfer
165825eb42bSJan Lentfer int result = 0;
166825eb42bSJan Lentfer
1675340022aSzrj uint8_t s6addr[16];
1685340022aSzrj char ip6_arpa_str[74];
169819dec71SDaniel Fojt uint8_t s4addr[4];
170819dec71SDaniel Fojt char in_addr_arpa_str[40];
1715340022aSzrj
172825eb42bSJan Lentfer #ifdef USE_WINSOCK
173825eb42bSJan Lentfer int r;
174825eb42bSJan Lentfer WSADATA wsa_data;
175825eb42bSJan Lentfer #endif
176*ee791febSAntonio Huete Jimenez ldns_output_format_storage fmt_storage;
177*ee791febSAntonio Huete Jimenez ldns_output_format* fmt = ldns_output_format_init(&fmt_storage);
178825eb42bSJan Lentfer
179825eb42bSJan Lentfer int_type = -1; serv = NULL; type = 0;
180825eb42bSJan Lentfer int_clas = -1; name = NULL; clas = 0;
1815340022aSzrj qname = NULL; src = NULL;
182825eb42bSJan Lentfer progname = strdup(argv[0]);
183825eb42bSJan Lentfer
184825eb42bSJan Lentfer #ifdef USE_WINSOCK
185825eb42bSJan Lentfer r = WSAStartup(MAKEWORD(2,2), &wsa_data);
186825eb42bSJan Lentfer if(r != 0) {
187825eb42bSJan Lentfer printf("Failed WSAStartup: %d\n", r);
188825eb42bSJan Lentfer result = EXIT_FAILURE;
189825eb42bSJan Lentfer goto exit;
190825eb42bSJan Lentfer }
191825eb42bSJan Lentfer #endif /* USE_WINSOCK */
192825eb42bSJan Lentfer
193825eb42bSJan Lentfer
194825eb42bSJan Lentfer PURPOSE = DRILL_QUERY;
195825eb42bSJan Lentfer qflags = LDNS_RD;
196825eb42bSJan Lentfer qport = LDNS_PORT;
197825eb42bSJan Lentfer verbosity = 2;
198825eb42bSJan Lentfer qdnssec = false;
199825eb42bSJan Lentfer qfamily = LDNS_RESOLV_INETANY;
200825eb42bSJan Lentfer qfallback = false;
201825eb42bSJan Lentfer qds = false;
202825eb42bSJan Lentfer qbuf = 0;
203825eb42bSJan Lentfer qusevc = false;
204825eb42bSJan Lentfer qrandom = true;
205825eb42bSJan Lentfer key_verified = NULL;
206*ee791febSAntonio Huete Jimenez ldns_edns_option_list* edns_list = NULL;
207825eb42bSJan Lentfer
208825eb42bSJan Lentfer ldns_init_random(NULL, 0);
209825eb42bSJan Lentfer
210825eb42bSJan Lentfer /* string from orig drill: "i:w:I46Sk:TNp:b:DsvhVcuaq:f:xr" */
211825eb42bSJan Lentfer /* global first, query opt next, option with parm's last
212825eb42bSJan Lentfer * and sorted */ /* "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */
213825eb42bSJan Lentfer
2145340022aSzrj while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:I:k:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) {
215825eb42bSJan Lentfer switch(c) {
216825eb42bSJan Lentfer /* global options */
217825eb42bSJan Lentfer case '4':
218825eb42bSJan Lentfer qfamily = LDNS_RESOLV_INET;
219825eb42bSJan Lentfer break;
220825eb42bSJan Lentfer case '6':
221825eb42bSJan Lentfer qfamily = LDNS_RESOLV_INET6;
222825eb42bSJan Lentfer break;
223825eb42bSJan Lentfer case 'D':
224825eb42bSJan Lentfer qdnssec = true;
225825eb42bSJan Lentfer break;
226825eb42bSJan Lentfer case 'I':
2275340022aSzrj src = optarg;
228825eb42bSJan Lentfer break;
229825eb42bSJan Lentfer case 'T':
230825eb42bSJan Lentfer if (PURPOSE == DRILL_CHASE) {
231825eb42bSJan Lentfer fprintf(stderr, "-T and -S cannot be used at the same time.\n");
232825eb42bSJan Lentfer exit(EXIT_FAILURE);
233825eb42bSJan Lentfer }
234825eb42bSJan Lentfer PURPOSE = DRILL_TRACE;
235825eb42bSJan Lentfer break;
236825eb42bSJan Lentfer #ifdef HAVE_SSL
237825eb42bSJan Lentfer case 'S':
238825eb42bSJan Lentfer if (PURPOSE == DRILL_TRACE) {
239825eb42bSJan Lentfer fprintf(stderr, "-T and -S cannot be used at the same time.\n");
240825eb42bSJan Lentfer exit(EXIT_FAILURE);
241825eb42bSJan Lentfer }
242825eb42bSJan Lentfer PURPOSE = DRILL_CHASE;
243825eb42bSJan Lentfer break;
244825eb42bSJan Lentfer #endif /* HAVE_SSL */
245825eb42bSJan Lentfer case 'V':
246d1b2b5caSJohn Marino if (strtok(optarg, "0123456789") != NULL) {
247d1b2b5caSJohn Marino fprintf(stderr, "-V expects an number as an argument.\n");
248d1b2b5caSJohn Marino exit(EXIT_FAILURE);
249d1b2b5caSJohn Marino }
250825eb42bSJan Lentfer verbosity = atoi(optarg);
251825eb42bSJan Lentfer break;
252825eb42bSJan Lentfer case 'Q':
253*ee791febSAntonio Huete Jimenez fmt->flags |= LDNS_FMT_SHORT;
254825eb42bSJan Lentfer verbosity = -1;
255825eb42bSJan Lentfer break;
256825eb42bSJan Lentfer case 'f':
257825eb42bSJan Lentfer query_file = optarg;
258825eb42bSJan Lentfer break;
259825eb42bSJan Lentfer case 'i':
260825eb42bSJan Lentfer answer_file = optarg;
261825eb42bSJan Lentfer PURPOSE = DRILL_AFROMFILE;
262825eb42bSJan Lentfer break;
263825eb42bSJan Lentfer case 'w':
264825eb42bSJan Lentfer answer_file = optarg;
265825eb42bSJan Lentfer break;
266825eb42bSJan Lentfer case 'q':
267825eb42bSJan Lentfer query_file = optarg;
268825eb42bSJan Lentfer PURPOSE = DRILL_QTOFILE;
269825eb42bSJan Lentfer break;
270825eb42bSJan Lentfer case 'r':
271825eb42bSJan Lentfer if (global_dns_root) {
272825eb42bSJan Lentfer fprintf(stderr, "There was already a series of root servers set\n");
273825eb42bSJan Lentfer exit(EXIT_FAILURE);
274825eb42bSJan Lentfer }
275825eb42bSJan Lentfer global_dns_root = read_root_hints(optarg);
276825eb42bSJan Lentfer if (!global_dns_root) {
277825eb42bSJan Lentfer fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg);
278825eb42bSJan Lentfer exit(EXIT_FAILURE);
279825eb42bSJan Lentfer }
280825eb42bSJan Lentfer break;
281825eb42bSJan Lentfer /* query options */
282825eb42bSJan Lentfer case 'a':
283825eb42bSJan Lentfer qfallback = true;
284825eb42bSJan Lentfer break;
285825eb42bSJan Lentfer case 'b':
286825eb42bSJan Lentfer qbuf = (uint16_t)atoi(optarg);
287825eb42bSJan Lentfer if (qbuf == 0) {
288825eb42bSJan Lentfer error("%s", "<bufsize> could not be converted");
289825eb42bSJan Lentfer }
290825eb42bSJan Lentfer break;
291825eb42bSJan Lentfer case 'c':
292825eb42bSJan Lentfer resolv_conf_file = optarg;
293825eb42bSJan Lentfer break;
294825eb42bSJan Lentfer case 't':
295825eb42bSJan Lentfer qusevc = true;
296825eb42bSJan Lentfer break;
297825eb42bSJan Lentfer case 'k':
298d1b2b5caSJohn Marino status = read_key_file(optarg,
299d1b2b5caSJohn Marino key_list, false);
300825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) {
301825eb42bSJan Lentfer error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status));
302825eb42bSJan Lentfer }
303825eb42bSJan Lentfer qdnssec = true; /* enable that too */
304825eb42bSJan Lentfer break;
305825eb42bSJan Lentfer case 'o':
306825eb42bSJan Lentfer /* only looks at the first hit: capital=ON, lowercase=OFF*/
307825eb42bSJan Lentfer if (strstr(optarg, "QR")) {
308825eb42bSJan Lentfer DRILL_ON(qflags, LDNS_QR);
309825eb42bSJan Lentfer }
310825eb42bSJan Lentfer if (strstr(optarg, "qr")) {
311825eb42bSJan Lentfer DRILL_OFF(qflags, LDNS_QR);
312825eb42bSJan Lentfer }
313825eb42bSJan Lentfer if (strstr(optarg, "AA")) {
314825eb42bSJan Lentfer DRILL_ON(qflags, LDNS_AA);
315825eb42bSJan Lentfer }
316825eb42bSJan Lentfer if (strstr(optarg, "aa")) {
317825eb42bSJan Lentfer DRILL_OFF(qflags, LDNS_AA);
318825eb42bSJan Lentfer }
319825eb42bSJan Lentfer if (strstr(optarg, "TC")) {
320825eb42bSJan Lentfer DRILL_ON(qflags, LDNS_TC);
321825eb42bSJan Lentfer }
322825eb42bSJan Lentfer if (strstr(optarg, "tc")) {
323825eb42bSJan Lentfer DRILL_OFF(qflags, LDNS_TC);
324825eb42bSJan Lentfer }
325825eb42bSJan Lentfer if (strstr(optarg, "RD")) {
326825eb42bSJan Lentfer DRILL_ON(qflags, LDNS_RD);
327825eb42bSJan Lentfer }
328825eb42bSJan Lentfer if (strstr(optarg, "rd")) {
329825eb42bSJan Lentfer DRILL_OFF(qflags, LDNS_RD);
330825eb42bSJan Lentfer }
331825eb42bSJan Lentfer if (strstr(optarg, "CD")) {
332825eb42bSJan Lentfer DRILL_ON(qflags, LDNS_CD);
333825eb42bSJan Lentfer }
334825eb42bSJan Lentfer if (strstr(optarg, "cd")) {
335825eb42bSJan Lentfer DRILL_OFF(qflags, LDNS_CD);
336825eb42bSJan Lentfer }
337825eb42bSJan Lentfer if (strstr(optarg, "RA")) {
338825eb42bSJan Lentfer DRILL_ON(qflags, LDNS_RA);
339825eb42bSJan Lentfer }
340825eb42bSJan Lentfer if (strstr(optarg, "ra")) {
341825eb42bSJan Lentfer DRILL_OFF(qflags, LDNS_RA);
342825eb42bSJan Lentfer }
343825eb42bSJan Lentfer if (strstr(optarg, "AD")) {
344825eb42bSJan Lentfer DRILL_ON(qflags, LDNS_AD);
345825eb42bSJan Lentfer }
346825eb42bSJan Lentfer if (strstr(optarg, "ad")) {
347825eb42bSJan Lentfer DRILL_OFF(qflags, LDNS_AD);
348825eb42bSJan Lentfer }
349825eb42bSJan Lentfer break;
350825eb42bSJan Lentfer case 'p':
351825eb42bSJan Lentfer qport = (uint16_t)atoi(optarg);
352825eb42bSJan Lentfer if (qport == 0) {
353825eb42bSJan Lentfer error("%s", "<port> could not be converted");
354825eb42bSJan Lentfer }
355825eb42bSJan Lentfer break;
356825eb42bSJan Lentfer case 's':
357825eb42bSJan Lentfer qds = true;
358825eb42bSJan Lentfer break;
359825eb42bSJan Lentfer case 'u':
360825eb42bSJan Lentfer qusevc = false;
361825eb42bSJan Lentfer break;
362825eb42bSJan Lentfer case 'v':
363825eb42bSJan Lentfer version(stdout, progname);
364825eb42bSJan Lentfer result = EXIT_SUCCESS;
365825eb42bSJan Lentfer goto exit;
366825eb42bSJan Lentfer case 'x':
367819dec71SDaniel Fojt drill_reverse = true;
368825eb42bSJan Lentfer break;
369825eb42bSJan Lentfer case 'y':
370825eb42bSJan Lentfer #ifdef HAVE_SSL
371825eb42bSJan Lentfer if (strchr(optarg, ':')) {
372825eb42bSJan Lentfer tsig_separator = (size_t) (strchr(optarg, ':') - optarg);
373819dec71SDaniel Fojt if (tsig_algorithm) {
374819dec71SDaniel Fojt free(tsig_algorithm);
375819dec71SDaniel Fojt tsig_algorithm = NULL;
376819dec71SDaniel Fojt }
377825eb42bSJan Lentfer if (strchr(optarg + tsig_separator + 1, ':')) {
378825eb42bSJan Lentfer tsig_separator2 = (size_t) (strchr(optarg + tsig_separator + 1, ':') - optarg);
379825eb42bSJan Lentfer tsig_algorithm = xmalloc(strlen(optarg) - tsig_separator2);
380825eb42bSJan Lentfer strncpy(tsig_algorithm, optarg + tsig_separator2 + 1, strlen(optarg) - tsig_separator2);
381825eb42bSJan Lentfer tsig_algorithm[strlen(optarg) - tsig_separator2 - 1] = '\0';
382825eb42bSJan Lentfer } else {
383825eb42bSJan Lentfer tsig_separator2 = strlen(optarg);
3845340022aSzrj tsig_algorithm = strdup("hmac-md5.sig-alg.reg.int");
385825eb42bSJan Lentfer }
386825eb42bSJan Lentfer tsig_name = xmalloc(tsig_separator + 1);
387825eb42bSJan Lentfer tsig_data = xmalloc(tsig_separator2 - tsig_separator);
388825eb42bSJan Lentfer strncpy(tsig_name, optarg, tsig_separator);
389825eb42bSJan Lentfer strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1);
390825eb42bSJan Lentfer /* strncpy does not append \0 if source is longer than n */
391825eb42bSJan Lentfer tsig_name[tsig_separator] = '\0';
392825eb42bSJan Lentfer tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0';
393825eb42bSJan Lentfer }
394825eb42bSJan Lentfer #else
395825eb42bSJan Lentfer fprintf(stderr, "TSIG requested, but SSL is not supported\n");
396825eb42bSJan Lentfer result = EXIT_FAILURE;
397825eb42bSJan Lentfer goto exit;
398825eb42bSJan Lentfer #endif /* HAVE_SSL */
399825eb42bSJan Lentfer break;
400825eb42bSJan Lentfer case 'z':
401825eb42bSJan Lentfer qrandom = false;
402825eb42bSJan Lentfer break;
403825eb42bSJan Lentfer case 'd':
404825eb42bSJan Lentfer trace_start_name = ldns_dname_new_frm_str(optarg);
405825eb42bSJan Lentfer if (!trace_start_name) {
406825eb42bSJan Lentfer fprintf(stderr, "Unable to parse argument for -%c\n", c);
407825eb42bSJan Lentfer result = EXIT_FAILURE;
408825eb42bSJan Lentfer goto exit;
409825eb42bSJan Lentfer }
410825eb42bSJan Lentfer break;
411825eb42bSJan Lentfer case 'h':
412825eb42bSJan Lentfer version(stdout, progname);
413825eb42bSJan Lentfer usage(stdout, progname);
414825eb42bSJan Lentfer result = EXIT_SUCCESS;
415825eb42bSJan Lentfer goto exit;
416825eb42bSJan Lentfer break;
417825eb42bSJan Lentfer default:
418825eb42bSJan Lentfer fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c);
419825eb42bSJan Lentfer result = EXIT_FAILURE;
420825eb42bSJan Lentfer goto exit;
421825eb42bSJan Lentfer }
422825eb42bSJan Lentfer }
423825eb42bSJan Lentfer argc -= optind;
424825eb42bSJan Lentfer argv += optind;
425825eb42bSJan Lentfer
426d1b2b5caSJohn Marino if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) &&
427d1b2b5caSJohn Marino ldns_rr_list_rr_count(key_list) == 0) {
428d1b2b5caSJohn Marino
429d1b2b5caSJohn Marino (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true);
430d1b2b5caSJohn Marino }
431d1b2b5caSJohn Marino if (ldns_rr_list_rr_count(key_list) > 0) {
432d1b2b5caSJohn Marino printf(";; Number of trusted keys: %d\n",
433d1b2b5caSJohn Marino (int) ldns_rr_list_rr_count(key_list));
434d1b2b5caSJohn Marino }
435825eb42bSJan Lentfer /* do a secure trace when requested */
436825eb42bSJan Lentfer if (PURPOSE == DRILL_TRACE && qdnssec) {
437825eb42bSJan Lentfer #ifdef HAVE_SSL
438825eb42bSJan Lentfer if (ldns_rr_list_rr_count(key_list) == 0) {
439825eb42bSJan Lentfer warning("%s", "No trusted keys were given. Will not be able to verify authenticity!");
440825eb42bSJan Lentfer }
441825eb42bSJan Lentfer PURPOSE = DRILL_SECTRACE;
442825eb42bSJan Lentfer #else
443825eb42bSJan Lentfer fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n");
444825eb42bSJan Lentfer exit(1);
445825eb42bSJan Lentfer #endif /* HAVE_SSL */
446825eb42bSJan Lentfer }
447825eb42bSJan Lentfer
448825eb42bSJan Lentfer /* parse the arguments, with multiple arguments, the last argument
449825eb42bSJan Lentfer * found is used */
450825eb42bSJan Lentfer for(i = 0; i < argc; i++) {
451825eb42bSJan Lentfer
452825eb42bSJan Lentfer /* if ^@ then it's a server */
453825eb42bSJan Lentfer if (argv[i][0] == '@') {
454825eb42bSJan Lentfer if (strlen(argv[i]) == 1) {
455825eb42bSJan Lentfer warning("%s", "No nameserver given");
456825eb42bSJan Lentfer exit(EXIT_FAILURE);
457825eb42bSJan Lentfer }
458825eb42bSJan Lentfer serv = argv[i] + 1;
459825eb42bSJan Lentfer continue;
460825eb42bSJan Lentfer }
461*ee791febSAntonio Huete Jimenez /* if ^+ then it's an EDNS option */
462*ee791febSAntonio Huete Jimenez if (argv[i][0] == '+') {
463*ee791febSAntonio Huete Jimenez if (!strcmp(argv[i]+1, "nsid")) {
464*ee791febSAntonio Huete Jimenez ldns_edns_option *edns;
465*ee791febSAntonio Huete Jimenez edns_list = ldns_edns_option_list_new();
466*ee791febSAntonio Huete Jimenez
467*ee791febSAntonio Huete Jimenez /* create NSID EDNS*/
468*ee791febSAntonio Huete Jimenez edns = ldns_edns_new_from_data(LDNS_EDNS_NSID, 0, NULL);
469*ee791febSAntonio Huete Jimenez
470*ee791febSAntonio Huete Jimenez if (edns_list == NULL || edns == NULL) {
471*ee791febSAntonio Huete Jimenez error("EDNS option could not be allocated");
472*ee791febSAntonio Huete Jimenez break;
473*ee791febSAntonio Huete Jimenez }
474*ee791febSAntonio Huete Jimenez
475*ee791febSAntonio Huete Jimenez if (!(ldns_edns_option_list_push(edns_list, edns))) {
476*ee791febSAntonio Huete Jimenez error("EDNS option NSID could not be attached");
477*ee791febSAntonio Huete Jimenez break;
478*ee791febSAntonio Huete Jimenez }
479*ee791febSAntonio Huete Jimenez continue;
480*ee791febSAntonio Huete Jimenez }
481*ee791febSAntonio Huete Jimenez else {
482*ee791febSAntonio Huete Jimenez error("Unsupported argument after '+'");
483*ee791febSAntonio Huete Jimenez break;
484*ee791febSAntonio Huete Jimenez }
485*ee791febSAntonio Huete Jimenez }
486825eb42bSJan Lentfer /* if has a dot, it's a name */
487825eb42bSJan Lentfer if (strchr(argv[i], '.')) {
488825eb42bSJan Lentfer name = argv[i];
489825eb42bSJan Lentfer continue;
490825eb42bSJan Lentfer }
491825eb42bSJan Lentfer /* if it matches a type, it's a type */
492825eb42bSJan Lentfer if (int_type == -1) {
493825eb42bSJan Lentfer type = ldns_get_rr_type_by_name(argv[i]);
494825eb42bSJan Lentfer if (type != 0) {
495825eb42bSJan Lentfer int_type = 0;
496825eb42bSJan Lentfer continue;
4975340022aSzrj } else if (is_ixfr_with_serial(argv[i], &serial)) {
4985340022aSzrj type = LDNS_RR_TYPE_IXFR;
4995340022aSzrj int_type = 0;
5005340022aSzrj continue;
501825eb42bSJan Lentfer }
502825eb42bSJan Lentfer }
503825eb42bSJan Lentfer /* if it matches a class, it's a class */
504825eb42bSJan Lentfer if (int_clas == -1) {
505825eb42bSJan Lentfer clas = ldns_get_rr_class_by_name(argv[i]);
506825eb42bSJan Lentfer if (clas != 0) {
507825eb42bSJan Lentfer int_clas = 0;
508825eb42bSJan Lentfer continue;
509825eb42bSJan Lentfer }
510825eb42bSJan Lentfer }
511825eb42bSJan Lentfer /* it all fails assume it's a name */
512825eb42bSJan Lentfer name = argv[i];
513825eb42bSJan Lentfer }
514825eb42bSJan Lentfer /* act like dig and use for . NS */
515825eb42bSJan Lentfer if (!name) {
516825eb42bSJan Lentfer name = ".";
517825eb42bSJan Lentfer int_type = 0;
518825eb42bSJan Lentfer type = LDNS_RR_TYPE_NS;
519825eb42bSJan Lentfer }
520825eb42bSJan Lentfer
521825eb42bSJan Lentfer /* defaults if not given */
522825eb42bSJan Lentfer if (int_clas == -1) {
523825eb42bSJan Lentfer clas = LDNS_RR_CLASS_IN;
524825eb42bSJan Lentfer }
525825eb42bSJan Lentfer if (int_type == -1) {
526819dec71SDaniel Fojt if (!drill_reverse) {
527825eb42bSJan Lentfer type = LDNS_RR_TYPE_A;
528825eb42bSJan Lentfer } else {
529825eb42bSJan Lentfer type = LDNS_RR_TYPE_PTR;
530825eb42bSJan Lentfer }
531825eb42bSJan Lentfer }
532819dec71SDaniel Fojt if (!drill_reverse)
533819dec71SDaniel Fojt ; /* pass */
534819dec71SDaniel Fojt else if (strchr(name, ':')) { /* ipv4 or ipv6 addr? */
535819dec71SDaniel Fojt if (!inet_pton(AF_INET6, name, &s6addr)) {
536819dec71SDaniel Fojt error("Syntax error: cannot parse IPv6 address\n");
537819dec71SDaniel Fojt }
538819dec71SDaniel Fojt (void) snprintf(ip6_arpa_str, sizeof(ip6_arpa_str),
539819dec71SDaniel Fojt "%x.%x.%x.%x.%x.%x.%x.%x."
540819dec71SDaniel Fojt "%x.%x.%x.%x.%x.%x.%x.%x."
541819dec71SDaniel Fojt "%x.%x.%x.%x.%x.%x.%x.%x."
542819dec71SDaniel Fojt "%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
543819dec71SDaniel Fojt (unsigned int)(s6addr[15] & 0x0F),
544819dec71SDaniel Fojt (unsigned int)(s6addr[15] >> 4),
545819dec71SDaniel Fojt (unsigned int)(s6addr[14] & 0x0F),
546819dec71SDaniel Fojt (unsigned int)(s6addr[14] >> 4),
547819dec71SDaniel Fojt (unsigned int)(s6addr[13] & 0x0F),
548819dec71SDaniel Fojt (unsigned int)(s6addr[13] >> 4),
549819dec71SDaniel Fojt (unsigned int)(s6addr[12] & 0x0F),
550819dec71SDaniel Fojt (unsigned int)(s6addr[12] >> 4),
551819dec71SDaniel Fojt (unsigned int)(s6addr[11] & 0x0F),
552819dec71SDaniel Fojt (unsigned int)(s6addr[11] >> 4),
553819dec71SDaniel Fojt (unsigned int)(s6addr[10] & 0x0F),
554819dec71SDaniel Fojt (unsigned int)(s6addr[10] >> 4),
555819dec71SDaniel Fojt (unsigned int)(s6addr[9] & 0x0F),
556819dec71SDaniel Fojt (unsigned int)(s6addr[9] >> 4),
557819dec71SDaniel Fojt (unsigned int)(s6addr[8] & 0x0F),
558819dec71SDaniel Fojt (unsigned int)(s6addr[8] >> 4),
559819dec71SDaniel Fojt (unsigned int)(s6addr[7] & 0x0F),
560819dec71SDaniel Fojt (unsigned int)(s6addr[7] >> 4),
561819dec71SDaniel Fojt (unsigned int)(s6addr[6] & 0x0F),
562819dec71SDaniel Fojt (unsigned int)(s6addr[6] >> 4),
563819dec71SDaniel Fojt (unsigned int)(s6addr[5] & 0x0F),
564819dec71SDaniel Fojt (unsigned int)(s6addr[5] >> 4),
565819dec71SDaniel Fojt (unsigned int)(s6addr[4] & 0x0F),
566819dec71SDaniel Fojt (unsigned int)(s6addr[4] >> 4),
567819dec71SDaniel Fojt (unsigned int)(s6addr[3] & 0x0F),
568819dec71SDaniel Fojt (unsigned int)(s6addr[3] >> 4),
569819dec71SDaniel Fojt (unsigned int)(s6addr[2] & 0x0F),
570819dec71SDaniel Fojt (unsigned int)(s6addr[2] >> 4),
571819dec71SDaniel Fojt (unsigned int)(s6addr[1] & 0x0F),
572819dec71SDaniel Fojt (unsigned int)(s6addr[1] >> 4),
573819dec71SDaniel Fojt (unsigned int)(s6addr[0] & 0x0F),
574819dec71SDaniel Fojt (unsigned int)(s6addr[0] >> 4));
575819dec71SDaniel Fojt name = ip6_arpa_str;
576819dec71SDaniel Fojt
577819dec71SDaniel Fojt } else if (!inet_pton(AF_INET, name, &s4addr)) {
578819dec71SDaniel Fojt error("Syntax error: cannot parse IPv4 address\n");
579819dec71SDaniel Fojt
580819dec71SDaniel Fojt } else {
581819dec71SDaniel Fojt (void) snprintf(in_addr_arpa_str, sizeof(in_addr_arpa_str),
582819dec71SDaniel Fojt "%d.%d.%d.%d.in-addr.arpa.", (int)s4addr[3],
583819dec71SDaniel Fojt (int)s4addr[2], (int)s4addr[1], (int)s4addr[0]);
584819dec71SDaniel Fojt name = in_addr_arpa_str;
585819dec71SDaniel Fojt }
586825eb42bSJan Lentfer
5875340022aSzrj if (src) {
5885340022aSzrj src_rdf = ldns_rdf_new_addr_frm_str(src);
5895340022aSzrj if(!src_rdf) {
5905340022aSzrj fprintf(stderr, "-I must be a valid IP[v6] address.\n");
5915340022aSzrj exit(EXIT_FAILURE);
5925340022aSzrj }
5935340022aSzrj if (ldns_rdf_size(src_rdf) == 4) {
5945340022aSzrj qfamily = LDNS_RESOLV_INET;
5955340022aSzrj
5965340022aSzrj } else if (ldns_rdf_size(src_rdf) == 16) {
5975340022aSzrj qfamily = LDNS_RESOLV_INET6;
5985340022aSzrj }
5995340022aSzrj }
6005340022aSzrj
601825eb42bSJan Lentfer /* set the nameserver to use */
602825eb42bSJan Lentfer if (!serv) {
6035340022aSzrj /* no server given -- make a resolver from /etc/resolv.conf */
604825eb42bSJan Lentfer status = ldns_resolver_new_frm_file(&res, resolv_conf_file);
605825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) {
606825eb42bSJan Lentfer warning("Could not create a resolver structure: %s (%s)\n"
607825eb42bSJan Lentfer "Try drill @localhost if you have a resolver running on your machine.",
608825eb42bSJan Lentfer ldns_get_errorstr_by_id(status), resolv_conf_file);
609825eb42bSJan Lentfer result = EXIT_FAILURE;
610825eb42bSJan Lentfer goto exit;
611825eb42bSJan Lentfer }
612825eb42bSJan Lentfer } else {
613825eb42bSJan Lentfer res = ldns_resolver_new();
614825eb42bSJan Lentfer if (!res || strlen(serv) <= 0) {
615825eb42bSJan Lentfer warning("Could not create a resolver structure");
616825eb42bSJan Lentfer result = EXIT_FAILURE;
617825eb42bSJan Lentfer goto exit;
618825eb42bSJan Lentfer }
619825eb42bSJan Lentfer /* add the nameserver */
620825eb42bSJan Lentfer serv_rdf = ldns_rdf_new_addr_frm_str(serv);
621825eb42bSJan Lentfer if (!serv_rdf) {
622825eb42bSJan Lentfer /* try to resolv the name if possible */
623825eb42bSJan Lentfer status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file);
624825eb42bSJan Lentfer
625825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) {
626825eb42bSJan Lentfer error("%s", "@server ip could not be converted");
627825eb42bSJan Lentfer }
628825eb42bSJan Lentfer ldns_resolver_set_dnssec(cmdline_res, qdnssec);
629825eb42bSJan Lentfer ldns_resolver_set_ip6(cmdline_res, qfamily);
630825eb42bSJan Lentfer ldns_resolver_set_fallback(cmdline_res, qfallback);
631825eb42bSJan Lentfer ldns_resolver_set_usevc(cmdline_res, qusevc);
6325340022aSzrj ldns_resolver_set_source(cmdline_res, src_rdf);
633825eb42bSJan Lentfer
634825eb42bSJan Lentfer cmdline_dname = ldns_dname_new_frm_str(serv);
635825eb42bSJan Lentfer
636825eb42bSJan Lentfer cmdline_rr_list = ldns_get_rr_list_addr_by_name(
637825eb42bSJan Lentfer cmdline_res,
638825eb42bSJan Lentfer cmdline_dname,
639825eb42bSJan Lentfer LDNS_RR_CLASS_IN,
640825eb42bSJan Lentfer qflags);
641825eb42bSJan Lentfer ldns_rdf_deep_free(cmdline_dname);
642825eb42bSJan Lentfer if (!cmdline_rr_list) {
643825eb42bSJan Lentfer /* This error msg is not always accurate */
644825eb42bSJan Lentfer error("%s `%s\'", "could not find any address for the name:", serv);
645825eb42bSJan Lentfer } else {
646825eb42bSJan Lentfer if (ldns_resolver_push_nameserver_rr_list(
647825eb42bSJan Lentfer res,
648825eb42bSJan Lentfer cmdline_rr_list
649825eb42bSJan Lentfer ) != LDNS_STATUS_OK) {
650825eb42bSJan Lentfer error("%s", "pushing nameserver");
651825eb42bSJan Lentfer }
652825eb42bSJan Lentfer }
653825eb42bSJan Lentfer } else {
654825eb42bSJan Lentfer if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) {
655825eb42bSJan Lentfer error("%s", "pushing nameserver");
656825eb42bSJan Lentfer } else {
657825eb42bSJan Lentfer ldns_rdf_deep_free(serv_rdf);
658825eb42bSJan Lentfer }
659825eb42bSJan Lentfer }
660825eb42bSJan Lentfer }
661825eb42bSJan Lentfer /* set the resolver options */
6625340022aSzrj ldns_resolver_set_ixfr_serial(res, serial);
663825eb42bSJan Lentfer ldns_resolver_set_port(res, qport);
6645340022aSzrj ldns_resolver_set_source(res, src_rdf);
665825eb42bSJan Lentfer if (verbosity >= 5) {
666825eb42bSJan Lentfer ldns_resolver_set_debug(res, true);
667825eb42bSJan Lentfer } else {
668825eb42bSJan Lentfer ldns_resolver_set_debug(res, false);
669825eb42bSJan Lentfer }
670825eb42bSJan Lentfer ldns_resolver_set_dnssec(res, qdnssec);
671825eb42bSJan Lentfer /* ldns_resolver_set_dnssec_cd(res, qdnssec);*/
672825eb42bSJan Lentfer ldns_resolver_set_ip6(res, qfamily);
673825eb42bSJan Lentfer ldns_resolver_set_fallback(res, qfallback);
674825eb42bSJan Lentfer ldns_resolver_set_usevc(res, qusevc);
675825eb42bSJan Lentfer ldns_resolver_set_random(res, qrandom);
676825eb42bSJan Lentfer if (qbuf != 0) {
677825eb42bSJan Lentfer ldns_resolver_set_edns_udp_size(res, qbuf);
678825eb42bSJan Lentfer }
679825eb42bSJan Lentfer
680825eb42bSJan Lentfer if (!name &&
681825eb42bSJan Lentfer PURPOSE != DRILL_AFROMFILE &&
682825eb42bSJan Lentfer !query_file
683825eb42bSJan Lentfer ) {
684825eb42bSJan Lentfer usage(stdout, progname);
685825eb42bSJan Lentfer result = EXIT_FAILURE;
686825eb42bSJan Lentfer goto exit;
687825eb42bSJan Lentfer }
688825eb42bSJan Lentfer
689825eb42bSJan Lentfer if (tsig_name && tsig_data) {
6905340022aSzrj /* With dig TSIG keys are also specified with -y,
6915340022aSzrj * but format with drill is: -y <name:key[:algo]>
6925340022aSzrj * and with dig: -y [hmac:]name:key
6935340022aSzrj *
6945340022aSzrj * When we detect an unknown tsig algorithm in algo,
6955340022aSzrj * but a known algorithm in name, we cane assume dig
6965340022aSzrj * order was used.
6975340022aSzrj *
6985340022aSzrj * Following if statement is to anticipate and correct dig order
6995340022aSzrj */
7005340022aSzrj if ( strcasecmp(tsig_algorithm, "hmac-md5.sig-alg.reg.int")
7015340022aSzrj && strcasecmp(tsig_algorithm, "hmac-md5")
7025340022aSzrj && strcasecmp(tsig_algorithm, "hmac-sha1")
7035340022aSzrj && strcasecmp(tsig_algorithm, "hmac-sha256")
7045340022aSzrj && (
7055340022aSzrj strcasecmp(tsig_name, "hmac-md5.sig-alg.reg.int") == 0
7065340022aSzrj || strcasecmp(tsig_name, "hmac-md5") == 0
7075340022aSzrj || strcasecmp(tsig_name, "hmac-sha1") == 0
7085340022aSzrj || strcasecmp(tsig_name, "hmac-sha256") == 0
7095340022aSzrj )) {
7105340022aSzrj
7115340022aSzrj /* Roll options */
7125340022aSzrj char *tmp_tsig_algorithm = tsig_name;
7135340022aSzrj tsig_name = tsig_data;
7145340022aSzrj tsig_data = tsig_algorithm;
7155340022aSzrj tsig_algorithm = tmp_tsig_algorithm;
7165340022aSzrj }
7175340022aSzrj
7185340022aSzrj if (strcasecmp(tsig_algorithm, "hmac-md5") == 0) {
7195340022aSzrj free(tsig_algorithm);
7205340022aSzrj tsig_algorithm = strdup("hmac-md5.sig-alg.reg.int");
7215340022aSzrj }
7225340022aSzrj
723825eb42bSJan Lentfer ldns_resolver_set_tsig_keyname(res, tsig_name);
724825eb42bSJan Lentfer ldns_resolver_set_tsig_keydata(res, tsig_data);
725825eb42bSJan Lentfer ldns_resolver_set_tsig_algorithm(res, tsig_algorithm);
726825eb42bSJan Lentfer }
727825eb42bSJan Lentfer
728825eb42bSJan Lentfer /* main switching part of drill */
729825eb42bSJan Lentfer switch(PURPOSE) {
730825eb42bSJan Lentfer case DRILL_TRACE:
731825eb42bSJan Lentfer /* do a trace from the root down */
732825eb42bSJan Lentfer if (!global_dns_root) {
733825eb42bSJan Lentfer init_root();
734825eb42bSJan Lentfer }
735825eb42bSJan Lentfer qname = ldns_dname_new_frm_str(name);
736825eb42bSJan Lentfer if (!qname) {
737825eb42bSJan Lentfer error("%s", "parsing query name");
738825eb42bSJan Lentfer }
739825eb42bSJan Lentfer /* don't care about return packet */
7405340022aSzrj do_trace(res, qname, type, clas);
741825eb42bSJan Lentfer clear_root();
742825eb42bSJan Lentfer break;
743825eb42bSJan Lentfer case DRILL_SECTRACE:
744825eb42bSJan Lentfer /* do a secure trace from the root down */
745825eb42bSJan Lentfer if (!global_dns_root) {
746825eb42bSJan Lentfer init_root();
747825eb42bSJan Lentfer }
748825eb42bSJan Lentfer qname = ldns_dname_new_frm_str(name);
749825eb42bSJan Lentfer if (!qname) {
750825eb42bSJan Lentfer error("%s", "making qname");
751825eb42bSJan Lentfer }
752825eb42bSJan Lentfer /* don't care about return packet */
753825eb42bSJan Lentfer #ifdef HAVE_SSL
754825eb42bSJan Lentfer result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name);
755825eb42bSJan Lentfer #endif /* HAVE_SSL */
756825eb42bSJan Lentfer clear_root();
757825eb42bSJan Lentfer break;
758825eb42bSJan Lentfer case DRILL_CHASE:
759825eb42bSJan Lentfer qname = ldns_dname_new_frm_str(name);
760825eb42bSJan Lentfer if (!qname) {
761825eb42bSJan Lentfer error("%s", "making qname");
762825eb42bSJan Lentfer }
763825eb42bSJan Lentfer
764825eb42bSJan Lentfer ldns_resolver_set_dnssec(res, true);
765825eb42bSJan Lentfer ldns_resolver_set_dnssec_cd(res, true);
766825eb42bSJan Lentfer /* set dnssec implies udp_size of 4096 */
767825eb42bSJan Lentfer ldns_resolver_set_edns_udp_size(res, 4096);
7685340022aSzrj pkt = NULL;
7695340022aSzrj status = ldns_resolver_query_status(
7705340022aSzrj &pkt, res, qname, type, clas, qflags);
7715340022aSzrj if (status != LDNS_STATUS_OK) {
7725340022aSzrj error("error sending query: %s",
7735340022aSzrj ldns_get_errorstr_by_id(status));
7745340022aSzrj }
775825eb42bSJan Lentfer if (!pkt) {
7765340022aSzrj if (status == LDNS_STATUS_OK) {
777825eb42bSJan Lentfer error("%s", "error pkt sending");
7785340022aSzrj }
779825eb42bSJan Lentfer result = EXIT_FAILURE;
780825eb42bSJan Lentfer } else {
781825eb42bSJan Lentfer if (verbosity >= 3) {
782825eb42bSJan Lentfer ldns_pkt_print(stdout, pkt);
783825eb42bSJan Lentfer }
784825eb42bSJan Lentfer
785825eb42bSJan Lentfer if (!ldns_pkt_answer(pkt)) {
786825eb42bSJan Lentfer mesg("No answer in packet");
787825eb42bSJan Lentfer } else {
788825eb42bSJan Lentfer #ifdef HAVE_SSL
789825eb42bSJan Lentfer ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list));
790825eb42bSJan Lentfer result = do_chase(res, qname, type,
791825eb42bSJan Lentfer clas, key_list,
7925340022aSzrj pkt, qflags, NULL);
793825eb42bSJan Lentfer if (result == LDNS_STATUS_OK) {
794825eb42bSJan Lentfer if (verbosity != -1) {
795825eb42bSJan Lentfer mesg("Chase successful");
796825eb42bSJan Lentfer }
797825eb42bSJan Lentfer result = 0;
798825eb42bSJan Lentfer } else {
799825eb42bSJan Lentfer if (verbosity != -1) {
800825eb42bSJan Lentfer mesg("Chase failed.");
801825eb42bSJan Lentfer }
802825eb42bSJan Lentfer }
803825eb42bSJan Lentfer #endif /* HAVE_SSL */
804825eb42bSJan Lentfer }
805825eb42bSJan Lentfer ldns_pkt_free(pkt);
806825eb42bSJan Lentfer }
807825eb42bSJan Lentfer break;
808825eb42bSJan Lentfer case DRILL_AFROMFILE:
809825eb42bSJan Lentfer pkt = read_hex_pkt(answer_file);
810825eb42bSJan Lentfer if (pkt) {
811825eb42bSJan Lentfer if (verbosity != -1) {
812825eb42bSJan Lentfer ldns_pkt_print(stdout, pkt);
813825eb42bSJan Lentfer }
814825eb42bSJan Lentfer ldns_pkt_free(pkt);
815825eb42bSJan Lentfer }
816825eb42bSJan Lentfer
817825eb42bSJan Lentfer break;
818825eb42bSJan Lentfer case DRILL_QTOFILE:
819825eb42bSJan Lentfer qname = ldns_dname_new_frm_str(name);
820825eb42bSJan Lentfer if (!qname) {
821825eb42bSJan Lentfer error("%s", "making qname");
822825eb42bSJan Lentfer }
823825eb42bSJan Lentfer status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags);
824825eb42bSJan Lentfer if(status != LDNS_STATUS_OK) {
825825eb42bSJan Lentfer error("%s", "making query: %s",
826825eb42bSJan Lentfer ldns_get_errorstr_by_id(status));
827825eb42bSJan Lentfer }
828825eb42bSJan Lentfer dump_hex(qpkt, query_file);
829825eb42bSJan Lentfer ldns_pkt_free(qpkt);
830825eb42bSJan Lentfer break;
831825eb42bSJan Lentfer case DRILL_NSEC:
832825eb42bSJan Lentfer break;
833825eb42bSJan Lentfer case DRILL_QUERY:
834825eb42bSJan Lentfer default:
835825eb42bSJan Lentfer if (query_file) {
836825eb42bSJan Lentfer /* this old way, the query packet needed
837825eb42bSJan Lentfer to be parseable, but we want to be able
838825eb42bSJan Lentfer to send mangled packets, so we need
839825eb42bSJan Lentfer to do it directly */
840825eb42bSJan Lentfer #if 0
841825eb42bSJan Lentfer qpkt = read_hex_pkt(query_file);
842825eb42bSJan Lentfer if (qpkt) {
843825eb42bSJan Lentfer status = ldns_resolver_send_pkt(&pkt, res, qpkt);
844825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) {
845825eb42bSJan Lentfer printf("Error: %s\n", ldns_get_errorstr_by_id(status));
846825eb42bSJan Lentfer exit(1);
847825eb42bSJan Lentfer }
848825eb42bSJan Lentfer } else {
849825eb42bSJan Lentfer /* qpkt was bogus, reset pkt */
850825eb42bSJan Lentfer pkt = NULL;
851825eb42bSJan Lentfer }
852825eb42bSJan Lentfer #endif
853825eb42bSJan Lentfer query_buffer = read_hex_buffer(query_file);
854825eb42bSJan Lentfer if (query_buffer) {
855825eb42bSJan Lentfer status = ldns_send_buffer(&pkt, res, query_buffer, NULL);
856825eb42bSJan Lentfer ldns_buffer_free(query_buffer);
857825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) {
858825eb42bSJan Lentfer printf("Error: %s\n", ldns_get_errorstr_by_id(status));
859825eb42bSJan Lentfer exit(1);
860825eb42bSJan Lentfer }
861825eb42bSJan Lentfer } else {
862825eb42bSJan Lentfer printf("NO BUFFER\n");
863825eb42bSJan Lentfer pkt = NULL;
864825eb42bSJan Lentfer }
865825eb42bSJan Lentfer } else {
866825eb42bSJan Lentfer qname = ldns_dname_new_frm_str(name);
867825eb42bSJan Lentfer if (!qname) {
868825eb42bSJan Lentfer error("%s", "error in making qname");
869825eb42bSJan Lentfer }
870825eb42bSJan Lentfer
871825eb42bSJan Lentfer if (type == LDNS_RR_TYPE_AXFR) {
872825eb42bSJan Lentfer status = ldns_axfr_start(res, qname, clas);
873825eb42bSJan Lentfer if(status != LDNS_STATUS_OK) {
874825eb42bSJan Lentfer error("Error starting axfr: %s",
875825eb42bSJan Lentfer ldns_get_errorstr_by_id(status));
876825eb42bSJan Lentfer }
877825eb42bSJan Lentfer axfr_rr = ldns_axfr_next(res);
878825eb42bSJan Lentfer if(!axfr_rr) {
879825eb42bSJan Lentfer fprintf(stderr, "AXFR failed.\n");
880825eb42bSJan Lentfer ldns_pkt_print(stdout,
881825eb42bSJan Lentfer ldns_axfr_last_pkt(res));
882825eb42bSJan Lentfer goto exit;
883825eb42bSJan Lentfer }
884825eb42bSJan Lentfer while (axfr_rr) {
885825eb42bSJan Lentfer if (verbosity != -1) {
886825eb42bSJan Lentfer ldns_rr_print(stdout, axfr_rr);
887825eb42bSJan Lentfer }
888825eb42bSJan Lentfer ldns_rr_free(axfr_rr);
889825eb42bSJan Lentfer axfr_rr = ldns_axfr_next(res);
890825eb42bSJan Lentfer }
891825eb42bSJan Lentfer
892825eb42bSJan Lentfer goto exit;
893825eb42bSJan Lentfer } else {
894825eb42bSJan Lentfer /* create a packet and set the RD flag on it */
8955340022aSzrj pkt = NULL;
896*ee791febSAntonio Huete Jimenez
897*ee791febSAntonio Huete Jimenez status = ldns_resolver_prepare_query_pkt(&qpkt,
898*ee791febSAntonio Huete Jimenez res, qname, type, clas, qflags);
899*ee791febSAntonio Huete Jimenez if(status != LDNS_STATUS_OK) {
900*ee791febSAntonio Huete Jimenez error("%s", "making query: %s",
901*ee791febSAntonio Huete Jimenez ldns_get_errorstr_by_id(status));
902*ee791febSAntonio Huete Jimenez }
903*ee791febSAntonio Huete Jimenez
904*ee791febSAntonio Huete Jimenez if (edns_list) {
905*ee791febSAntonio Huete Jimenez /* attach the structed EDNS options */
906*ee791febSAntonio Huete Jimenez ldns_pkt_set_edns_option_list(qpkt, edns_list);
907*ee791febSAntonio Huete Jimenez }
908*ee791febSAntonio Huete Jimenez
909*ee791febSAntonio Huete Jimenez status = ldns_resolver_send_pkt(&pkt, res, qpkt);
910*ee791febSAntonio Huete Jimenez ldns_pkt_free(qpkt);
911*ee791febSAntonio Huete Jimenez
9125340022aSzrj if (status != LDNS_STATUS_OK) {
9135340022aSzrj error("error sending query: %s"
9145340022aSzrj , ldns_get_errorstr_by_id(
9155340022aSzrj status));
9165340022aSzrj }
917825eb42bSJan Lentfer }
918825eb42bSJan Lentfer }
919825eb42bSJan Lentfer
920*ee791febSAntonio Huete Jimenez /* now handling the response message/packet */
921825eb42bSJan Lentfer if (!pkt) {
922825eb42bSJan Lentfer mesg("No packet received");
923825eb42bSJan Lentfer result = EXIT_FAILURE;
924825eb42bSJan Lentfer } else {
925*ee791febSAntonio Huete Jimenez ldns_pkt_print_fmt(stdout, fmt, pkt);
926825eb42bSJan Lentfer if (verbosity != -1) {
927825eb42bSJan Lentfer if (ldns_pkt_tc(pkt)) {
928825eb42bSJan Lentfer fprintf(stdout,
929825eb42bSJan Lentfer "\n;; WARNING: The answer packet was truncated; you might want to\n");
930825eb42bSJan Lentfer fprintf(stdout,
931825eb42bSJan Lentfer ";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n");
932825eb42bSJan Lentfer }
933825eb42bSJan Lentfer }
934825eb42bSJan Lentfer if (qds) {
935825eb42bSJan Lentfer if (verbosity != -1) {
936825eb42bSJan Lentfer print_ds_of_keys(pkt);
937825eb42bSJan Lentfer printf("\n");
938825eb42bSJan Lentfer }
939825eb42bSJan Lentfer }
940825eb42bSJan Lentfer
941825eb42bSJan Lentfer if (ldns_rr_list_rr_count(key_list) > 0) {
942825eb42bSJan Lentfer /* -k's were given on the cmd line */
943825eb42bSJan Lentfer ldns_rr_list *rrset_verified;
944825eb42bSJan Lentfer uint16_t key_count;
945825eb42bSJan Lentfer
946825eb42bSJan Lentfer rrset_verified = ldns_pkt_rr_list_by_name_and_type(
947825eb42bSJan Lentfer pkt, qname, type,
948825eb42bSJan Lentfer LDNS_SECTION_ANY_NOQUESTION);
949825eb42bSJan Lentfer
950825eb42bSJan Lentfer if (type == LDNS_RR_TYPE_ANY) {
951825eb42bSJan Lentfer /* don't verify this */
952825eb42bSJan Lentfer break;
953825eb42bSJan Lentfer }
954825eb42bSJan Lentfer
955825eb42bSJan Lentfer if (verbosity != -1) {
956825eb42bSJan Lentfer printf("; ");
957825eb42bSJan Lentfer ldns_rr_list_print(stdout, rrset_verified);
958825eb42bSJan Lentfer }
959825eb42bSJan Lentfer
960825eb42bSJan Lentfer /* verify */
961825eb42bSJan Lentfer #ifdef HAVE_SSL
962825eb42bSJan Lentfer key_verified = ldns_rr_list_new();
963825eb42bSJan Lentfer result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified);
964825eb42bSJan Lentfer
965825eb42bSJan Lentfer if (result == LDNS_STATUS_ERR) {
966825eb42bSJan Lentfer /* is the existence denied then? */
967825eb42bSJan Lentfer result = ldns_verify_denial(pkt, qname, type, NULL, NULL);
968825eb42bSJan Lentfer if (result == LDNS_STATUS_OK) {
969825eb42bSJan Lentfer if (verbosity != -1) {
970825eb42bSJan Lentfer printf("Existence denied for ");
971825eb42bSJan Lentfer ldns_rdf_print(stdout, qname);
972825eb42bSJan Lentfer type_str = ldns_rr_type2str(type);
973825eb42bSJan Lentfer printf("\t%s\n", type_str);
974825eb42bSJan Lentfer LDNS_FREE(type_str);
975825eb42bSJan Lentfer }
976825eb42bSJan Lentfer } else {
977825eb42bSJan Lentfer if (verbosity != -1) {
978825eb42bSJan Lentfer printf("Bad data; RR for name and "
979825eb42bSJan Lentfer "type not found or failed to "
980825eb42bSJan Lentfer "verify, and denial of "
981825eb42bSJan Lentfer "existence failed.\n");
982825eb42bSJan Lentfer }
983825eb42bSJan Lentfer }
984825eb42bSJan Lentfer } else if (result == LDNS_STATUS_OK) {
985825eb42bSJan Lentfer for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified);
986825eb42bSJan Lentfer key_count++) {
987825eb42bSJan Lentfer if (verbosity != -1) {
988fd185f4dSJan Lentfer printf("; VALIDATED by id = %u, owner = ",
989fd185f4dSJan Lentfer (unsigned int)ldns_calc_keytag(
990825eb42bSJan Lentfer ldns_rr_list_rr(key_verified, key_count)));
991825eb42bSJan Lentfer ldns_rdf_print(stdout, ldns_rr_owner(
992825eb42bSJan Lentfer ldns_rr_list_rr(key_list, key_count)));
993825eb42bSJan Lentfer printf("\n");
994825eb42bSJan Lentfer }
995825eb42bSJan Lentfer }
996825eb42bSJan Lentfer } else {
997825eb42bSJan Lentfer for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list);
998825eb42bSJan Lentfer key_count++) {
999825eb42bSJan Lentfer if (verbosity != -1) {
1000fd185f4dSJan Lentfer printf("; %s for id = %u, owner = ",
1001825eb42bSJan Lentfer ldns_get_errorstr_by_id(result),
1002fd185f4dSJan Lentfer (unsigned int)ldns_calc_keytag(
1003825eb42bSJan Lentfer ldns_rr_list_rr(key_list, key_count)));
1004825eb42bSJan Lentfer ldns_rdf_print(stdout, ldns_rr_owner(
1005825eb42bSJan Lentfer
1006825eb42bSJan Lentfer ldns_rr_list_rr(key_list,
1007825eb42bSJan Lentfer key_count)));
1008825eb42bSJan Lentfer printf("\n");
1009825eb42bSJan Lentfer }
1010825eb42bSJan Lentfer }
1011825eb42bSJan Lentfer }
1012825eb42bSJan Lentfer ldns_rr_list_free(key_verified);
1013825eb42bSJan Lentfer #else
1014825eb42bSJan Lentfer (void) key_count;
1015825eb42bSJan Lentfer #endif /* HAVE_SSL */
1016825eb42bSJan Lentfer }
1017825eb42bSJan Lentfer if (answer_file) {
1018825eb42bSJan Lentfer dump_hex(pkt, answer_file);
1019825eb42bSJan Lentfer }
1020825eb42bSJan Lentfer ldns_pkt_free(pkt);
1021825eb42bSJan Lentfer }
1022825eb42bSJan Lentfer
1023825eb42bSJan Lentfer break;
1024825eb42bSJan Lentfer }
1025825eb42bSJan Lentfer
1026825eb42bSJan Lentfer exit:
1027825eb42bSJan Lentfer ldns_rdf_deep_free(qname);
10285340022aSzrj ldns_rdf_deep_free(src_rdf);
1029825eb42bSJan Lentfer ldns_resolver_deep_free(res);
1030825eb42bSJan Lentfer ldns_resolver_deep_free(cmdline_res);
1031825eb42bSJan Lentfer ldns_rr_list_deep_free(key_list);
1032825eb42bSJan Lentfer ldns_rr_list_deep_free(cmdline_rr_list);
1033825eb42bSJan Lentfer ldns_rdf_deep_free(trace_start_name);
1034825eb42bSJan Lentfer xfree(progname);
1035825eb42bSJan Lentfer xfree(tsig_name);
1036825eb42bSJan Lentfer xfree(tsig_data);
1037825eb42bSJan Lentfer xfree(tsig_algorithm);
1038825eb42bSJan Lentfer
1039825eb42bSJan Lentfer #ifdef HAVE_SSL
1040*ee791febSAntonio Huete Jimenez #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(HAVE_LIBRESSL)
1041*ee791febSAntonio Huete Jimenez #ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
1042825eb42bSJan Lentfer CRYPTO_cleanup_all_ex_data ();
1043*ee791febSAntonio Huete Jimenez #endif
1044*ee791febSAntonio Huete Jimenez #ifdef HAVE_ERR_FREE_STRINGS
1045825eb42bSJan Lentfer ERR_free_strings ();
1046*ee791febSAntonio Huete Jimenez #endif
1047*ee791febSAntonio Huete Jimenez #ifdef HAVE_EVP_CLEANUP
1048825eb42bSJan Lentfer EVP_cleanup ();
1049825eb42bSJan Lentfer #endif
1050*ee791febSAntonio Huete Jimenez #endif
1051*ee791febSAntonio Huete Jimenez #endif
1052825eb42bSJan Lentfer #ifdef USE_WINSOCK
1053825eb42bSJan Lentfer WSACleanup();
1054825eb42bSJan Lentfer #endif
1055825eb42bSJan Lentfer
1056825eb42bSJan Lentfer return result;
1057825eb42bSJan Lentfer }
1058