2
* netstat This file contains an implementation of the command
3
* that helps in debugging the networking modules.
5
* NET-TOOLS A collection of programs that form the base set of the
6
* NET-3 Networking Distribution for the LINUX operating
9
* Version: $Id: netstat.c,v 1.54 2007/12/01 18:12:34 ecki Exp $
11
* Authors: Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
12
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
13
* Phil Packer, <pep@wicked.demon.co.uk>
14
* Johannes Stille, <johannes@titan.os.open.de>
15
* Bernd Eckenfels, <net-tools@lina.inka.de>
16
* Phil Blundell <philb@gnu.org>
17
* Tuan Hoang <tqhoang@bigfoot.com>
20
* Alan Cox, <A.Cox@swansea.ac.uk>
21
* Copyright (c) 1993 Fred Baumgarten
25
*960116 {1.01} Bernd Eckenfels: verbose, cleanups
26
*960204 {1.10} Bernd Eckenfels: aftrans, usage, new route_info,
28
*960204 {1.11} Bernd Eckenfels: netlink support
29
*960204 {1.12} Bernd Eckenfels: route_init()
30
*960215 {1.13} Bernd Eckenfels: netlink_print honors HAVE_
31
*960217 {1.14} Bernd Eckenfels: masq_info from Jos Vos and
32
* ax25_info from Jonathan Naylor.
33
*960218 {1.15} Bernd Eckenfels: ipx_info rewritten, -e for tcp/ipx
34
*960220 {1.16} Bernd Eckenfels: minor output reformats, -a for -x
35
*960221 {1.17} Bernd Eckenfels: route_init->getroute_init
36
*960426 {1.18} Bernd Eckenfels: new RTACTION, SYM/NUM, FIB/CACHE
37
*960517 {1.19} Bernd Eckenfels: usage() spelling fix and --unix inode,
38
* ':' is part of sock_addr for --inet
39
*960822 {x.xx} Frank Strauss: INET6 support
41
*970406 {1.33} Philip Copeland Added snmp reporting support module -s
42
* code provided by Andi Kleen
43
* (relly needs to be kernel hooked but
44
* this will do in the meantime)
45
* minor header file misplacement tidy up.
46
*980815 {1.xx} Stephane Fillod: X.25 support
47
*980411 {1.34} Arnaldo Carvalho i18n: catgets -> gnu gettext, substitution
48
* of sprintf for snprintf
49
*10/1998 Andi Kleen Use new interface primitives.
50
*990101 {1.36} Bernd Eckenfels usage updated to include -s and -C -F,
51
* fixed netstat -rC output (lib/inet_gr.c)
52
* removed broken NETLINK Support
53
* fixed format for /proc/net/udp|tcp|raw
54
* added -w,-t,-u TcpExt support to -s
55
*990131 {1.37} Jan Kratochvil added -p for prg_cache() & friends
56
* Flames to <short@ucw.cz>.
57
* Tuan Hoang added IGMP support for IPv4 and IPv6
59
*990420 {1.38} Tuan Hoang removed a useless assignment from igmp_do_one()
60
*20010404 {1.39} Arnaldo Carvalho de Melo - use setlocale
62
* This program is free software; you can redistribute it
63
* and/or modify it under the terms of the GNU General
64
* Public License as published by the Free Software
65
* Foundation; either version 2 of the License, or (at
66
* your option) any later version.
81
#include <sys/param.h>
82
#include <sys/socket.h>
83
#include <arpa/inet.h>
84
#include <netinet/in.h>
85
#include <sys/ioctl.h>
89
#include "net-support.h"
90
#include "pathnames.h"
95
#include "interface.h"
98
#define PROGNAME_WIDTH 20
100
#if !defined(s6_addr32) && defined(in6a_words)
101
#define s6_addr32 in6a_words /* libinet6 */
104
/* prototypes for statistics.c */
105
void parsesnmp(int, int, int);
109
SS_FREE = 0, /* not allocated */
110
SS_UNCONNECTED, /* unconnected to any socket */
111
SS_CONNECTING, /* in process of connecting */
112
SS_CONNECTED, /* connected to socket */
113
SS_DISCONNECTING /* in process of disconnecting */
116
#define SO_ACCEPTCON (1<<16) /* performed a listen */
117
#define SO_WAITDATA (1<<17) /* wait data to read */
118
#define SO_NOSPACE (1<<18) /* no space to write */
120
#define DFLT_AF "inet"
122
#define FEATURE_NETSTAT
123
#include "lib/net-features.h"
125
char *Release = RELEASE, *Version = "netstat 1.42 (2001-04-15)", *Signature = "Fred Baumgarten, Alan Cox, Bernd Eckenfels, Phil Blundell, Tuan Hoang and others";
155
#define INFO_GUTS1(file,name,proc) \
156
procinfo = fopen((file), "r"); \
157
if (procinfo == NULL) { \
158
if (errno != ENOENT) { \
162
if (flag_arg || flag_ver) \
163
ESYSNOT("netstat", (name)); \
168
if (fgets(buffer, sizeof(buffer), procinfo)) \
169
(proc)(lnr++, buffer); \
170
} while (!feof(procinfo)); \
175
#define INFO_GUTS2(file,proc) \
177
procinfo = fopen((file), "r"); \
178
if (procinfo != NULL) { \
180
if (fgets(buffer, sizeof(buffer), procinfo)) \
181
(proc)(lnr++, buffer); \
182
} while (!feof(procinfo)); \
186
#define INFO_GUTS2(file,proc)
192
#define INFO_GUTS6(file,file6,name,proc) \
196
if (!flag_arg || flag_inet) { \
197
INFO_GUTS1(file,name,proc) \
199
if (!flag_arg || flag_inet6) { \
200
INFO_GUTS2(file6,proc) \
204
#define INFO_GUTS(file,name,proc) \
208
INFO_GUTS1(file,name,proc) \
211
#define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)
212
#define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)
213
#define PROGNAME_WIDTH2(s) #s
215
#define PRG_HASH_SIZE 211
217
static struct prg_node {
218
struct prg_node *next;
220
char name[PROGNAME_WIDTH];
221
} *prg_hash[PRG_HASH_SIZE];
223
static char prg_cache_loaded = 0;
225
#define PRG_HASHIT(x) ((x) % PRG_HASH_SIZE)
227
#define PROGNAME_BANNER "PID/Program name"
229
#define print_progname_banner() do { if (flag_prg) printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER); } while (0)
231
#define PRG_LOCAL_ADDRESS "local_address"
232
#define PRG_INODE "inode"
233
#define PRG_SOCKET_PFX "socket:["
234
#define PRG_SOCKET_PFXl (strlen(PRG_SOCKET_PFX))
235
#define PRG_SOCKET_PFX2 "[0000]:"
236
#define PRG_SOCKET_PFX2l (strlen(PRG_SOCKET_PFX2))
240
#define LINE_MAX 4096
243
#define PATH_PROC "/proc"
244
#define PATH_FD_SUFF "fd"
245
#define PATH_FD_SUFFl strlen(PATH_FD_SUFF)
246
#define PATH_PROC_X_FD PATH_PROC "/%s/" PATH_FD_SUFF
247
#define PATH_CMDLINE "cmdline"
248
#define PATH_CMDLINEl strlen(PATH_CMDLINE)
249
/* NOT working as of glibc-2.0.7: */
250
#undef DIRENT_HAVE_D_TYPE_WORKS
252
static void prg_cache_add(unsigned long inode, char *name)
254
unsigned hi = PRG_HASHIT(inode);
255
struct prg_node **pnp,*pn;
258
for (pnp=prg_hash+hi;(pn=*pnp);pnp=&pn->next) {
259
if (pn->inode==inode) {
260
/* Some warning should be appropriate here
261
as we got multiple processes for one i-node */
265
if (!(*pnp=malloc(sizeof(**pnp))))
270
if (strlen(name)>sizeof(pn->name)-1)
271
name[sizeof(pn->name)-1]='\0';
272
strcpy(pn->name,name);
275
static const char *prg_cache_get(unsigned long inode)
277
unsigned hi=PRG_HASHIT(inode);
280
for (pn=prg_hash[hi];pn;pn=pn->next)
281
if (pn->inode==inode) return(pn->name);
285
static void prg_cache_clear(void)
287
struct prg_node **pnp,*pn;
289
if (prg_cache_loaded == 2)
290
for (pnp=prg_hash;pnp<prg_hash+PRG_HASH_SIZE;pnp++)
298
static int extract_type_1_socket_inode(const char lname[], unsigned long * inode_p) {
300
/* If lname is of the form "socket:[12345]", extract the "12345"
301
as *inode_p. Otherwise, return -1 as *inode_p.
304
if (strlen(lname) < PRG_SOCKET_PFXl+3) return(-1);
306
if (memcmp(lname, PRG_SOCKET_PFX, PRG_SOCKET_PFXl)) return(-1);
307
if (lname[strlen(lname)-1] != ']') return(-1);
310
char inode_str[strlen(lname + 1)]; /* e.g. "12345" */
311
const int inode_str_len = strlen(lname) - PRG_SOCKET_PFXl - 1;
314
strncpy(inode_str, lname+PRG_SOCKET_PFXl, inode_str_len);
315
inode_str[inode_str_len] = '\0';
316
*inode_p = strtol(inode_str,&serr,0);
317
if (!serr || *serr || *inode_p < 0 || *inode_p >= INT_MAX)
325
static int extract_type_2_socket_inode(const char lname[], unsigned long * inode_p) {
327
/* If lname is of the form "[0000]:12345", extract the "12345"
328
as *inode_p. Otherwise, return -1 as *inode_p.
331
if (strlen(lname) < PRG_SOCKET_PFX2l+1) return(-1);
332
if (memcmp(lname, PRG_SOCKET_PFX2, PRG_SOCKET_PFX2l)) return(-1);
337
*inode_p=strtol(lname + PRG_SOCKET_PFX2l,&serr,0);
338
if (!serr || *serr || *inode_p < 0 || *inode_p >= INT_MAX)
347
static void prg_cache_load(void)
349
char line[LINE_MAX],eacces=0;
350
int procfdlen,fd,cmdllen,lnamelen;
351
char lname[30],cmdlbuf[512],finbuf[PROGNAME_WIDTH];
353
const char *cs,*cmdlp;
354
DIR *dirproc=NULL,*dirfd=NULL;
355
struct dirent *direproc,*direfd;
357
if (prg_cache_loaded || !flag_prg) return;
359
cmdlbuf[sizeof(cmdlbuf)-1]='\0';
360
if (!(dirproc=opendir(PATH_PROC))) goto fail;
361
while (errno=0,direproc=readdir(dirproc)) {
362
#ifdef DIRENT_HAVE_D_TYPE_WORKS
363
if (direproc->d_type!=DT_DIR) continue;
365
for (cs=direproc->d_name;*cs;cs++)
370
procfdlen=snprintf(line,sizeof(line),PATH_PROC_X_FD,direproc->d_name);
371
if (procfdlen<=0 || procfdlen>=sizeof(line)-5)
380
line[procfdlen] = '/';
382
while ((direfd = readdir(dirfd))) {
383
#ifdef DIRENT_HAVE_D_TYPE_WORKS
384
if (direfd->d_type!=DT_LNK)
387
if (procfdlen+1+strlen(direfd->d_name)+1>sizeof(line))
389
memcpy(line + procfdlen - PATH_FD_SUFFl, PATH_FD_SUFF "/",
391
strcpy(line + procfdlen + 1, direfd->d_name);
392
lnamelen=readlink(line,lname,sizeof(lname)-1);
393
lname[lnamelen] = '\0'; /*make it a null-terminated string*/
395
if (extract_type_1_socket_inode(lname, &inode) < 0)
396
if (extract_type_2_socket_inode(lname, &inode) < 0)
400
if (procfdlen - PATH_FD_SUFFl + PATH_CMDLINEl >=
403
strcpy(line + procfdlen-PATH_FD_SUFFl, PATH_CMDLINE);
404
fd = open(line, O_RDONLY);
407
cmdllen = read(fd, cmdlbuf, sizeof(cmdlbuf) - 1);
412
if (cmdllen < sizeof(cmdlbuf) - 1)
413
cmdlbuf[cmdllen]='\0';
414
if ((cmdlp = strrchr(cmdlbuf, '/')))
420
snprintf(finbuf, sizeof(finbuf), "%s/%s", direproc->d_name, cmdlp);
421
prg_cache_add(inode, finbuf);
432
if (prg_cache_loaded == 1) {
434
fprintf(stderr,_("(No info could be read for \"-p\": geteuid()=%d but you should be root.)\n"),
438
fprintf(stderr, _("(Not all processes could be identified, non-owned process info\n"
439
" will not be shown, you would have to be root to see it all.)\n"));
443
static const char *netrom_state[] =
451
static int netrom_info(void)
454
char buffer[256], dev[16];
455
int st, vs, vr, sendq, recvq, ret;
457
f = fopen(_PATH_PROCNET_NR, "r");
459
if (errno != ENOENT) {
460
perror(_PATH_PROCNET_NR);
463
if (flag_arg || flag_ver)
464
ESYSNOT("netstat", "AF NETROM");
470
printf(_("Active NET/ROM sockets\n"));
471
printf(_("User Dest Source Device State Vr/Vs Send-Q Recv-Q\n"));
472
fgets(buffer, 256, f);
474
while (fgets(buffer, 256, f)) {
478
ret = sscanf(buffer + 30, "%s %*x/%*x %*x/%*x %d %d %d %*d %*d/%*d %*d/%*d %*d/%*d %*d/%*d %*d/%*d %*d %d %d %*d",
479
dev, &st, &vs, &vr, &sendq, &recvq);
481
printf(_("Problem reading data from %s\n"), _PATH_PROCNET_NR);
484
printf("%-9s %-9s %-9s %-6s %-11s %03d/%03d %-6d %-6d\n",
485
buffer, buffer + 10, buffer + 20,
488
vr, vs, sendq, recvq);
495
/* These enums are used by IPX too. :-( */
507
TCP_CLOSING /* now a valid state */
510
#if HAVE_AFINET || HAVE_AFINET6
512
static const char *tcp_state[] =
528
static void finish_this_one(int uid, unsigned long inode, const char *timers)
533
if (!(flag_not & FLAG_NUM_USER) && ((pw = getpwuid(uid)) != NULL))
534
printf(" %-10s ", pw->pw_name);
536
printf(" %-10d ", uid);
537
printf("%-10lu ",inode);
540
printf("%-" PROGNAME_WIDTHs "s",prg_cache_get(inode));
542
printf("%s", timers);
546
static void igmp_do_one(int lnr, const char *line)
548
char mcast_addr[128];
550
struct sockaddr_in6 mcastaddr;
551
char addr6[INET6_ADDRSTRLEN];
553
extern struct aftype inet6_aftype;
555
struct sockaddr_in mcastaddr;
558
static int idx_flag = 0;
559
static int igmp6_flag = 0;
560
static char device[16];
561
int num, idx, refcnt;
565
/* igmp6 file does not have any comments on first line */
566
if ( strstr( line, "Device" ) == NULL ) {
570
/* 2.1.x kernels and up have Idx field */
571
/* 2.0.x and below do not have Idx field */
572
if ( strncmp( line, "Idx", strlen("Idx") ) == 0 )
580
if (igmp6_flag) { /* IPV6 */
582
num = sscanf( line, "%d %15s %64[0-9A-Fa-f] %d", &idx, device, mcast_addr, &refcnt );
584
/* Demangle what the kernel gives us */
585
sscanf(mcast_addr, "%08X%08X%08X%08X",
586
&in6.s6_addr32[0], &in6.s6_addr32[1],
587
&in6.s6_addr32[2], &in6.s6_addr32[3]);
588
in6.s6_addr32[0] = htonl(in6.s6_addr32[0]);
589
in6.s6_addr32[1] = htonl(in6.s6_addr32[1]);
590
in6.s6_addr32[2] = htonl(in6.s6_addr32[2]);
591
in6.s6_addr32[3] = htonl(in6.s6_addr32[3]);
592
inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
593
inet6_aftype.input(1, addr6, (struct sockaddr *) &mcastaddr);
594
mcastaddr.sin6_family = AF_INET6;
596
fprintf(stderr, _("warning, got bogus igmp6 line %d.\n"), lnr);
600
if ((ap = get_afntype(((struct sockaddr *) &mcastaddr)->sa_family)) == NULL) {
601
fprintf(stderr, _("netstat: unsupported address family %d !\n"),
602
((struct sockaddr *) &mcastaddr)->sa_family);
605
safe_strncpy(mcast_addr, ap->sprint((struct sockaddr *) &mcastaddr,
606
flag_not), sizeof(mcast_addr));
607
printf("%-15s %-6d %s\n", device, refcnt, mcast_addr);
611
if (line[0] != '\t') {
613
if ((num = sscanf( line, "%d\t%10c", &idx, device)) < 2) {
614
fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
618
if ( (num = sscanf( line, "%10c", device )) < 1 ) {
619
fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
625
} else if ( line[0] == '\t' ) {
626
if ( (num = sscanf(line, "\t%8[0-9A-Fa-f] %d", mcast_addr, &refcnt)) < 2 ) {
627
fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
630
sscanf( mcast_addr, "%X",
631
&((struct sockaddr_in *) &mcastaddr)->sin_addr.s_addr );
632
((struct sockaddr *) &mcastaddr)->sa_family = AF_INET;
634
fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
638
if ((ap = get_afntype(((struct sockaddr *) &mcastaddr)->sa_family)) == NULL) {
639
fprintf(stderr, _("netstat: unsupported address family %d !\n"),
640
((struct sockaddr *) &mcastaddr)->sa_family);
643
safe_strncpy(mcast_addr, ap->sprint((struct sockaddr *) &mcastaddr,
644
flag_not), sizeof(mcast_addr));
645
printf("%-15s %-6d %s\n", device, refcnt, mcast_addr );
651
static int x25_info(void)
653
FILE *f=fopen(_PATH_PROCNET_X25, "r");
654
char buffer[256],dev[16];
655
int st,vs,vr,sendq,recvq,lci;
656
static char *x25_state[5]=
664
if(!(f=fopen(_PATH_PROCNET_X25, "r")))
666
if (errno != ENOENT) {
667
perror(_PATH_PROCNET_X25);
670
if (flag_arg || flag_ver)
671
ESYSNOT("netstat","AF X25");
677
printf( _("Active X.25 sockets\n"));
678
/* IMHO, Vr/Vs is not very usefull --SF */
679
printf( _("Dest Source Device LCI State Vr/Vs Send-Q Recv-Q\n"));
681
while(fgets(buffer,256,f))
685
sscanf(buffer+22,"%s %d %d %d %d %*d %*d %*d %*d %*d %*d %d %d %*d",
686
dev,&lci,&st,&vs,&vr,&sendq,&recvq);
687
if (!(flag_all || lci))
689
printf("%-15s %-15s %-7s %-3d %-11s %02d/%02d %-6d %-6d\n",
701
static int igmp_info(void)
703
INFO_GUTS6(_PATH_PROCNET_IGMP, _PATH_PROCNET_IGMP6, "AF INET (igmp)",
707
static void tcp_do_one(int lnr, const char *line)
709
unsigned long rxq, txq, time_len, retr, inode;
710
int num, local_port, rem_port, d, state, uid, timer_run, timeout;
711
char rem_addr[128], local_addr[128], timers[64], buffer[1024], more[512];
715
struct sockaddr_in6 localaddr, remaddr;
716
char addr6[INET6_ADDRSTRLEN];
718
extern struct aftype inet6_aftype;
720
struct sockaddr_in localaddr, remaddr;
727
"%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %512s\n",
728
&d, local_addr, &local_port, rem_addr, &rem_port, &state,
729
&txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
731
if (strlen(local_addr) > 8) {
734
/* Demangle what the kernel gives us */
735
sscanf(local_addr, "%08X%08X%08X%08X",
736
&in6.s6_addr32[0], &in6.s6_addr32[1],
737
&in6.s6_addr32[2], &in6.s6_addr32[3]);
738
inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
739
inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
740
sscanf(rem_addr, "%08X%08X%08X%08X",
741
&in6.s6_addr32[0], &in6.s6_addr32[1],
742
&in6.s6_addr32[2], &in6.s6_addr32[3]);
743
inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
744
inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
745
localaddr.sin6_family = AF_INET6;
746
remaddr.sin6_family = AF_INET6;
750
sscanf(local_addr, "%X",
751
&((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
752
sscanf(rem_addr, "%X",
753
&((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
754
((struct sockaddr *) &localaddr)->sa_family = AF_INET;
755
((struct sockaddr *) &remaddr)->sa_family = AF_INET;
759
fprintf(stderr, _("warning, got bogus tcp line.\n"));
762
if ((ap = get_afntype(((struct sockaddr *) &localaddr)->sa_family)) == NULL) {
763
fprintf(stderr, _("netstat: unsupported address family %d !\n"),
764
((struct sockaddr *) &localaddr)->sa_family);
767
if (state == TCP_LISTEN) {
773
safe_strncpy(local_addr, ap->sprint((struct sockaddr *) &localaddr,
774
flag_not), sizeof(local_addr));
775
safe_strncpy(rem_addr, ap->sprint((struct sockaddr *) &remaddr, flag_not),
777
if (flag_all || (flag_lst && !rem_port) || (!flag_lst && rem_port)) {
778
snprintf(buffer, sizeof(buffer), "%s",
779
get_sname(htons(local_port), "tcp",
780
flag_not & FLAG_NUM_PORT));
782
if ((strlen(local_addr) + strlen(buffer)) > 22)
783
local_addr[22 - strlen(buffer)] = '\0';
785
strcat(local_addr, ":");
786
strcat(local_addr, buffer);
787
snprintf(buffer, sizeof(buffer), "%s",
788
get_sname(htons(rem_port), "tcp", flag_not & FLAG_NUM_PORT));
790
if ((strlen(rem_addr) + strlen(buffer)) > 22)
791
rem_addr[22 - strlen(buffer)] = '\0';
793
strcat(rem_addr, ":");
794
strcat(rem_addr, buffer);
800
snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
804
snprintf(timers, sizeof(timers), _("on (%2.2f/%ld/%d)"),
805
(double) time_len / HZ, retr, timeout);
809
snprintf(timers, sizeof(timers), _("keepalive (%2.2f/%ld/%d)"),
810
(double) time_len / HZ, retr, timeout);
814
snprintf(timers, sizeof(timers), _("timewait (%2.2f/%ld/%d)"),
815
(double) time_len / HZ, retr, timeout);
819
snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
820
timer_run, (double) time_len / HZ, retr, timeout);
823
printf("%-4s %6ld %6ld %-*s %-*s %-11s",
824
protname, rxq, txq, netmax(23,strlen(local_addr)), local_addr, netmax(23,strlen(rem_addr)), rem_addr, _(tcp_state[state]));
826
finish_this_one(uid,inode,timers);
830
static int tcp_info(void)
832
INFO_GUTS6(_PATH_PROCNET_TCP, _PATH_PROCNET_TCP6, "AF INET (tcp)",
836
static void udp_do_one(int lnr, const char *line)
838
char buffer[8192], local_addr[64], rem_addr[64];
839
char *udp_state, timers[64], more[512];
840
int num, local_port, rem_port, d, state, timer_run, uid, timeout;
843
struct sockaddr_in6 localaddr, remaddr;
844
char addr6[INET6_ADDRSTRLEN];
846
extern struct aftype inet6_aftype;
848
struct sockaddr_in localaddr, remaddr;
851
unsigned long rxq, txq, time_len, retr, inode;
858
"%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %512s\n",
859
&d, local_addr, &local_port,
860
rem_addr, &rem_port, &state,
861
&txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
863
if (strlen(local_addr) > 8) {
866
sscanf(local_addr, "%08X%08X%08X%08X",
867
&in6.s6_addr32[0], &in6.s6_addr32[1],
868
&in6.s6_addr32[2], &in6.s6_addr32[3]);
869
inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
870
inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
871
sscanf(rem_addr, "%08X%08X%08X%08X",
872
&in6.s6_addr32[0], &in6.s6_addr32[1],
873
&in6.s6_addr32[2], &in6.s6_addr32[3]);
874
inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
875
inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
876
localaddr.sin6_family = AF_INET6;
877
remaddr.sin6_family = AF_INET6;
881
sscanf(local_addr, "%X",
882
&((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
883
sscanf(rem_addr, "%X",
884
&((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
885
((struct sockaddr *) &localaddr)->sa_family = AF_INET;
886
((struct sockaddr *) &remaddr)->sa_family = AF_INET;
894
fprintf(stderr, _("warning, got bogus udp line.\n"));
897
if ((ap = get_afntype(((struct sockaddr *) &localaddr)->sa_family)) == NULL) {
898
fprintf(stderr, _("netstat: unsupported address family %d !\n"),
899
((struct sockaddr *) &localaddr)->sa_family);
903
case TCP_ESTABLISHED:
904
udp_state = _("ESTABLISHED");
912
udp_state = _("UNKNOWN");
917
#define notnull(A) (((A.sin6_family == AF_INET6) && \
918
((A.sin6_addr.s6_addr32[0]) || \
919
(A.sin6_addr.s6_addr32[1]) || \
920
(A.sin6_addr.s6_addr32[2]) || \
921
(A.sin6_addr.s6_addr32[3]))) || \
922
((A.sin6_family == AF_INET) && \
923
((struct sockaddr_in *) &A)->sin_addr.s_addr))
925
#define notnull(A) (A.sin_addr.s_addr)
928
if (flag_all || (notnull(remaddr) && !flag_lst) || (!notnull(remaddr) && flag_lst))
930
safe_strncpy(local_addr, ap->sprint((struct sockaddr *) &localaddr,
931
flag_not), sizeof(local_addr));
932
snprintf(buffer, sizeof(buffer), "%s",
933
get_sname(htons(local_port), "udp",
934
flag_not & FLAG_NUM_PORT));
936
if ((strlen(local_addr) + strlen(buffer)) > 22)
937
local_addr[22 - strlen(buffer)] = '\0';
939
strcat(local_addr, ":");
940
strcat(local_addr, buffer);
942
snprintf(buffer, sizeof(buffer), "%s",
943
get_sname(htons(rem_port), "udp", flag_not & FLAG_NUM_PORT));
944
safe_strncpy(rem_addr, ap->sprint((struct sockaddr *) &remaddr,
945
flag_not), sizeof(rem_addr));
947
if ((strlen(rem_addr) + strlen(buffer)) > 22)
948
rem_addr[22 - strlen(buffer)] = '\0';
950
strcat(rem_addr, ":");
951
strcat(rem_addr, buffer);
957
snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
962
snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100, retr, timeout);
966
snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
970
printf("%-4s %6ld %6ld %-23s %-23s %-11s",
971
protname, rxq, txq, local_addr, rem_addr, udp_state);
973
finish_this_one(uid,inode,timers);
977
static int udp_info(void)
979
INFO_GUTS6(_PATH_PROCNET_UDP, _PATH_PROCNET_UDP6, "AF INET (udp)",
983
static void raw_do_one(int lnr, const char *line)
985
char buffer[8192], local_addr[64], rem_addr[64];
986
char timers[64], more[512];
987
int num, local_port, rem_port, d, state, timer_run, uid, timeout;
990
struct sockaddr_in6 localaddr, remaddr;
991
char addr6[INET6_ADDRSTRLEN];
993
extern struct aftype inet6_aftype;
995
struct sockaddr_in localaddr, remaddr;
998
unsigned long rxq, txq, time_len, retr, inode;
1005
"%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %512s\n",
1006
&d, local_addr, &local_port, rem_addr, &rem_port, &state,
1007
&txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
1009
if (strlen(local_addr) > 8) {
1012
sscanf(local_addr, "%08X%08X%08X%08X",
1013
&in6.s6_addr32[0], &in6.s6_addr32[1],
1014
&in6.s6_addr32[2], &in6.s6_addr32[3]);
1015
inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1016
inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
1017
sscanf(rem_addr, "%08X%08X%08X%08X",
1018
&in6.s6_addr32[0], &in6.s6_addr32[1],
1019
&in6.s6_addr32[2], &in6.s6_addr32[3]);
1020
inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1021
inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
1022
localaddr.sin6_family = AF_INET6;
1023
remaddr.sin6_family = AF_INET6;
1027
sscanf(local_addr, "%X",
1028
&((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
1029
sscanf(rem_addr, "%X",
1030
&((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
1031
((struct sockaddr *) &localaddr)->sa_family = AF_INET;
1032
((struct sockaddr *) &remaddr)->sa_family = AF_INET;
1035
if ((ap = get_afntype(localaddr.sin6_family)) == NULL) {
1036
fprintf(stderr, _("netstat: unsupported address family %d !\n"), localaddr.sin6_family);
1040
if ((ap = get_afntype(localaddr.sin_family)) == NULL) {
1041
fprintf(stderr, _("netstat: unsupported address family %d !\n"), localaddr.sin_family);
1050
fprintf(stderr, _("warning, got bogus raw line.\n"));
1054
if (flag_all || (notnull(remaddr) && !flag_lst) || (!notnull(remaddr) && flag_lst))
1056
snprintf(buffer, sizeof(buffer), "%s",
1057
get_sname(htons(local_port), "raw",
1058
flag_not & FLAG_NUM_PORT));
1059
safe_strncpy(local_addr, ap->sprint((struct sockaddr *) &localaddr,
1060
flag_not), sizeof(local_addr));
1062
if ((strlen(local_addr) + strlen(buffer)) > 22)
1063
local_addr[22 - strlen(buffer)] = '\0';
1065
strcat(local_addr, ":");
1066
strcat(local_addr, buffer);
1068
snprintf(buffer, sizeof(buffer), "%s",
1069
get_sname(htons(rem_port), "raw", flag_not & FLAG_NUM_PORT));
1070
safe_strncpy(rem_addr, ap->sprint((struct sockaddr *) &remaddr,
1071
flag_not), sizeof(rem_addr));
1073
if ((strlen(rem_addr) + strlen(buffer)) > 22)
1074
rem_addr[22 - strlen(buffer)] = '\0';
1076
strcat(rem_addr, ":");
1077
strcat(rem_addr, buffer);
1081
switch (timer_run) {
1083
snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
1088
snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
1093
snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
1094
timer_run, (double) time_len / 100,
1098
printf("%-4s %6ld %6ld %-23s %-23s %-11d",
1099
protname, rxq, txq, local_addr, rem_addr, state);
1101
finish_this_one(uid,inode,timers);
1105
static int raw_info(void)
1107
INFO_GUTS6(_PATH_PROCNET_RAW, _PATH_PROCNET_RAW6, "AF INET (raw)",
1118
static void unix_do_one(int nr, const char *line)
1121
char path[MAXPATHLEN], ss_flags[32];
1122
char *ss_proto, *ss_state, *ss_type;
1123
int num, state, type;
1125
unsigned long refcnt, proto, flags, inode;
1128
if (strstr(line, "Inode"))
1133
num = sscanf(line, "%p: %lX %lX %lX %X %X %lu %s",
1134
&d, &refcnt, &proto, &flags, &type, &state, &inode, path);
1136
fprintf(stderr, _("warning, got bogus unix line.\n"));
1139
if (!(has & HAS_INODE))
1140
snprintf(path,sizeof(path),"%lu",inode);
1143
if ((state == SS_UNCONNECTED) && (flags & SO_ACCEPTCON)) {
1163
ss_type = _("STREAM");
1167
ss_type = _("DGRAM");
1178
case SOCK_SEQPACKET:
1179
ss_type = _("SEQPACKET");
1183
ss_type = _("UNKNOWN");
1188
ss_state = _("FREE");
1191
case SS_UNCONNECTED:
1193
* Unconnected sockets may be listening
1196
if (flags & SO_ACCEPTCON) {
1197
ss_state = _("LISTENING");
1204
ss_state = _("CONNECTING");
1208
ss_state = _("CONNECTED");
1211
case SS_DISCONNECTING:
1212
ss_state = _("DISCONNECTING");
1216
ss_state = _("UNKNOWN");
1219
strcpy(ss_flags, "[ ");
1220
if (flags & SO_ACCEPTCON)
1221
strcat(ss_flags, "ACC ");
1222
if (flags & SO_WAITDATA)
1223
strcat(ss_flags, "W ");
1224
if (flags & SO_NOSPACE)
1225
strcat(ss_flags, "N ");
1227
strcat(ss_flags, "]");
1229
printf("%-5s %-6ld %-11s %-10s %-13s ",
1230
ss_proto, refcnt, ss_flags, ss_type, ss_state);
1231
if (has & HAS_INODE)
1232
printf("%-8lu ",inode);
1236
printf("%-" PROGNAME_WIDTHs "s",(has & HAS_INODE?prg_cache_get(inode):"-"));
1240
static int unix_info(void)
1243
printf(_("Active UNIX domain sockets "));
1245
printf(_("(servers and established)"));
1248
printf(_("(only servers)"));
1250
printf(_("(w/o servers)"));
1253
printf(_("\nProto RefCnt Flags Type State I-Node"));
1254
print_progname_banner();
1255
printf(_(" Path\n")); /* xxx */
1258
INFO_GUTS(_PATH_PROCNET_UNIX, "AF UNIX", unix_do_one);
1265
static int ax25_info(void)
1268
char buffer[256], buf[16];
1269
char *src, *dst, *dev, *p;
1270
int st, vs, vr, sendq, recvq, ret;
1271
int new = -1; /* flag for new (2.1.x) kernels */
1272
static char *ax25_state[5] =
1280
if (!(f = fopen(_PATH_PROCNET_AX25, "r"))) {
1281
if (errno != ENOENT) {
1282
perror(_PATH_PROCNET_AX25);
1285
if (flag_arg || flag_ver)
1286
ESYSNOT("netstat", "AF AX25");
1292
printf(_("Active AX.25 sockets\n"));
1293
printf(_("Dest Source Device State Vr/Vs Send-Q Recv-Q\n"));
1294
while (fgets(buffer, 256, f)) {
1296
if (!strncmp(buffer, "dest_addr", 9)) {
1298
continue; /* old kernels have a header line */
1303
* In a network connection with no user socket the Snd-Q, Rcv-Q
1304
* and Inode fields are empty in 2.0.x and '*' in 2.1.x
1313
ret = sscanf(buffer + 20, "%s %d %d %d %*d %*d/%*d %*d/%*d %*d/%*d %*d/%*d %*d/%*d %*d %*d %*d %d %d %*d",
1314
buf, &st, &vs, &vr, &sendq, &recvq);
1315
if (ret != 4 && ret != 6) {
1316
printf(_("Problem reading data from %s\n"), _PATH_PROCNET_AX25);
1322
while (*p != ' ') p++;
1325
while (*p != ' ') p++;
1328
while (*p != ' ') p++;
1331
while (*p != ' ') p++;
1333
ret = sscanf(p, "%d %d %d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d %*d",
1334
&st, &vs, &vr, &sendq, &recvq);
1335
if (ret != 3 && ret != 5) {
1336
printf(_("problem reading data from %s\n"), _PATH_PROCNET_AX25);
1340
* FIXME: digipeaters should be handled somehow.
1341
* For now we just strip them.
1344
while (*p && *p != ',') p++;
1347
printf("%-9s %-9s %-6s %-11s %03d/%03d %-6d %-6d\n",
1351
vr, vs, sendq, recvq);
1360
static int ipx_info(void)
1364
unsigned long txq, rxq;
1371
char sad[50], dad[50];
1373
unsigned sport = 0, dport = 0;
1376
f = fopen(_PATH_PROCNET_IPX_SOCKET1, "r");
1378
if (errno != ENOENT) {
1379
perror(_PATH_PROCNET_IPX_SOCKET1);
1382
f = fopen(_PATH_PROCNET_IPX_SOCKET2, "r");
1384
/* We need to check for directory */
1386
fstat(fileno(f), &s);
1387
if (!S_ISREG(s.st_mode)) {
1394
if (errno != ENOENT) {
1395
perror(_PATH_PROCNET_IPX_SOCKET2);
1398
if (flag_arg || flag_ver)
1399
ESYSNOT("netstat", "AF IPX");
1406
printf(_("Active IPX sockets\nProto Recv-Q Send-Q Local Address Foreign Address State")); /* xxx */
1408
printf(_(" User")); /* xxx */
1410
if ((ap = get_afntype(AF_IPX)) == NULL) {
1411
EINTERN("netstat.c", "AF_IPX missing");
1416
while (fgets(buf, 255, f) != NULL) {
1417
sscanf(buf, "%s %s %lX %lX %d %d",
1418
sad, dad, &txq, &rxq, &state, &uid);
1419
if ((st = rindex(sad, ':'))) {
1421
sscanf(st, "%X", &sport); /* net byt order */
1422
sport = ntohs(sport);
1424
EINTERN("netstat.c", "ipx socket format error in source port");
1428
if (strcmp(dad, "Not_Connected") != 0) {
1429
if ((st = rindex(dad, ':'))) {
1431
sscanf(st, "%X", &dport); /* net byt order */
1432
dport = ntohs(dport);
1434
EINTERN("netstat.c", "ipx soket format error in destination port");
1441
case TCP_ESTABLISHED:
1454
/* Fetch and resolve the Source */
1455
(void) ap->input(4, sad, &sa);
1456
safe_strncpy(buf, ap->sprint(&sa, flag_not), sizeof(buf));
1457
snprintf(sad, sizeof(sad), "%s:%04X", buf, sport);
1460
/* Fetch and resolve the Destination */
1461
(void) ap->input(4, dad, &sa);
1462
safe_strncpy(buf, ap->sprint(&sa, flag_not), sizeof(buf));
1463
snprintf(dad, sizeof(dad), "%s:%04X", buf, dport);
1467
printf("IPX %6ld %6ld %-26s %-26s %-5s", txq, rxq, sad, dad, st);
1469
if (!(flag_not & FLAG_NUM_USER) && ((pw = getpwuid(uid)) != NULL))
1470
printf(" %-10s", pw->pw_name);
1472
printf(" %-10d", uid);
1481
static int iface_info(void)
1484
if ((skfd = sockets_open(0)) < 0) {
1488
printf(_("Kernel Interface table\n"));
1492
printf(_("Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg\n"));
1495
if (for_all_interfaces(do_if_print, &flag_all) < 0) {
1496
perror(_("missing interface information"));
1510
static void version(void)
1512
printf("%s\n%s\n%s\n%s\n", Release, Version, Signature, Features);
1517
static void usage(void)
1519
fprintf(stderr, _("usage: netstat [-veenNcCF] [<Af>] -r netstat {-V|--version|-h|--help}\n"));
1520
fprintf(stderr, _(" netstat [-vnNcaeol] [<Socket> ...]\n"));
1521
fprintf(stderr, _(" netstat { [-veenNac] -i | [-cnNe] -M | -s }\n\n"));
1523
fprintf(stderr, _(" -r, --route display routing table\n"));
1524
fprintf(stderr, _(" -i, --interfaces display interface table\n"));
1525
fprintf(stderr, _(" -g, --groups display multicast group memberships\n"));
1526
fprintf(stderr, _(" -s, --statistics display networking statistics (like SNMP)\n"));
1527
#if HAVE_FW_MASQUERADE
1528
fprintf(stderr, _(" -M, --masquerade display masqueraded connections\n\n"));
1530
fprintf(stderr, _(" -v, --verbose be verbose\n"));
1531
fprintf(stderr, _(" -n, --numeric don't resolve names\n"));
1532
fprintf(stderr, _(" --numeric-hosts don't resolve host names\n"));
1533
fprintf(stderr, _(" --numeric-ports don't resolve port names\n"));
1534
fprintf(stderr, _(" --numeric-users don't resolve user names\n"));
1535
fprintf(stderr, _(" -N, --symbolic resolve hardware names\n"));
1536
fprintf(stderr, _(" -e, --extend display other/more information\n"));
1537
fprintf(stderr, _(" -p, --programs display PID/Program name for sockets\n"));
1538
fprintf(stderr, _(" -c, --continuous continuous listing\n\n"));
1539
fprintf(stderr, _(" -l, --listening display listening server sockets\n"));
1540
fprintf(stderr, _(" -a, --all, --listening display all sockets (default: connected)\n"));
1541
fprintf(stderr, _(" -o, --timers display timers\n"));
1542
fprintf(stderr, _(" -F, --fib display Forwarding Information Base (default)\n"));
1543
fprintf(stderr, _(" -C, --cache display routing cache instead of FIB\n\n"));
1545
fprintf(stderr, _(" <Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom\n"));
1546
fprintf(stderr, _(" <AF>=Use '-6|-4' or '-A <af>' or '--<af>'; default: %s\n"), DFLT_AF);
1547
fprintf(stderr, _(" List of possible address families (which support routing):\n"));
1548
print_aflist(1); /* 1 = routeable */
1554
(int argc, char *argv[]) {
1557
static struct option longopts[] =
1560
{"version", 0, 0, 'V'},
1561
{"interfaces", 0, 0, 'i'},
1562
{"help", 0, 0, 'h'},
1563
{"route", 0, 0, 'r'},
1564
#if HAVE_FW_MASQUERADE
1565
{"masquerade", 0, 0, 'M'},
1567
{"protocol", 1, 0, 'A'},
1571
{"unix", 0, 0, 'x'},
1572
{"listening", 0, 0, 'l'},
1574
{"timers", 0, 0, 'o'},
1575
{"continuous", 0, 0, 'c'},
1576
{"extend", 0, 0, 'e'},
1577
{"programs", 0, 0, 'p'},
1578
{"verbose", 0, 0, 'v'},
1579
{"statistics", 0, 0, 's'},
1580
{"numeric", 0, 0, 'n'},
1581
{"numeric-hosts", 0, 0, '!'},
1582
{"numeric-ports", 0, 0, '@'},
1583
{"numeric-users", 0, 0, '#'},
1584
{"symbolic", 0, 0, 'N'},
1585
{"cache", 0, 0, 'C'},
1587
{"groups", 0, 0, 'g'},
1592
setlocale (LC_ALL, "");
1593
bindtextdomain("net-tools", "/usr/share/locale");
1594
textdomain("net-tools");
1596
getroute_init(); /* Set up AF routing support */
1599
while ((i = getopt_long(argc, argv, "MCFA:acdegphinNorstuVv?wxl64", longopts, &lop)) != EOF)
1604
if (lop < 0 || lop >= AFTRANS_CNT) {
1605
EINTERN("netstat.c", "longopts 1 range");
1608
if (aftrans_opt(longopts[lop].name))
1612
if (aftrans_opt(optarg))
1644
flag_not |= FLAG_NUM;
1647
flag_not |= FLAG_NUM_HOST;
1650
flag_not |= FLAG_NUM_PORT;
1653
flag_not |= FLAG_NUM_USER;
1656
flag_not |= FLAG_SYM;
1659
flag_cf |= FLAG_CACHE;
1662
flag_cf |= FLAG_FIB;
1668
if (aftrans_opt("inet6"))
1672
if (aftrans_opt("inet"))
1679
flag_ver |= FLAG_VERBOSE;
1696
if (aftrans_opt("unix"))
1706
if (flag_int + flag_rou + flag_mas + flag_sta > 1)
1709
if ((flag_inet || flag_inet6 || flag_sta) && !(flag_tcp || flag_udp || flag_raw))
1710
flag_tcp = flag_udp = flag_raw = 1;
1712
if ((flag_tcp || flag_udp || flag_raw || flag_igmp) && !(flag_inet || flag_inet6))
1713
flag_inet = flag_inet6 = 1;
1715
flag_arg = flag_tcp + flag_udp + flag_raw + flag_unx + flag_ipx
1716
+ flag_ax25 + flag_netrom + flag_igmp + flag_x25;
1719
#if HAVE_FW_MASQUERADE && HAVE_AFINET
1720
#if MORE_THAN_ONE_MASQ_AF
1722
strcpy(afname, DFLT_AF);
1725
i = ip_masq_info(flag_not & FLAG_NUM_HOST,
1726
flag_not & FLAG_NUM_PORT, flag_exp);
1732
ENOSUPP("netstat.c", "FW_MASQUERADE");
1740
parsesnmp(flag_raw, flag_tcp, flag_udp);
1748
strcpy(afname, DFLT_AF);
1752
else if (flag_exp == 1)
1755
options = (flag_exp & FLAG_EXT) | flag_not | flag_cf | flag_ver;
1757
options |= FLAG_FIB;
1760
i = route_info(afname, options);
1777
if (!flag_arg || flag_tcp || flag_udp || flag_raw) {
1780
printf(_("Active Internet connections ")); /* xxx */
1783
printf(_("(servers and established)"));
1786
printf(_("(only servers)"));
1788
printf(_("(w/o servers)"));
1790
printf(_("\nProto Recv-Q Send-Q Local Address Foreign Address State ")); /* xxx */
1792
printf(_(" User Inode "));
1793
print_progname_banner();
1795
printf(_(" Timer")); /* xxx */
1800
ENOSUPP("netstat", "AF INET");
1805
if (!flag_arg || flag_tcp) {
1810
if (!flag_arg || flag_udp) {
1815
if (!flag_arg || flag_raw) {
1825
printf( _("IPv4 Group Memberships\n") );
1826
printf( _("Interface RefCnt Group\n") );
1827
printf( "--------------- ------ ---------------------\n" );
1834
if (!flag_arg || flag_unx) {
1843
ENOSUPP("netstat", "AF UNIX");
1847
if (!flag_arg || flag_ipx) {
1855
ENOSUPP("netstat", "AF IPX");
1859
if (!flag_arg || flag_ax25) {
1867
ENOSUPP("netstat", "AF AX25");
1871
if(!flag_arg || flag_x25) {
1880
ENOSUPP("netstat", "AF X25");
1884
if (!flag_arg || flag_netrom) {
1892
ENOSUPP("netstat", "AF NETROM");