diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-10-26 17:17:59 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-10-26 17:17:59 +0000 |
commit | ebe578ab2fc19e9ce0d876a10fc389b018a30eba (patch) | |
tree | 73c94891fb79c1da22c2397e4b80e90f617f573b | |
parent | 68f21872652975e4541cec841c581d4c594273c5 (diff) | |
download | busybox-w32-ebe578ab2fc19e9ce0d876a10fc389b018a30eba.tar.gz busybox-w32-ebe578ab2fc19e9ce0d876a10fc389b018a30eba.tar.bz2 busybox-w32-ebe578ab2fc19e9ce0d876a10fc389b018a30eba.zip |
nslookup: make it more IPv6 friendly
-rw-r--r-- | networking/nslookup.c | 205 | ||||
-rw-r--r-- | networking/ping6.c | 2 |
2 files changed, 81 insertions, 126 deletions
diff --git a/networking/nslookup.c b/networking/nslookup.c index 54e71c47e..dd49e2669 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c | |||
@@ -11,152 +11,116 @@ | |||
11 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 11 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <ctype.h> | ||
15 | #include <errno.h> | ||
16 | #include <stdio.h> | ||
17 | #include <string.h> | ||
18 | #include <stdlib.h> | ||
19 | |||
20 | #include <stdint.h> | ||
21 | #include <netdb.h> | ||
22 | #include <sys/socket.h> | ||
23 | #include <sys/types.h> | ||
24 | #include <netinet/in.h> | ||
25 | #include <resolv.h> | 14 | #include <resolv.h> |
26 | #include <arpa/inet.h> | ||
27 | #include "busybox.h" | 15 | #include "busybox.h" |
28 | 16 | ||
29 | /* | 17 | /* |
30 | | I'm only implementing non-interactive mode; | 18 | * I'm only implementing non-interactive mode; |
31 | | I totally forgot nslookup even had an interactive mode. | 19 | * I totally forgot nslookup even had an interactive mode. |
32 | */ | 20 | */ |
33 | 21 | ||
34 | /* only works for IPv4 */ | 22 | /* Examples of 'standard' nslookup output |
35 | static int addr_fprint(char *addr) | 23 | * $ nslookup yahoo.com |
36 | { | 24 | * Server: 128.193.0.10 |
37 | uint8_t split[4]; | 25 | * Address: 128.193.0.10#53 |
38 | uint32_t ip; | 26 | * |
39 | uint32_t *x = (uint32_t *) addr; | 27 | * Non-authoritative answer: |
40 | 28 | * Name: yahoo.com | |
41 | ip = ntohl(*x); | 29 | * Address: 216.109.112.135 |
42 | split[0] = (ip & 0xff000000) >> 24; | 30 | * Name: yahoo.com |
43 | split[1] = (ip & 0x00ff0000) >> 16; | 31 | * Address: 66.94.234.13 |
44 | split[2] = (ip & 0x0000ff00) >> 8; | 32 | * |
45 | split[3] = (ip & 0x000000ff); | 33 | * $ nslookup 204.152.191.37 |
46 | printf("%d.%d.%d.%d", split[0], split[1], split[2], split[3]); | 34 | * Server: 128.193.4.20 |
47 | return 0; | 35 | * Address: 128.193.4.20#53 |
48 | } | 36 | * |
49 | 37 | * Non-authoritative answer: | |
50 | /* takes the NULL-terminated array h_addr_list, and | 38 | * 37.191.152.204.in-addr.arpa canonical name = 37.32-27.191.152.204.in-addr.arpa. |
51 | * prints its contents appropriately | 39 | * 37.32-27.191.152.204.in-addr.arpa name = zeus-pub2.kernel.org. |
40 | * | ||
41 | * Authoritative answers can be found from: | ||
42 | * 32-27.191.152.204.in-addr.arpa nameserver = ns1.kernel.org. | ||
43 | * 32-27.191.152.204.in-addr.arpa nameserver = ns2.kernel.org. | ||
44 | * 32-27.191.152.204.in-addr.arpa nameserver = ns3.kernel.org. | ||
45 | * ns1.kernel.org internet address = 140.211.167.34 | ||
46 | * ns2.kernel.org internet address = 204.152.191.4 | ||
47 | * ns3.kernel.org internet address = 204.152.191.36 | ||
52 | */ | 48 | */ |
53 | static int addr_list_fprint(char **h_addr_list) | ||
54 | { | ||
55 | int i, j; | ||
56 | char *addr_string = (h_addr_list[1]) | ||
57 | ? "Addresses: " : "Address: "; | ||
58 | |||
59 | printf("%s ", addr_string); | ||
60 | for (i = 0, j = 0; h_addr_list[i]; i++, j++) { | ||
61 | addr_fprint(h_addr_list[i]); | ||
62 | |||
63 | /* real nslookup does this */ | ||
64 | if (j == 4) { | ||
65 | if (h_addr_list[i + 1]) { | ||
66 | printf("\n "); | ||
67 | } | ||
68 | j = 0; | ||
69 | } else { | ||
70 | if (h_addr_list[i + 1]) { | ||
71 | printf(", "); | ||
72 | } | ||
73 | } | ||
74 | 49 | ||
50 | static int sockaddr_to_dotted(struct sockaddr *saddr, char *buf, int buflen) | ||
51 | { | ||
52 | if (buflen <= 0) return -1; | ||
53 | buf[0] = '\0'; | ||
54 | if (saddr->sa_family == AF_INET) { | ||
55 | inet_ntop(AF_INET, &((struct sockaddr_in*)saddr)->sin_addr, buf, buflen); | ||
56 | return 0; | ||
75 | } | 57 | } |
76 | puts(""); | 58 | if (saddr->sa_family == AF_INET6) { |
77 | return 0; | 59 | inet_ntop(AF_INET6, &((struct sockaddr_in6*)saddr)->sin6_addr, buf, buflen); |
60 | return 0; | ||
61 | } | ||
62 | return -1; | ||
78 | } | 63 | } |
79 | 64 | ||
80 | /* print the results as nslookup would */ | 65 | static int print_host(const char *hostname, const char *header) |
81 | static struct hostent *hostent_fprint(struct hostent *host, const char *server_host) | ||
82 | { | 66 | { |
83 | if (host) { | 67 | char str[128]; /* IPv6 address will fit, hostnames hopefully too */ |
84 | printf("%s %s\n", server_host, host->h_name); | 68 | struct addrinfo *result = NULL; |
85 | addr_list_fprint(host->h_addr_list); | 69 | int rc; |
70 | struct addrinfo hint; | ||
71 | |||
72 | memset(&hint, 0 , sizeof(hint)); | ||
73 | /* hint.ai_family = AF_UNSPEC; - zero anyway */ | ||
74 | /* Needed. Or else we will get each address thrice (or more) | ||
75 | * for each possible socket type (tcp,udp,raw...): */ | ||
76 | hint.ai_socktype = SOCK_STREAM; | ||
77 | // hint.ai_flags = AI_CANONNAME; | ||
78 | rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result); | ||
79 | if (!rc) { | ||
80 | struct addrinfo *cur = result; | ||
81 | // printf("%s\n", cur->ai_canonname); ? | ||
82 | while (cur) { | ||
83 | sockaddr_to_dotted(cur->ai_addr, str, sizeof(str)); | ||
84 | printf("%s %s\nAddress: %s", header, hostname, str); | ||
85 | if (getnameinfo(cur->ai_addr, cur->ai_addrlen, str, sizeof(str), NULL, 0, NI_NAMEREQD)) | ||
86 | str[0] = '\0'; | ||
87 | printf(" %s\n", str); | ||
88 | cur = cur->ai_next; | ||
89 | } | ||
86 | } else { | 90 | } else { |
87 | printf("*** Unknown host\n"); | 91 | bb_error_msg("getaddrinfo('%s') failed: %s", hostname, gai_strerror(rc)); |
88 | } | 92 | } |
89 | return host; | 93 | freeaddrinfo(result); |
90 | } | 94 | return (rc != 0); |
91 | |||
92 | /* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+ | ||
93 | * into a uint32_t | ||
94 | */ | ||
95 | static uint32_t str_to_addr(const char *addr) | ||
96 | { | ||
97 | uint32_t split[4]; | ||
98 | uint32_t ip; | ||
99 | |||
100 | sscanf(addr, "%d.%d.%d.%d", | ||
101 | &split[0], &split[1], &split[2], &split[3]); | ||
102 | |||
103 | /* assuming sscanf worked */ | ||
104 | ip = (split[0] << 24) | | ||
105 | (split[1] << 16) | (split[2] << 8) | (split[3]); | ||
106 | |||
107 | return htonl(ip); | ||
108 | } | ||
109 | |||
110 | /* gethostbyaddr wrapper */ | ||
111 | static struct hostent *gethostbyaddr_wrapper(const char *address) | ||
112 | { | ||
113 | struct in_addr addr; | ||
114 | |||
115 | addr.s_addr = str_to_addr(address); | ||
116 | return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */ | ||
117 | } | 95 | } |
118 | 96 | ||
119 | /* lookup the default nameserver and display it */ | ||
120 | static inline void server_print(void) | ||
121 | { | ||
122 | struct sockaddr_in def = _res.nsaddr_list[0]; | ||
123 | char *ip = inet_ntoa(def.sin_addr); | ||
124 | |||
125 | hostent_fprint(gethostbyaddr_wrapper(ip), "Server:"); | ||
126 | puts(""); | ||
127 | } | ||
128 | 97 | ||
129 | /* alter the global _res nameserver structure to use | 98 | /* alter the global _res nameserver structure to use |
130 | an explicit dns server instead of what is in /etc/resolv.h */ | 99 | an explicit dns server instead of what is in /etc/resolv.h */ |
131 | static inline void set_default_dns(char *server) | 100 | static void set_default_dns(char *server) |
132 | { | 101 | { |
133 | struct in_addr server_in_addr; | 102 | struct in_addr server_in_addr; |
134 | 103 | ||
135 | if(inet_aton(server,&server_in_addr)) | 104 | if (inet_pton(AF_INET, server, &server_in_addr) > 0) { |
136 | { | ||
137 | _res.nscount = 1; | 105 | _res.nscount = 1; |
138 | _res.nsaddr_list[0].sin_addr = server_in_addr; | 106 | _res.nsaddr_list[0].sin_addr = server_in_addr; |
139 | } | 107 | } |
140 | } | 108 | } |
141 | 109 | ||
142 | /* naive function to check whether char *s is an ip address */ | 110 | |
143 | static int is_ip_address(const char *s) | 111 | /* lookup the default nameserver and display it */ |
112 | static void server_print(void) | ||
144 | { | 113 | { |
145 | while (*s) { | 114 | char str[INET6_ADDRSTRLEN]; |
146 | if ((isdigit(*s)) || (*s == '.')) { | 115 | |
147 | s++; | 116 | sockaddr_to_dotted((struct sockaddr*)&_res.nsaddr_list[0], str, sizeof(str)); |
148 | continue; | 117 | print_host(str, "Server:"); |
149 | } | 118 | puts(""); |
150 | return 0; | ||
151 | } | ||
152 | return 1; | ||
153 | } | 119 | } |
154 | 120 | ||
155 | /* ________________________________________________________________________ */ | 121 | |
156 | int nslookup_main(int argc, char **argv) | 122 | int nslookup_main(int argc, char **argv) |
157 | { | 123 | { |
158 | struct hostent *host; | ||
159 | |||
160 | /* | 124 | /* |
161 | * initialize DNS structure _res used in printing the default | 125 | * initialize DNS structure _res used in printing the default |
162 | * name server and in the explicit name server option feature. | 126 | * name server and in the explicit name server option feature. |
@@ -172,22 +136,13 @@ int nslookup_main(int argc, char **argv) | |||
172 | * standard nslookup | 136 | * standard nslookup |
173 | */ | 137 | */ |
174 | 138 | ||
175 | if (argc < 2 || *argv[1]=='-' || argc > 3) | 139 | if (argc < 2 || *argv[1] == '-' || argc > 3) |
176 | bb_show_usage(); | 140 | bb_show_usage(); |
177 | else if(argc == 3) | 141 | else if(argc == 3) |
178 | set_default_dns(argv[2]); | 142 | set_default_dns(argv[2]); |
179 | 143 | ||
180 | server_print(); | 144 | server_print(); |
181 | if (is_ip_address(argv[1])) { | 145 | return print_host(argv[1], "Name: "); |
182 | host = gethostbyaddr_wrapper(argv[1]); | ||
183 | } else { | ||
184 | host = xgethostbyname(argv[1]); | ||
185 | } | ||
186 | hostent_fprint(host, "Name: "); | ||
187 | if (host) { | ||
188 | return EXIT_SUCCESS; | ||
189 | } | ||
190 | return EXIT_FAILURE; | ||
191 | } | 146 | } |
192 | 147 | ||
193 | /* $Id: nslookup.c,v 1.33 2004/10/13 07:25:01 andersen Exp $ */ | 148 | /* $Id: nslookup.c,v 1.33 2004/10/13 07:25:01 andersen Exp $ */ |
diff --git a/networking/ping6.c b/networking/ping6.c index a064f2f0b..af9c00e22 100644 --- a/networking/ping6.c +++ b/networking/ping6.c | |||
@@ -329,7 +329,7 @@ static void ping(const char *host) | |||
329 | pingaddr.sin6_family = AF_INET6; | 329 | pingaddr.sin6_family = AF_INET6; |
330 | hostent = xgethostbyname2(host, AF_INET6); | 330 | hostent = xgethostbyname2(host, AF_INET6); |
331 | if (hostent->h_addrtype != AF_INET6) | 331 | if (hostent->h_addrtype != AF_INET6) |
332 | bb_error_msg_and_die("unknown address type; only AF_INET6 is currently supported."); | 332 | bb_error_msg_and_die("unknown address type; only AF_INET6 is currently supported"); |
333 | 333 | ||
334 | memcpy(&pingaddr.sin6_addr, hostent->h_addr, sizeof(pingaddr.sin6_addr)); | 334 | memcpy(&pingaddr.sin6_addr, hostent->h_addr, sizeof(pingaddr.sin6_addr)); |
335 | 335 | ||