3
0

nslookup.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini nslookup implementation for busybox
  4. *
  5. * Copyright (C) 1999,2000 by Lineo, inc. and John Beppu
  6. * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
  7. *
  8. * Correct default name server display and explicit name server option
  9. * added by Ben Zeckel <bzeckel@hmc.edu> June 2001
  10. *
  11. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  12. */
  13. #include <resolv.h>
  14. #include "busybox.h"
  15. /*
  16. * I'm only implementing non-interactive mode;
  17. * I totally forgot nslookup even had an interactive mode.
  18. */
  19. /* Examples of 'standard' nslookup output
  20. * $ nslookup yahoo.com
  21. * Server: 128.193.0.10
  22. * Address: 128.193.0.10#53
  23. *
  24. * Non-authoritative answer:
  25. * Name: yahoo.com
  26. * Address: 216.109.112.135
  27. * Name: yahoo.com
  28. * Address: 66.94.234.13
  29. *
  30. * $ nslookup 204.152.191.37
  31. * Server: 128.193.4.20
  32. * Address: 128.193.4.20#53
  33. *
  34. * Non-authoritative answer:
  35. * 37.191.152.204.in-addr.arpa canonical name = 37.32-27.191.152.204.in-addr.arpa.
  36. * 37.32-27.191.152.204.in-addr.arpa name = zeus-pub2.kernel.org.
  37. *
  38. * Authoritative answers can be found from:
  39. * 32-27.191.152.204.in-addr.arpa nameserver = ns1.kernel.org.
  40. * 32-27.191.152.204.in-addr.arpa nameserver = ns2.kernel.org.
  41. * 32-27.191.152.204.in-addr.arpa nameserver = ns3.kernel.org.
  42. * ns1.kernel.org internet address = 140.211.167.34
  43. * ns2.kernel.org internet address = 204.152.191.4
  44. * ns3.kernel.org internet address = 204.152.191.36
  45. */
  46. static int sockaddr_to_dotted(struct sockaddr *saddr, char *buf, int buflen)
  47. {
  48. if (buflen <= 0) return -1;
  49. buf[0] = '\0';
  50. if (saddr->sa_family == AF_INET) {
  51. inet_ntop(AF_INET, &((struct sockaddr_in*)saddr)->sin_addr, buf, buflen);
  52. return 0;
  53. }
  54. if (saddr->sa_family == AF_INET6) {
  55. inet_ntop(AF_INET6, &((struct sockaddr_in6*)saddr)->sin6_addr, buf, buflen);
  56. return 0;
  57. }
  58. return -1;
  59. }
  60. static int print_host(const char *hostname, const char *header)
  61. {
  62. char str[128]; /* IPv6 address will fit, hostnames hopefully too */
  63. struct addrinfo *result = NULL;
  64. int rc;
  65. struct addrinfo hint;
  66. memset(&hint, 0 , sizeof(hint));
  67. /* hint.ai_family = AF_UNSPEC; - zero anyway */
  68. /* Needed. Or else we will get each address thrice (or more)
  69. * for each possible socket type (tcp,udp,raw...): */
  70. hint.ai_socktype = SOCK_STREAM;
  71. // hint.ai_flags = AI_CANONNAME;
  72. rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result);
  73. if (!rc) {
  74. struct addrinfo *cur = result;
  75. // printf("%s\n", cur->ai_canonname); ?
  76. while (cur) {
  77. sockaddr_to_dotted(cur->ai_addr, str, sizeof(str));
  78. printf("%s %s\nAddress: %s", header, hostname, str);
  79. str[0] = ' ';
  80. if (getnameinfo(cur->ai_addr, cur->ai_addrlen, str+1, sizeof(str)-1, NULL, 0, NI_NAMEREQD))
  81. str[0] = '\0';
  82. puts(str);
  83. cur = cur->ai_next;
  84. }
  85. } else {
  86. bb_error_msg("getaddrinfo('%s') failed: %s", hostname, gai_strerror(rc));
  87. }
  88. freeaddrinfo(result);
  89. return (rc != 0);
  90. }
  91. /* alter the global _res nameserver structure to use
  92. an explicit dns server instead of what is in /etc/resolv.h */
  93. static void set_default_dns(char *server)
  94. {
  95. struct in_addr server_in_addr;
  96. if (inet_pton(AF_INET, server, &server_in_addr) > 0) {
  97. _res.nscount = 1;
  98. _res.nsaddr_list[0].sin_addr = server_in_addr;
  99. }
  100. }
  101. /* lookup the default nameserver and display it */
  102. static void server_print(void)
  103. {
  104. char str[INET6_ADDRSTRLEN];
  105. sockaddr_to_dotted((struct sockaddr*)&_res.nsaddr_list[0], str, sizeof(str));
  106. print_host(str, "Server:");
  107. puts("");
  108. }
  109. int nslookup_main(int argc, char **argv)
  110. {
  111. /*
  112. * initialize DNS structure _res used in printing the default
  113. * name server and in the explicit name server option feature.
  114. */
  115. res_init();
  116. /*
  117. * We allow 1 or 2 arguments.
  118. * The first is the name to be looked up and the second is an
  119. * optional DNS server with which to do the lookup.
  120. * More than 3 arguments is an error to follow the pattern of the
  121. * standard nslookup
  122. */
  123. if (argc < 2 || *argv[1] == '-' || argc > 3)
  124. bb_show_usage();
  125. else if(argc == 3)
  126. set_default_dns(argv[2]);
  127. server_print();
  128. return print_host(argv[1], "Name: ");
  129. }
  130. /* $Id: nslookup.c,v 1.33 2004/10/13 07:25:01 andersen Exp $ */