adig.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /* Copyright 1998 by the Massachusetts Institute of Technology.
  2. *
  3. * $Id$
  4. *
  5. * Permission to use, copy, modify, and distribute this
  6. * software and its documentation for any purpose and without
  7. * fee is hereby granted, provided that the above copyright
  8. * notice appear in all copies and that both that copyright
  9. * notice and this permission notice appear in supporting
  10. * documentation, and that the name of M.I.T. not be used in
  11. * advertising or publicity pertaining to distribution of the
  12. * software without specific, written prior permission.
  13. * M.I.T. makes no representations about the suitability of
  14. * this software for any purpose. It is provided "as is"
  15. * without express or implied warranty.
  16. */
  17. #include "setup.h"
  18. #ifdef HAVE_SYS_SOCKET_H
  19. # include <sys/socket.h>
  20. #endif
  21. #ifdef HAVE_NETINET_IN_H
  22. # include <netinet/in.h>
  23. #endif
  24. #ifdef HAVE_ARPA_INET_H
  25. # include <arpa/inet.h>
  26. #endif
  27. #ifdef HAVE_NETDB_H
  28. # include <netdb.h>
  29. #endif
  30. #ifdef HAVE_ARPA_NAMESER_H
  31. # include <arpa/nameser.h>
  32. #else
  33. # include "nameser.h"
  34. #endif
  35. #ifdef HAVE_ARPA_NAMESER_COMPAT_H
  36. # include <arpa/nameser_compat.h>
  37. #endif
  38. #ifdef HAVE_SYS_TIME_H
  39. # include <sys/time.h>
  40. #endif
  41. #ifdef HAVE_UNISTD_H
  42. # include <unistd.h>
  43. #endif
  44. #ifdef HAVE_STRINGS_H
  45. # include <strings.h>
  46. #endif
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <ctype.h>
  51. #include <errno.h>
  52. #include "ares.h"
  53. #include "ares_dns.h"
  54. #include "inet_ntop.h"
  55. #include "inet_net_pton.h"
  56. #include "ares_getopt.h"
  57. #ifndef HAVE_STRDUP
  58. # include "ares_strdup.h"
  59. # define strdup(ptr) ares_strdup(ptr)
  60. #endif
  61. #ifndef HAVE_STRCASECMP
  62. # include "ares_strcasecmp.h"
  63. # define strcasecmp(p1,p2) ares_strcasecmp(p1,p2)
  64. #endif
  65. #ifndef HAVE_STRNCASECMP
  66. # include "ares_strcasecmp.h"
  67. # define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n)
  68. #endif
  69. #ifdef WATT32
  70. #undef WIN32 /* Redefined in MingW headers */
  71. #endif
  72. /* Mac OS X portability check */
  73. #ifndef T_SRV
  74. #define T_SRV 33 /* server selection */
  75. #endif
  76. struct nv {
  77. const char *name;
  78. int value;
  79. };
  80. static const struct nv flags[] = {
  81. { "usevc", ARES_FLAG_USEVC },
  82. { "primary", ARES_FLAG_PRIMARY },
  83. { "igntc", ARES_FLAG_IGNTC },
  84. { "norecurse", ARES_FLAG_NORECURSE },
  85. { "stayopen", ARES_FLAG_STAYOPEN },
  86. { "noaliases", ARES_FLAG_NOALIASES }
  87. };
  88. static const int nflags = sizeof(flags) / sizeof(flags[0]);
  89. static const struct nv classes[] = {
  90. { "IN", C_IN },
  91. { "CHAOS", C_CHAOS },
  92. { "HS", C_HS },
  93. { "ANY", C_ANY }
  94. };
  95. static const int nclasses = sizeof(classes) / sizeof(classes[0]);
  96. static const struct nv types[] = {
  97. { "A", T_A },
  98. { "NS", T_NS },
  99. { "MD", T_MD },
  100. { "MF", T_MF },
  101. { "CNAME", T_CNAME },
  102. { "SOA", T_SOA },
  103. { "MB", T_MB },
  104. { "MG", T_MG },
  105. { "MR", T_MR },
  106. { "NULL", T_NULL },
  107. { "WKS", T_WKS },
  108. { "PTR", T_PTR },
  109. { "HINFO", T_HINFO },
  110. { "MINFO", T_MINFO },
  111. { "MX", T_MX },
  112. { "TXT", T_TXT },
  113. { "RP", T_RP },
  114. { "AFSDB", T_AFSDB },
  115. { "X25", T_X25 },
  116. { "ISDN", T_ISDN },
  117. { "RT", T_RT },
  118. { "NSAP", T_NSAP },
  119. { "NSAP_PTR", T_NSAP_PTR },
  120. { "SIG", T_SIG },
  121. { "KEY", T_KEY },
  122. { "PX", T_PX },
  123. { "GPOS", T_GPOS },
  124. { "AAAA", T_AAAA },
  125. { "LOC", T_LOC },
  126. { "SRV", T_SRV },
  127. { "AXFR", T_AXFR },
  128. { "MAILB", T_MAILB },
  129. { "MAILA", T_MAILA },
  130. { "NAPTR", T_NAPTR },
  131. { "ANY", T_ANY }
  132. };
  133. static const int ntypes = sizeof(types) / sizeof(types[0]);
  134. static const char *opcodes[] = {
  135. "QUERY", "IQUERY", "STATUS", "(reserved)", "NOTIFY",
  136. "(unknown)", "(unknown)", "(unknown)", "(unknown)",
  137. "UPDATEA", "UPDATED", "UPDATEDA", "UPDATEM", "UPDATEMA",
  138. "ZONEINIT", "ZONEREF"
  139. };
  140. struct in_addr inaddr;
  141. static const char *rcodes[] = {
  142. "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED",
  143. "(unknown)", "(unknown)", "(unknown)", "(unknown)", "(unknown)",
  144. "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
  145. };
  146. static void callback(void *arg, int status, int timeouts,
  147. unsigned char *abuf, int alen);
  148. static const unsigned char *display_question(const unsigned char *aptr,
  149. const unsigned char *abuf,
  150. int alen);
  151. static const unsigned char *display_rr(const unsigned char *aptr,
  152. const unsigned char *abuf, int alen);
  153. static const char *type_name(int type);
  154. static const char *class_name(int dnsclass);
  155. static void usage(void);
  156. int main(int argc, char **argv)
  157. {
  158. ares_channel channel;
  159. int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
  160. int status, nfds, count;
  161. struct ares_options options;
  162. struct hostent *hostent;
  163. fd_set read_fds, write_fds;
  164. struct timeval *tvp, tv;
  165. #ifdef USE_WINSOCK
  166. WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
  167. WSADATA wsaData;
  168. WSAStartup(wVersionRequested, &wsaData);
  169. #endif
  170. options.flags = ARES_FLAG_NOCHECKRESP;
  171. options.servers = NULL;
  172. options.nservers = 0;
  173. while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
  174. {
  175. switch (c)
  176. {
  177. case 'd':
  178. #ifdef WATT32
  179. dbug_init();
  180. #endif
  181. break;
  182. case 'f':
  183. /* Add a flag. */
  184. for (i = 0; i < nflags; i++)
  185. {
  186. if (strcmp(flags[i].name, optarg) == 0)
  187. break;
  188. }
  189. if (i == nflags)
  190. usage();
  191. options.flags |= flags[i].value;
  192. break;
  193. case 's':
  194. /* Add a server, and specify servers in the option mask. */
  195. if (ares_inet_pton(AF_INET, optarg, &inaddr) <= 0)
  196. {
  197. hostent = gethostbyname(optarg);
  198. if (!hostent || hostent->h_addrtype != AF_INET)
  199. {
  200. fprintf(stderr, "adig: server %s not found.\n", optarg);
  201. return 1;
  202. }
  203. memcpy(&inaddr, hostent->h_addr, sizeof(struct in_addr));
  204. }
  205. options.servers = realloc(options.servers, (options.nservers + 1)
  206. * sizeof(struct in_addr));
  207. if (!options.servers)
  208. {
  209. fprintf(stderr, "Out of memory!\n");
  210. return 1;
  211. }
  212. memcpy(&options.servers[options.nservers], &inaddr,
  213. sizeof(struct in_addr));
  214. options.nservers++;
  215. optmask |= ARES_OPT_SERVERS;
  216. break;
  217. case 'c':
  218. /* Set the query class. */
  219. for (i = 0; i < nclasses; i++)
  220. {
  221. if (strcasecmp(classes[i].name, optarg) == 0)
  222. break;
  223. }
  224. if (i == nclasses)
  225. usage();
  226. dnsclass = classes[i].value;
  227. break;
  228. case 't':
  229. /* Set the query type. */
  230. for (i = 0; i < ntypes; i++)
  231. {
  232. if (strcasecmp(types[i].name, optarg) == 0)
  233. break;
  234. }
  235. if (i == ntypes)
  236. usage();
  237. type = types[i].value;
  238. break;
  239. case 'T':
  240. /* Set the TCP port number. */
  241. if (!ISDIGIT(*optarg))
  242. usage();
  243. options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
  244. optmask |= ARES_OPT_TCP_PORT;
  245. break;
  246. case 'U':
  247. /* Set the UDP port number. */
  248. if (!ISDIGIT(*optarg))
  249. usage();
  250. options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
  251. optmask |= ARES_OPT_UDP_PORT;
  252. break;
  253. }
  254. }
  255. argc -= optind;
  256. argv += optind;
  257. if (argc == 0)
  258. usage();
  259. status = ares_init_options(&channel, &options, optmask);
  260. if (status != ARES_SUCCESS)
  261. {
  262. fprintf(stderr, "ares_init_options: %s\n",
  263. ares_strerror(status));
  264. return 1;
  265. }
  266. /* Initiate the queries, one per command-line argument. If there is
  267. * only one query to do, supply NULL as the callback argument;
  268. * otherwise, supply the query name as an argument so we can
  269. * distinguish responses for the user when printing them out.
  270. */
  271. if (argc == 1)
  272. ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
  273. else
  274. {
  275. for (; *argv; argv++)
  276. ares_query(channel, *argv, dnsclass, type, callback, *argv);
  277. }
  278. /* Wait for all queries to complete. */
  279. while (1)
  280. {
  281. FD_ZERO(&read_fds);
  282. FD_ZERO(&write_fds);
  283. nfds = ares_fds(channel, &read_fds, &write_fds);
  284. if (nfds == 0)
  285. break;
  286. tvp = ares_timeout(channel, NULL, &tv);
  287. count = select(nfds, &read_fds, &write_fds, NULL, tvp);
  288. if (count < 0 && SOCKERRNO != EINVAL)
  289. {
  290. perror("select");
  291. return 1;
  292. }
  293. ares_process(channel, &read_fds, &write_fds);
  294. }
  295. ares_destroy(channel);
  296. #ifdef USE_WINSOCK
  297. WSACleanup();
  298. #endif
  299. return 0;
  300. }
  301. static void callback(void *arg, int status, int timeouts,
  302. unsigned char *abuf, int alen)
  303. {
  304. char *name = (char *) arg;
  305. int id, qr, opcode, aa, tc, rd, ra, rcode;
  306. unsigned int qdcount, ancount, nscount, arcount, i;
  307. const unsigned char *aptr;
  308. (void) timeouts;
  309. /* Display the query name if given. */
  310. if (name)
  311. printf("Answer for query %s:\n", name);
  312. /* Display an error message if there was an error, but only stop if
  313. * we actually didn't get an answer buffer.
  314. */
  315. if (status != ARES_SUCCESS)
  316. {
  317. printf("%s\n", ares_strerror(status));
  318. if (!abuf)
  319. return;
  320. }
  321. /* Won't happen, but check anyway, for safety. */
  322. if (alen < HFIXEDSZ)
  323. return;
  324. /* Parse the answer header. */
  325. id = DNS_HEADER_QID(abuf);
  326. qr = DNS_HEADER_QR(abuf);
  327. opcode = DNS_HEADER_OPCODE(abuf);
  328. aa = DNS_HEADER_AA(abuf);
  329. tc = DNS_HEADER_TC(abuf);
  330. rd = DNS_HEADER_RD(abuf);
  331. ra = DNS_HEADER_RA(abuf);
  332. rcode = DNS_HEADER_RCODE(abuf);
  333. qdcount = DNS_HEADER_QDCOUNT(abuf);
  334. ancount = DNS_HEADER_ANCOUNT(abuf);
  335. nscount = DNS_HEADER_NSCOUNT(abuf);
  336. arcount = DNS_HEADER_ARCOUNT(abuf);
  337. /* Display the answer header. */
  338. printf("id: %d\n", id);
  339. printf("flags: %s%s%s%s%s\n",
  340. qr ? "qr " : "",
  341. aa ? "aa " : "",
  342. tc ? "tc " : "",
  343. rd ? "rd " : "",
  344. ra ? "ra " : "");
  345. printf("opcode: %s\n", opcodes[opcode]);
  346. printf("rcode: %s\n", rcodes[rcode]);
  347. /* Display the questions. */
  348. printf("Questions:\n");
  349. aptr = abuf + HFIXEDSZ;
  350. for (i = 0; i < qdcount; i++)
  351. {
  352. aptr = display_question(aptr, abuf, alen);
  353. if (aptr == NULL)
  354. return;
  355. }
  356. /* Display the answers. */
  357. printf("Answers:\n");
  358. for (i = 0; i < ancount; i++)
  359. {
  360. aptr = display_rr(aptr, abuf, alen);
  361. if (aptr == NULL)
  362. return;
  363. }
  364. /* Display the NS records. */
  365. printf("NS records:\n");
  366. for (i = 0; i < nscount; i++)
  367. {
  368. aptr = display_rr(aptr, abuf, alen);
  369. if (aptr == NULL)
  370. return;
  371. }
  372. /* Display the additional records. */
  373. printf("Additional records:\n");
  374. for (i = 0; i < arcount; i++)
  375. {
  376. aptr = display_rr(aptr, abuf, alen);
  377. if (aptr == NULL)
  378. return;
  379. }
  380. }
  381. static const unsigned char *display_question(const unsigned char *aptr,
  382. const unsigned char *abuf,
  383. int alen)
  384. {
  385. char *name;
  386. int type, dnsclass, status;
  387. long len;
  388. /* Parse the question name. */
  389. status = ares_expand_name(aptr, abuf, alen, &name, &len);
  390. if (status != ARES_SUCCESS)
  391. return NULL;
  392. aptr += len;
  393. /* Make sure there's enough data after the name for the fixed part
  394. * of the question.
  395. */
  396. if (aptr + QFIXEDSZ > abuf + alen)
  397. {
  398. ares_free_string(name);
  399. return NULL;
  400. }
  401. /* Parse the question type and class. */
  402. type = DNS_QUESTION_TYPE(aptr);
  403. dnsclass = DNS_QUESTION_CLASS(aptr);
  404. aptr += QFIXEDSZ;
  405. /* Display the question, in a format sort of similar to how we will
  406. * display RRs.
  407. */
  408. printf("\t%-15s.\t", name);
  409. if (dnsclass != C_IN)
  410. printf("\t%s", class_name(dnsclass));
  411. printf("\t%s\n", type_name(type));
  412. ares_free_string(name);
  413. return aptr;
  414. }
  415. static const unsigned char *display_rr(const unsigned char *aptr,
  416. const unsigned char *abuf, int alen)
  417. {
  418. const unsigned char *p;
  419. int type, dnsclass, ttl, dlen, status;
  420. long len;
  421. char addr[46];
  422. union {
  423. unsigned char * as_uchar;
  424. char * as_char;
  425. } name;
  426. /* Parse the RR name. */
  427. status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
  428. if (status != ARES_SUCCESS)
  429. return NULL;
  430. aptr += len;
  431. /* Make sure there is enough data after the RR name for the fixed
  432. * part of the RR.
  433. */
  434. if (aptr + RRFIXEDSZ > abuf + alen)
  435. {
  436. ares_free_string(name.as_char);
  437. return NULL;
  438. }
  439. /* Parse the fixed part of the RR, and advance to the RR data
  440. * field. */
  441. type = DNS_RR_TYPE(aptr);
  442. dnsclass = DNS_RR_CLASS(aptr);
  443. ttl = DNS_RR_TTL(aptr);
  444. dlen = DNS_RR_LEN(aptr);
  445. aptr += RRFIXEDSZ;
  446. if (aptr + dlen > abuf + alen)
  447. {
  448. ares_free_string(name.as_char);
  449. return NULL;
  450. }
  451. /* Display the RR name, class, and type. */
  452. printf("\t%-15s.\t%d", name.as_char, ttl);
  453. if (dnsclass != C_IN)
  454. printf("\t%s", class_name(dnsclass));
  455. printf("\t%s", type_name(type));
  456. ares_free_string(name.as_char);
  457. /* Display the RR data. Don't touch aptr. */
  458. switch (type)
  459. {
  460. case T_CNAME:
  461. case T_MB:
  462. case T_MD:
  463. case T_MF:
  464. case T_MG:
  465. case T_MR:
  466. case T_NS:
  467. case T_PTR:
  468. /* For these types, the RR data is just a domain name. */
  469. status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
  470. if (status != ARES_SUCCESS)
  471. return NULL;
  472. printf("\t%s.", name.as_char);
  473. ares_free_string(name.as_char);
  474. break;
  475. case T_HINFO:
  476. /* The RR data is two length-counted character strings. */
  477. p = aptr;
  478. len = *p;
  479. if (p + len + 1 > aptr + dlen)
  480. return NULL;
  481. printf("\t%.*s", (int)len, p + 1);
  482. p += len + 1;
  483. len = *p;
  484. if (p + len + 1 > aptr + dlen)
  485. return NULL;
  486. printf("\t%.*s", (int)len, p + 1);
  487. break;
  488. case T_MINFO:
  489. /* The RR data is two domain names. */
  490. p = aptr;
  491. status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
  492. if (status != ARES_SUCCESS)
  493. return NULL;
  494. printf("\t%s.", name.as_char);
  495. ares_free_string(name.as_char);
  496. p += len;
  497. status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
  498. if (status != ARES_SUCCESS)
  499. return NULL;
  500. printf("\t%s.", name.as_char);
  501. ares_free_string(name.as_char);
  502. break;
  503. case T_MX:
  504. /* The RR data is two bytes giving a preference ordering, and
  505. * then a domain name.
  506. */
  507. if (dlen < 2)
  508. return NULL;
  509. printf("\t%d", DNS__16BIT(aptr));
  510. status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len);
  511. if (status != ARES_SUCCESS)
  512. return NULL;
  513. printf("\t%s.", name.as_char);
  514. ares_free_string(name.as_char);
  515. break;
  516. case T_SOA:
  517. /* The RR data is two domain names and then five four-byte
  518. * numbers giving the serial number and some timeouts.
  519. */
  520. p = aptr;
  521. status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
  522. if (status != ARES_SUCCESS)
  523. return NULL;
  524. printf("\t%s.\n", name.as_char);
  525. ares_free_string(name.as_char);
  526. p += len;
  527. status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
  528. if (status != ARES_SUCCESS)
  529. return NULL;
  530. printf("\t\t\t\t\t\t%s.\n", name.as_char);
  531. ares_free_string(name.as_char);
  532. p += len;
  533. if (p + 20 > aptr + dlen)
  534. return NULL;
  535. printf("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )",
  536. (unsigned long)DNS__32BIT(p), (unsigned long)DNS__32BIT(p+4),
  537. (unsigned long)DNS__32BIT(p+8), (unsigned long)DNS__32BIT(p+12),
  538. (unsigned long)DNS__32BIT(p+16));
  539. break;
  540. case T_TXT:
  541. /* The RR data is one or more length-counted character
  542. * strings. */
  543. p = aptr;
  544. while (p < aptr + dlen)
  545. {
  546. len = *p;
  547. if (p + len + 1 > aptr + dlen)
  548. return NULL;
  549. printf("\t%.*s", (int)len, p + 1);
  550. p += len + 1;
  551. }
  552. break;
  553. case T_A:
  554. /* The RR data is a four-byte Internet address. */
  555. if (dlen != 4)
  556. return NULL;
  557. printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr)));
  558. break;
  559. case T_AAAA:
  560. /* The RR data is a 16-byte IPv6 address. */
  561. if (dlen != 16)
  562. return NULL;
  563. printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr)));
  564. break;
  565. case T_WKS:
  566. /* Not implemented yet */
  567. break;
  568. case T_SRV:
  569. /* The RR data is three two-byte numbers representing the
  570. * priority, weight, and port, followed by a domain name.
  571. */
  572. printf("\t%d", DNS__16BIT(aptr));
  573. printf(" %d", DNS__16BIT(aptr + 2));
  574. printf(" %d", DNS__16BIT(aptr + 4));
  575. status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len);
  576. if (status != ARES_SUCCESS)
  577. return NULL;
  578. printf("\t%s.", name.as_char);
  579. ares_free_string(name.as_char);
  580. break;
  581. case T_NAPTR:
  582. printf("\t%d", DNS__16BIT(aptr)); /* order */
  583. printf(" %d\n", DNS__16BIT(aptr + 2)); /* preference */
  584. p = aptr + 4;
  585. status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
  586. if (status != ARES_SUCCESS)
  587. return NULL;
  588. printf("\t\t\t\t\t\t%s\n", name.as_char);
  589. ares_free_string(name.as_char);
  590. p += len;
  591. status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
  592. if (status != ARES_SUCCESS)
  593. return NULL;
  594. printf("\t\t\t\t\t\t%s\n", name.as_char);
  595. ares_free_string(name.as_char);
  596. p += len;
  597. status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
  598. if (status != ARES_SUCCESS)
  599. return NULL;
  600. printf("\t\t\t\t\t\t%s\n", name.as_char);
  601. ares_free_string(name.as_char);
  602. p += len;
  603. status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
  604. if (status != ARES_SUCCESS)
  605. return NULL;
  606. printf("\t\t\t\t\t\t%s", name.as_char);
  607. ares_free_string(name.as_char);
  608. break;
  609. default:
  610. printf("\t[Unknown RR; cannot parse]");
  611. break;
  612. }
  613. printf("\n");
  614. return aptr + dlen;
  615. }
  616. static const char *type_name(int type)
  617. {
  618. int i;
  619. for (i = 0; i < ntypes; i++)
  620. {
  621. if (types[i].value == type)
  622. return types[i].name;
  623. }
  624. return "(unknown)";
  625. }
  626. static const char *class_name(int dnsclass)
  627. {
  628. int i;
  629. for (i = 0; i < nclasses; i++)
  630. {
  631. if (classes[i].value == dnsclass)
  632. return classes[i].name;
  633. }
  634. return "(unknown)";
  635. }
  636. static void usage(void)
  637. {
  638. fprintf(stderr, "usage: adig [-f flag] [-s server] [-c class] "
  639. "[-t type] [-p port] name ...\n");
  640. exit(1);
  641. }