12 |
*/ |
*/ |
13 |
|
|
14 |
#include <resolv.h> |
#include <resolv.h> |
15 |
#include "busybox.h" |
#include "libbb.h" |
16 |
|
|
17 |
/* |
/* |
18 |
* I'm only implementing non-interactive mode; |
* I'm only implementing non-interactive mode; |
19 |
* I totally forgot nslookup even had an interactive mode. |
* I totally forgot nslookup even had an interactive mode. |
20 |
|
* |
21 |
|
* This applet is the only user of res_init(). Without it, |
22 |
|
* you may avoid pulling in _res global from libc. |
23 |
*/ |
*/ |
24 |
|
|
25 |
/* Examples of 'standard' nslookup output |
/* Examples of 'standard' nslookup output |
50 |
* ns3.kernel.org internet address = 204.152.191.36 |
* ns3.kernel.org internet address = 204.152.191.36 |
51 |
*/ |
*/ |
52 |
|
|
|
static int sockaddr_to_dotted(struct sockaddr *saddr, char *buf, int buflen) |
|
|
{ |
|
|
if (buflen <= 0) return -1; |
|
|
buf[0] = '\0'; |
|
|
if (saddr->sa_family == AF_INET) { |
|
|
inet_ntop(AF_INET, &((struct sockaddr_in*)saddr)->sin_addr, buf, buflen); |
|
|
return 0; |
|
|
} |
|
|
if (saddr->sa_family == AF_INET6) { |
|
|
inet_ntop(AF_INET6, &((struct sockaddr_in6*)saddr)->sin6_addr, buf, buflen); |
|
|
return 0; |
|
|
} |
|
|
return -1; |
|
|
} |
|
|
|
|
53 |
static int print_host(const char *hostname, const char *header) |
static int print_host(const char *hostname, const char *header) |
54 |
{ |
{ |
55 |
char str[128]; /* IPv6 address will fit, hostnames hopefully too */ |
/* We can't use xhost2sockaddr() - we want to get ALL addresses, |
56 |
|
* not just one */ |
57 |
struct addrinfo *result = NULL; |
struct addrinfo *result = NULL; |
58 |
int rc; |
int rc; |
59 |
struct addrinfo hint; |
struct addrinfo hint; |
65 |
hint.ai_socktype = SOCK_STREAM; |
hint.ai_socktype = SOCK_STREAM; |
66 |
// hint.ai_flags = AI_CANONNAME; |
// hint.ai_flags = AI_CANONNAME; |
67 |
rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result); |
rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result); |
68 |
|
|
69 |
if (!rc) { |
if (!rc) { |
70 |
struct addrinfo *cur = result; |
struct addrinfo *cur = result; |
71 |
// printf("%s\n", cur->ai_canonname); ? |
unsigned cnt = 0; |
72 |
|
|
73 |
|
printf("%-10s %s\n", header, hostname); |
74 |
|
// puts(cur->ai_canonname); ? |
75 |
while (cur) { |
while (cur) { |
76 |
sockaddr_to_dotted(cur->ai_addr, str, sizeof(str)); |
char *dotted, *revhost; |
77 |
printf("%s %s\nAddress: %s", header, hostname, str); |
dotted = xmalloc_sockaddr2dotted_noport(cur->ai_addr); |
78 |
str[0] = ' '; |
revhost = xmalloc_sockaddr2hostonly_noport(cur->ai_addr); |
79 |
if (getnameinfo(cur->ai_addr, cur->ai_addrlen, str+1, sizeof(str)-1, NULL, 0, NI_NAMEREQD)) |
|
80 |
str[0] = '\0'; |
printf("Address %u: %s%c", ++cnt, dotted, revhost ? ' ' : '\n'); |
81 |
puts(str); |
if (revhost) { |
82 |
|
puts(revhost); |
83 |
|
if (ENABLE_FEATURE_CLEAN_UP) |
84 |
|
free(revhost); |
85 |
|
} |
86 |
|
if (ENABLE_FEATURE_CLEAN_UP) |
87 |
|
free(dotted); |
88 |
cur = cur->ai_next; |
cur = cur->ai_next; |
89 |
} |
} |
90 |
} else { |
} else { |
91 |
bb_error_msg("getaddrinfo('%s') failed: %s", hostname, gai_strerror(rc)); |
#if ENABLE_VERBOSE_RESOLUTION_ERRORS |
92 |
|
bb_error_msg("can't resolve '%s': %s", hostname, gai_strerror(rc)); |
93 |
|
#else |
94 |
|
bb_error_msg("can't resolve '%s'", hostname); |
95 |
|
#endif |
96 |
} |
} |
97 |
freeaddrinfo(result); |
if (ENABLE_FEATURE_CLEAN_UP) |
98 |
|
freeaddrinfo(result); |
99 |
return (rc != 0); |
return (rc != 0); |
100 |
} |
} |
101 |
|
|
102 |
|
/* lookup the default nameserver and display it */ |
103 |
|
static void server_print(void) |
104 |
|
{ |
105 |
|
char *server; |
106 |
|
|
107 |
|
server = xmalloc_sockaddr2dotted_noport((struct sockaddr*)&_res.nsaddr_list[0]); |
108 |
|
/* I honestly don't know what to do if DNS server has _IPv6 address_. |
109 |
|
* Probably it is listed in |
110 |
|
* _res._u._ext_.nsaddrs[MAXNS] (of type "struct sockaddr_in6*" each) |
111 |
|
* but how to find out whether resolver uses |
112 |
|
* _res.nsaddr_list[] or _res._u._ext_.nsaddrs[], or both? |
113 |
|
* Looks like classic design from hell, BIND-grade. Hard to surpass. */ |
114 |
|
print_host(server, "Server:"); |
115 |
|
if (ENABLE_FEATURE_CLEAN_UP) |
116 |
|
free(server); |
117 |
|
bb_putchar('\n'); |
118 |
|
} |
119 |
|
|
120 |
/* alter the global _res nameserver structure to use |
/* alter the global _res nameserver structure to use |
121 |
an explicit dns server instead of what is in /etc/resolv.h */ |
an explicit dns server instead of what is in /etc/resolv.conf */ |
122 |
static void set_default_dns(char *server) |
static void set_default_dns(char *server) |
123 |
{ |
{ |
124 |
struct in_addr server_in_addr; |
struct in_addr server_in_addr; |
129 |
} |
} |
130 |
} |
} |
131 |
|
|
132 |
|
int nslookup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
|
/* lookup the default nameserver and display it */ |
|
|
static void server_print(void) |
|
|
{ |
|
|
char str[INET6_ADDRSTRLEN]; |
|
|
|
|
|
sockaddr_to_dotted((struct sockaddr*)&_res.nsaddr_list[0], str, sizeof(str)); |
|
|
print_host(str, "Server:"); |
|
|
puts(""); |
|
|
} |
|
|
|
|
|
|
|
133 |
int nslookup_main(int argc, char **argv) |
int nslookup_main(int argc, char **argv) |
134 |
{ |
{ |
135 |
/* |
/* We allow 1 or 2 arguments. |
136 |
* initialize DNS structure _res used in printing the default |
* The first is the name to be looked up and the second is an |
137 |
* name server and in the explicit name server option feature. |
* optional DNS server with which to do the lookup. |
138 |
*/ |
* More than 3 arguments is an error to follow the pattern of the |
139 |
|
* standard nslookup */ |
140 |
|
if (!argv[1] || argv[1][0] == '-' || argc > 3) |
141 |
|
bb_show_usage(); |
142 |
|
|
143 |
|
/* initialize DNS structure _res used in printing the default |
144 |
|
* name server and in the explicit name server option feature. */ |
145 |
res_init(); |
res_init(); |
146 |
|
/* rfc2133 says this enables IPv6 lookups */ |
147 |
|
/* (but it also says "may be enabled in /etc/resolv.conf") */ |
148 |
|
/*_res.options |= RES_USE_INET6;*/ |
149 |
|
|
150 |
/* |
if (argv[2]) |
|
* We allow 1 or 2 arguments. |
|
|
* The first is the name to be looked up and the second is an |
|
|
* optional DNS server with which to do the lookup. |
|
|
* More than 3 arguments is an error to follow the pattern of the |
|
|
* standard nslookup |
|
|
*/ |
|
|
|
|
|
if (argc < 2 || *argv[1] == '-' || argc > 3) |
|
|
bb_show_usage(); |
|
|
else if(argc == 3) |
|
151 |
set_default_dns(argv[2]); |
set_default_dns(argv[2]); |
152 |
|
|
153 |
server_print(); |
server_print(); |
154 |
return print_host(argv[1], "Name: "); |
return print_host(argv[1], "Name:"); |
155 |
} |
} |
|
|
|
|
/* $Id: nslookup.c,v 1.1 2007-09-01 22:43:53 niro Exp $ */ |
|