blob: e5cef7b9c6d9df3e72451d4178c29e9418cc89bb [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* 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
87struct nv {
88 const char *name;
89 int value;
90};
91
92static 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};
100static const int nflags = sizeof(flags) / sizeof(flags[0]);
101
102static const struct nv classes[] = {
103 { "IN", C_IN },
104 { "CHAOS", C_CHAOS },
105 { "HS", C_HS },
106 { "ANY", C_ANY }
107};
108static const int nclasses = sizeof(classes) / sizeof(classes[0]);
109
110static 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};
152static const int ntypes = sizeof(types) / sizeof(types[0]);
153
154static 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
161static const char *rcodes[] = {
162 "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED",
163 "(unknown)", "(unknown)", "(unknown)", "(unknown)", "(unknown)",
164 "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
165};
166
167static void callback(void *arg, int status, int timeouts,
168 unsigned char *abuf, int alen);
169static const unsigned char *display_question(const unsigned char *aptr,
170 const unsigned char *abuf,
171 int alen);
172static const unsigned char *display_rr(const unsigned char *aptr,
173 const unsigned char *abuf, int alen);
174static const char *type_name(int type);
175static const char *class_name(int dnsclass);
176static void usage(void);
177static void destroy_addr_list(struct ares_addr_node *head);
178static void append_addr_list(struct ares_addr_node **head,
179 struct ares_addr_node *node);
180int main(int argc, char **argv)
181{
182 ares_channel channel;
183 int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
184 int status, nfds, count;
185 struct ares_options options;
186 struct hostent *hostent;
187 fd_set read_fds, write_fds;
188 struct timeval *tvp, tv;
189 struct ares_addr_node *srvr, *servers = NULL;
190 char * ares_dev = NULL;
191#ifdef USE_WINSOCK
192 WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
193 WSADATA wsaData;
194 WSAStartup(wVersionRequested, &wsaData);
195#endif
196
197 status = ares_library_init(ARES_LIB_INIT_ALL);
198 if (status != ARES_SUCCESS)
199 {
200 fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
201 return 1;
202 }
203
204 options.flags = ARES_FLAG_NOCHECKRESP;
205 options.servers = NULL;
206 options.nservers = 0;
207 while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:i:")) != -1)
208 {
209 switch (c)
210 {
211 case 'd':
212#ifdef WATT32
213 dbug_init();
214#endif
215 break;
216
217 case 'f':
218 /* Add a flag. */
219 for (i = 0; i < nflags; i++)
220 {
221 if (strcmp(flags[i].name, optarg) == 0)
222 break;
223 }
224 if (i < nflags)
225 options.flags |= flags[i].value;
226 else
227 usage();
228 break;
229 #if 1
230 case 'i':
231
232 ares_dev = (char * )strdup(optarg);
233 fprintf(stderr, "ares_dev is %s\n", ares_dev);
234 break;
235 #endif
236 case 's':
237 /* User-specified name servers override default ones. */
238 srvr = malloc(sizeof(struct ares_addr_node));
239 if (!srvr)
240 {
241 fprintf(stderr, "Out of memory!\n");
242 destroy_addr_list(servers);
243 return 1;
244 }
245 append_addr_list(&servers, srvr);
246 if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
247 srvr->family = AF_INET;
248 else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0)
249 srvr->family = AF_INET6;
250 else
251 {
252 hostent = gethostbyname(optarg);
253 if (!hostent)
254 {
255 fprintf(stderr, "adig: server %s not found.\n", optarg);
256 destroy_addr_list(servers);
257 return 1;
258 }
259 switch (hostent->h_addrtype)
260 {
261 case AF_INET:
262 srvr->family = AF_INET;
263 memcpy(&srvr->addr.addr4, hostent->h_addr,
264 sizeof(srvr->addr.addr4));
265 break;
266 case AF_INET6:
267 srvr->family = AF_INET6;
268 memcpy(&srvr->addr.addr6, hostent->h_addr,
269 sizeof(srvr->addr.addr6));
270 break;
271 default:
272 fprintf(stderr,
273 "adig: server %s unsupported address family.\n", optarg);
274 destroy_addr_list(servers);
275 return 1;
276 }
277 }
278 /* Notice that calling ares_init_options() without servers in the
279 * options struct and with ARES_OPT_SERVERS set simultaneously in
280 * the options mask, results in an initialization with no servers.
281 * When alternative name servers have been specified these are set
282 * later calling ares_set_servers() overriding any existing server
283 * configuration. To prevent initial configuration with default
284 * servers that will be discarded later, ARES_OPT_SERVERS is set.
285 * If this flag is not set here the result shall be the same but
286 * ares_init_options() will do needless work. */
287 optmask |= ARES_OPT_SERVERS;
288 break;
289
290 case 'c':
291 /* Set the query class. */
292 for (i = 0; i < nclasses; i++)
293 {
294 if (strcasecmp(classes[i].name, optarg) == 0)
295 break;
296 }
297 if (i < nclasses)
298 dnsclass = classes[i].value;
299 else
300 usage();
301 break;
302
303 case 't':
304 /* Set the query type. */
305 for (i = 0; i < ntypes; i++)
306 {
307 if (strcasecmp(types[i].name, optarg) == 0)
308 break;
309 }
310 if (i < ntypes)
311 type = types[i].value;
312 else
313 usage();
314 break;
315
316 case 'T':
317 /* Set the TCP port number. */
318 if (!ISDIGIT(*optarg))
319 usage();
320 options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
321 optmask |= ARES_OPT_TCP_PORT;
322 break;
323
324 case 'U':
325 /* Set the UDP port number. */
326 if (!ISDIGIT(*optarg))
327 usage();
328 options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
329 optmask |= ARES_OPT_UDP_PORT;
330 break;
331 }
332 }
333 argc -= optind;
334 argv += optind;
335 if (argc == 0)
336 usage();
337
338 status = ares_init_options(&channel, &options, optmask, ares_dev);
339
340 if (status != ARES_SUCCESS)
341 {
342 fprintf(stderr, "ares_init_options: %s\n",
343 ares_strerror(status));
344 return 1;
345 }
346
347 if(servers)
348 {
349 status = ares_set_servers(channel, servers);
350 destroy_addr_list(servers);
351 if (status != ARES_SUCCESS)
352 {
353 fprintf(stderr, "ares_init_options: %s\n",
354 ares_strerror(status));
355 return 1;
356 }
357 }
358
359 /* Initiate the queries, one per command-line argument. If there is
360 * only one query to do, supply NULL as the callback argument;
361 * otherwise, supply the query name as an argument so we can
362 * distinguish responses for the user when printing them out.
363 */
364 if (argc == 1)
365 ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
366 else
367 {
368 for (; *argv; argv++)
369 ares_query(channel, *argv, dnsclass, type, callback, *argv);
370 }
371
372 /* Wait for all queries to complete. */
373 for (;;)
374 {
375 FD_ZERO(&read_fds);
376 FD_ZERO(&write_fds);
377 nfds = ares_fds(channel, &read_fds, &write_fds);
378 if (nfds == 0)
379 break;
380 tvp = ares_timeout(channel, NULL, &tv);
381 count = select(nfds, &read_fds, &write_fds, NULL, tvp);
382 if (count < 0 && (status = SOCKERRNO) != EINVAL)
383 {
384 printf("select fail: %d", status);
385 return 1;
386 }
387 ares_process(channel, &read_fds, &write_fds);
388 }
389
390 ares_destroy(channel);
391
392 ares_library_cleanup();
393
394#ifdef USE_WINSOCK
395 WSACleanup();
396#endif
397
398 return 0;
399}
400
401static void callback(void *arg, int status, int timeouts,
402 unsigned char *abuf, int alen)
403{
404 char *name = (char *) arg;
405 int id, qr, opcode, aa, tc, rd, ra, rcode;
406 unsigned int qdcount, ancount, nscount, arcount, i;
407 const unsigned char *aptr;
408
409 (void) timeouts;
410
411 /* Display the query name if given. */
412 if (name)
413 printf("Answer for query %s:\n", name);
414
415 /* Display an error message if there was an error, but only stop if
416 * we actually didn't get an answer buffer.
417 */
418 if (status != ARES_SUCCESS)
419 {
420 printf("%s\n", ares_strerror(status));
421 if (!abuf)
422 return;
423 }
424
425 /* Won't happen, but check anyway, for safety. */
426 if (alen < HFIXEDSZ)
427 return;
428
429 /* Parse the answer header. */
430 id = DNS_HEADER_QID(abuf);
431 qr = DNS_HEADER_QR(abuf);
432 opcode = DNS_HEADER_OPCODE(abuf);
433 aa = DNS_HEADER_AA(abuf);
434 tc = DNS_HEADER_TC(abuf);
435 rd = DNS_HEADER_RD(abuf);
436 ra = DNS_HEADER_RA(abuf);
437 rcode = DNS_HEADER_RCODE(abuf);
438 qdcount = DNS_HEADER_QDCOUNT(abuf);
439 ancount = DNS_HEADER_ANCOUNT(abuf);
440 nscount = DNS_HEADER_NSCOUNT(abuf);
441 arcount = DNS_HEADER_ARCOUNT(abuf);
442
443 /* Display the answer header. */
444 printf("id: %d\n", id);
445 printf("flags: %s%s%s%s%s\n",
446 qr ? "qr " : "",
447 aa ? "aa " : "",
448 tc ? "tc " : "",
449 rd ? "rd " : "",
450 ra ? "ra " : "");
451 printf("opcode: %s\n", opcodes[opcode]);
452 printf("rcode: %s\n", rcodes[rcode]);
453
454 /* Display the questions. */
455 printf("Questions:\n");
456 aptr = abuf + HFIXEDSZ;
457 for (i = 0; i < qdcount; i++)
458 {
459 aptr = display_question(aptr, abuf, alen);
460 if (aptr == NULL)
461 return;
462 }
463
464 /* Display the answers. */
465 printf("Answers:\n");
466 for (i = 0; i < ancount; i++)
467 {
468 aptr = display_rr(aptr, abuf, alen);
469 if (aptr == NULL)
470 return;
471 }
472
473 /* Display the NS records. */
474 printf("NS records:\n");
475 for (i = 0; i < nscount; i++)
476 {
477 aptr = display_rr(aptr, abuf, alen);
478 if (aptr == NULL)
479 return;
480 }
481
482 /* Display the additional records. */
483 printf("Additional records:\n");
484 for (i = 0; i < arcount; i++)
485 {
486 aptr = display_rr(aptr, abuf, alen);
487 if (aptr == NULL)
488 return;
489 }
490}
491
492static const unsigned char *display_question(const unsigned char *aptr,
493 const unsigned char *abuf,
494 int alen)
495{
496 char *name;
497 int type, dnsclass, status;
498 long len;
499
500 /* Parse the question name. */
501 status = ares_expand_name(aptr, abuf, alen, &name, &len);
502 if (status != ARES_SUCCESS)
503 return NULL;
504 aptr += len;
505
506 /* Make sure there's enough data after the name for the fixed part
507 * of the question.
508 */
509 if (aptr + QFIXEDSZ > abuf + alen)
510 {
511 ares_free_string(name);
512 return NULL;
513 }
514
515 /* Parse the question type and class. */
516 type = DNS_QUESTION_TYPE(aptr);
517 dnsclass = DNS_QUESTION_CLASS(aptr);
518 aptr += QFIXEDSZ;
519
520 /* Display the question, in a format sort of similar to how we will
521 * display RRs.
522 */
523 printf("\t%-15s.\t", name);
524 if (dnsclass != C_IN)
525 printf("\t%s", class_name(dnsclass));
526 printf("\t%s\n", type_name(type));
527 ares_free_string(name);
528 return aptr;
529}
530
531static const unsigned char *display_rr(const unsigned char *aptr,
532 const unsigned char *abuf, int alen)
533{
534 const unsigned char *p;
535 int type, dnsclass, ttl, dlen, status;
536 long len;
537 char addr[46];
538 union {
539 unsigned char * as_uchar;
540 char * as_char;
541 } name;
542
543 /* Parse the RR name. */
544 status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
545 if (status != ARES_SUCCESS)
546 return NULL;
547 aptr += len;
548
549 /* Make sure there is enough data after the RR name for the fixed
550 * part of the RR.
551 */
552 if (aptr + RRFIXEDSZ > abuf + alen)
553 {
554 ares_free_string(name.as_char);
555 return NULL;
556 }
557
558 /* Parse the fixed part of the RR, and advance to the RR data
559 * field. */
560 type = DNS_RR_TYPE(aptr);
561 dnsclass = DNS_RR_CLASS(aptr);
562 ttl = DNS_RR_TTL(aptr);
563 dlen = DNS_RR_LEN(aptr);
564 aptr += RRFIXEDSZ;
565 if (aptr + dlen > abuf + alen)
566 {
567 ares_free_string(name.as_char);
568 return NULL;
569 }
570
571 /* Display the RR name, class, and type. */
572 printf("\t%-15s.\t%d", name.as_char, ttl);
573 if (dnsclass != C_IN)
574 printf("\t%s", class_name(dnsclass));
575 printf("\t%s", type_name(type));
576 ares_free_string(name.as_char);
577
578 /* Display the RR data. Don't touch aptr. */
579 switch (type)
580 {
581 case T_CNAME:
582 case T_MB:
583 case T_MD:
584 case T_MF:
585 case T_MG:
586 case T_MR:
587 case T_NS:
588 case T_PTR:
589 /* For these types, the RR data is just a domain name. */
590 status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
591 if (status != ARES_SUCCESS)
592 return NULL;
593 printf("\t%s.", name.as_char);
594 ares_free_string(name.as_char);
595 break;
596
597 case T_HINFO:
598 /* The RR data is two length-counted character strings. */
599 p = aptr;
600 len = *p;
601 if (p + len + 1 > aptr + dlen)
602 return NULL;
603 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
604 if (status != ARES_SUCCESS)
605 return NULL;
606 printf("\t%s", name.as_char);
607 ares_free_string(name.as_char);
608 p += len;
609 len = *p;
610 if (p + len + 1 > aptr + dlen)
611 return NULL;
612 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
613 if (status != ARES_SUCCESS)
614 return NULL;
615 printf("\t%s", name.as_char);
616 ares_free_string(name.as_char);
617 break;
618
619 case T_MINFO:
620 /* The RR data is two domain names. */
621 p = aptr;
622 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
623 if (status != ARES_SUCCESS)
624 return NULL;
625 printf("\t%s.", name.as_char);
626 ares_free_string(name.as_char);
627 p += len;
628 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
629 if (status != ARES_SUCCESS)
630 return NULL;
631 printf("\t%s.", name.as_char);
632 ares_free_string(name.as_char);
633 break;
634
635 case T_MX:
636 /* The RR data is two bytes giving a preference ordering, and
637 * then a domain name.
638 */
639 if (dlen < 2)
640 return NULL;
641 printf("\t%d", (int)DNS__16BIT(aptr));
642 status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len);
643 if (status != ARES_SUCCESS)
644 return NULL;
645 printf("\t%s.", name.as_char);
646 ares_free_string(name.as_char);
647 break;
648
649 case T_SOA:
650 /* The RR data is two domain names and then five four-byte
651 * numbers giving the serial number and some timeouts.
652 */
653 p = aptr;
654 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
655 if (status != ARES_SUCCESS)
656 return NULL;
657 printf("\t%s.\n", name.as_char);
658 ares_free_string(name.as_char);
659 p += len;
660 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
661 if (status != ARES_SUCCESS)
662 return NULL;
663 printf("\t\t\t\t\t\t%s.\n", name.as_char);
664 ares_free_string(name.as_char);
665 p += len;
666 if (p + 20 > aptr + dlen)
667 return NULL;
668 printf("\t\t\t\t\t\t( %u %u %u %u %u )",
669 DNS__32BIT(p), DNS__32BIT(p+4),
670 DNS__32BIT(p+8), DNS__32BIT(p+12),
671 DNS__32BIT(p+16));
672 break;
673
674 case T_TXT:
675 /* The RR data is one or more length-counted character
676 * strings. */
677 p = aptr;
678 while (p < aptr + dlen)
679 {
680 len = *p;
681 if (p + len + 1 > aptr + dlen)
682 return NULL;
683 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
684 if (status != ARES_SUCCESS)
685 return NULL;
686 printf("\t%s", name.as_char);
687 ares_free_string(name.as_char);
688 p += len;
689 }
690 break;
691
692 case T_A:
693 /* The RR data is a four-byte Internet address. */
694 if (dlen != 4)
695 return NULL;
696 printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr)));
697 break;
698
699 case T_AAAA:
700 /* The RR data is a 16-byte IPv6 address. */
701 if (dlen != 16)
702 return NULL;
703 printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr)));
704 break;
705
706 case T_WKS:
707 /* Not implemented yet */
708 break;
709
710 case T_SRV:
711 /* The RR data is three two-byte numbers representing the
712 * priority, weight, and port, followed by a domain name.
713 */
714
715 printf("\t%d", (int)DNS__16BIT(aptr));
716 printf(" %d", (int)DNS__16BIT(aptr + 2));
717 printf(" %d", (int)DNS__16BIT(aptr + 4));
718
719 status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len);
720 if (status != ARES_SUCCESS)
721 return NULL;
722 printf("\t%s.", name.as_char);
723 ares_free_string(name.as_char);
724 break;
725
726 case T_NAPTR:
727
728 printf("\t%d", (int)DNS__16BIT(aptr)); /* order */
729 printf(" %d\n", (int)DNS__16BIT(aptr + 2)); /* preference */
730
731 p = aptr + 4;
732 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
733 if (status != ARES_SUCCESS)
734 return NULL;
735 printf("\t\t\t\t\t\t%s\n", name.as_char);
736 ares_free_string(name.as_char);
737 p += len;
738
739 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
740 if (status != ARES_SUCCESS)
741 return NULL;
742 printf("\t\t\t\t\t\t%s\n", name.as_char);
743 ares_free_string(name.as_char);
744 p += len;
745
746 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
747 if (status != ARES_SUCCESS)
748 return NULL;
749 printf("\t\t\t\t\t\t%s\n", name.as_char);
750 ares_free_string(name.as_char);
751 p += len;
752
753 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
754 if (status != ARES_SUCCESS)
755 return NULL;
756 printf("\t\t\t\t\t\t%s", name.as_char);
757 ares_free_string(name.as_char);
758 break;
759
760 case T_DS:
761 case T_SSHFP:
762 case T_RRSIG:
763 case T_NSEC:
764 case T_DNSKEY:
765 printf("\t[RR type parsing unavailable]");
766 break;
767
768 default:
769 printf("\t[Unknown RR; cannot parse]");
770 break;
771 }
772 printf("\n");
773
774 return aptr + dlen;
775}
776
777static const char *type_name(int type)
778{
779 int i;
780
781 for (i = 0; i < ntypes; i++)
782 {
783 if (types[i].value == type)
784 return types[i].name;
785 }
786 return "(unknown)";
787}
788
789static const char *class_name(int dnsclass)
790{
791 int i;
792
793 for (i = 0; i < nclasses; i++)
794 {
795 if (classes[i].value == dnsclass)
796 return classes[i].name;
797 }
798 return "(unknown)";
799}
800
801static void usage(void)
802{
803 fprintf(stderr, "usage: adig [-f flag] [-s server] [-c class] "
804 "[-t type] [-p port] name ...\n");
805 exit(1);
806}
807
808static void destroy_addr_list(struct ares_addr_node *head)
809{
810 while(head)
811 {
812 struct ares_addr_node *detached = head;
813 head = head->next;
814 free(detached);
815 }
816}
817
818static void append_addr_list(struct ares_addr_node **head,
819 struct ares_addr_node *node)
820{
821 struct ares_addr_node *last;
822 node->next = NULL;
823 if(*head)
824 {
825 last = *head;
826 while(last->next)
827 last = last->next;
828 last->next = node;
829 }
830 else
831 *head = node;
832}
833
834int compat_gethostbyname2(const char *name ,const char *dev_name, int family)
835{
836 ares_channel channel;
837 struct ares_options options;
838 int optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
839 fd_set read_fds, write_fds;
840 int status, nfds, count;
841 struct timeval *tvp, tv;
842
843#ifdef USE_WINSOCK
844 WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
845 WSADATA wsaData;
846 WSAStartup(wVersionRequested, &wsaData);
847#endif
848 if (family == AF_INET)
849 type = T_A;
850 else if (family == AF_INET6)
851 type = T_AAAA;
852 options.flags = ARES_FLAG_NOCHECKRESP;
853 options.servers = NULL;
854 options.nservers = 0;
855 status = ares_init_options(&channel, &options, optmask, dev_name);
856 if (status != ARES_SUCCESS)
857 {
858 fprintf(stderr, "ares_init_options: %s\n",
859 ares_strerror(status));
860 return 1;
861 }
862 ares_query(channel, name, dnsclass, type, callback, NULL); /* Wait for all queries to complete. */
863 for (;;)
864 {
865 FD_ZERO(&read_fds);
866 FD_ZERO(&write_fds);
867 nfds = ares_fds(channel, &read_fds, &write_fds);
868 if (nfds == 0)
869 break;
870 tvp = ares_timeout(channel, NULL, &tv);
871 count = select(nfds, &read_fds, &write_fds, NULL, tvp);
872 if (count < 0 && (status = SOCKERRNO) != EINVAL)
873 {
874 printf("select fail: %d", status);
875 return 1;
876 }
877 ares_process(channel, &read_fds, &write_fds);
878 }
879 ares_destroy(channel);
880 ares_library_cleanup();
881#ifdef USE_WINSOCK
882 WSACleanup();
883#endif
884 return 0;
885}
886
887int showone_mark = 0;
888struct hostent showone;
889
890void free_hostent(struct hostent* host){
891 if(host == NULL)
892 return;
893 char **pptr;
894 if(host->h_name)
895 free(host->h_name);
896 if(host->h_aliases){
897 for(pptr = host->h_aliases; *pptr != NULL; pptr++)
898 free(*pptr);
899 free(host->h_aliases);
900 }
901 if(host->h_addr_list){
902 for(pptr = host->h_addr_list; *pptr != NULL; pptr++)
903 free(*pptr);
904 free(host->h_addr_list);
905 }
906 host->h_name = NULL;
907 host->h_aliases = NULL;
908 host->h_addrtype = 0;
909 host->h_length = 0;
910 host->h_addr_list = NULL;
911}
912void dns_callback (void* arg, int status, int timeouts, struct hostent* host) //ares ´¦ÀíÍê³É£¬·µ»ØDNS½âÎöµÄÐÅÏ¢
913{
914 char *ptr, **pptr;
915 char str[30];
916 int len = 0;
917 char *hostname = NULL;
918 char **aliases = NULL;
919 char **addr_list = NULL;
920 int i = 0;
921 printf("dns_callback\n");
922 if(status == ARES_SUCCESS){
923
924 showone.h_addrtype = host->h_addrtype;
925 showone.h_length = host->h_length;
926 if(strlen(host->h_name)){
927 printf("host->h_name = %s\n", host->h_name);
928 hostname = malloc(strlen(host->h_name) + 1);
929 memcpy(hostname, host->h_name, strlen(host->h_name));
930 hostname[strlen(host->h_name)] = '\0';
931 showone.h_name = hostname;
932 } else
933 showone.h_name = NULL;
934
935 i = 0;
936 for(pptr = host->h_aliases; *pptr != NULL; pptr++){
937 i++;
938 }
939 if(i != 0){
940 aliases = (char **)malloc((i+1) * sizeof(char *));
941 i = 0;
942 for(pptr = host->h_aliases; *pptr != NULL; pptr++){
943 aliases[i] = malloc(strlen(*pptr) + 1);
944 memcpy(aliases[i], *pptr, strlen(*pptr));
945 aliases[i][strlen(*pptr)] = '\0';
946 i++;
947 }
948 aliases[i] = NULL;
949 }
950 showone.h_aliases = aliases;
951
952 switch(host->h_addrtype){
953 case AF_INET:
954 case AF_INET6:
955 i = 0;
956 for(pptr = host->h_addr_list; *pptr != NULL; pptr++){
957 i++;
958 inet_ntop(host->h_addrtype, *pptr, str, sizeof(str));
959 printf("\t address: %s , %d, %x\n", str, strlen(str), *pptr);
960 }
961 if(i != 0){
962 addr_list = (char **)malloc((i+1) * sizeof(char *));
963 i = 0;
964 for(pptr = host->h_addr_list; *pptr != NULL; pptr++){
965 addr_list[i] = malloc(host->h_length);
966 memcpy(addr_list[i], *pptr, host->h_length);
967 i++;
968 }
969 addr_list[i] = NULL;
970 }
971 showone.h_addr_list = addr_list;
972 break;
973 default:
974 break;
975 }
976 showone_mark = 2;
977 }
978 else{
979 //printf("lookup failed: %d\n", status);
980 showone_mark = 3;
981 }
982
983}
984
985/**************************************************************************
986* º¯ÊýÃû³Æ£º compat_gethostbyname3
987* ¹¦ÄÜÃèÊö£º Ö¸¶¨Íø¿Ú½øÐÐdnsÇëÇó
988* ²ÎÊý˵Ã÷£º ÓòÃû£¬Íø¿ÚÃû£¬Ð­Òé×壬»Øµ÷º¯Êý
989* ·µ »Ø Öµ£º s
990* ÆäËü˵Ã÷£º ²ÎÊýdev±ØÐëÊÇÖ¸ÕëÔÙmalloc£¬c-ares¿âÌṩµÄ½Ó¿ÚÄÚ»áfree(dev)
991**************************************************************************/
992struct hostent *compat_gethostbyname3(char *name, char *dev, int family)
993{
994 ares_channel channel;
995 int nfds, count;
996 int status;
997 fd_set readers, writers;
998 struct timeval *tvp, tv;
999 struct ares_options options;
1000 int optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
1001
1002 if (strlen(name) == 0 || strlen(dev) == 0) {
1003 printf("\tinvalid name or dev \n");
1004 return NULL;
1005 }
1006 options.servers = NULL;
1007 options.nservers = 0;
1008 status = ares_init_options(&channel, &options, optmask, dev);
1009 if (status != ARES_SUCCESS)
1010 {
1011 fprintf(stderr, "ares_init_options: %s\n",
1012 ares_strerror(status));
1013 return NULL;
1014 }
1015
1016 while(showone_mark != 0){
1017 sleep(1);
1018 }
1019 showone_mark = 1;
1020 memset(&showone, 0, sizeof(showone));
1021 ares_gethostbyname(channel, name, family, dns_callback, NULL); //´«µÝ¸øc-ares channal ºÍ »Øµ÷
1022 // main_loop(&channel); //Ö÷³ÌÐòʼþÑ­»·
1023 while (1) {
1024 FD_ZERO(&readers);
1025 FD_ZERO(&writers);
1026 nfds = ares_fds(channel, &readers, &writers); //»ñÈ¡ares channelʹÓõÄFD
1027 if (nfds == 0)
1028 break;
1029 tvp = ares_timeout(channel, NULL, &tv);
1030 count = select(nfds, &readers, &writers, NULL, tvp); //½«aresµÄSOCKET FD ¼ÓÈëʼþÑ­»·
1031 if (count < 0 && (status = SOCKERRNO) != EINVAL)
1032 {
1033 printf("select fail: %d", status);
1034 showone_mark = 0;
1035 return NULL;
1036 }
1037 ares_process(channel, &readers, &writers); // ÓÐʼþ·¢Éú ½»ÓÉares ´¦Àí
1038 }
1039 ares_destroy(channel);
1040 ares_library_cleanup();
1041 while(showone_mark == 1){
1042 sleep(1);
1043 }
1044 if (showone_mark == 2){
1045 showone_mark = 0;
1046 return &showone;
1047 }
1048 if(showone_mark == 3)
1049 {
1050 showone_mark = 0;
1051 return NULL;
1052 }
1053
1054 printf("adig unexpect error showone_mark = %d\n", showone_mark);
1055 return NULL;
1056}