X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Fnetstat.c;h=dcbcee21d87310b5be4ac3ce585a407520ea13f8;hb=887ca79f04cdf45874ed783c1fb9b950bf25a246;hp=28ae9bc3233787ae8150cfba090c5e2f5d64f69b;hpb=cd8c436d811a5a077a0b61a6616c900173e2dcfb;p=oweals%2Fbusybox.git diff --git a/networking/netstat.c b/networking/netstat.c index 28ae9bc32..dcbcee21d 100644 --- a/networking/netstat.c +++ b/networking/netstat.c @@ -3,7 +3,7 @@ * Mini netstat implementation(s) for busybox * based in part on the netstat implementation from net-tools. * - * Copyright (C) 2001 by Bart Visscher + * Copyright (C) 2002 by Bart Visscher * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 2002-04-20 + * IPV6 support added by Bart Visscher */ #include @@ -29,9 +32,13 @@ #include #include #include -#include #include "inet_common.h" #include "busybox.h" +#include "pwd_.h" + +#ifdef CONFIG_ROUTE +extern void displayroutes(int noresolve, int netstatfmt); +#endif #define NETSTAT_CONNECTED 0x01 #define NETSTAT_LISTENING 0x02 @@ -41,7 +48,7 @@ #define NETSTAT_RAW 0x40 #define NETSTAT_UNIX 0x80 -int flags = NETSTAT_CONNECTED | +static int flags = NETSTAT_CONNECTED | NETSTAT_TCP | NETSTAT_UDP | NETSTAT_RAW | NETSTAT_UNIX; #define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH) @@ -64,7 +71,7 @@ enum { TCP_CLOSING /* now a valid state */ }; -static const char *tcp_state[] = +static const char * const tcp_state[] = { "", "ESTABLISHED", @@ -124,9 +131,17 @@ static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int { char *port_name; +#if CONFIG_FEATURE_IPV6 + if (addr->sa_family == AF_INET6) { + INET6_rresolve(ip_port, size, (struct sockaddr_in6 *)addr, + (numeric&NETSTAT_NUMERIC) ? 0x0fff : 0); + } else +#endif + { INET_rresolve(ip_port, size, (struct sockaddr_in *)addr, 0x4000 | ((numeric&NETSTAT_NUMERIC) ? 0x0fff : 0), 0xffffffff); + } port_name=get_sname(htons(port), proto, numeric); if ((strlen(ip_port) + strlen(port_name)) > 22) ip_port[22 - strlen(port_name)] = '\0'; @@ -138,9 +153,16 @@ static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int static void tcp_do_one(int lnr, const char *line) { char local_addr[64], rem_addr[64]; - char *state_str, more[512]; + const char *state_str; + char more[512]; int num, local_port, rem_port, d, state, timer_run, uid, timeout; +#if CONFIG_FEATURE_IPV6 + struct sockaddr_in6 localaddr, remaddr; + char addr6[INET6_ADDRSTRLEN]; + struct in6_addr in6; +#else struct sockaddr_in localaddr, remaddr; +#endif unsigned long rxq, txq, time_len, retr, inode; if (lnr == 0) @@ -154,6 +176,20 @@ static void tcp_do_one(int lnr, const char *line) &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); if (strlen(local_addr) > 8) { +#if CONFIG_FEATURE_IPV6 + sscanf(local_addr, "%08X%08X%08X%08X", + &in6.s6_addr32[0], &in6.s6_addr32[1], + &in6.s6_addr32[2], &in6.s6_addr32[3]); + inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); + inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr); + sscanf(rem_addr, "%08X%08X%08X%08X", + &in6.s6_addr32[0], &in6.s6_addr32[1], + &in6.s6_addr32[2], &in6.s6_addr32[3]); + inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); + inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr); + localaddr.sin6_family = AF_INET6; + remaddr.sin6_family = AF_INET6; +#endif } else { sscanf(local_addr, "%X", &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); @@ -164,10 +200,10 @@ static void tcp_do_one(int lnr, const char *line) } if (num < 10) { - error_msg("warning, got bogus tcp line.\n"); + error_msg("warning, got bogus tcp line."); return; } - state_str=(char*)tcp_state[state]; + state_str = tcp_state[state]; if ((rem_port && (flags&NETSTAT_CONNECTED)) || (!rem_port && (flags&NETSTAT_LISTENING))) { @@ -190,7 +226,13 @@ static void udp_do_one(int lnr, const char *line) char local_addr[64], rem_addr[64]; char *state_str, more[512]; int num, local_port, rem_port, d, state, timer_run, uid, timeout; +#if CONFIG_FEATURE_IPV6 + struct sockaddr_in6 localaddr, remaddr; + char addr6[INET6_ADDRSTRLEN]; + struct in6_addr in6; +#else struct sockaddr_in localaddr, remaddr; +#endif unsigned long rxq, txq, time_len, retr, inode; if (lnr == 0) @@ -204,6 +246,21 @@ static void udp_do_one(int lnr, const char *line) &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); if (strlen(local_addr) > 8) { +#if CONFIG_FEATURE_IPV6 + /* Demangle what the kernel gives us */ + sscanf(local_addr, "%08X%08X%08X%08X", + &in6.s6_addr32[0], &in6.s6_addr32[1], + &in6.s6_addr32[2], &in6.s6_addr32[3]); + inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); + inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr); + sscanf(rem_addr, "%08X%08X%08X%08X", + &in6.s6_addr32[0], &in6.s6_addr32[1], + &in6.s6_addr32[2], &in6.s6_addr32[3]); + inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); + inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr); + localaddr.sin6_family = AF_INET6; + remaddr.sin6_family = AF_INET6; +#endif } else { sscanf(local_addr, "%X", &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); @@ -214,7 +271,7 @@ static void udp_do_one(int lnr, const char *line) } if (num < 10) { - error_msg("warning, got bogus udp line.\n"); + error_msg("warning, got bogus udp line."); return; } switch (state) { @@ -231,7 +288,17 @@ static void udp_do_one(int lnr, const char *line) break; } +#if CONFIG_FEATURE_IPV6 +#define notnull(A) (((A.sin6_family == AF_INET6) && \ + ((A.sin6_addr.s6_addr32[0]) || \ + (A.sin6_addr.s6_addr32[1]) || \ + (A.sin6_addr.s6_addr32[2]) || \ + (A.sin6_addr.s6_addr32[3]))) || \ + ((A.sin6_family == AF_INET) && \ + ((struct sockaddr_in *) &A)->sin_addr.s_addr)) +#else #define notnull(A) (A.sin_addr.s_addr) +#endif if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) || (!notnull(remaddr) && (flags&NETSTAT_LISTENING))) { @@ -254,7 +321,13 @@ static void raw_do_one(int lnr, const char *line) char local_addr[64], rem_addr[64]; char *state_str, more[512]; int num, local_port, rem_port, d, state, timer_run, uid, timeout; +#if CONFIG_FEATURE_IPV6 + struct sockaddr_in6 localaddr, remaddr; + char addr6[INET6_ADDRSTRLEN]; + struct in6_addr in6; +#else struct sockaddr_in localaddr, remaddr; +#endif unsigned long rxq, txq, time_len, retr, inode; if (lnr == 0) @@ -268,6 +341,20 @@ static void raw_do_one(int lnr, const char *line) &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); if (strlen(local_addr) > 8) { +#if CONFIG_FEATURE_IPV6 + sscanf(local_addr, "%08X%08X%08X%08X", + &in6.s6_addr32[0], &in6.s6_addr32[1], + &in6.s6_addr32[2], &in6.s6_addr32[3]); + inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); + inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr); + sscanf(rem_addr, "%08X%08X%08X%08X", + &in6.s6_addr32[0], &in6.s6_addr32[1], + &in6.s6_addr32[2], &in6.s6_addr32[3]); + inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); + inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr); + localaddr.sin6_family = AF_INET6; + remaddr.sin6_family = AF_INET6; +#endif } else { sscanf(local_addr, "%X", &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); @@ -278,12 +365,22 @@ static void raw_do_one(int lnr, const char *line) } if (num < 10) { - error_msg("warning, got bogus raw line.\n"); + error_msg("warning, got bogus raw line."); return; } state_str=itoa(state); +#if CONFIG_FEATURE_IPV6 +#define notnull(A) (((A.sin6_family == AF_INET6) && \ + ((A.sin6_addr.s6_addr32[0]) || \ + (A.sin6_addr.s6_addr32[1]) || \ + (A.sin6_addr.s6_addr32[2]) || \ + (A.sin6_addr.s6_addr32[3]))) || \ + ((A.sin6_family == AF_INET) && \ + ((struct sockaddr_in *) &A)->sin_addr.s_addr)) +#else #define notnull(A) (A.sin_addr.s_addr) +#endif if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) || (!notnull(remaddr) && (flags&NETSTAT_LISTENING))) { @@ -321,7 +418,7 @@ static void unix_do_one(int nr, const char *line) num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s", &d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path); if (num < 6) { - error_msg("warning, got bogus unix line.\n"); + error_msg("warning, got bogus unix line."); return; } if (!(has & HAS_INODE)) @@ -424,26 +521,26 @@ static void unix_do_one(int nr, const char *line) } #define _PATH_PROCNET_UDP "/proc/net/udp" +#define _PATH_PROCNET_UDP6 "/proc/net/udp6" #define _PATH_PROCNET_TCP "/proc/net/tcp" +#define _PATH_PROCNET_TCP6 "/proc/net/tcp6" #define _PATH_PROCNET_RAW "/proc/net/raw" +#define _PATH_PROCNET_RAW6 "/proc/net/raw6" #define _PATH_PROCNET_UNIX "/proc/net/unix" -static int do_info(char *file, char *name, void (*proc)(int, const char *)) +static void do_info(const char *file, const char *name, void (*proc)(int, const char *)) { char buffer[8192]; - int rc = 0; int lnr = 0; FILE *procinfo; - procinfo = fopen((file), "r"); + procinfo = fopen(file, "r"); if (procinfo == NULL) { if (errno != ENOENT) { - perror((file)); - return -1; + perror(file); + } else { + error_msg("no support for `%s' on this system.", name); } - error_msg("%s: no support for `%s' on this system.\n", - "netstat", (name)); - rc = 1; } else { do { if (fgets(buffer, sizeof(buffer), procinfo)) @@ -451,7 +548,6 @@ static int do_info(char *file, char *name, void (*proc)(int, const char *)) } while (!feof(procinfo)); fclose(procinfo); } - return rc; } /* @@ -462,7 +558,15 @@ int netstat_main(int argc, char **argv) { int opt; int new_flags=0; - while ((opt = getopt(argc, argv, "lantuwx")) != -1) + int showroute = 0, extended = 0; +#if CONFIG_FEATURE_IPV6 + int inet=1; + int inet6=1; +#else +#define inet 1 +#define inet6 0 +#endif + while ((opt = getopt(argc, argv, "laenrtuwx")) != -1) switch (opt) { case 'l': flags &= ~NETSTAT_CONNECTED; @@ -474,6 +578,12 @@ int netstat_main(int argc, char **argv) case 'n': flags |= NETSTAT_NUMERIC; break; + case 'r': + showroute = 1; + break; + case 'e': + extended = 1; + break; case 't': new_flags |= NETSTAT_TCP; break; @@ -489,6 +599,15 @@ int netstat_main(int argc, char **argv) default: show_usage(); } + if ( showroute ) { +#ifdef CONFIG_ROUTE + displayroutes ( flags & NETSTAT_NUMERIC, !extended ); + return 0; +#else + error_msg_and_die( "-r (display routing table) is not compiled in." ); +#endif + } + if (new_flags) { flags &= ~(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW|NETSTAT_UNIX); flags |= new_flags; @@ -506,12 +625,24 @@ int netstat_main(int argc, char **argv) } printf("\nProto Recv-Q Send-Q Local Address Foreign Address State \n"); } - if (flags&NETSTAT_TCP) + if (inet && flags&NETSTAT_TCP) do_info(_PATH_PROCNET_TCP,"AF INET (tcp)",tcp_do_one); - if (flags&NETSTAT_UDP) +#if CONFIG_FEATURE_IPV6 + if (inet6 && flags&NETSTAT_TCP) + do_info(_PATH_PROCNET_TCP6,"AF INET6 (tcp)",tcp_do_one); +#endif + if (inet && flags&NETSTAT_UDP) do_info(_PATH_PROCNET_UDP,"AF INET (udp)",udp_do_one); - if (flags&NETSTAT_RAW) +#if CONFIG_FEATURE_IPV6 + if (inet6 && flags&NETSTAT_UDP) + do_info(_PATH_PROCNET_UDP6,"AF INET6 (udp)",udp_do_one); +#endif + if (inet && flags&NETSTAT_RAW) do_info(_PATH_PROCNET_RAW,"AF INET (raw)",raw_do_one); +#if CONFIG_FEATURE_IPV6 + if (inet6 && flags&NETSTAT_RAW) + do_info(_PATH_PROCNET_RAW6,"AF INET6 (raw)",raw_do_one); +#endif if (flags&NETSTAT_UNIX) { printf("Active UNIX domain sockets "); if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))