X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Fnetstat.c;h=dcbcee21d87310b5be4ac3ce585a407520ea13f8;hb=887ca79f04cdf45874ed783c1fb9b950bf25a246;hp=e33a89a645aa7694004f440d5d4cd36ae4bc1def;hpb=31a0ece3a711dd24cdb49c3a0a83ad4838f27e6e;p=oweals%2Fbusybox.git diff --git a/networking/netstat.c b/networking/netstat.c index e33a89a64..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,12 +32,13 @@ #include #include #include -#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 @@ -44,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) @@ -67,7 +71,7 @@ enum { TCP_CLOSING /* now a valid state */ }; -static const char *tcp_state[] = +static const char * const tcp_state[] = { "", "ESTABLISHED", @@ -95,7 +99,7 @@ typedef enum { #define SO_WAITDATA (1<<17) /* wait data to read */ #define SO_NOSPACE (1<<18) /* no space to write */ -char *itoa(unsigned int i) +static char *itoa(unsigned int i) { /* 21 digits plus null terminator, good for 64-bit or smaller ints */ static char local[22]; @@ -108,24 +112,7 @@ char *itoa(unsigned int i) return p + 1; } -char *inet_sprint(struct sockaddr* addr, int num) -{ - char *str; - str=inet_ntoa(((struct sockaddr_in*)addr)->sin_addr); - if (!strcmp(str,"0.0.0.0")) { - str="*"; - } - if (num) - { - } else { - struct hostent *he=gethostbyaddr(&((struct sockaddr_in*)addr)->sin_addr,4,AF_INET); - if (he) - str=he->h_name; - } - return str; -} - -char *get_sname(int port, const char *proto, int num) +static char *get_sname(int port, const char *proto, int num) { char *str=itoa(ntohs(port)); if (num) { @@ -140,10 +127,21 @@ char *get_sname(int port, const char *proto, int num) return str; } -void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int port, char *proto, int numeric) +static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int port, char *proto, int numeric) { char *port_name; - safe_strncpy(ip_port, inet_sprint(addr, numeric), size); + +#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'; @@ -155,9 +153,16 @@ void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int port, c 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) @@ -171,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); @@ -181,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))) { @@ -207,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) @@ -221,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); @@ -231,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) { @@ -248,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))) { @@ -271,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) @@ -285,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); @@ -295,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))) { @@ -338,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)) @@ -441,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)) @@ -468,7 +548,6 @@ static int do_info(char *file, char *name, void (*proc)(int, const char *)) } while (!feof(procinfo)); fclose(procinfo); } - return rc; } /* @@ -479,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; @@ -491,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; @@ -506,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; @@ -523,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))