diff options
Diffstat (limited to 'networking/netstat.c')
-rw-r--r-- | networking/netstat.c | 198 |
1 files changed, 119 insertions, 79 deletions
diff --git a/networking/netstat.c b/networking/netstat.c index 3114a3902..2a83af3ac 100644 --- a/networking/netstat.c +++ b/networking/netstat.c | |||
@@ -17,16 +17,37 @@ | |||
17 | #include "libbb.h" | 17 | #include "libbb.h" |
18 | #include "inet_common.h" | 18 | #include "inet_common.h" |
19 | 19 | ||
20 | //usage:#define netstat_trivial_usage | ||
21 | //usage: "[-"IF_ROUTE("r")"al] [-tuwx] [-en"IF_FEATURE_NETSTAT_WIDE("W")IF_FEATURE_NETSTAT_PRG("p")"]" | ||
22 | //usage:#define netstat_full_usage "\n\n" | ||
23 | //usage: "Display networking information\n" | ||
24 | //usage: "\nOptions:" | ||
25 | //usage: IF_ROUTE( | ||
26 | //usage: "\n -r Routing table" | ||
27 | //usage: ) | ||
28 | //usage: "\n -a All sockets" | ||
29 | //usage: "\n -l Listening sockets" | ||
30 | //usage: "\n Else: connected sockets" | ||
31 | //usage: "\n -t TCP sockets" | ||
32 | //usage: "\n -u UDP sockets" | ||
33 | //usage: "\n -w Raw sockets" | ||
34 | //usage: "\n -x Unix sockets" | ||
35 | //usage: "\n Else: all socket types" | ||
36 | //usage: "\n -e Other/more information" | ||
37 | //usage: "\n -n Don't resolve names" | ||
38 | //usage: IF_FEATURE_NETSTAT_WIDE( | ||
39 | //usage: "\n -W Wide display" | ||
40 | //usage: ) | ||
41 | //usage: IF_FEATURE_NETSTAT_PRG( | ||
42 | //usage: "\n -p Show PID/program name for sockets" | ||
43 | //usage: ) | ||
44 | |||
20 | #define NETSTAT_OPTS "laentuwx" \ | 45 | #define NETSTAT_OPTS "laentuwx" \ |
21 | IF_ROUTE( "r") \ | 46 | IF_ROUTE( "r") \ |
22 | IF_FEATURE_NETSTAT_WIDE("W") \ | 47 | IF_FEATURE_NETSTAT_WIDE("W") \ |
23 | IF_FEATURE_NETSTAT_PRG( "p") | 48 | IF_FEATURE_NETSTAT_PRG( "p") |
24 | 49 | ||
25 | enum { | 50 | enum { |
26 | OPTBIT_KEEP_OLD = 7, | ||
27 | IF_ROUTE( OPTBIT_ROUTE,) | ||
28 | IF_FEATURE_NETSTAT_WIDE(OPTBIT_WIDE ,) | ||
29 | IF_FEATURE_NETSTAT_PRG( OPTBIT_PRG ,) | ||
30 | OPT_sock_listen = 1 << 0, // l | 51 | OPT_sock_listen = 1 << 0, // l |
31 | OPT_sock_all = 1 << 1, // a | 52 | OPT_sock_all = 1 << 1, // a |
32 | OPT_extended = 1 << 2, // e | 53 | OPT_extended = 1 << 2, // e |
@@ -35,6 +56,10 @@ enum { | |||
35 | OPT_sock_udp = 1 << 5, // u | 56 | OPT_sock_udp = 1 << 5, // u |
36 | OPT_sock_raw = 1 << 6, // w | 57 | OPT_sock_raw = 1 << 6, // w |
37 | OPT_sock_unix = 1 << 7, // x | 58 | OPT_sock_unix = 1 << 7, // x |
59 | OPTBIT_x = 7, | ||
60 | IF_ROUTE( OPTBIT_ROUTE,) | ||
61 | IF_FEATURE_NETSTAT_WIDE(OPTBIT_WIDE ,) | ||
62 | IF_FEATURE_NETSTAT_PRG( OPTBIT_PRG ,) | ||
38 | OPT_route = IF_ROUTE( (1 << OPTBIT_ROUTE)) + 0, // r | 63 | OPT_route = IF_ROUTE( (1 << OPTBIT_ROUTE)) + 0, // r |
39 | OPT_wide = IF_FEATURE_NETSTAT_WIDE((1 << OPTBIT_WIDE )) + 0, // W | 64 | OPT_wide = IF_FEATURE_NETSTAT_WIDE((1 << OPTBIT_WIDE )) + 0, // W |
40 | OPT_prg = IF_FEATURE_NETSTAT_PRG( (1 << OPTBIT_PRG )) + 0, // p | 65 | OPT_prg = IF_FEATURE_NETSTAT_PRG( (1 << OPTBIT_PRG )) + 0, // p |
@@ -88,24 +113,25 @@ typedef enum { | |||
88 | SS_DISCONNECTING /* in process of disconnecting */ | 113 | SS_DISCONNECTING /* in process of disconnecting */ |
89 | } socket_state; | 114 | } socket_state; |
90 | 115 | ||
91 | #define SO_ACCEPTCON (1<<16) /* performed a listen */ | 116 | #define SO_ACCEPTCON (1<<16) /* performed a listen */ |
92 | #define SO_WAITDATA (1<<17) /* wait data to read */ | 117 | #define SO_WAITDATA (1<<17) /* wait data to read */ |
93 | #define SO_NOSPACE (1<<18) /* no space to write */ | 118 | #define SO_NOSPACE (1<<18) /* no space to write */ |
94 | |||
95 | /* Standard printout size */ | ||
96 | #define PRINT_IP_MAX_SIZE 23 | ||
97 | #define PRINT_NET_CONN "%s %6ld %6ld %-23s %-23s %-12s" | ||
98 | #define PRINT_NET_CONN_HEADER "\nProto Recv-Q Send-Q %-23s %-23s State " | ||
99 | 119 | ||
120 | #define ADDR_NORMAL_WIDTH 23 | ||
100 | /* When there are IPv6 connections the IPv6 addresses will be | 121 | /* When there are IPv6 connections the IPv6 addresses will be |
101 | * truncated to none-recognition. The '-W' option makes the | 122 | * truncated to none-recognition. The '-W' option makes the |
102 | * address columns wide enough to accomodate for longest possible | 123 | * address columns wide enough to accomodate for longest possible |
103 | * IPv6 addresses, i.e. addresses of the form | 124 | * IPv6 addresses, i.e. addresses of the form |
104 | * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd | 125 | * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd |
105 | */ | 126 | */ |
106 | #define PRINT_IP_MAX_SIZE_WIDE 51 /* INET6_ADDRSTRLEN + 5 for the port number */ | 127 | #define ADDR_WIDE 51 /* INET6_ADDRSTRLEN + 5 for the port number */ |
107 | #define PRINT_NET_CONN_WIDE "%s %6ld %6ld %-51s %-51s %-12s" | 128 | #if ENABLE_FEATURE_NETSTAT_WIDE |
108 | #define PRINT_NET_CONN_HEADER_WIDE "\nProto Recv-Q Send-Q %-51s %-51s State " | 129 | # define FMT_NET_CONN_DATA "%s %6ld %6ld %-*s %-*s %-12s" |
130 | # define FMT_NET_CONN_HEADER "\nProto Recv-Q Send-Q %-*s %-*s State %s\n" | ||
131 | #else | ||
132 | # define FMT_NET_CONN_DATA "%s %6ld %6ld %-23s %-23s %-12s" | ||
133 | # define FMT_NET_CONN_HEADER "\nProto Recv-Q Send-Q %-23s %-23s State %s\n" | ||
134 | #endif | ||
109 | 135 | ||
110 | #define PROGNAME_WIDTH 20 | 136 | #define PROGNAME_WIDTH 20 |
111 | #define PROGNAME_WIDTH_STR "20" | 137 | #define PROGNAME_WIDTH_STR "20" |
@@ -121,22 +147,30 @@ struct prg_node { | |||
121 | #define PRG_HASH_SIZE 211 | 147 | #define PRG_HASH_SIZE 211 |
122 | 148 | ||
123 | struct globals { | 149 | struct globals { |
124 | const char *net_conn_line; | ||
125 | smallint flags; | 150 | smallint flags; |
126 | #if ENABLE_FEATURE_NETSTAT_PRG | 151 | #if ENABLE_FEATURE_NETSTAT_PRG |
127 | smallint prg_cache_loaded; | 152 | smallint prg_cache_loaded; |
128 | struct prg_node *prg_hash[PRG_HASH_SIZE]; | 153 | struct prg_node *prg_hash[PRG_HASH_SIZE]; |
129 | #endif | 154 | #endif |
155 | #if ENABLE_FEATURE_NETSTAT_PRG | ||
156 | const char *progname_banner; | ||
157 | #endif | ||
158 | #if ENABLE_FEATURE_NETSTAT_WIDE | ||
159 | unsigned addr_width; | ||
160 | #endif | ||
130 | }; | 161 | }; |
131 | #define G (*ptr_to_globals) | 162 | #define G (*ptr_to_globals) |
132 | #define flags (G.flags ) | 163 | #define flags (G.flags ) |
133 | #define net_conn_line (G.net_conn_line ) | ||
134 | #define prg_hash (G.prg_hash ) | ||
135 | #define prg_cache_loaded (G.prg_cache_loaded) | 164 | #define prg_cache_loaded (G.prg_cache_loaded) |
165 | #define prg_hash (G.prg_hash ) | ||
166 | #if ENABLE_FEATURE_NETSTAT_PRG | ||
167 | # define progname_banner (G.progname_banner ) | ||
168 | #else | ||
169 | # define progname_banner "" | ||
170 | #endif | ||
136 | #define INIT_G() do { \ | 171 | #define INIT_G() do { \ |
137 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 172 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
138 | flags = NETSTAT_CONNECTED | NETSTAT_ALLPROTO; \ | 173 | flags = NETSTAT_CONNECTED | NETSTAT_ALLPROTO; \ |
139 | net_conn_line = PRINT_NET_CONN; \ | ||
140 | } while (0) | 174 | } while (0) |
141 | 175 | ||
142 | 176 | ||
@@ -145,10 +179,6 @@ struct globals { | |||
145 | /* Deliberately truncating long to unsigned *int* */ | 179 | /* Deliberately truncating long to unsigned *int* */ |
146 | #define PRG_HASHIT(x) ((unsigned)(x) % PRG_HASH_SIZE) | 180 | #define PRG_HASHIT(x) ((unsigned)(x) % PRG_HASH_SIZE) |
147 | 181 | ||
148 | #define print_progname_banner() do { \ | ||
149 | if (option_mask32 & OPT_prg) printf(PROGNAME_BANNER); \ | ||
150 | } while (0) | ||
151 | |||
152 | static void prg_cache_add(long inode, char *name) | 182 | static void prg_cache_add(long inode, char *name) |
153 | { | 183 | { |
154 | unsigned hi = PRG_HASHIT(inode); | 184 | unsigned hi = PRG_HASHIT(inode); |
@@ -201,12 +231,12 @@ static long extract_socket_inode(const char *lname) | |||
201 | 231 | ||
202 | if (strncmp(lname, "socket:[", sizeof("socket:[")-1) == 0) { | 232 | if (strncmp(lname, "socket:[", sizeof("socket:[")-1) == 0) { |
203 | /* "socket:[12345]", extract the "12345" as inode */ | 233 | /* "socket:[12345]", extract the "12345" as inode */ |
204 | inode = bb_strtol(lname + sizeof("socket:[")-1, (char**)&lname, 0); | 234 | inode = bb_strtoul(lname + sizeof("socket:[")-1, (char**)&lname, 0); |
205 | if (*lname != ']') | 235 | if (*lname != ']') |
206 | inode = -1; | 236 | inode = -1; |
207 | } else if (strncmp(lname, "[0000]:", sizeof("[0000]:")-1) == 0) { | 237 | } else if (strncmp(lname, "[0000]:", sizeof("[0000]:")-1) == 0) { |
208 | /* "[0000]:12345", extract the "12345" as inode */ | 238 | /* "[0000]:12345", extract the "12345" as inode */ |
209 | inode = bb_strtol(lname + sizeof("[0000]:")-1, NULL, 0); | 239 | inode = bb_strtoul(lname + sizeof("[0000]:")-1, NULL, 0); |
210 | if (errno) /* not NUL terminated? */ | 240 | if (errno) /* not NUL terminated? */ |
211 | inode = -1; | 241 | inode = -1; |
212 | } | 242 | } |
@@ -218,9 +248,9 @@ static long extract_socket_inode(const char *lname) | |||
218 | return inode; | 248 | return inode; |
219 | } | 249 | } |
220 | 250 | ||
221 | static int FAST_FUNC file_act(const char *fileName, | 251 | static int FAST_FUNC add_to_prg_cache_if_socket(const char *fileName, |
222 | struct stat *statbuf UNUSED_PARAM, | 252 | struct stat *statbuf UNUSED_PARAM, |
223 | void *userData, | 253 | void *pid_slash_progname, |
224 | int depth UNUSED_PARAM) | 254 | int depth UNUSED_PARAM) |
225 | { | 255 | { |
226 | char *linkname; | 256 | char *linkname; |
@@ -231,7 +261,7 @@ static int FAST_FUNC file_act(const char *fileName, | |||
231 | inode = extract_socket_inode(linkname); | 261 | inode = extract_socket_inode(linkname); |
232 | free(linkname); | 262 | free(linkname); |
233 | if (inode >= 0) | 263 | if (inode >= 0) |
234 | prg_cache_add(inode, (char *)userData); | 264 | prg_cache_add(inode, (char *)pid_slash_progname); |
235 | } | 265 | } |
236 | return TRUE; | 266 | return TRUE; |
237 | } | 267 | } |
@@ -241,38 +271,40 @@ static int FAST_FUNC dir_act(const char *fileName, | |||
241 | void *userData UNUSED_PARAM, | 271 | void *userData UNUSED_PARAM, |
242 | int depth) | 272 | int depth) |
243 | { | 273 | { |
244 | const char *shortName; | 274 | const char *pid; |
245 | char *p, *q; | 275 | char *pid_slash_progname; |
276 | char proc_pid_fname[sizeof("/proc/%u/cmdline") + sizeof(long)*3]; | ||
246 | char cmdline_buf[512]; | 277 | char cmdline_buf[512]; |
247 | int i; | 278 | int n, len; |
248 | 279 | ||
249 | if (depth == 0) /* "/proc" itself */ | 280 | if (depth == 0) /* "/proc" itself */ |
250 | return TRUE; /* continue looking one level below /proc */ | 281 | return TRUE; /* continue looking one level below /proc */ |
251 | 282 | ||
252 | shortName = fileName + sizeof("/proc/")-1; /* point after "/proc/" */ | 283 | pid = fileName + sizeof("/proc/")-1; /* point after "/proc/" */ |
253 | if (!isdigit(shortName[0])) /* skip /proc entries whic aren't processes */ | 284 | if (!isdigit(pid[0])) /* skip /proc entries which aren't processes */ |
254 | return SKIP; | 285 | return SKIP; |
255 | 286 | ||
256 | p = concat_path_file(fileName, "cmdline"); /* "/proc/PID/cmdline" */ | 287 | len = snprintf(proc_pid_fname, sizeof(proc_pid_fname), "%s/cmdline", fileName); |
257 | i = open_read_close(p, cmdline_buf, sizeof(cmdline_buf) - 1); | 288 | n = open_read_close(proc_pid_fname, cmdline_buf, sizeof(cmdline_buf) - 1); |
258 | free(p); | 289 | if (n < 0) |
259 | if (i < 0) | ||
260 | return FALSE; | 290 | return FALSE; |
261 | cmdline_buf[i] = '\0'; | 291 | cmdline_buf[n] = '\0'; |
262 | q = concat_path_file(shortName, bb_basename(cmdline_buf)); /* "PID/argv0" */ | 292 | |
263 | 293 | /* go through all files in /proc/PID/fd and check whether they are sockets */ | |
264 | /* go through all files in /proc/PID/fd */ | 294 | strcpy(proc_pid_fname + len - (sizeof("cmdline")-1), "fd"); |
265 | p = concat_path_file(fileName, "fd"); | 295 | pid_slash_progname = concat_path_file(pid, bb_basename(cmdline_buf)); /* "PID/argv0" */ |
266 | i = recursive_action(p, ACTION_RECURSE | ACTION_QUIET, | 296 | n = recursive_action(proc_pid_fname, |
267 | file_act, NULL, (void *)q, 0); | 297 | ACTION_RECURSE | ACTION_QUIET, |
268 | 298 | add_to_prg_cache_if_socket, | |
269 | free(p); | 299 | NULL, |
270 | free(q); | 300 | (void *)pid_slash_progname, |
271 | 301 | 0); | |
272 | if (!i) | 302 | free(pid_slash_progname); |
273 | return FALSE; /* signal permissions error to caller */ | 303 | |
274 | 304 | if (!n) | |
275 | return SKIP; /* caller should not recurse further into this dir. */ | 305 | return FALSE; /* signal permissions error to caller */ |
306 | |||
307 | return SKIP; /* caller should not recurse further into this dir */ | ||
276 | } | 308 | } |
277 | 309 | ||
278 | static void prg_cache_load(void) | 310 | static void prg_cache_load(void) |
@@ -294,7 +326,6 @@ static void prg_cache_load(void) | |||
294 | #else | 326 | #else |
295 | 327 | ||
296 | #define prg_cache_clear() ((void)0) | 328 | #define prg_cache_clear() ((void)0) |
297 | #define print_progname_banner() ((void)0) | ||
298 | 329 | ||
299 | #endif //ENABLE_FEATURE_NETSTAT_PRG | 330 | #endif //ENABLE_FEATURE_NETSTAT_PRG |
300 | 331 | ||
@@ -364,11 +395,14 @@ struct inet_params { | |||
364 | static int scan_inet_proc_line(struct inet_params *param, char *line) | 395 | static int scan_inet_proc_line(struct inet_params *param, char *line) |
365 | { | 396 | { |
366 | int num; | 397 | int num; |
367 | char local_addr[64], rem_addr[64]; | 398 | /* IPv6 /proc files use 32-char hex representation |
399 | * of IPv6 address, followed by :PORT_IN_HEX | ||
400 | */ | ||
401 | char local_addr[33], rem_addr[33]; /* 32 + 1 for NUL */ | ||
368 | 402 | ||
369 | num = sscanf(line, | 403 | num = sscanf(line, |
370 | "%*d: %64[0-9A-Fa-f]:%X " | 404 | "%*d: %32[0-9A-Fa-f]:%X " |
371 | "%64[0-9A-Fa-f]:%X %X " | 405 | "%32[0-9A-Fa-f]:%X %X " |
372 | "%lX:%lX %*X:%*X " | 406 | "%lX:%lX %*X:%*X " |
373 | "%*X %d %*d %ld ", | 407 | "%*X %d %*d %ld ", |
374 | local_addr, ¶m->local_port, | 408 | local_addr, ¶m->local_port, |
@@ -403,8 +437,11 @@ static void print_inet_line(struct inet_params *param, | |||
403 | char *r = ip_port_str( | 437 | char *r = ip_port_str( |
404 | ¶m->remaddr.sa, param->rem_port, | 438 | ¶m->remaddr.sa, param->rem_port, |
405 | proto, flags & NETSTAT_NUMERIC); | 439 | proto, flags & NETSTAT_NUMERIC); |
406 | printf(net_conn_line, | 440 | printf(FMT_NET_CONN_DATA, |
407 | proto, param->rxq, param->txq, l, r, state_str); | 441 | proto, param->rxq, param->txq, |
442 | IF_FEATURE_NETSTAT_WIDE(G.addr_width,) l, | ||
443 | IF_FEATURE_NETSTAT_WIDE(G.addr_width,) r, | ||
444 | state_str); | ||
408 | #if ENABLE_FEATURE_NETSTAT_PRG | 445 | #if ENABLE_FEATURE_NETSTAT_PRG |
409 | if (option_mask32 & OPT_prg) | 446 | if (option_mask32 & OPT_prg) |
410 | printf("%."PROGNAME_WIDTH_STR"s", prg_cache_get(param->inode)); | 447 | printf("%."PROGNAME_WIDTH_STR"s", prg_cache_get(param->inode)); |
@@ -419,6 +456,7 @@ static int FAST_FUNC tcp_do_one(char *line) | |||
419 | { | 456 | { |
420 | struct inet_params param; | 457 | struct inet_params param; |
421 | 458 | ||
459 | memset(¶m, 0, sizeof(param)); | ||
422 | if (scan_inet_proc_line(¶m, line)) | 460 | if (scan_inet_proc_line(¶m, line)) |
423 | return 1; | 461 | return 1; |
424 | 462 | ||
@@ -446,6 +484,7 @@ static int FAST_FUNC udp_do_one(char *line) | |||
446 | const char *state_str; | 484 | const char *state_str; |
447 | struct inet_params param; | 485 | struct inet_params param; |
448 | 486 | ||
487 | memset(¶m, 0, sizeof(param)); /* otherwise we display garbage IPv6 scope_ids */ | ||
449 | if (scan_inet_proc_line(¶m, line)) | 488 | if (scan_inet_proc_line(¶m, line)) |
450 | return 1; | 489 | return 1; |
451 | 490 | ||
@@ -617,38 +656,39 @@ static void do_info(const char *file, int FAST_FUNC (*proc)(char *)) | |||
617 | int netstat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 656 | int netstat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
618 | int netstat_main(int argc UNUSED_PARAM, char **argv) | 657 | int netstat_main(int argc UNUSED_PARAM, char **argv) |
619 | { | 658 | { |
620 | const char *net_conn_line_header = PRINT_NET_CONN_HEADER; | ||
621 | unsigned opt; | 659 | unsigned opt; |
622 | 660 | ||
623 | INIT_G(); | 661 | INIT_G(); |
624 | 662 | ||
625 | /* Option string must match NETSTAT_xxx constants */ | 663 | /* Option string must match NETSTAT_xxx constants */ |
626 | opt = getopt32(argv, NETSTAT_OPTS); | 664 | opt = getopt32(argv, NETSTAT_OPTS); |
627 | if (opt & 0x1) { // -l | 665 | if (opt & OPT_sock_listen) { // -l |
628 | flags &= ~NETSTAT_CONNECTED; | 666 | flags &= ~NETSTAT_CONNECTED; |
629 | flags |= NETSTAT_LISTENING; | 667 | flags |= NETSTAT_LISTENING; |
630 | } | 668 | } |
631 | if (opt & 0x2) flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED; // -a | 669 | if (opt & OPT_sock_all) flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED; // -a |
632 | //if (opt & 0x4) // -e | 670 | //if (opt & OPT_extended) // -e |
633 | if (opt & 0x8) flags |= NETSTAT_NUMERIC; // -n | 671 | if (opt & OPT_noresolve) flags |= NETSTAT_NUMERIC; // -n |
634 | //if (opt & 0x10) // -t: NETSTAT_TCP | 672 | //if (opt & OPT_sock_tcp) // -t: NETSTAT_TCP |
635 | //if (opt & 0x20) // -u: NETSTAT_UDP | 673 | //if (opt & OPT_sock_udp) // -u: NETSTAT_UDP |
636 | //if (opt & 0x40) // -w: NETSTAT_RAW | 674 | //if (opt & OPT_sock_raw) // -w: NETSTAT_RAW |
637 | //if (opt & 0x80) // -x: NETSTAT_UNIX | 675 | //if (opt & OPT_sock_unix) // -x: NETSTAT_UNIX |
638 | if (opt & OPT_route) { // -r | ||
639 | #if ENABLE_ROUTE | 676 | #if ENABLE_ROUTE |
677 | if (opt & OPT_route) { // -r | ||
640 | bb_displayroutes(flags & NETSTAT_NUMERIC, !(opt & OPT_extended)); | 678 | bb_displayroutes(flags & NETSTAT_NUMERIC, !(opt & OPT_extended)); |
641 | return 0; | 679 | return 0; |
642 | #else | ||
643 | bb_show_usage(); | ||
644 | #endif | ||
645 | } | 680 | } |
681 | #endif | ||
682 | #if ENABLE_FEATURE_NETSTAT_WIDE | ||
683 | G.addr_width = ADDR_NORMAL_WIDTH; | ||
646 | if (opt & OPT_wide) { // -W | 684 | if (opt & OPT_wide) { // -W |
647 | net_conn_line = PRINT_NET_CONN_WIDE; | 685 | G.addr_width = ADDR_WIDE; |
648 | net_conn_line_header = PRINT_NET_CONN_HEADER_WIDE; | ||
649 | } | 686 | } |
687 | #endif | ||
650 | #if ENABLE_FEATURE_NETSTAT_PRG | 688 | #if ENABLE_FEATURE_NETSTAT_PRG |
689 | progname_banner = ""; | ||
651 | if (opt & OPT_prg) { // -p | 690 | if (opt & OPT_prg) { // -p |
691 | progname_banner = PROGNAME_BANNER; | ||
652 | prg_cache_load(); | 692 | prg_cache_load(); |
653 | } | 693 | } |
654 | #endif | 694 | #endif |
@@ -667,9 +707,11 @@ int netstat_main(int argc UNUSED_PARAM, char **argv) | |||
667 | printf("(only servers)"); | 707 | printf("(only servers)"); |
668 | else | 708 | else |
669 | printf("(w/o servers)"); | 709 | printf("(w/o servers)"); |
670 | printf(net_conn_line_header, "Local Address", "Foreign Address"); | 710 | printf(FMT_NET_CONN_HEADER, |
671 | print_progname_banner(); | 711 | IF_FEATURE_NETSTAT_WIDE(G.addr_width,) "Local Address", |
672 | bb_putchar('\n'); | 712 | IF_FEATURE_NETSTAT_WIDE(G.addr_width,) "Foreign Address", |
713 | progname_banner | ||
714 | ); | ||
673 | } | 715 | } |
674 | if (flags & NETSTAT_TCP) { | 716 | if (flags & NETSTAT_TCP) { |
675 | do_info("/proc/net/tcp", tcp_do_one); | 717 | do_info("/proc/net/tcp", tcp_do_one); |
@@ -697,9 +739,7 @@ int netstat_main(int argc UNUSED_PARAM, char **argv) | |||
697 | printf("(only servers)"); | 739 | printf("(only servers)"); |
698 | else | 740 | else |
699 | printf("(w/o servers)"); | 741 | printf("(w/o servers)"); |
700 | printf("\nProto RefCnt Flags Type State I-Node "); | 742 | printf("\nProto RefCnt Flags Type State I-Node %sPath\n", progname_banner); |
701 | print_progname_banner(); | ||
702 | printf("Path\n"); | ||
703 | do_info("/proc/net/unix", unix_do_one); | 743 | do_info("/proc/net/unix", unix_do_one); |
704 | } | 744 | } |
705 | prg_cache_clear(); | 745 | prg_cache_clear(); |