diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-07-03 11:46:38 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-07-03 11:46:38 +0000 |
commit | 51b8bd68bb22b1cc5d95e418813c2f08a194ec2b (patch) | |
tree | 905d4f1b1e557950272ac98e1540fa06f732f42f /networking/netstat.c | |
parent | 599e3ce163c43c3dfb24d06f8f707c783bc9ab9c (diff) | |
download | busybox-w32-51b8bd68bb22b1cc5d95e418813c2f08a194ec2b.tar.gz busybox-w32-51b8bd68bb22b1cc5d95e418813c2f08a194ec2b.tar.bz2 busybox-w32-51b8bd68bb22b1cc5d95e418813c2f08a194ec2b.zip |
This patch from Bart Visscher <magick@linux-fan.com> adds
IPV6 support to busybox. This patch does the following:
* Add IPv6 support to libbb
* Enable IPv6 interface address display
* Add IPv6 config option
* Adds ping6, an adaptation of the ping applet for IPv6
* Adds support routines for ping6:
- xgethostbyname2
- create_icmp6_socket
* Adds ifconfig support for IPv6
* Add support IPv6 to netstat
* Add IPv6 support to route
Thanks Bart!
Diffstat (limited to 'networking/netstat.c')
-rw-r--r-- | networking/netstat.c | 122 |
1 files changed, 118 insertions, 4 deletions
diff --git a/networking/netstat.c b/networking/netstat.c index 00b58228e..67ecc0105 100644 --- a/networking/netstat.c +++ b/networking/netstat.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * Mini netstat implementation(s) for busybox | 3 | * Mini netstat implementation(s) for busybox |
4 | * based in part on the netstat implementation from net-tools. | 4 | * based in part on the netstat implementation from net-tools. |
5 | * | 5 | * |
6 | * Copyright (C) 2001 by Bart Visscher <magick@linux-fan.com> | 6 | * Copyright (C) 2002 by Bart Visscher <magick@linux-fan.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -18,6 +18,9 @@ | |||
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | * | ||
22 | * 2002-04-20 | ||
23 | * IPV6 support added by Bart Visscher <magick@linux-fan.com> | ||
21 | */ | 24 | */ |
22 | 25 | ||
23 | #include <stdio.h> | 26 | #include <stdio.h> |
@@ -128,9 +131,17 @@ static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int | |||
128 | { | 131 | { |
129 | char *port_name; | 132 | char *port_name; |
130 | 133 | ||
134 | #if CONFIG_FEATURE_IPV6 | ||
135 | if (addr->sa_family == AF_INET6) { | ||
136 | INET6_rresolve(ip_port, size, (struct sockaddr_in6 *)addr, | ||
137 | (numeric&NETSTAT_NUMERIC) ? 0x0fff : 0); | ||
138 | } else | ||
139 | #endif | ||
140 | { | ||
131 | INET_rresolve(ip_port, size, (struct sockaddr_in *)addr, | 141 | INET_rresolve(ip_port, size, (struct sockaddr_in *)addr, |
132 | 0x4000 | ((numeric&NETSTAT_NUMERIC) ? 0x0fff : 0), | 142 | 0x4000 | ((numeric&NETSTAT_NUMERIC) ? 0x0fff : 0), |
133 | 0xffffffff); | 143 | 0xffffffff); |
144 | } | ||
134 | port_name=get_sname(htons(port), proto, numeric); | 145 | port_name=get_sname(htons(port), proto, numeric); |
135 | if ((strlen(ip_port) + strlen(port_name)) > 22) | 146 | if ((strlen(ip_port) + strlen(port_name)) > 22) |
136 | ip_port[22 - strlen(port_name)] = '\0'; | 147 | ip_port[22 - strlen(port_name)] = '\0'; |
@@ -145,7 +156,13 @@ static void tcp_do_one(int lnr, const char *line) | |||
145 | const char *state_str; | 156 | const char *state_str; |
146 | char more[512]; | 157 | char more[512]; |
147 | int num, local_port, rem_port, d, state, timer_run, uid, timeout; | 158 | int num, local_port, rem_port, d, state, timer_run, uid, timeout; |
159 | #if CONFIG_FEATURE_IPV6 | ||
160 | struct sockaddr_in6 localaddr, remaddr; | ||
161 | char addr6[INET6_ADDRSTRLEN]; | ||
162 | struct in6_addr in6; | ||
163 | #else | ||
148 | struct sockaddr_in localaddr, remaddr; | 164 | struct sockaddr_in localaddr, remaddr; |
165 | #endif | ||
149 | unsigned long rxq, txq, time_len, retr, inode; | 166 | unsigned long rxq, txq, time_len, retr, inode; |
150 | 167 | ||
151 | if (lnr == 0) | 168 | if (lnr == 0) |
@@ -159,6 +176,20 @@ static void tcp_do_one(int lnr, const char *line) | |||
159 | &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); | 176 | &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); |
160 | 177 | ||
161 | if (strlen(local_addr) > 8) { | 178 | if (strlen(local_addr) > 8) { |
179 | #if CONFIG_FEATURE_IPV6 | ||
180 | sscanf(local_addr, "%08X%08X%08X%08X", | ||
181 | &in6.s6_addr32[0], &in6.s6_addr32[1], | ||
182 | &in6.s6_addr32[2], &in6.s6_addr32[3]); | ||
183 | inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); | ||
184 | inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr); | ||
185 | sscanf(rem_addr, "%08X%08X%08X%08X", | ||
186 | &in6.s6_addr32[0], &in6.s6_addr32[1], | ||
187 | &in6.s6_addr32[2], &in6.s6_addr32[3]); | ||
188 | inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); | ||
189 | inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr); | ||
190 | localaddr.sin6_family = AF_INET6; | ||
191 | remaddr.sin6_family = AF_INET6; | ||
192 | #endif | ||
162 | } else { | 193 | } else { |
163 | sscanf(local_addr, "%X", | 194 | sscanf(local_addr, "%X", |
164 | &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); | 195 | &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); |
@@ -195,7 +226,13 @@ static void udp_do_one(int lnr, const char *line) | |||
195 | char local_addr[64], rem_addr[64]; | 226 | char local_addr[64], rem_addr[64]; |
196 | char *state_str, more[512]; | 227 | char *state_str, more[512]; |
197 | int num, local_port, rem_port, d, state, timer_run, uid, timeout; | 228 | int num, local_port, rem_port, d, state, timer_run, uid, timeout; |
229 | #if CONFIG_FEATURE_IPV6 | ||
230 | struct sockaddr_in6 localaddr, remaddr; | ||
231 | char addr6[INET6_ADDRSTRLEN]; | ||
232 | struct in6_addr in6; | ||
233 | #else | ||
198 | struct sockaddr_in localaddr, remaddr; | 234 | struct sockaddr_in localaddr, remaddr; |
235 | #endif | ||
199 | unsigned long rxq, txq, time_len, retr, inode; | 236 | unsigned long rxq, txq, time_len, retr, inode; |
200 | 237 | ||
201 | if (lnr == 0) | 238 | if (lnr == 0) |
@@ -209,6 +246,21 @@ static void udp_do_one(int lnr, const char *line) | |||
209 | &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); | 246 | &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); |
210 | 247 | ||
211 | if (strlen(local_addr) > 8) { | 248 | if (strlen(local_addr) > 8) { |
249 | #if CONFIG_FEATURE_IPV6 | ||
250 | /* Demangle what the kernel gives us */ | ||
251 | sscanf(local_addr, "%08X%08X%08X%08X", | ||
252 | &in6.s6_addr32[0], &in6.s6_addr32[1], | ||
253 | &in6.s6_addr32[2], &in6.s6_addr32[3]); | ||
254 | inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); | ||
255 | inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr); | ||
256 | sscanf(rem_addr, "%08X%08X%08X%08X", | ||
257 | &in6.s6_addr32[0], &in6.s6_addr32[1], | ||
258 | &in6.s6_addr32[2], &in6.s6_addr32[3]); | ||
259 | inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); | ||
260 | inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr); | ||
261 | localaddr.sin6_family = AF_INET6; | ||
262 | remaddr.sin6_family = AF_INET6; | ||
263 | #endif | ||
212 | } else { | 264 | } else { |
213 | sscanf(local_addr, "%X", | 265 | sscanf(local_addr, "%X", |
214 | &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); | 266 | &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); |
@@ -236,7 +288,17 @@ static void udp_do_one(int lnr, const char *line) | |||
236 | break; | 288 | break; |
237 | } | 289 | } |
238 | 290 | ||
291 | #if CONFIG_FEATURE_IPV6 | ||
292 | #define notnull(A) (((A.sin6_family == AF_INET6) && \ | ||
293 | ((A.sin6_addr.s6_addr32[0]) || \ | ||
294 | (A.sin6_addr.s6_addr32[1]) || \ | ||
295 | (A.sin6_addr.s6_addr32[2]) || \ | ||
296 | (A.sin6_addr.s6_addr32[3]))) || \ | ||
297 | ((A.sin6_family == AF_INET) && \ | ||
298 | ((struct sockaddr_in *) &A)->sin_addr.s_addr)) | ||
299 | #else | ||
239 | #define notnull(A) (A.sin_addr.s_addr) | 300 | #define notnull(A) (A.sin_addr.s_addr) |
301 | #endif | ||
240 | if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) || | 302 | if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) || |
241 | (!notnull(remaddr) && (flags&NETSTAT_LISTENING))) | 303 | (!notnull(remaddr) && (flags&NETSTAT_LISTENING))) |
242 | { | 304 | { |
@@ -259,7 +321,13 @@ static void raw_do_one(int lnr, const char *line) | |||
259 | char local_addr[64], rem_addr[64]; | 321 | char local_addr[64], rem_addr[64]; |
260 | char *state_str, more[512]; | 322 | char *state_str, more[512]; |
261 | int num, local_port, rem_port, d, state, timer_run, uid, timeout; | 323 | int num, local_port, rem_port, d, state, timer_run, uid, timeout; |
324 | #if CONFIG_FEATURE_IPV6 | ||
325 | struct sockaddr_in6 localaddr, remaddr; | ||
326 | char addr6[INET6_ADDRSTRLEN]; | ||
327 | struct in6_addr in6; | ||
328 | #else | ||
262 | struct sockaddr_in localaddr, remaddr; | 329 | struct sockaddr_in localaddr, remaddr; |
330 | #endif | ||
263 | unsigned long rxq, txq, time_len, retr, inode; | 331 | unsigned long rxq, txq, time_len, retr, inode; |
264 | 332 | ||
265 | if (lnr == 0) | 333 | if (lnr == 0) |
@@ -273,6 +341,20 @@ static void raw_do_one(int lnr, const char *line) | |||
273 | &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); | 341 | &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); |
274 | 342 | ||
275 | if (strlen(local_addr) > 8) { | 343 | if (strlen(local_addr) > 8) { |
344 | #if CONFIG_FEATURE_IPV6 | ||
345 | sscanf(local_addr, "%08X%08X%08X%08X", | ||
346 | &in6.s6_addr32[0], &in6.s6_addr32[1], | ||
347 | &in6.s6_addr32[2], &in6.s6_addr32[3]); | ||
348 | inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); | ||
349 | inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr); | ||
350 | sscanf(rem_addr, "%08X%08X%08X%08X", | ||
351 | &in6.s6_addr32[0], &in6.s6_addr32[1], | ||
352 | &in6.s6_addr32[2], &in6.s6_addr32[3]); | ||
353 | inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); | ||
354 | inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr); | ||
355 | localaddr.sin6_family = AF_INET6; | ||
356 | remaddr.sin6_family = AF_INET6; | ||
357 | #endif | ||
276 | } else { | 358 | } else { |
277 | sscanf(local_addr, "%X", | 359 | sscanf(local_addr, "%X", |
278 | &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); | 360 | &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); |
@@ -288,7 +370,17 @@ static void raw_do_one(int lnr, const char *line) | |||
288 | } | 370 | } |
289 | state_str=itoa(state); | 371 | state_str=itoa(state); |
290 | 372 | ||
373 | #if CONFIG_FEATURE_IPV6 | ||
374 | #define notnull(A) (((A.sin6_family == AF_INET6) && \ | ||
375 | ((A.sin6_addr.s6_addr32[0]) || \ | ||
376 | (A.sin6_addr.s6_addr32[1]) || \ | ||
377 | (A.sin6_addr.s6_addr32[2]) || \ | ||
378 | (A.sin6_addr.s6_addr32[3]))) || \ | ||
379 | ((A.sin6_family == AF_INET) && \ | ||
380 | ((struct sockaddr_in *) &A)->sin_addr.s_addr)) | ||
381 | #else | ||
291 | #define notnull(A) (A.sin_addr.s_addr) | 382 | #define notnull(A) (A.sin_addr.s_addr) |
383 | #endif | ||
292 | if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) || | 384 | if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) || |
293 | (!notnull(remaddr) && (flags&NETSTAT_LISTENING))) | 385 | (!notnull(remaddr) && (flags&NETSTAT_LISTENING))) |
294 | { | 386 | { |
@@ -429,8 +521,11 @@ static void unix_do_one(int nr, const char *line) | |||
429 | } | 521 | } |
430 | 522 | ||
431 | #define _PATH_PROCNET_UDP "/proc/net/udp" | 523 | #define _PATH_PROCNET_UDP "/proc/net/udp" |
524 | #define _PATH_PROCNET_UDP6 "/proc/net/udp6" | ||
432 | #define _PATH_PROCNET_TCP "/proc/net/tcp" | 525 | #define _PATH_PROCNET_TCP "/proc/net/tcp" |
526 | #define _PATH_PROCNET_TCP6 "/proc/net/tcp6" | ||
433 | #define _PATH_PROCNET_RAW "/proc/net/raw" | 527 | #define _PATH_PROCNET_RAW "/proc/net/raw" |
528 | #define _PATH_PROCNET_RAW6 "/proc/net/raw6" | ||
434 | #define _PATH_PROCNET_UNIX "/proc/net/unix" | 529 | #define _PATH_PROCNET_UNIX "/proc/net/unix" |
435 | 530 | ||
436 | static void do_info(const char *file, const char *name, void (*proc)(int, const char *)) | 531 | static void do_info(const char *file, const char *name, void (*proc)(int, const char *)) |
@@ -464,6 +559,13 @@ int netstat_main(int argc, char **argv) | |||
464 | int opt; | 559 | int opt; |
465 | int new_flags=0; | 560 | int new_flags=0; |
466 | int showroute = 0, extended = 0; | 561 | int showroute = 0, extended = 0; |
562 | #if CONFIG_FEATURE_IPV6 | ||
563 | int inet=1; | ||
564 | int inet6=1; | ||
565 | #else | ||
566 | #define inet 1 | ||
567 | #define inet6 0 | ||
568 | #endif | ||
467 | while ((opt = getopt(argc, argv, "laenrtuwx")) != -1) | 569 | while ((opt = getopt(argc, argv, "laenrtuwx")) != -1) |
468 | switch (opt) { | 570 | switch (opt) { |
469 | case 'l': | 571 | case 'l': |
@@ -523,12 +625,24 @@ int netstat_main(int argc, char **argv) | |||
523 | } | 625 | } |
524 | printf("\nProto Recv-Q Send-Q Local Address Foreign Address State \n"); | 626 | printf("\nProto Recv-Q Send-Q Local Address Foreign Address State \n"); |
525 | } | 627 | } |
526 | if (flags&NETSTAT_TCP) | 628 | if (inet && flags&NETSTAT_TCP) |
527 | do_info(_PATH_PROCNET_TCP,"AF INET (tcp)",tcp_do_one); | 629 | do_info(_PATH_PROCNET_TCP,"AF INET (tcp)",tcp_do_one); |
528 | if (flags&NETSTAT_UDP) | 630 | #if CONFIG_FEATURE_IPV6 |
631 | if (inet6 && flags&NETSTAT_TCP) | ||
632 | do_info(_PATH_PROCNET_TCP6,"AF INET6 (tcp)",tcp_do_one); | ||
633 | #endif | ||
634 | if (inet && flags&NETSTAT_UDP) | ||
529 | do_info(_PATH_PROCNET_UDP,"AF INET (udp)",udp_do_one); | 635 | do_info(_PATH_PROCNET_UDP,"AF INET (udp)",udp_do_one); |
530 | if (flags&NETSTAT_RAW) | 636 | #if CONFIG_FEATURE_IPV6 |
637 | if (inet6 && flags&NETSTAT_UDP) | ||
638 | do_info(_PATH_PROCNET_UDP6,"AF INET6 (udp)",udp_do_one); | ||
639 | #endif | ||
640 | if (inet && flags&NETSTAT_RAW) | ||
531 | do_info(_PATH_PROCNET_RAW,"AF INET (raw)",raw_do_one); | 641 | do_info(_PATH_PROCNET_RAW,"AF INET (raw)",raw_do_one); |
642 | #if CONFIG_FEATURE_IPV6 | ||
643 | if (inet6 && flags&NETSTAT_RAW) | ||
644 | do_info(_PATH_PROCNET_RAW6,"AF INET6 (raw)",raw_do_one); | ||
645 | #endif | ||
532 | if (flags&NETSTAT_UNIX) { | 646 | if (flags&NETSTAT_UNIX) { |
533 | printf("Active UNIX domain sockets "); | 647 | printf("Active UNIX domain sockets "); |
534 | if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED)) | 648 | if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED)) |