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