Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/netstat.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/netstat.c
r821 r1770 6 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 modify9 * it under the terms of the GNU General Public License as published by10 * the Free Software Foundation; either version 2 of the License, or11 * (at your option) any later version.12 *13 * This program is distributed in the hope that it will be useful,14 * but WITHOUT ANY WARRANTY; without even the implied warranty of15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU16 * General Public License for more details.17 *18 * You should have received a copy of the GNU General Public License19 * along with this program; if not, write to the Free Software20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA21 *22 8 * 2002-04-20 23 9 * IPV6 support added by Bart Visscher <magick@linux-fan.com> 10 * 11 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 24 12 */ 25 13 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <stdarg.h> 30 #include <signal.h> 31 #include <errno.h> 32 #include <sys/stat.h> 33 #include <dirent.h> 34 #include <unistd.h> 14 #include "libbb.h" 35 15 #include "inet_common.h" 36 #include "busybox.h"37 #include "pwd_.h"38 39 #ifdef CONFIG_ROUTE40 extern void displayroutes(int noresolve, int netstatfmt);41 #endif42 43 #define NETSTAT_CONNECTED 0x0144 #define NETSTAT_LISTENING 0x0245 #define NETSTAT_NUMERIC 0x0446 #define NETSTAT_TCP 0x1047 #define NETSTAT_UDP 0x2048 #define NETSTAT_RAW 0x4049 #define NETSTAT_UNIX 0x8050 51 static int flags = NETSTAT_CONNECTED |52 NETSTAT_TCP | NETSTAT_UDP | NETSTAT_RAW | NETSTAT_UNIX;53 54 #define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)55 #define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)56 #define PROGNAME_WIDTH2(s) #s57 58 #define PRG_HASH_SIZE 21159 16 60 17 enum { 61 TCP_ESTABLISHED = 1, 62 TCP_SYN_SENT, 63 TCP_SYN_RECV, 64 TCP_FIN_WAIT1, 65 TCP_FIN_WAIT2, 66 TCP_TIME_WAIT, 67 TCP_CLOSE, 68 TCP_CLOSE_WAIT, 69 TCP_LAST_ACK, 70 TCP_LISTEN, 71 TCP_CLOSING /* now a valid state */ 18 OPT_extended = 0x4, 19 OPT_showroute = 0x100, 20 OPT_widedisplay = 0x200 * ENABLE_FEATURE_NETSTAT_WIDE, 72 21 }; 73 74 static const char * const tcp_state[] = 75 { 76 "", 77 "ESTABLISHED", 78 "SYN_SENT", 79 "SYN_RECV", 80 "FIN_WAIT1", 81 "FIN_WAIT2", 82 "TIME_WAIT", 83 "CLOSE", 84 "CLOSE_WAIT", 85 "LAST_ACK", 86 "LISTEN", 87 "CLOSING" 22 # define NETSTAT_OPTS "laentuwxr"USE_FEATURE_NETSTAT_WIDE("W") 23 24 #define NETSTAT_CONNECTED 0x01 25 #define NETSTAT_LISTENING 0x02 26 #define NETSTAT_NUMERIC 0x04 27 /* Must match getopt32 option string */ 28 #define NETSTAT_TCP 0x10 29 #define NETSTAT_UDP 0x20 30 #define NETSTAT_RAW 0x40 31 #define NETSTAT_UNIX 0x80 32 #define NETSTAT_ALLPROTO (NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW|NETSTAT_UNIX) 33 34 static smallint flags = NETSTAT_CONNECTED | NETSTAT_ALLPROTO; 35 36 enum { 37 TCP_ESTABLISHED = 1, 38 TCP_SYN_SENT, 39 TCP_SYN_RECV, 40 TCP_FIN_WAIT1, 41 TCP_FIN_WAIT2, 42 TCP_TIME_WAIT, 43 TCP_CLOSE, 44 TCP_CLOSE_WAIT, 45 TCP_LAST_ACK, 46 TCP_LISTEN, 47 TCP_CLOSING /* now a valid state */ 88 48 }; 89 49 50 static const char *const tcp_state[] = { 51 "", 52 "ESTABLISHED", 53 "SYN_SENT", 54 "SYN_RECV", 55 "FIN_WAIT1", 56 "FIN_WAIT2", 57 "TIME_WAIT", 58 "CLOSE", 59 "CLOSE_WAIT", 60 "LAST_ACK", 61 "LISTEN", 62 "CLOSING" 63 }; 64 90 65 typedef enum { 91 SS_FREE = 0,/* not allocated */92 SS_UNCONNECTED,/* unconnected to any socket */93 SS_CONNECTING,/* in process of connecting */94 SS_CONNECTED,/* connected to socket */95 SS_DISCONNECTING/* in process of disconnecting */66 SS_FREE = 0, /* not allocated */ 67 SS_UNCONNECTED, /* unconnected to any socket */ 68 SS_CONNECTING, /* in process of connecting */ 69 SS_CONNECTED, /* connected to socket */ 70 SS_DISCONNECTING /* in process of disconnecting */ 96 71 } socket_state; 97 72 98 #define SO_ACCEPTCON (1<<16) /* performed a listen */ 99 #define SO_WAITDATA (1<<17) /* wait data to read */ 100 #define SO_NOSPACE (1<<18) /* no space to write */ 101 102 static char *itoa(unsigned int i) 103 { 104 /* 21 digits plus null terminator, good for 64-bit or smaller ints */ 105 static char local[22]; 106 char *p = &local[21]; 107 *p-- = '\0'; 108 do { 109 *p-- = '0' + i % 10; 110 i /= 10; 111 } while (i > 0); 112 return p + 1; 113 } 114 115 static char *get_sname(int port, const char *proto, int num) 116 { 117 char *str=itoa(ntohs(port)); 118 if (num) { 73 #define SO_ACCEPTCON (1<<16) /* performed a listen */ 74 #define SO_WAITDATA (1<<17) /* wait data to read */ 75 #define SO_NOSPACE (1<<18) /* no space to write */ 76 77 /* Standard printout size */ 78 #define PRINT_IP_MAX_SIZE 23 79 #define PRINT_NET_CONN "%s %6ld %6ld %-23s %-23s %-12s\n" 80 #define PRINT_NET_CONN_HEADER "\nProto Recv-Q Send-Q %-23s %-23s State\n" 81 82 /* When there are IPv6 connections the IPv6 addresses will be 83 * truncated to none-recognition. The '-W' option makes the 84 * address columns wide enough to accomodate for longest possible 85 * IPv6 addresses, i.e. addresses of the form 86 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd 87 */ 88 #define PRINT_IP_MAX_SIZE_WIDE 51 /* INET6_ADDRSTRLEN + 5 for the port number */ 89 #define PRINT_NET_CONN_WIDE "%s %6ld %6ld %-51s %-51s %-12s\n" 90 #define PRINT_NET_CONN_HEADER_WIDE "\nProto Recv-Q Send-Q %-51s %-51s State\n" 91 92 static const char *net_conn_line = PRINT_NET_CONN; 93 94 95 #if ENABLE_FEATURE_IPV6 96 static void build_ipv6_addr(char* local_addr, struct sockaddr_in6* localaddr) 97 { 98 char addr6[INET6_ADDRSTRLEN]; 99 struct in6_addr in6; 100 101 sscanf(local_addr, "%08X%08X%08X%08X", 102 &in6.s6_addr32[0], &in6.s6_addr32[1], 103 &in6.s6_addr32[2], &in6.s6_addr32[3]); 104 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6)); 105 inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr->sin6_addr); 106 107 localaddr->sin6_family = AF_INET6; 108 } 109 #endif 110 111 #if ENABLE_FEATURE_IPV6 112 static void build_ipv4_addr(char* local_addr, struct sockaddr_in6* localaddr) 113 #else 114 static void build_ipv4_addr(char* local_addr, struct sockaddr_in* localaddr) 115 #endif 116 { 117 sscanf(local_addr, "%X", 118 &((struct sockaddr_in *) localaddr)->sin_addr.s_addr); 119 ((struct sockaddr *) localaddr)->sa_family = AF_INET; 120 } 121 122 static const char *get_sname(int port, const char *proto, int numeric) 123 { 124 if (!port) 125 return "*"; 126 if (!numeric) { 127 struct servent *se = getservbyport(port, proto); 128 if (se) 129 return se->s_name; 130 } 131 /* hummm, we may return static buffer here!! */ 132 return itoa(ntohs(port)); 133 } 134 135 static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int numeric) 136 { 137 enum { salen = USE_FEATURE_IPV6(sizeof(struct sockaddr_in6)) SKIP_FEATURE_IPV6(sizeof(struct sockaddr_in)) }; 138 char *host, *host_port; 139 140 /* Code which used "*" for INADDR_ANY is removed: it's ambiguous in IPv6, 141 * while "0.0.0.0" is not. */ 142 143 host = numeric ? xmalloc_sockaddr2dotted_noport(addr) 144 : xmalloc_sockaddr2host_noport(addr); 145 146 host_port = xasprintf("%s:%s", host, get_sname(htons(port), proto, numeric)); 147 free(host); 148 return host_port; 149 } 150 151 static void tcp_do_one(int lnr, const char *line) 152 { 153 char local_addr[64], rem_addr[64]; 154 char more[512]; 155 int num, local_port, rem_port, d, state, timer_run, uid, timeout; 156 #if ENABLE_FEATURE_IPV6 157 struct sockaddr_in6 localaddr, remaddr; 158 #else 159 struct sockaddr_in localaddr, remaddr; 160 #endif 161 unsigned long rxq, txq, time_len, retr, inode; 162 163 if (lnr == 0) 164 return; 165 166 more[0] = '\0'; 167 num = sscanf(line, 168 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n", 169 &d, local_addr, &local_port, 170 rem_addr, &rem_port, &state, 171 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); 172 173 if (strlen(local_addr) > 8) { 174 #if ENABLE_FEATURE_IPV6 175 build_ipv6_addr(local_addr, &localaddr); 176 build_ipv6_addr(rem_addr, &remaddr); 177 #endif 119 178 } else { 120 struct servent *se=getservbyport(port,proto); 121 if (se) 122 str=se->s_name; 123 } 124 if (!port) { 125 str="*"; 126 } 127 return str; 128 } 129 130 static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int port, char *proto, int numeric) 131 { 132 char *port_name; 133 134 #ifdef 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 { 141 INET_rresolve(ip_port, size, (struct sockaddr_in *)addr, 142 0x4000 | ((numeric&NETSTAT_NUMERIC) ? 0x0fff : 0), 143 0xffffffff); 144 } 145 port_name=get_sname(htons(port), proto, numeric); 146 if ((strlen(ip_port) + strlen(port_name)) > 22) 147 ip_port[22 - strlen(port_name)] = '\0'; 148 ip_port+=strlen(ip_port); 149 strcat(ip_port, ":"); 150 strcat(ip_port, port_name); 151 } 152 153 static void tcp_do_one(int lnr, const char *line) 179 build_ipv4_addr(local_addr, &localaddr); 180 build_ipv4_addr(rem_addr, &remaddr); 181 } 182 183 if (num < 10) { 184 bb_error_msg("warning, got bogus tcp line"); 185 return; 186 } 187 188 if ((rem_port && (flags & NETSTAT_CONNECTED)) 189 || (!rem_port && (flags & NETSTAT_LISTENING)) 190 ) { 191 char *l = ip_port_str( 192 (struct sockaddr *) &localaddr, local_port, 193 "tcp", flags & NETSTAT_NUMERIC); 194 char *r = ip_port_str( 195 (struct sockaddr *) &remaddr, rem_port, 196 "tcp", flags & NETSTAT_NUMERIC); 197 printf(net_conn_line, 198 "tcp", rxq, txq, l, r, tcp_state[state]); 199 free(l); 200 free(r); 201 } 202 } 203 204 static void udp_do_one(int lnr, const char *line) 154 205 { 155 206 char local_addr[64], rem_addr[64]; … … 157 208 char more[512]; 158 209 int num, local_port, rem_port, d, state, timer_run, uid, timeout; 159 #if def CONFIG_FEATURE_IPV6210 #if ENABLE_FEATURE_IPV6 160 211 struct sockaddr_in6 localaddr, remaddr; 161 char addr6[INET6_ADDRSTRLEN];162 struct in6_addr in6;163 212 #else 164 213 struct sockaddr_in localaddr, remaddr; … … 171 220 more[0] = '\0'; 172 221 num = sscanf(line, 173 174 175 176 222 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n", 223 &d, local_addr, &local_port, 224 rem_addr, &rem_port, &state, 225 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); 177 226 178 227 if (strlen(local_addr) > 8) { 179 #ifdef 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; 228 #if ENABLE_FEATURE_IPV6 229 /* Demangle what the kernel gives us */ 230 build_ipv6_addr(local_addr, &localaddr); 231 build_ipv6_addr(rem_addr, &remaddr); 192 232 #endif 193 233 } else { 194 sscanf(local_addr, "%X", 195 &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); 196 sscanf(rem_addr, "%X", 197 &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr); 198 ((struct sockaddr *) &localaddr)->sa_family = AF_INET; 199 ((struct sockaddr *) &remaddr)->sa_family = AF_INET; 234 build_ipv4_addr(local_addr, &localaddr); 235 build_ipv4_addr(rem_addr, &remaddr); 200 236 } 201 237 202 238 if (num < 10) { 203 bb_error_msg("warning, got bogus tcp line."); 204 return; 205 } 206 state_str = tcp_state[state]; 207 if ((rem_port && (flags&NETSTAT_CONNECTED)) || 208 (!rem_port && (flags&NETSTAT_LISTENING))) 209 { 210 snprint_ip_port(local_addr, sizeof(local_addr), 211 (struct sockaddr *) &localaddr, local_port, 212 "tcp", flags&NETSTAT_NUMERIC); 213 214 snprint_ip_port(rem_addr, sizeof(rem_addr), 215 (struct sockaddr *) &remaddr, rem_port, 216 "tcp", flags&NETSTAT_NUMERIC); 217 218 printf("tcp %6ld %6ld %-23s %-23s %-12s\n", 219 rxq, txq, local_addr, rem_addr, state_str); 220 221 } 222 } 223 224 static void udp_do_one(int lnr, const char *line) 225 { 226 char local_addr[64], rem_addr[64]; 227 char *state_str, more[512]; 228 int num, local_port, rem_port, d, state, timer_run, uid, timeout; 229 #ifdef CONFIG_FEATURE_IPV6 230 struct sockaddr_in6 localaddr, remaddr; 231 char addr6[INET6_ADDRSTRLEN]; 232 struct in6_addr in6; 233 #else 234 struct sockaddr_in localaddr, remaddr; 235 #endif 236 unsigned long rxq, txq, time_len, retr, inode; 237 238 if (lnr == 0) 239 return; 240 241 more[0] = '\0'; 242 num = sscanf(line, 243 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n", 244 &d, local_addr, &local_port, 245 rem_addr, &rem_port, &state, 246 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); 247 248 if (strlen(local_addr) > 8) { 249 #ifdef 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 264 } else { 265 sscanf(local_addr, "%X", 266 &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); 267 sscanf(rem_addr, "%X", 268 &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr); 269 ((struct sockaddr *) &localaddr)->sa_family = AF_INET; 270 ((struct sockaddr *) &remaddr)->sa_family = AF_INET; 271 } 272 273 if (num < 10) { 274 bb_error_msg("warning, got bogus udp line."); 239 bb_error_msg("warning, got bogus udp line"); 275 240 return; 276 241 } … … 279 244 state_str = "ESTABLISHED"; 280 245 break; 281 282 246 case TCP_CLOSE: 283 247 state_str = ""; 284 248 break; 285 286 249 default: 287 250 state_str = "UNKNOWN"; … … 289 252 } 290 253 291 #ifdef 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)) 254 #if ENABLE_FEATURE_IPV6 255 # define notnull(A) ( \ 256 ( (A.sin6_family == AF_INET6) \ 257 && (A.sin6_addr.s6_addr32[0] | A.sin6_addr.s6_addr32[1] | \ 258 A.sin6_addr.s6_addr32[2] | A.sin6_addr.s6_addr32[3]) \ 259 ) || ( \ 260 (A.sin6_family == AF_INET) \ 261 && ((struct sockaddr_in*)&A)->sin_addr.s_addr \ 262 ) \ 263 ) 299 264 #else 300 265 # define notnull(A) (A.sin_addr.s_addr) 301 266 #endif 302 if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) ||303 (!notnull(remaddr) && (flags&NETSTAT_LISTENING)))304 267 { 305 snprint_ip_port(local_addr, sizeof(local_addr), 306 (struct sockaddr *) &localaddr, local_port, 307 "udp", flags&NETSTAT_NUMERIC); 308 309 snprint_ip_port(rem_addr, sizeof(rem_addr), 310 (struct sockaddr *) &remaddr, rem_port, 311 "udp", flags&NETSTAT_NUMERIC); 312 313 printf("udp %6ld %6ld %-23s %-23s %-12s\n", 314 rxq, txq, local_addr, rem_addr, state_str); 315 268 int have_remaddr = notnull(remaddr); 269 if ((have_remaddr && (flags & NETSTAT_CONNECTED)) 270 || (!have_remaddr && (flags & NETSTAT_LISTENING)) 271 ) { 272 char *l = ip_port_str( 273 (struct sockaddr *) &localaddr, local_port, 274 "udp", flags & NETSTAT_NUMERIC); 275 char *r = ip_port_str( 276 (struct sockaddr *) &remaddr, rem_port, 277 "udp", flags & NETSTAT_NUMERIC); 278 printf(net_conn_line, 279 "udp", rxq, txq, l, r, state_str); 280 free(l); 281 free(r); 282 } 316 283 } 317 284 } … … 320 287 { 321 288 char local_addr[64], rem_addr[64]; 322 char *state_str,more[512];289 char more[512]; 323 290 int num, local_port, rem_port, d, state, timer_run, uid, timeout; 324 #if def CONFIG_FEATURE_IPV6291 #if ENABLE_FEATURE_IPV6 325 292 struct sockaddr_in6 localaddr, remaddr; 326 char addr6[INET6_ADDRSTRLEN];327 struct in6_addr in6;328 293 #else 329 294 struct sockaddr_in localaddr, remaddr; … … 336 301 more[0] = '\0'; 337 302 num = sscanf(line, 338 339 340 341 303 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n", 304 &d, local_addr, &local_port, 305 rem_addr, &rem_port, &state, 306 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more); 342 307 343 308 if (strlen(local_addr) > 8) { 344 #ifdef 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; 309 #if ENABLE_FEATURE_IPV6 310 build_ipv6_addr(local_addr, &localaddr); 311 build_ipv6_addr(rem_addr, &remaddr); 357 312 #endif 358 313 } else { 359 sscanf(local_addr, "%X", 360 &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr); 361 sscanf(rem_addr, "%X", 362 &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr); 363 ((struct sockaddr *) &localaddr)->sa_family = AF_INET; 364 ((struct sockaddr *) &remaddr)->sa_family = AF_INET; 314 build_ipv4_addr(local_addr, &localaddr); 315 build_ipv4_addr(rem_addr, &remaddr); 365 316 } 366 317 367 318 if (num < 10) { 368 bb_error_msg("warning, got bogus raw line."); 369 return; 370 } 371 state_str=itoa(state); 372 373 #ifdef 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 382 # define notnull(A) (A.sin_addr.s_addr) 383 #endif 384 if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) || 385 (!notnull(remaddr) && (flags&NETSTAT_LISTENING))) 319 bb_error_msg("warning, got bogus raw line"); 320 return; 321 } 322 386 323 { 387 snprint_ip_port(local_addr, sizeof(local_addr), 388 (struct sockaddr *) &localaddr, local_port, 389 "raw", flags&NETSTAT_NUMERIC); 390 391 snprint_ip_port(rem_addr, sizeof(rem_addr), 392 (struct sockaddr *) &remaddr, rem_port, 393 "raw", flags&NETSTAT_NUMERIC); 394 395 printf("raw %6ld %6ld %-23s %-23s %-12s\n", 396 rxq, txq, local_addr, rem_addr, state_str); 397 398 } 399 } 400 401 #define HAS_INODE 1 324 int have_remaddr = notnull(remaddr); 325 if ((have_remaddr && (flags & NETSTAT_CONNECTED)) 326 || (!have_remaddr && (flags & NETSTAT_LISTENING)) 327 ) { 328 char *l = ip_port_str( 329 (struct sockaddr *) &localaddr, local_port, 330 "raw", flags & NETSTAT_NUMERIC); 331 char *r = ip_port_str( 332 (struct sockaddr *) &remaddr, rem_port, 333 "raw", flags & NETSTAT_NUMERIC); 334 printf(net_conn_line, 335 "raw", rxq, txq, l, r, itoa(state)); 336 free(l); 337 free(r); 338 } 339 } 340 } 402 341 403 342 static void unix_do_one(int nr, const char *line) 404 343 { 405 static int has = 0; 344 static smallint has_inode = 0; 345 406 346 char path[PATH_MAX], ss_flags[32]; 407 c har *ss_proto, *ss_state, *ss_type;347 const char *ss_proto, *ss_state, *ss_type; 408 348 int num, state, type, inode; 409 349 void *d; … … 412 352 if (nr == 0) { 413 353 if (strstr(line, "Inode")) 414 has |= HAS_INODE;354 has_inode = 1; 415 355 return; 416 356 } 417 357 path[0] = '\0'; 418 358 num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s", 419 359 &d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path); 420 360 if (num < 6) { 421 bb_error_msg("warning, got bogus unix line .");422 return; 423 } 424 if (! (has & HAS_INODE))425 s nprintf(path,sizeof(path),"%d",inode);426 427 if ((flags &(NETSTAT_LISTENING|NETSTAT_CONNECTED))!=(NETSTAT_LISTENING|NETSTAT_CONNECTED)) {361 bb_error_msg("warning, got bogus unix line"); 362 return; 363 } 364 if (!has_inode) 365 sprintf(path, "%d", inode); 366 367 if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) != (NETSTAT_LISTENING|NETSTAT_CONNECTED)) { 428 368 if ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) { 429 if (!(flags &NETSTAT_LISTENING))369 if (!(flags & NETSTAT_LISTENING)) 430 370 return; 431 371 } else { 432 if (!(flags &NETSTAT_CONNECTED))372 if (!(flags & NETSTAT_CONNECTED)) 433 373 return; 434 374 } … … 439 379 ss_proto = "unix"; 440 380 break; 441 442 381 default: 443 382 ss_proto = "??"; … … 448 387 ss_type = "STREAM"; 449 388 break; 450 451 389 case SOCK_DGRAM: 452 390 ss_type = "DGRAM"; 453 391 break; 454 455 392 case SOCK_RAW: 456 393 ss_type = "RAW"; 457 394 break; 458 459 395 case SOCK_RDM: 460 396 ss_type = "RDM"; 461 397 break; 462 463 398 case SOCK_SEQPACKET: 464 399 ss_type = "SEQPACKET"; 465 400 break; 466 467 401 default: 468 402 ss_type = "UNKNOWN"; … … 473 407 ss_state = "FREE"; 474 408 break; 475 476 409 case SS_UNCONNECTED: 477 410 /* … … 485 418 } 486 419 break; 487 488 420 case SS_CONNECTING: 489 421 ss_state = "CONNECTING"; 490 422 break; 491 492 423 case SS_CONNECTED: 493 424 ss_state = "CONNECTED"; 494 425 break; 495 496 426 case SS_DISCONNECTING: 497 427 ss_state = "DISCONNECTING"; 498 428 break; 499 500 429 default: 501 430 ss_state = "UNKNOWN"; … … 509 438 if (unix_flags & SO_NOSPACE) 510 439 strcat(ss_flags, "N "); 511 512 440 strcat(ss_flags, "]"); 513 441 514 442 printf("%-5s %-6ld %-11s %-10s %-13s ", 515 443 ss_proto, refcnt, ss_flags, ss_type, ss_state); 516 if (has & HAS_INODE)517 printf("%-6d ", inode);444 if (has_inode) 445 printf("%-6d ", inode); 518 446 else 519 447 printf("- "); … … 531 459 static void do_info(const char *file, const char *name, void (*proc)(int, const char *)) 532 460 { 533 char buffer[8192];534 461 int lnr = 0; 535 462 FILE *procinfo; … … 538 465 if (procinfo == NULL) { 539 466 if (errno != ENOENT) { 540 perror(file);467 bb_perror_msg("%s", file); 541 468 } else { 542 bb_error_msg("no support for `%s' on this system.", name);469 bb_error_msg("no support for '%s' on this system", name); 543 470 } 544 } else { 545 do { 546 if (fgets(buffer, sizeof(buffer), procinfo)) 547 (proc)(lnr++, buffer); 548 } while (!feof(procinfo)); 549 fclose(procinfo); 550 } 471 return; 472 } 473 do { 474 char *buffer = xmalloc_fgets(procinfo); 475 if (buffer) { 476 (proc)(lnr++, buffer); 477 free(buffer); 478 } 479 } while (!feof(procinfo)); 480 fclose(procinfo); 551 481 } 552 482 … … 555 485 */ 556 486 487 int netstat_main(int argc, char **argv); 557 488 int netstat_main(int argc, char **argv) 558 489 { 559 int opt; 560 int new_flags=0; 561 int showroute = 0, extended = 0; 562 #ifdef CONFIG_FEATURE_IPV6 563 int inet=1; 564 int inet6=1; 565 #else 566 # define inet 1 567 # define inet6 0 568 #endif 569 while ((opt = getopt(argc, argv, "laenrtuwx")) != -1) 570 switch (opt) { 571 case 'l': 572 flags &= ~NETSTAT_CONNECTED; 573 flags |= NETSTAT_LISTENING; 574 break; 575 case 'a': 576 flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED; 577 break; 578 case 'n': 579 flags |= NETSTAT_NUMERIC; 580 break; 581 case 'r': 582 showroute = 1; 583 break; 584 case 'e': 585 extended = 1; 586 break; 587 case 't': 588 new_flags |= NETSTAT_TCP; 589 break; 590 case 'u': 591 new_flags |= NETSTAT_UDP; 592 break; 593 case 'w': 594 new_flags |= NETSTAT_RAW; 595 break; 596 case 'x': 597 new_flags |= NETSTAT_UNIX; 598 break; 599 default: 600 bb_show_usage(); 601 } 602 if ( showroute ) { 603 #ifdef CONFIG_ROUTE 604 displayroutes ( flags & NETSTAT_NUMERIC, !extended ); 490 const char *net_conn_line_header = PRINT_NET_CONN_HEADER; 491 unsigned opt; 492 #if ENABLE_FEATURE_IPV6 493 smallint inet = 1; 494 smallint inet6 = 1; 495 #else 496 enum { inet = 1, inet6 = 0 }; 497 #endif 498 499 /* Option string must match NETSTAT_xxx constants */ 500 opt = getopt32(argv, NETSTAT_OPTS); 501 if (opt & 0x1) { // -l 502 flags &= ~NETSTAT_CONNECTED; 503 flags |= NETSTAT_LISTENING; 504 } 505 if (opt & 0x2) flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED; // -a 506 //if (opt & 0x4) // -e 507 if (opt & 0x8) flags |= NETSTAT_NUMERIC; // -n 508 //if (opt & 0x10) // -t: NETSTAT_TCP 509 //if (opt & 0x20) // -u: NETSTAT_UDP 510 //if (opt & 0x40) // -w: NETSTAT_RAW 511 //if (opt & 0x80) // -x: NETSTAT_UNIX 512 if (opt & OPT_showroute) { // -r 513 #if ENABLE_ROUTE 514 bb_displayroutes(flags & NETSTAT_NUMERIC, !(opt & OPT_extended)); 605 515 return 0; 606 516 #else 607 bb_error_msg_and_die( "-r (display routing table) is not compiled in." ); 608 #endif 609 } 610 611 if (new_flags) { 612 flags &= ~(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW|NETSTAT_UNIX); 613 flags |= new_flags; 614 } 615 if (flags&(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) { 517 bb_show_usage(); 518 #endif 519 } 520 521 if (opt & OPT_widedisplay) { // -W 522 net_conn_line = PRINT_NET_CONN_WIDE; 523 net_conn_line_header = PRINT_NET_CONN_HEADER_WIDE; 524 } 525 526 opt &= NETSTAT_ALLPROTO; 527 if (opt) { 528 flags &= ~NETSTAT_ALLPROTO; 529 flags |= opt; 530 } 531 if (flags & (NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) { 616 532 printf("Active Internet connections "); /* xxx */ 617 533 618 if ((flags &(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))534 if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) == (NETSTAT_LISTENING|NETSTAT_CONNECTED)) 619 535 printf("(servers and established)"); 620 else { 621 if (flags&NETSTAT_LISTENING) 622 printf("(only servers)"); 623 else 624 printf("(w/o servers)"); 625 } 626 printf("\nProto Recv-Q Send-Q Local Address Foreign Address State \n"); 627 } 628 if (inet && flags&NETSTAT_TCP) 629 do_info(_PATH_PROCNET_TCP,"AF INET (tcp)",tcp_do_one); 630 #ifdef 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) 635 do_info(_PATH_PROCNET_UDP,"AF INET (udp)",udp_do_one); 636 #ifdef 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) 641 do_info(_PATH_PROCNET_RAW,"AF INET (raw)",raw_do_one); 642 #ifdef CONFIG_FEATURE_IPV6 643 if (inet6 && flags&NETSTAT_RAW) 644 do_info(_PATH_PROCNET_RAW6,"AF INET6 (raw)",raw_do_one); 645 #endif 646 if (flags&NETSTAT_UNIX) { 536 else if (flags & NETSTAT_LISTENING) 537 printf("(only servers)"); 538 else 539 printf("(w/o servers)"); 540 printf(net_conn_line_header, "Local Address", "Foreign Address"); 541 } 542 if (inet && flags & NETSTAT_TCP) 543 do_info(_PATH_PROCNET_TCP, "AF INET (tcp)", tcp_do_one); 544 #if ENABLE_FEATURE_IPV6 545 if (inet6 && flags & NETSTAT_TCP) 546 do_info(_PATH_PROCNET_TCP6, "AF INET6 (tcp)", tcp_do_one); 547 #endif 548 if (inet && flags & NETSTAT_UDP) 549 do_info(_PATH_PROCNET_UDP, "AF INET (udp)", udp_do_one); 550 #if ENABLE_FEATURE_IPV6 551 if (inet6 && flags & NETSTAT_UDP) 552 do_info(_PATH_PROCNET_UDP6, "AF INET6 (udp)", udp_do_one); 553 #endif 554 if (inet && flags & NETSTAT_RAW) 555 do_info(_PATH_PROCNET_RAW, "AF INET (raw)", raw_do_one); 556 #if ENABLE_FEATURE_IPV6 557 if (inet6 && flags & NETSTAT_RAW) 558 do_info(_PATH_PROCNET_RAW6, "AF INET6 (raw)", raw_do_one); 559 #endif 560 if (flags & NETSTAT_UNIX) { 647 561 printf("Active UNIX domain sockets "); 648 if ((flags &(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))562 if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) == (NETSTAT_LISTENING|NETSTAT_CONNECTED)) 649 563 printf("(servers and established)"); 650 else { 651 if (flags&NETSTAT_LISTENING) 652 printf("(only servers)"); 653 else 654 printf("(w/o servers)"); 655 } 656 564 else if (flags & NETSTAT_LISTENING) 565 printf("(only servers)"); 566 else 567 printf("(w/o servers)"); 657 568 printf("\nProto RefCnt Flags Type State I-Node Path\n"); 658 do_info(_PATH_PROCNET_UNIX, "AF UNIX",unix_do_one);569 do_info(_PATH_PROCNET_UNIX, "AF UNIX", unix_do_one); 659 570 } 660 571 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.