1 /* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 *
4 * Permission to use, copy, modify, and distribute this
5 * software and its documentation for any purpose and without
6 * fee is hereby granted, provided that the above copyright
7 * notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting
9 * documentation, and that the name of M.I.T. not be used in
10 * advertising or publicity pertaining to distribution of the
11 * software without specific, written prior permission.
12 * M.I.T. makes no representations about the suitability of
13 * this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
15 */
16
17 #include "ares_setup.h"
18
19 #ifdef HAVE_SYS_SOCKET_H
20 # include <sys/socket.h>
21 #endif
22 #ifdef HAVE_NETINET_IN_H
23 # include <netinet/in.h>
24 #endif
25 #ifdef HAVE_ARPA_INET_H
26 # include <arpa/inet.h>
27 #endif
28 #ifdef HAVE_NETDB_H
29 # include <netdb.h>
30 #endif
31 #ifdef HAVE_ARPA_NAMESER_H
32 # include <arpa/nameser.h>
33 #else
34 # include "nameser.h"
35 #endif
36 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
37 # include <arpa/nameser_compat.h>
38 #endif
39
40 #ifdef HAVE_SYS_TIME_H
41 # include <sys/time.h>
42 #endif
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 #ifdef HAVE_STRINGS_H
47 # include <strings.h>
48 #endif
49
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <ctype.h>
54
55 #include "ares.h"
56 #include "ares_dns.h"
57 #include "inet_ntop.h"
58 #include "inet_net_pton.h"
59 #include "ares_getopt.h"
60 #include "ares_nowarn.h"
61
62 #ifndef HAVE_STRDUP
63 # include "ares_strdup.h"
64 # define strdup(ptr) ares_strdup(ptr)
65 #endif
66
67 #ifndef HAVE_STRCASECMP
68 # include "ares_strcasecmp.h"
69 # define strcasecmp(p1,p2) ares_strcasecmp(p1,p2)
70 #endif
71
72 #ifndef HAVE_STRNCASECMP
73 # include "ares_strcasecmp.h"
74 # define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n)
75 #endif
76
77 #ifdef WATT32
78 #undef WIN32 /* Redefined in MingW headers */
79 #endif
80
81 #ifndef T_SRV
82 # define T_SRV 33 /* Server selection */
83 #endif
84 #ifndef T_NAPTR
85 # define T_NAPTR 35 /* Naming authority pointer */
86 #endif
87 #ifndef T_DS
88 # define T_DS 43 /* Delegation Signer (RFC4034) */
89 #endif
90 #ifndef T_SSHFP
91 # define T_SSHFP 44 /* SSH Key Fingerprint (RFC4255) */
92 #endif
93 #ifndef T_RRSIG
94 # define T_RRSIG 46 /* Resource Record Signature (RFC4034) */
95 #endif
96 #ifndef T_NSEC
97 # define T_NSEC 47 /* Next Secure (RFC4034) */
98 #endif
99 #ifndef T_DNSKEY
100 # define T_DNSKEY 48 /* DNS Public Key (RFC4034) */
101 #endif
102
103 struct nv {
104 const char *name;
105 int value;
106 };
107
108 static const struct nv flags[] = {
109 { "usevc", ARES_FLAG_USEVC },
110 { "primary", ARES_FLAG_PRIMARY },
111 { "igntc", ARES_FLAG_IGNTC },
112 { "norecurse", ARES_FLAG_NORECURSE },
113 { "stayopen", ARES_FLAG_STAYOPEN },
114 { "noaliases", ARES_FLAG_NOALIASES }
115 };
116 static const int nflags = sizeof(flags) / sizeof(flags[0]);
117
118 static const struct nv classes[] = {
119 { "IN", C_IN },
120 { "CHAOS", C_CHAOS },
121 { "HS", C_HS },
122 { "ANY", C_ANY }
123 };
124 static const int nclasses = sizeof(classes) / sizeof(classes[0]);
125
126 static const struct nv types[] = {
127 { "A", T_A },
128 { "NS", T_NS },
129 { "MD", T_MD },
130 { "MF", T_MF },
131 { "CNAME", T_CNAME },
132 { "SOA", T_SOA },
133 { "MB", T_MB },
134 { "MG", T_MG },
135 { "MR", T_MR },
136 { "NULL", T_NULL },
137 { "WKS", T_WKS },
138 { "PTR", T_PTR },
139 { "HINFO", T_HINFO },
140 { "MINFO", T_MINFO },
141 { "MX", T_MX },
142 { "TXT", T_TXT },
143 { "RP", T_RP },
144 { "AFSDB", T_AFSDB },
145 { "X25", T_X25 },
146 { "ISDN", T_ISDN },
147 { "RT", T_RT },
148 { "NSAP", T_NSAP },
149 { "NSAP_PTR", T_NSAP_PTR },
150 { "SIG", T_SIG },
151 { "KEY", T_KEY },
152 { "PX", T_PX },
153 { "GPOS", T_GPOS },
154 { "AAAA", T_AAAA },
155 { "LOC", T_LOC },
156 { "SRV", T_SRV },
157 { "AXFR", T_AXFR },
158 { "MAILB", T_MAILB },
159 { "MAILA", T_MAILA },
160 { "NAPTR", T_NAPTR },
161 { "DS", T_DS },
162 { "SSHFP", T_SSHFP },
163 { "RRSIG", T_RRSIG },
164 { "NSEC", T_NSEC },
165 { "DNSKEY", T_DNSKEY },
166 { "ANY", T_ANY }
167 };
168 static const int ntypes = sizeof(types) / sizeof(types[0]);
169
170 static const char *opcodes[] = {
171 "QUERY", "IQUERY", "STATUS", "(reserved)", "NOTIFY",
172 "(unknown)", "(unknown)", "(unknown)", "(unknown)",
173 "UPDATEA", "UPDATED", "UPDATEDA", "UPDATEM", "UPDATEMA",
174 "ZONEINIT", "ZONEREF"
175 };
176
177 static const char *rcodes[] = {
178 "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED",
179 "(unknown)", "(unknown)", "(unknown)", "(unknown)", "(unknown)",
180 "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
181 };
182
183 static void callback(void *arg, int status, int timeouts,
184 unsigned char *abuf, int alen);
185 static const unsigned char *display_question(const unsigned char *aptr,
186 const unsigned char *abuf,
187 int alen);
188 static const unsigned char *display_rr(const unsigned char *aptr,
189 const unsigned char *abuf, int alen);
190 static const char *type_name(int type);
191 static const char *class_name(int dnsclass);
192 static void usage(void);
193 static void destroy_addr_list(struct ares_addr_node *head);
194 static void append_addr_list(struct ares_addr_node **head,
195 struct ares_addr_node *node);
196
main(int argc,char ** argv)197 int main(int argc, char **argv)
198 {
199 ares_channel channel;
200 int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
201 int status, nfds, count;
202 struct ares_options options;
203 struct hostent *hostent;
204 fd_set read_fds, write_fds;
205 struct timeval *tvp, tv;
206 struct ares_addr_node *srvr, *servers = NULL;
207
208 #ifdef USE_WINSOCK
209 WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
210 WSADATA wsaData;
211 WSAStartup(wVersionRequested, &wsaData);
212 #endif
213
214 status = ares_library_init(ARES_LIB_INIT_ALL);
215 if (status != ARES_SUCCESS)
216 {
217 fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
218 return 1;
219 }
220
221 options.flags = ARES_FLAG_NOCHECKRESP;
222 options.servers = NULL;
223 options.nservers = 0;
224 while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
225 {
226 switch (c)
227 {
228 case 'd':
229 #ifdef WATT32
230 dbug_init();
231 #endif
232 break;
233
234 case 'f':
235 /* Add a flag. */
236 for (i = 0; i < nflags; i++)
237 {
238 if (strcmp(flags[i].name, optarg) == 0)
239 break;
240 }
241 if (i < nflags)
242 options.flags |= flags[i].value;
243 else
244 usage();
245 break;
246
247 case 's':
248 /* User-specified name servers override default ones. */
249 srvr = malloc(sizeof(struct ares_addr_node));
250 if (!srvr)
251 {
252 fprintf(stderr, "Out of memory!\n");
253 destroy_addr_list(servers);
254 return 1;
255 }
256 append_addr_list(&servers, srvr);
257 if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
258 srvr->family = AF_INET;
259 else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0)
260 srvr->family = AF_INET6;
261 else
262 {
263 hostent = gethostbyname(optarg);
264 if (!hostent)
265 {
266 fprintf(stderr, "adig: server %s not found.\n", optarg);
267 destroy_addr_list(servers);
268 return 1;
269 }
270 switch (hostent->h_addrtype)
271 {
272 case AF_INET:
273 srvr->family = AF_INET;
274 memcpy(&srvr->addr.addr4, hostent->h_addr,
275 sizeof(srvr->addr.addr4));
276 break;
277 case AF_INET6:
278 srvr->family = AF_INET6;
279 memcpy(&srvr->addr.addr6, hostent->h_addr,
280 sizeof(srvr->addr.addr6));
281 break;
282 default:
283 fprintf(stderr,
284 "adig: server %s unsupported address family.\n", optarg);
285 destroy_addr_list(servers);
286 return 1;
287 }
288 }
289 /* Notice that calling ares_init_options() without servers in the
290 * options struct and with ARES_OPT_SERVERS set simultaneously in
291 * the options mask, results in an initialization with no servers.
292 * When alternative name servers have been specified these are set
293 * later calling ares_set_servers() overriding any existing server
294 * configuration. To prevent initial configuration with default
295 * servers that will be discarded later, ARES_OPT_SERVERS is set.
296 * If this flag is not set here the result shall be the same but
297 * ares_init_options() will do needless work. */
298 optmask |= ARES_OPT_SERVERS;
299 break;
300
301 case 'c':
302 /* Set the query class. */
303 for (i = 0; i < nclasses; i++)
304 {
305 if (strcasecmp(classes[i].name, optarg) == 0)
306 break;
307 }
308 if (i < nclasses)
309 dnsclass = classes[i].value;
310 else
311 usage();
312 break;
313
314 case 't':
315 /* Set the query type. */
316 for (i = 0; i < ntypes; i++)
317 {
318 if (strcasecmp(types[i].name, optarg) == 0)
319 break;
320 }
321 if (i < ntypes)
322 type = types[i].value;
323 else
324 usage();
325 break;
326
327 case 'T':
328 /* Set the TCP port number. */
329 if (!ISDIGIT(*optarg))
330 usage();
331 options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
332 optmask |= ARES_OPT_TCP_PORT;
333 break;
334
335 case 'U':
336 /* Set the UDP port number. */
337 if (!ISDIGIT(*optarg))
338 usage();
339 options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
340 optmask |= ARES_OPT_UDP_PORT;
341 break;
342 }
343 }
344 argc -= optind;
345 argv += optind;
346 if (argc == 0)
347 usage();
348
349 status = ares_init_options(&channel, &options, optmask);
350
351 if (status != ARES_SUCCESS)
352 {
353 fprintf(stderr, "ares_init_options: %s\n",
354 ares_strerror(status));
355 return 1;
356 }
357
358 if(servers)
359 {
360 status = ares_set_servers(channel, servers);
361 destroy_addr_list(servers);
362 if (status != ARES_SUCCESS)
363 {
364 fprintf(stderr, "ares_init_options: %s\n",
365 ares_strerror(status));
366 return 1;
367 }
368 }
369
370 /* Initiate the queries, one per command-line argument. If there is
371 * only one query to do, supply NULL as the callback argument;
372 * otherwise, supply the query name as an argument so we can
373 * distinguish responses for the user when printing them out.
374 */
375 if (argc == 1)
376 ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
377 else
378 {
379 for (; *argv; argv++)
380 ares_query(channel, *argv, dnsclass, type, callback, *argv);
381 }
382
383 /* Wait for all queries to complete. */
384 for (;;)
385 {
386 FD_ZERO(&read_fds);
387 FD_ZERO(&write_fds);
388 nfds = ares_fds(channel, &read_fds, &write_fds);
389 if (nfds == 0)
390 break;
391 tvp = ares_timeout(channel, NULL, &tv);
392 count = select(nfds, &read_fds, &write_fds, NULL, tvp);
393 if (count < 0 && SOCKERRNO != EINVAL)
394 {
395 perror("select");
396 return 1;
397 }
398 ares_process(channel, &read_fds, &write_fds);
399 }
400
401 ares_destroy(channel);
402
403 ares_library_cleanup();
404
405 #ifdef USE_WINSOCK
406 WSACleanup();
407 #endif
408
409 return 0;
410 }
411
callback(void * arg,int status,int timeouts,unsigned char * abuf,int alen)412 static void callback(void *arg, int status, int timeouts,
413 unsigned char *abuf, int alen)
414 {
415 char *name = (char *) arg;
416 int id, qr, opcode, aa, tc, rd, ra, rcode;
417 unsigned int qdcount, ancount, nscount, arcount, i;
418 const unsigned char *aptr;
419
420 (void) timeouts;
421
422 /* Display the query name if given. */
423 if (name)
424 printf("Answer for query %s:\n", name);
425
426 /* Display an error message if there was an error, but only stop if
427 * we actually didn't get an answer buffer.
428 */
429 if (status != ARES_SUCCESS)
430 {
431 printf("%s\n", ares_strerror(status));
432 if (!abuf)
433 return;
434 }
435
436 /* Won't happen, but check anyway, for safety. */
437 if (alen < HFIXEDSZ)
438 return;
439
440 /* Parse the answer header. */
441 id = DNS_HEADER_QID(abuf);
442 qr = DNS_HEADER_QR(abuf);
443 opcode = DNS_HEADER_OPCODE(abuf);
444 aa = DNS_HEADER_AA(abuf);
445 tc = DNS_HEADER_TC(abuf);
446 rd = DNS_HEADER_RD(abuf);
447 ra = DNS_HEADER_RA(abuf);
448 rcode = DNS_HEADER_RCODE(abuf);
449 qdcount = DNS_HEADER_QDCOUNT(abuf);
450 ancount = DNS_HEADER_ANCOUNT(abuf);
451 nscount = DNS_HEADER_NSCOUNT(abuf);
452 arcount = DNS_HEADER_ARCOUNT(abuf);
453
454 /* Display the answer header. */
455 printf("id: %d\n", id);
456 printf("flags: %s%s%s%s%s\n",
457 qr ? "qr " : "",
458 aa ? "aa " : "",
459 tc ? "tc " : "",
460 rd ? "rd " : "",
461 ra ? "ra " : "");
462 printf("opcode: %s\n", opcodes[opcode]);
463 printf("rcode: %s\n", rcodes[rcode]);
464
465 /* Display the questions. */
466 printf("Questions:\n");
467 aptr = abuf + HFIXEDSZ;
468 for (i = 0; i < qdcount; i++)
469 {
470 aptr = display_question(aptr, abuf, alen);
471 if (aptr == NULL)
472 return;
473 }
474
475 /* Display the answers. */
476 printf("Answers:\n");
477 for (i = 0; i < ancount; i++)
478 {
479 aptr = display_rr(aptr, abuf, alen);
480 if (aptr == NULL)
481 return;
482 }
483
484 /* Display the NS records. */
485 printf("NS records:\n");
486 for (i = 0; i < nscount; i++)
487 {
488 aptr = display_rr(aptr, abuf, alen);
489 if (aptr == NULL)
490 return;
491 }
492
493 /* Display the additional records. */
494 printf("Additional records:\n");
495 for (i = 0; i < arcount; i++)
496 {
497 aptr = display_rr(aptr, abuf, alen);
498 if (aptr == NULL)
499 return;
500 }
501 }
502
display_question(const unsigned char * aptr,const unsigned char * abuf,int alen)503 static const unsigned char *display_question(const unsigned char *aptr,
504 const unsigned char *abuf,
505 int alen)
506 {
507 char *name;
508 int type, dnsclass, status;
509 long len;
510
511 /* Parse the question name. */
512 status = ares_expand_name(aptr, abuf, alen, &name, &len);
513 if (status != ARES_SUCCESS)
514 return NULL;
515 aptr += len;
516
517 /* Make sure there's enough data after the name for the fixed part
518 * of the question.
519 */
520 if (aptr + QFIXEDSZ > abuf + alen)
521 {
522 ares_free_string(name);
523 return NULL;
524 }
525
526 /* Parse the question type and class. */
527 type = DNS_QUESTION_TYPE(aptr);
528 dnsclass = DNS_QUESTION_CLASS(aptr);
529 aptr += QFIXEDSZ;
530
531 /* Display the question, in a format sort of similar to how we will
532 * display RRs.
533 */
534 printf("\t%-15s.\t", name);
535 if (dnsclass != C_IN)
536 printf("\t%s", class_name(dnsclass));
537 printf("\t%s\n", type_name(type));
538 ares_free_string(name);
539 return aptr;
540 }
541
display_rr(const unsigned char * aptr,const unsigned char * abuf,int alen)542 static const unsigned char *display_rr(const unsigned char *aptr,
543 const unsigned char *abuf, int alen)
544 {
545 const unsigned char *p;
546 int type, dnsclass, ttl, dlen, status;
547 long len;
548 char addr[46];
549 union {
550 unsigned char * as_uchar;
551 char * as_char;
552 } name;
553
554 /* Parse the RR name. */
555 status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
556 if (status != ARES_SUCCESS)
557 return NULL;
558 aptr += len;
559
560 /* Make sure there is enough data after the RR name for the fixed
561 * part of the RR.
562 */
563 if (aptr + RRFIXEDSZ > abuf + alen)
564 {
565 ares_free_string(name.as_char);
566 return NULL;
567 }
568
569 /* Parse the fixed part of the RR, and advance to the RR data
570 * field. */
571 type = DNS_RR_TYPE(aptr);
572 dnsclass = DNS_RR_CLASS(aptr);
573 ttl = DNS_RR_TTL(aptr);
574 dlen = DNS_RR_LEN(aptr);
575 aptr += RRFIXEDSZ;
576 if (aptr + dlen > abuf + alen)
577 {
578 ares_free_string(name.as_char);
579 return NULL;
580 }
581
582 /* Display the RR name, class, and type. */
583 printf("\t%-15s.\t%d", name.as_char, ttl);
584 if (dnsclass != C_IN)
585 printf("\t%s", class_name(dnsclass));
586 printf("\t%s", type_name(type));
587 ares_free_string(name.as_char);
588
589 /* Display the RR data. Don't touch aptr. */
590 switch (type)
591 {
592 case T_CNAME:
593 case T_MB:
594 case T_MD:
595 case T_MF:
596 case T_MG:
597 case T_MR:
598 case T_NS:
599 case T_PTR:
600 /* For these types, the RR data is just a domain name. */
601 status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
602 if (status != ARES_SUCCESS)
603 return NULL;
604 printf("\t%s.", name.as_char);
605 ares_free_string(name.as_char);
606 break;
607
608 case T_HINFO:
609 /* The RR data is two length-counted character strings. */
610 p = aptr;
611 len = *p;
612 if (p + len + 1 > aptr + dlen)
613 return NULL;
614 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
615 if (status != ARES_SUCCESS)
616 return NULL;
617 printf("\t%s", name.as_char);
618 ares_free_string(name.as_char);
619 p += len;
620 len = *p;
621 if (p + len + 1 > aptr + dlen)
622 return NULL;
623 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
624 if (status != ARES_SUCCESS)
625 return NULL;
626 printf("\t%s", name.as_char);
627 ares_free_string(name.as_char);
628 break;
629
630 case T_MINFO:
631 /* The RR data is two domain names. */
632 p = aptr;
633 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
634 if (status != ARES_SUCCESS)
635 return NULL;
636 printf("\t%s.", name.as_char);
637 ares_free_string(name.as_char);
638 p += len;
639 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
640 if (status != ARES_SUCCESS)
641 return NULL;
642 printf("\t%s.", name.as_char);
643 ares_free_string(name.as_char);
644 break;
645
646 case T_MX:
647 /* The RR data is two bytes giving a preference ordering, and
648 * then a domain name.
649 */
650 if (dlen < 2)
651 return NULL;
652 printf("\t%d", DNS__16BIT(aptr));
653 status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len);
654 if (status != ARES_SUCCESS)
655 return NULL;
656 printf("\t%s.", name.as_char);
657 ares_free_string(name.as_char);
658 break;
659
660 case T_SOA:
661 /* The RR data is two domain names and then five four-byte
662 * numbers giving the serial number and some timeouts.
663 */
664 p = aptr;
665 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
666 if (status != ARES_SUCCESS)
667 return NULL;
668 printf("\t%s.\n", name.as_char);
669 ares_free_string(name.as_char);
670 p += len;
671 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
672 if (status != ARES_SUCCESS)
673 return NULL;
674 printf("\t\t\t\t\t\t%s.\n", name.as_char);
675 ares_free_string(name.as_char);
676 p += len;
677 if (p + 20 > aptr + dlen)
678 return NULL;
679 printf("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )",
680 (unsigned long)DNS__32BIT(p), (unsigned long)DNS__32BIT(p+4),
681 (unsigned long)DNS__32BIT(p+8), (unsigned long)DNS__32BIT(p+12),
682 (unsigned long)DNS__32BIT(p+16));
683 break;
684
685 case T_TXT:
686 /* The RR data is one or more length-counted character
687 * strings. */
688 p = aptr;
689 while (p < aptr + dlen)
690 {
691 len = *p;
692 if (p + len + 1 > aptr + dlen)
693 return NULL;
694 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
695 if (status != ARES_SUCCESS)
696 return NULL;
697 printf("\t%s", name.as_char);
698 ares_free_string(name.as_char);
699 p += len;
700 }
701 break;
702
703 case T_A:
704 /* The RR data is a four-byte Internet address. */
705 if (dlen != 4)
706 return NULL;
707 printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr)));
708 break;
709
710 case T_AAAA:
711 /* The RR data is a 16-byte IPv6 address. */
712 if (dlen != 16)
713 return NULL;
714 printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr)));
715 break;
716
717 case T_WKS:
718 /* Not implemented yet */
719 break;
720
721 case T_SRV:
722 /* The RR data is three two-byte numbers representing the
723 * priority, weight, and port, followed by a domain name.
724 */
725
726 printf("\t%d", DNS__16BIT(aptr));
727 printf(" %d", DNS__16BIT(aptr + 2));
728 printf(" %d", DNS__16BIT(aptr + 4));
729
730 status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len);
731 if (status != ARES_SUCCESS)
732 return NULL;
733 printf("\t%s.", name.as_char);
734 ares_free_string(name.as_char);
735 break;
736
737 case T_NAPTR:
738
739 printf("\t%d", DNS__16BIT(aptr)); /* order */
740 printf(" %d\n", DNS__16BIT(aptr + 2)); /* preference */
741
742 p = aptr + 4;
743 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
744 if (status != ARES_SUCCESS)
745 return NULL;
746 printf("\t\t\t\t\t\t%s\n", name.as_char);
747 ares_free_string(name.as_char);
748 p += len;
749
750 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
751 if (status != ARES_SUCCESS)
752 return NULL;
753 printf("\t\t\t\t\t\t%s\n", name.as_char);
754 ares_free_string(name.as_char);
755 p += len;
756
757 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
758 if (status != ARES_SUCCESS)
759 return NULL;
760 printf("\t\t\t\t\t\t%s\n", name.as_char);
761 ares_free_string(name.as_char);
762 p += len;
763
764 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
765 if (status != ARES_SUCCESS)
766 return NULL;
767 printf("\t\t\t\t\t\t%s", name.as_char);
768 ares_free_string(name.as_char);
769 break;
770
771 case T_DS:
772 case T_SSHFP:
773 case T_RRSIG:
774 case T_NSEC:
775 case T_DNSKEY:
776 printf("\t[RR type parsing unavailable]");
777 break;
778
779 default:
780 printf("\t[Unknown RR; cannot parse]");
781 break;
782 }
783 printf("\n");
784
785 return aptr + dlen;
786 }
787
type_name(int type)788 static const char *type_name(int type)
789 {
790 int i;
791
792 for (i = 0; i < ntypes; i++)
793 {
794 if (types[i].value == type)
795 return types[i].name;
796 }
797 return "(unknown)";
798 }
799
class_name(int dnsclass)800 static const char *class_name(int dnsclass)
801 {
802 int i;
803
804 for (i = 0; i < nclasses; i++)
805 {
806 if (classes[i].value == dnsclass)
807 return classes[i].name;
808 }
809 return "(unknown)";
810 }
811
usage(void)812 static void usage(void)
813 {
814 fprintf(stderr, "usage: adig [-f flag] [-s server] [-c class] "
815 "[-t type] [-p port] name ...\n");
816 exit(1);
817 }
818
destroy_addr_list(struct ares_addr_node * head)819 static void destroy_addr_list(struct ares_addr_node *head)
820 {
821 while(head)
822 {
823 struct ares_addr_node *detached = head;
824 head = head->next;
825 free(detached);
826 }
827 }
828
append_addr_list(struct ares_addr_node ** head,struct ares_addr_node * node)829 static void append_addr_list(struct ares_addr_node **head,
830 struct ares_addr_node *node)
831 {
832 struct ares_addr_node *last;
833 node->next = NULL;
834 if(*head)
835 {
836 last = *head;
837 while(last->next)
838 last = last->next;
839 last->next = node;
840 }
841 else
842 *head = node;
843 }
844