fixed wording of binary units counters and interpunctuation in netstat(8)
[oss-qm-packages.git] / netstat.c
blobd45477dee385793d8e09c3d6083ad4766b92e450
1 /*
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
7 * system.
9 * Version: $Id: netstat.c,v 1.50 2002/12/10 00:56:41 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>
19 * Tuned for NET3 by:
20 * Alan Cox, <A.Cox@swansea.ac.uk>
21 * Copyright (c) 1993 Fred Baumgarten
23 * Modified:
25 *960116 {1.01} Bernd Eckenfels: verbose, cleanups
26 *960204 {1.10} Bernd Eckenfels: aftrans, usage, new route_info,
27 * DLFT_AF
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.
69 #include <errno.h>
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <strings.h>
74 #include <unistd.h>
75 #include <ctype.h>
76 #include <fcntl.h>
77 #include <netdb.h>
78 #include <paths.h>
79 #include <pwd.h>
80 #include <getopt.h>
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>
86 #include <net/if.h>
87 #include <dirent.h>
89 #include "net-support.h"
90 #include "pathnames.h"
91 #include "version.h"
92 #include "config.h"
93 #include "intl.h"
94 #include "sockets.h"
95 #include "interface.h"
96 #include "util.h"
98 #define PROGNAME_WIDTH 20
100 #if !defined(s6_addr32) && defined(in6a_words)
101 #define s6_addr32 in6a_words /* libinet6 */
102 #endif
104 /* prototypes for statistics.c */
105 void parsesnmp(int, int, int);
106 void inittab(void);
108 typedef enum {
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 */
114 } socket_state;
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";
128 #define E_READ -1
129 #define E_IOCTL -3
131 int flag_int = 0;
132 int flag_rou = 0;
133 int flag_mas = 0;
134 int flag_sta = 0;
136 int flag_all = 0;
137 int flag_lst = 0;
138 int flag_cnt = 0;
139 int flag_deb = 0;
140 int flag_not = 0;
141 int flag_cf = 0;
142 int flag_opt = 0;
143 int flag_raw = 0;
144 int flag_tcp = 0;
145 int flag_udp = 0;
146 int flag_igmp= 0;
147 int flag_rom = 0;
148 int flag_exp = 1;
149 int flag_prg = 0;
150 int flag_arg = 0;
151 int flag_ver = 0;
153 FILE *procinfo;
155 #define INFO_GUTS1(file,name,proc) \
156 procinfo = fopen((file), "r"); \
157 if (procinfo == NULL) { \
158 if (errno != ENOENT) { \
159 perror((file)); \
160 return -1; \
162 if (flag_arg || flag_ver) \
163 ESYSNOT("netstat", (name)); \
164 if (flag_arg) \
165 rc = 1; \
166 } else { \
167 do { \
168 if (fgets(buffer, sizeof(buffer), procinfo)) \
169 (proc)(lnr++, buffer); \
170 } while (!feof(procinfo)); \
171 fclose(procinfo); \
174 #if HAVE_AFINET6
175 #define INFO_GUTS2(file,proc) \
176 lnr = 0; \
177 procinfo = fopen((file), "r"); \
178 if (procinfo != NULL) { \
179 do { \
180 if (fgets(buffer, sizeof(buffer), procinfo)) \
181 (proc)(lnr++, buffer); \
182 } while (!feof(procinfo)); \
183 fclose(procinfo); \
185 #else
186 #define INFO_GUTS2(file,proc)
187 #endif
189 #define INFO_GUTS3 \
190 return rc;
192 #define INFO_GUTS6(file,file6,name,proc) \
193 char buffer[8192]; \
194 int rc = 0; \
195 int lnr = 0; \
196 if (!flag_arg || flag_inet) { \
197 INFO_GUTS1(file,name,proc) \
199 if (!flag_arg || flag_inet6) { \
200 INFO_GUTS2(file6,proc) \
202 INFO_GUTS3
204 #define INFO_GUTS(file,name,proc) \
205 char buffer[8192]; \
206 int rc = 0; \
207 int lnr = 0; \
208 INFO_GUTS1(file,name,proc) \
209 INFO_GUTS3
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;
219 unsigned long inode;
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))
239 #ifndef LINE_MAX
240 #define LINE_MAX 4096
241 #endif
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;
257 prg_cache_loaded=2;
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 */
262 return;
265 if (!(*pnp=malloc(sizeof(**pnp))))
266 return;
267 pn=*pnp;
268 pn->next=NULL;
269 pn->inode=inode;
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);
278 struct prg_node *pn;
280 for (pn=prg_hash[hi];pn;pn=pn->next)
281 if (pn->inode==inode) return(pn->name);
282 return("-");
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++)
291 while ((pn=*pnp)) {
292 *pnp=pn->next;
293 free(pn);
295 prg_cache_loaded=0;
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;
312 char *serr;
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)
318 return(-1);
320 return(0);
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);
335 char *serr;
337 *inode_p=strtol(lname + PRG_SOCKET_PFX2l,&serr,0);
338 if (!serr || *serr || *inode_p < 0 || *inode_p >= INT_MAX)
339 return(-1);
341 return(0);
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];
352 unsigned long inode;
353 const char *cs,*cmdlp;
354 DIR *dirproc=NULL,*dirfd=NULL;
355 struct dirent *direproc,*direfd;
357 if (prg_cache_loaded || !flag_prg) return;
358 prg_cache_loaded=1;
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;
364 #endif
365 for (cs=direproc->d_name;*cs;cs++)
366 if (!isdigit(*cs))
367 break;
368 if (*cs)
369 continue;
370 procfdlen=snprintf(line,sizeof(line),PATH_PROC_X_FD,direproc->d_name);
371 if (procfdlen<=0 || procfdlen>=sizeof(line)-5)
372 continue;
373 errno=0;
374 dirfd=opendir(line);
375 if (! dirfd) {
376 if (errno==EACCES)
377 eacces=1;
378 continue;
380 line[procfdlen] = '/';
381 cmdlp = NULL;
382 while ((direfd = readdir(dirfd))) {
383 #ifdef DIRENT_HAVE_D_TYPE_WORKS
384 if (direfd->d_type!=DT_LNK)
385 continue;
386 #endif
387 if (procfdlen+1+strlen(direfd->d_name)+1>sizeof(line))
388 continue;
389 memcpy(line + procfdlen - PATH_FD_SUFFl, PATH_FD_SUFF "/",
390 PATH_FD_SUFFl+1);
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)
397 continue;
399 if (!cmdlp) {
400 if (procfdlen - PATH_FD_SUFFl + PATH_CMDLINEl >=
401 sizeof(line) - 5)
402 continue;
403 strcpy(line + procfdlen-PATH_FD_SUFFl, PATH_CMDLINE);
404 fd = open(line, O_RDONLY);
405 if (fd < 0)
406 continue;
407 cmdllen = read(fd, cmdlbuf, sizeof(cmdlbuf) - 1);
408 if (close(fd))
409 continue;
410 if (cmdllen == -1)
411 continue;
412 if (cmdllen < sizeof(cmdlbuf) - 1)
413 cmdlbuf[cmdllen]='\0';
414 if ((cmdlp = strrchr(cmdlbuf, '/')))
415 cmdlp++;
416 else
417 cmdlp = cmdlbuf;
420 snprintf(finbuf, sizeof(finbuf), "%s/%s", direproc->d_name, cmdlp);
421 prg_cache_add(inode, finbuf);
423 closedir(dirfd);
424 dirfd = NULL;
426 if (dirproc)
427 closedir(dirproc);
428 if (dirfd)
429 closedir(dirfd);
430 if (!eacces)
431 return;
432 if (prg_cache_loaded == 1) {
433 fail:
434 fprintf(stderr,_("(No info could be read for \"-p\": geteuid()=%d but you should be root.)\n"),
435 geteuid());
437 else
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"));
442 #if HAVE_AFNETROM
443 static const char *netrom_state[] =
445 N_("LISTENING"),
446 N_("CONN SENT"),
447 N_("DISC SENT"),
448 N_("ESTABLISHED")
451 static int netrom_info(void)
453 FILE *f;
454 char buffer[256], dev[16];
455 int st, vs, vr, sendq, recvq, ret;
457 f = fopen(_PATH_PROCNET_NR, "r");
458 if (f == NULL) {
459 if (errno != ENOENT) {
460 perror(_PATH_PROCNET_NR);
461 return (-1);
463 if (flag_arg || flag_ver)
464 ESYSNOT("netstat", "AF NETROM");
465 if (flag_arg)
466 return (1);
467 else
468 return (0);
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)) {
475 buffer[9] = 0;
476 buffer[19] = 0;
477 buffer[29] = 0;
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);
480 if (ret != 6) {
481 printf(_("Problem reading data from %s\n"), _PATH_PROCNET_NR);
482 continue;
484 printf("%-9s %-9s %-9s %-6s %-11s %03d/%03d %-6d %-6d\n",
485 buffer, buffer + 10, buffer + 20,
486 dev,
487 _(netrom_state[st]),
488 vr, vs, sendq, recvq);
490 fclose(f);
491 return 0;
493 #endif
495 /* These enums are used by IPX too. :-( */
496 enum {
497 TCP_ESTABLISHED = 1,
498 TCP_SYN_SENT,
499 TCP_SYN_RECV,
500 TCP_FIN_WAIT1,
501 TCP_FIN_WAIT2,
502 TCP_TIME_WAIT,
503 TCP_CLOSE,
504 TCP_CLOSE_WAIT,
505 TCP_LAST_ACK,
506 TCP_LISTEN,
507 TCP_CLOSING /* now a valid state */
510 #if HAVE_AFINET || HAVE_AFINET6
512 static const char *tcp_state[] =
515 N_("ESTABLISHED"),
516 N_("SYN_SENT"),
517 N_("SYN_RECV"),
518 N_("FIN_WAIT1"),
519 N_("FIN_WAIT2"),
520 N_("TIME_WAIT"),
521 N_("CLOSE"),
522 N_("CLOSE_WAIT"),
523 N_("LAST_ACK"),
524 N_("LISTEN"),
525 N_("CLOSING")
528 static void finish_this_one(int uid, unsigned long inode, const char *timers)
530 struct passwd *pw;
532 if (flag_exp > 1) {
533 if (!(flag_not & FLAG_NUM_USER) && ((pw = getpwuid(uid)) != NULL))
534 printf("%-10s ", pw->pw_name);
535 else
536 printf("%-10d ", uid);
537 printf("%-10lu ",inode);
539 if (flag_prg)
540 printf("%-" PROGNAME_WIDTHs "s",prg_cache_get(inode));
541 if (flag_opt)
542 printf("%s", timers);
543 putchar('\n');
546 static void igmp_do_one(int lnr, const char *line)
548 char mcast_addr[128];
549 #if HAVE_AFINET6
550 struct sockaddr_in6 mcastaddr;
551 char addr6[INET6_ADDRSTRLEN];
552 struct in6_addr in6;
553 extern struct aftype inet6_aftype;
554 #else
555 struct sockaddr_in mcastaddr;
556 #endif
557 struct aftype *ap;
558 static int idx_flag = 0;
559 static int igmp6_flag = 0;
560 static char device[16];
561 int num, idx, refcnt;
563 if (lnr == 0) {
564 /* IPV6 ONLY */
565 /* igmp6 file does not have any comments on first line */
566 if ( strstr( line, "Device" ) == NULL ) {
567 igmp6_flag = 1;
568 } else {
569 /* IPV4 ONLY */
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 )
573 idx_flag = 1;
574 else
575 idx_flag = 0;
576 return;
580 if (igmp6_flag) { /* IPV6 */
581 #if HAVE_AFINET6
582 num = sscanf( line, "%d %15s %64[0-9A-Fa-f] %d", &idx, device, mcast_addr, &refcnt );
583 if (num == 4) {
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;
595 } else {
596 fprintf(stderr, _("warning, got bogus igmp6 line %d.\n"), lnr);
597 return;
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);
603 return;
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);
608 #endif
609 } else { /* IPV4 */
610 #if HAVE_AFINET
611 if (line[0] != '\t') {
612 if (idx_flag) {
613 if ((num = sscanf( line, "%d\t%10c", &idx, device)) < 2) {
614 fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
615 return;
617 } else {
618 if ( (num = sscanf( line, "%10c", device )) < 1 ) {
619 fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
620 return;
623 device[10] = '\0';
624 return;
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);
628 return;
630 sscanf( mcast_addr, "%X",
631 &((struct sockaddr_in *) &mcastaddr)->sin_addr.s_addr );
632 ((struct sockaddr *) &mcastaddr)->sa_family = AF_INET;
633 } else {
634 fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
635 return;
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);
641 return;
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 );
646 #endif
647 } /* IPV4 */
650 #if HAVE_AFX25
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]=
658 "LISTENING",
659 "SABM_SENT",
660 "DISC_SENT",
661 "ESTABLISHED",
662 "RECOVERY"
664 if(!(f=fopen(_PATH_PROCNET_X25, "r")))
666 if (errno != ENOENT) {
667 perror(_PATH_PROCNET_X25);
668 return(-1);
670 if (flag_arg || flag_ver)
671 ESYSNOT("netstat","AF X25");
672 if (flag_arg)
673 return(1);
674 else
675 return(0);
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"));
680 fgets(buffer,256,f);
681 while(fgets(buffer,256,f))
683 buffer[10]=0;
684 buffer[20]=0;
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))
688 continue;
689 printf("%-15s %-15s %-7s %-3d %-11s %02d/%02d %-6d %-6d\n",
690 buffer,buffer+11,
691 dev,
692 lci,
693 x25_state[st],
694 vr,vs,sendq,recvq);
696 fclose(f);
697 return 0;
699 #endif
701 static int igmp_info(void)
703 INFO_GUTS6(_PATH_PROCNET_IGMP, _PATH_PROCNET_IGMP6, "AF INET (igmp)",
704 igmp_do_one);
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];
712 char *protname;
713 struct aftype *ap;
714 #if HAVE_AFINET6
715 struct sockaddr_in6 localaddr, remaddr;
716 char addr6[INET6_ADDRSTRLEN];
717 struct in6_addr in6;
718 extern struct aftype inet6_aftype;
719 #else
720 struct sockaddr_in localaddr, remaddr;
721 #endif
723 if (lnr == 0)
724 return;
726 num = sscanf(line,
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) {
732 #if HAVE_AFINET6
733 protname = "tcp6";
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;
747 #endif
748 } else {
749 protname = "tcp";
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;
758 if (num < 11) {
759 fprintf(stderr, _("warning, got bogus tcp line.\n"));
760 return;
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);
765 return;
767 if (state == TCP_LISTEN) {
768 time_len = 0;
769 retr = 0L;
770 rxq = 0L;
771 txq = 0L;
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),
776 sizeof(rem_addr));
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);
795 timers[0] = '\0';
797 if (flag_opt)
798 switch (timer_run) {
799 case 0:
800 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
801 break;
803 case 1:
804 snprintf(timers, sizeof(timers), _("on (%2.2f/%ld/%d)"),
805 (double) time_len / HZ, retr, timeout);
806 break;
808 case 2:
809 snprintf(timers, sizeof(timers), _("keepalive (%2.2f/%ld/%d)"),
810 (double) time_len / HZ, retr, timeout);
811 break;
813 case 3:
814 snprintf(timers, sizeof(timers), _("timewait (%2.2f/%ld/%d)"),
815 (double) time_len / HZ, retr, timeout);
816 break;
818 default:
819 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
820 timer_run, (double) time_len / HZ, retr, timeout);
821 break;
823 printf("%-4s %6ld %6ld %-*s %-*s %-11s",
824 protname, rxq, txq, max(23,strlen(local_addr)), local_addr, max(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)",
833 tcp_do_one);
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;
841 char *protname;
842 #if HAVE_AFINET6
843 struct sockaddr_in6 localaddr, remaddr;
844 char addr6[INET6_ADDRSTRLEN];
845 struct in6_addr in6;
846 extern struct aftype inet6_aftype;
847 #else
848 struct sockaddr_in localaddr, remaddr;
849 #endif
850 struct aftype *ap;
851 unsigned long rxq, txq, time_len, retr, inode;
853 if (lnr == 0)
854 return;
856 more[0] = '\0';
857 num = sscanf(line,
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) {
864 #if HAVE_AFINET6
865 protname="udp6";
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;
878 #endif
879 } else {
880 protname="udp";
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;
889 retr = 0L;
890 if (!flag_opt)
891 more[0] = '\0';
893 if (num < 10) {
894 fprintf(stderr, _("warning, got bogus udp line.\n"));
895 return;
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);
900 return;
902 switch (state) {
903 case TCP_ESTABLISHED:
904 udp_state = _("ESTABLISHED");
905 break;
907 case TCP_CLOSE:
908 udp_state = "";
909 break;
911 default:
912 udp_state = _("UNKNOWN");
913 break;
916 #if HAVE_AFINET6
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))
924 #else
925 #define notnull(A) (A.sin_addr.s_addr)
926 #endif
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));
935 if ((strlen(local_addr) + strlen(buffer)) > 22)
936 local_addr[22 - strlen(buffer)] = '\0';
937 strcat(local_addr, ":");
938 strcat(local_addr, buffer);
940 snprintf(buffer, sizeof(buffer), "%s",
941 get_sname(htons(rem_port), "udp", flag_not & FLAG_NUM_PORT));
942 safe_strncpy(rem_addr, ap->sprint((struct sockaddr *) &remaddr,
943 flag_not), sizeof(rem_addr));
944 if ((strlen(rem_addr) + strlen(buffer)) > 22)
945 rem_addr[22 - strlen(buffer)] = '\0';
946 strcat(rem_addr, ":");
947 strcat(rem_addr, buffer);
949 timers[0] = '\0';
950 if (flag_opt)
951 switch (timer_run) {
952 case 0:
953 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
954 break;
956 case 1:
957 case 2:
958 snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100, retr, timeout);
959 break;
961 default:
962 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
963 retr, timeout);
964 break;
966 printf("%-4s %6ld %6ld %-23s %-23s %-11s",
967 protname, rxq, txq, local_addr, rem_addr, udp_state);
969 finish_this_one(uid,inode,timers);
973 static int udp_info(void)
975 INFO_GUTS6(_PATH_PROCNET_UDP, _PATH_PROCNET_UDP6, "AF INET (udp)",
976 udp_do_one);
979 static void raw_do_one(int lnr, const char *line)
981 char buffer[8192], local_addr[64], rem_addr[64];
982 char timers[64], more[512];
983 int num, local_port, rem_port, d, state, timer_run, uid, timeout;
984 char *protname;
985 #if HAVE_AFINET6
986 struct sockaddr_in6 localaddr, remaddr;
987 char addr6[INET6_ADDRSTRLEN];
988 struct in6_addr in6;
989 extern struct aftype inet6_aftype;
990 #else
991 struct sockaddr_in localaddr, remaddr;
992 #endif
993 struct aftype *ap;
994 unsigned long rxq, txq, time_len, retr, inode;
996 if (lnr == 0)
997 return;
999 more[0] = '\0';
1000 num = sscanf(line,
1001 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %512s\n",
1002 &d, local_addr, &local_port, rem_addr, &rem_port, &state,
1003 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
1005 if (strlen(local_addr) > 8) {
1006 #if HAVE_AFINET6
1007 protname = "raw6";
1008 sscanf(local_addr, "%08X%08X%08X%08X",
1009 &in6.s6_addr32[0], &in6.s6_addr32[1],
1010 &in6.s6_addr32[2], &in6.s6_addr32[3]);
1011 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1012 inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
1013 sscanf(rem_addr, "%08X%08X%08X%08X",
1014 &in6.s6_addr32[0], &in6.s6_addr32[1],
1015 &in6.s6_addr32[2], &in6.s6_addr32[3]);
1016 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1017 inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
1018 localaddr.sin6_family = AF_INET6;
1019 remaddr.sin6_family = AF_INET6;
1020 #endif
1021 } else {
1022 protname = "raw";
1023 sscanf(local_addr, "%X",
1024 &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
1025 sscanf(rem_addr, "%X",
1026 &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
1027 ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
1028 ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
1030 #if HAVE_AFINET6
1031 if ((ap = get_afntype(localaddr.sin6_family)) == NULL) {
1032 fprintf(stderr, _("netstat: unsupported address family %d !\n"), localaddr.sin6_family);
1033 return;
1035 #else
1036 if ((ap = get_afntype(localaddr.sin_family)) == NULL) {
1037 fprintf(stderr, _("netstat: unsupported address family %d !\n"), localaddr.sin_family);
1038 return;
1040 #endif
1042 if (!flag_opt)
1043 more[0] = '\0';
1045 if (num < 10) {
1046 fprintf(stderr, _("warning, got bogus raw line.\n"));
1047 return;
1050 if (flag_all || (notnull(remaddr) && !flag_lst) || (!notnull(remaddr) && flag_lst))
1052 snprintf(buffer, sizeof(buffer), "%s",
1053 get_sname(htons(local_port), "raw",
1054 flag_not & FLAG_NUM_PORT));
1055 safe_strncpy(local_addr, ap->sprint((struct sockaddr *) &localaddr,
1056 flag_not), sizeof(local_addr));
1057 if ((strlen(local_addr) + strlen(buffer)) > 22)
1058 local_addr[22 - strlen(buffer)] = '\0';
1059 strcat(local_addr, ":");
1060 strcat(local_addr, buffer);
1062 snprintf(buffer, sizeof(buffer), "%s",
1063 get_sname(htons(rem_port), "raw", flag_not & FLAG_NUM_PORT));
1064 safe_strncpy(rem_addr, ap->sprint((struct sockaddr *) &remaddr,
1065 flag_not), sizeof(rem_addr));
1066 if ((strlen(rem_addr) + strlen(buffer)) > 22)
1067 rem_addr[22 - strlen(buffer)] = '\0';
1068 strcat(rem_addr, ":");
1069 strcat(rem_addr, buffer);
1071 timers[0] = '\0';
1072 if (flag_opt)
1073 switch (timer_run) {
1074 case 0:
1075 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
1076 break;
1078 case 1:
1079 case 2:
1080 snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
1081 retr, timeout);
1082 break;
1084 default:
1085 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
1086 timer_run, (double) time_len / 100,
1087 retr, timeout);
1088 break;
1090 printf("%-4s %6ld %6ld %-23s %-23s %-11d",
1091 protname, rxq, txq, local_addr, rem_addr, state);
1093 finish_this_one(uid,inode,timers);
1097 static int raw_info(void)
1099 INFO_GUTS6(_PATH_PROCNET_RAW, _PATH_PROCNET_RAW6, "AF INET (raw)",
1100 raw_do_one);
1103 #endif
1106 #if HAVE_AFUNIX
1108 #define HAS_INODE 1
1110 static void unix_do_one(int nr, const char *line)
1112 static int has = 0;
1113 char path[MAXPATHLEN], ss_flags[32];
1114 char *ss_proto, *ss_state, *ss_type;
1115 int num, state, type;
1116 void *d;
1117 unsigned long refcnt, proto, flags, inode;
1119 if (nr == 0) {
1120 if (strstr(line, "Inode"))
1121 has |= HAS_INODE;
1122 return;
1124 path[0] = '\0';
1125 num = sscanf(line, "%p: %lX %lX %lX %X %X %lu %s",
1126 &d, &refcnt, &proto, &flags, &type, &state, &inode, path);
1127 if (num < 6) {
1128 fprintf(stderr, _("warning, got bogus unix line.\n"));
1129 return;
1131 if (!(has & HAS_INODE))
1132 snprintf(path,sizeof(path),"%lu",inode);
1134 if (!flag_all) {
1135 if ((state == SS_UNCONNECTED) && (flags & SO_ACCEPTCON)) {
1136 if (!flag_lst)
1137 return;
1138 } else {
1139 if (flag_lst)
1140 return;
1144 switch (proto) {
1145 case 0:
1146 ss_proto = "unix";
1147 break;
1149 default:
1150 ss_proto = "??";
1153 switch (type) {
1154 case SOCK_STREAM:
1155 ss_type = _("STREAM");
1156 break;
1158 case SOCK_DGRAM:
1159 ss_type = _("DGRAM");
1160 break;
1162 case SOCK_RAW:
1163 ss_type = _("RAW");
1164 break;
1166 case SOCK_RDM:
1167 ss_type = _("RDM");
1168 break;
1170 case SOCK_SEQPACKET:
1171 ss_type = _("SEQPACKET");
1172 break;
1174 default:
1175 ss_type = _("UNKNOWN");
1178 switch (state) {
1179 case SS_FREE:
1180 ss_state = _("FREE");
1181 break;
1183 case SS_UNCONNECTED:
1185 * Unconnected sockets may be listening
1186 * for something.
1188 if (flags & SO_ACCEPTCON) {
1189 ss_state = _("LISTENING");
1190 } else {
1191 ss_state = "";
1193 break;
1195 case SS_CONNECTING:
1196 ss_state = _("CONNECTING");
1197 break;
1199 case SS_CONNECTED:
1200 ss_state = _("CONNECTED");
1201 break;
1203 case SS_DISCONNECTING:
1204 ss_state = _("DISCONNECTING");
1205 break;
1207 default:
1208 ss_state = _("UNKNOWN");
1211 strcpy(ss_flags, "[ ");
1212 if (flags & SO_ACCEPTCON)
1213 strcat(ss_flags, "ACC ");
1214 if (flags & SO_WAITDATA)
1215 strcat(ss_flags, "W ");
1216 if (flags & SO_NOSPACE)
1217 strcat(ss_flags, "N ");
1219 strcat(ss_flags, "]");
1221 printf("%-5s %-6ld %-11s %-10s %-13s ",
1222 ss_proto, refcnt, ss_flags, ss_type, ss_state);
1223 if (has & HAS_INODE)
1224 printf("%-8lu ",inode);
1225 else
1226 printf("- ");
1227 if (flag_prg)
1228 printf("%-" PROGNAME_WIDTHs "s",(has & HAS_INODE?prg_cache_get(inode):"-"));
1229 puts(path);
1232 static int unix_info(void)
1235 printf(_("Active UNIX domain sockets "));
1236 if (flag_all)
1237 printf(_("(servers and established)"));
1238 else {
1239 if (flag_lst)
1240 printf(_("(only servers)"));
1241 else
1242 printf(_("(w/o servers)"));
1245 printf(_("\nProto RefCnt Flags Type State I-Node"));
1246 print_progname_banner();
1247 printf(_(" Path\n")); /* xxx */
1250 INFO_GUTS(_PATH_PROCNET_UNIX, "AF UNIX", unix_do_one);
1253 #endif
1256 #if HAVE_AFAX25
1257 static int ax25_info(void)
1259 FILE *f;
1260 char buffer[256], buf[16];
1261 char *src, *dst, *dev, *p;
1262 int st, vs, vr, sendq, recvq, ret;
1263 int new = -1; /* flag for new (2.1.x) kernels */
1264 static char *ax25_state[5] =
1266 N_("LISTENING"),
1267 N_("SABM SENT"),
1268 N_("DISC SENT"),
1269 N_("ESTABLISHED"),
1270 N_("RECOVERY")
1272 if (!(f = fopen(_PATH_PROCNET_AX25, "r"))) {
1273 if (errno != ENOENT) {
1274 perror(_PATH_PROCNET_AX25);
1275 return (-1);
1277 if (flag_arg || flag_ver)
1278 ESYSNOT("netstat", "AF AX25");
1279 if (flag_arg)
1280 return (1);
1281 else
1282 return (0);
1284 printf(_("Active AX.25 sockets\n"));
1285 printf(_("Dest Source Device State Vr/Vs Send-Q Recv-Q\n"));
1286 while (fgets(buffer, 256, f)) {
1287 if (new == -1) {
1288 if (!strncmp(buffer, "dest_addr", 9)) {
1289 new = 0;
1290 continue; /* old kernels have a header line */
1291 } else
1292 new = 1;
1295 * In a network connection with no user socket the Snd-Q, Rcv-Q
1296 * and Inode fields are empty in 2.0.x and '*' in 2.1.x
1298 sendq = 0;
1299 recvq = 0;
1300 if (new == 0) {
1301 dst = buffer;
1302 src = buffer + 10;
1303 dst[9] = 0;
1304 src[9] = 0;
1305 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",
1306 buf, &st, &vs, &vr, &sendq, &recvq);
1307 if (ret != 4 && ret != 6) {
1308 printf(_("Problem reading data from %s\n"), _PATH_PROCNET_AX25);
1309 continue;
1311 dev = buf;
1312 } else {
1313 p = buffer;
1314 while (*p != ' ') p++;
1315 p++;
1316 dev = p;
1317 while (*p != ' ') p++;
1318 *p++ = 0;
1319 src = p;
1320 while (*p != ' ') p++;
1321 *p++ = 0;
1322 dst = p;
1323 while (*p != ' ') p++;
1324 *p++ = 0;
1325 ret = sscanf(p, "%d %d %d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d %*d",
1326 &st, &vs, &vr, &sendq, &recvq);
1327 if (ret != 3 && ret != 5) {
1328 printf(_("problem reading data from %s\n"), _PATH_PROCNET_AX25);
1329 continue;
1332 * FIXME: digipeaters should be handled somehow.
1333 * For now we just strip them.
1335 p = dst;
1336 while (*p && *p != ',') p++;
1337 *p = 0;
1339 printf("%-9s %-9s %-6s %-11s %03d/%03d %-6d %-6d\n",
1340 dst, src,
1341 dev,
1342 _(ax25_state[st]),
1343 vr, vs, sendq, recvq);
1345 fclose(f);
1346 return 0;
1348 #endif
1351 #if HAVE_AFIPX
1352 static int ipx_info(void)
1354 FILE *f;
1355 char buf[256];
1356 unsigned long txq, rxq;
1357 unsigned int state;
1358 unsigned int uid;
1359 char *st;
1360 int nc;
1361 struct aftype *ap;
1362 struct passwd *pw;
1363 char sad[50], dad[50];
1364 struct sockaddr sa;
1365 unsigned sport = 0, dport = 0;
1367 if (!(f = fopen(_PATH_PROCNET_IPX, "r"))) {
1368 if (errno != ENOENT) {
1369 perror(_PATH_PROCNET_IPX);
1370 return (-1);
1372 if (flag_arg || flag_ver)
1373 ESYSNOT("netstat", "AF IPX");
1374 if (flag_arg)
1375 return (1);
1376 else
1377 return (0);
1379 printf(_("Active IPX sockets\nProto Recv-Q Send-Q Local Address Foreign Address State")); /* xxx */
1380 if (flag_exp > 1)
1381 printf(_(" User")); /* xxx */
1382 printf("\n");
1383 if ((ap = get_afntype(AF_IPX)) == NULL) {
1384 EINTERN("netstat.c", "AF_IPX missing");
1385 return (-1);
1387 fgets(buf, 255, f);
1389 while (fgets(buf, 255, f) != NULL) {
1390 sscanf(buf, "%s %s %lX %lX %d %d",
1391 sad, dad, &txq, &rxq, &state, &uid);
1392 if ((st = rindex(sad, ':'))) {
1393 *st++ = '\0';
1394 sscanf(st, "%X", &sport); /* net byt order */
1395 sport = ntohs(sport);
1396 } else {
1397 EINTERN("netstat.c", _PATH_PROCNET_IPX " sport format error");
1398 return (-1);
1400 nc = 0;
1401 if (strcmp(dad, "Not_Connected") != 0) {
1402 if ((st = rindex(dad, ':'))) {
1403 *st++ = '\0';
1404 sscanf(st, "%X", &dport); /* net byt order */
1405 dport = ntohs(dport);
1406 } else {
1407 EINTERN("netstat.c", _PATH_PROCNET_IPX " dport format error");
1408 return (-1);
1410 } else
1411 nc = 1;
1413 switch (state) {
1414 case TCP_ESTABLISHED:
1415 st = _("ESTAB");
1416 break;
1418 case TCP_CLOSE:
1419 st = "";
1420 break;
1422 default:
1423 st = _("UNK.");
1424 break;
1427 /* Fetch and resolve the Source */
1428 (void) ap->input(4, sad, &sa);
1429 safe_strncpy(buf, ap->sprint(&sa, flag_not), sizeof(buf));
1430 snprintf(sad, sizeof(sad), "%s:%04X", buf, sport);
1432 if (!nc) {
1433 /* Fetch and resolve the Destination */
1434 (void) ap->input(4, dad, &sa);
1435 safe_strncpy(buf, ap->sprint(&sa, flag_not), sizeof(buf));
1436 snprintf(dad, sizeof(dad), "%s:%04X", buf, dport);
1437 } else
1438 strcpy(dad, "-");
1440 printf("IPX %6ld %6ld %-26s %-26s %-5s", txq, rxq, sad, dad, st);
1441 if (flag_exp > 1) {
1442 if (!(flag_not & FLAG_NUM_USER) && ((pw = getpwuid(uid)) != NULL))
1443 printf(" %-10s", pw->pw_name);
1444 else
1445 printf(" %-10d", uid);
1447 printf("\n");
1449 fclose(f);
1450 return 0;
1452 #endif
1454 static int iface_info(void)
1456 if (skfd < 0) {
1457 if ((skfd = sockets_open(0)) < 0) {
1458 perror("socket");
1459 exit(1);
1461 printf(_("Kernel Interface table\n"));
1463 if (flag_exp < 2) {
1464 ife_short = 1;
1465 printf(_("Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg\n"));
1468 if (for_all_interfaces(do_if_print, &flag_all) < 0) {
1469 perror(_("missing interface information"));
1470 exit(1);
1472 if (flag_cnt)
1473 if_cache_free();
1474 else {
1475 close(skfd);
1476 skfd = -1;
1479 return 0;
1483 static void version(void)
1485 printf("%s\n%s\n%s\n%s\n", Release, Version, Signature, Features);
1486 exit(E_VERSION);
1490 static void usage(void)
1492 fprintf(stderr, _("usage: netstat [-veenNcCF] [<Af>] -r netstat {-V|--version|-h|--help}\n"));
1493 fprintf(stderr, _(" netstat [-vnNcaeol] [<Socket> ...]\n"));
1494 fprintf(stderr, _(" netstat { [-veenNac] -i | [-cnNe] -M | -s }\n\n"));
1496 fprintf(stderr, _(" -r, --route display routing table\n"));
1497 fprintf(stderr, _(" -i, --interfaces display interface table\n"));
1498 fprintf(stderr, _(" -g, --groups display multicast group memberships\n"));
1499 fprintf(stderr, _(" -s, --statistics display networking statistics (like SNMP)\n"));
1500 #if HAVE_FW_MASQUERADE
1501 fprintf(stderr, _(" -M, --masquerade display masqueraded connections\n\n"));
1502 #endif
1503 fprintf(stderr, _(" -v, --verbose be verbose\n"));
1504 fprintf(stderr, _(" -n, --numeric don't resolve names\n"));
1505 fprintf(stderr, _(" --numeric-hosts don't resolve host names\n"));
1506 fprintf(stderr, _(" --numeric-ports don't resolve port names\n"));
1507 fprintf(stderr, _(" --numeric-users don't resolve user names\n"));
1508 fprintf(stderr, _(" -N, --symbolic resolve hardware names\n"));
1509 fprintf(stderr, _(" -e, --extend display other/more information\n"));
1510 fprintf(stderr, _(" -p, --programs display PID/Program name for sockets\n"));
1511 fprintf(stderr, _(" -c, --continuous continuous listing\n\n"));
1512 fprintf(stderr, _(" -l, --listening display listening server sockets\n"));
1513 fprintf(stderr, _(" -a, --all, --listening display all sockets (default: connected)\n"));
1514 fprintf(stderr, _(" -o, --timers display timers\n"));
1515 fprintf(stderr, _(" -F, --fib display Forwarding Information Base (default)\n"));
1516 fprintf(stderr, _(" -C, --cache display routing cache instead of FIB\n\n"));
1518 fprintf(stderr, _(" <Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom\n"));
1519 fprintf(stderr, _(" <AF>=Use '-6|-4' or '-A <af>' or '--<af>'; default: %s\n"), DFLT_AF);
1520 fprintf(stderr, _(" List of possible address families (which support routing):\n"));
1521 print_aflist(1); /* 1 = routeable */
1522 exit(E_USAGE);
1526 int main
1527 (int argc, char *argv[]) {
1528 int i;
1529 int lop;
1530 static struct option longopts[] =
1532 AFTRANS_OPTS,
1533 {"version", 0, 0, 'V'},
1534 {"interfaces", 0, 0, 'i'},
1535 {"help", 0, 0, 'h'},
1536 {"route", 0, 0, 'r'},
1537 #if HAVE_FW_MASQUERADE
1538 {"masquerade", 0, 0, 'M'},
1539 #endif
1540 {"protocol", 1, 0, 'A'},
1541 {"tcp", 0, 0, 't'},
1542 {"udp", 0, 0, 'u'},
1543 {"raw", 0, 0, 'w'},
1544 {"unix", 0, 0, 'x'},
1545 {"listening", 0, 0, 'l'},
1546 {"all", 0, 0, 'a'},
1547 {"timers", 0, 0, 'o'},
1548 {"continuous", 0, 0, 'c'},
1549 {"extend", 0, 0, 'e'},
1550 {"programs", 0, 0, 'p'},
1551 {"verbose", 0, 0, 'v'},
1552 {"statistics", 0, 0, 's'},
1553 {"numeric", 0, 0, 'n'},
1554 {"numeric-hosts", 0, 0, '!'},
1555 {"numeric-ports", 0, 0, '@'},
1556 {"numeric-users", 0, 0, '#'},
1557 {"symbolic", 0, 0, 'N'},
1558 {"cache", 0, 0, 'C'},
1559 {"fib", 0, 0, 'F'},
1560 {"groups", 0, 0, 'g'},
1561 {NULL, 0, 0, 0}
1564 #if I18N
1565 setlocale (LC_ALL, "");
1566 bindtextdomain("net-tools", "/usr/share/locale");
1567 textdomain("net-tools");
1568 #endif
1569 getroute_init(); /* Set up AF routing support */
1571 afname[0] = '\0';
1572 while ((i = getopt_long(argc, argv, "MCFA:acdegphinNorstuVv?wxl64", longopts, &lop)) != EOF)
1573 switch (i) {
1574 case -1:
1575 break;
1576 case 1:
1577 if (lop < 0 || lop >= AFTRANS_CNT) {
1578 EINTERN("netstat.c", "longopts 1 range");
1579 break;
1581 if (aftrans_opt(longopts[lop].name))
1582 exit(1);
1583 break;
1584 case 'A':
1585 if (aftrans_opt(optarg))
1586 exit(1);
1587 break;
1588 case 'M':
1589 flag_mas++;
1590 break;
1591 case 'a':
1592 flag_all++;
1593 break;
1594 case 'l':
1595 flag_lst++;
1596 break;
1597 case 'c':
1598 flag_cnt++;
1599 break;
1601 case 'd':
1602 flag_deb++;
1603 break;
1604 case 'g':
1605 flag_igmp++;
1606 break;
1607 case 'e':
1608 flag_exp++;
1609 break;
1610 case 'p':
1611 flag_prg++;
1612 break;
1613 case 'i':
1614 flag_int++;
1615 break;
1616 case 'n':
1617 flag_not |= FLAG_NUM;
1618 break;
1619 case '!':
1620 flag_not |= FLAG_NUM_HOST;
1621 break;
1622 case '@':
1623 flag_not |= FLAG_NUM_PORT;
1624 break;
1625 case '#':
1626 flag_not |= FLAG_NUM_USER;
1627 break;
1628 case 'N':
1629 flag_not |= FLAG_SYM;
1630 break;
1631 case 'C':
1632 flag_cf |= FLAG_CACHE;
1633 break;
1634 case 'F':
1635 flag_cf |= FLAG_FIB;
1636 break;
1637 case 'o':
1638 flag_opt++;
1639 break;
1640 case '6':
1641 if (aftrans_opt("inet6"))
1642 exit(1);
1643 break;
1644 case '4':
1645 if (aftrans_opt("inet"))
1646 exit(1);
1647 break;
1648 case 'V':
1649 version();
1650 /*NOTREACHED */
1651 case 'v':
1652 flag_ver |= FLAG_VERBOSE;
1653 break;
1654 case 'r':
1655 flag_rou++;
1656 break;
1658 case 't':
1659 flag_tcp++;
1660 break;
1662 case 'u':
1663 flag_udp++;
1664 break;
1665 case 'w':
1666 flag_raw++;
1667 break;
1668 case 'x':
1669 if (aftrans_opt("unix"))
1670 exit(1);
1671 break;
1672 case '?':
1673 case 'h':
1674 usage();
1675 case 's':
1676 flag_sta++;
1679 if (flag_int + flag_rou + flag_mas + flag_sta > 1)
1680 usage();
1682 if ((flag_inet || flag_inet6 || flag_sta) && !(flag_tcp || flag_udp || flag_raw))
1683 flag_tcp = flag_udp = flag_raw = 1;
1685 if ((flag_tcp || flag_udp || flag_raw || flag_igmp) && !(flag_inet || flag_inet6))
1686 flag_inet = flag_inet6 = 1;
1688 flag_arg = flag_tcp + flag_udp + flag_raw + flag_unx + flag_ipx
1689 + flag_ax25 + flag_netrom + flag_igmp + flag_x25;
1691 if (flag_mas) {
1692 #if HAVE_FW_MASQUERADE && HAVE_AFINET
1693 #if MORE_THAN_ONE_MASQ_AF
1694 if (!afname[0])
1695 strcpy(afname, DFLT_AF);
1696 #endif
1697 for (;;) {
1698 i = ip_masq_info(flag_not & FLAG_NUM_HOST,
1699 flag_not & FLAG_NUM_PORT, flag_exp);
1700 if (i || !flag_cnt)
1701 break;
1702 sleep(1);
1704 #else
1705 ENOSUPP("netstat.c", "FW_MASQUERADE");
1706 i = -1;
1707 #endif
1708 return (i);
1711 if (flag_sta) {
1712 inittab();
1713 parsesnmp(flag_raw, flag_tcp, flag_udp);
1714 exit(0);
1717 if (flag_rou) {
1718 int options = 0;
1720 if (!afname[0])
1721 strcpy(afname, DFLT_AF);
1723 if (flag_exp == 2)
1724 flag_exp = 1;
1725 else if (flag_exp == 1)
1726 flag_exp = 2;
1728 options = (flag_exp & FLAG_EXT) | flag_not | flag_cf | flag_ver;
1729 if (!flag_cf)
1730 options |= FLAG_FIB;
1732 for (;;) {
1733 i = route_info(afname, options);
1734 if (i || !flag_cnt)
1735 break;
1736 sleep(1);
1738 return (i);
1740 if (flag_int) {
1741 for (;;) {
1742 i = iface_info();
1743 if (!flag_cnt || i)
1744 break;
1745 sleep(1);
1747 return (i);
1749 for (;;) {
1750 if (!flag_arg || flag_tcp || flag_udp || flag_raw) {
1751 #if HAVE_AFINET
1752 prg_cache_load();
1753 printf(_("Active Internet connections ")); /* xxx */
1755 if (flag_all)
1756 printf(_("(servers and established)"));
1757 else {
1758 if (flag_lst)
1759 printf(_("(only servers)"));
1760 else
1761 printf(_("(w/o servers)"));
1763 printf(_("\nProto Recv-Q Send-Q Local Address Foreign Address State ")); /* xxx */
1764 if (flag_exp > 1)
1765 printf(_(" User Inode "));
1766 print_progname_banner();
1767 if (flag_opt)
1768 printf(_(" Timer")); /* xxx */
1769 printf("\n");
1770 #else
1771 if (flag_arg) {
1772 i = 1;
1773 ENOSUPP("netstat", "AF INET");
1775 #endif
1777 #if HAVE_AFINET
1778 if (!flag_arg || flag_tcp) {
1779 i = tcp_info();
1780 if (i)
1781 return (i);
1783 if (!flag_arg || flag_udp) {
1784 i = udp_info();
1785 if (i)
1786 return (i);
1788 if (!flag_arg || flag_raw) {
1789 i = raw_info();
1790 if (i)
1791 return (i);
1794 if (flag_igmp) {
1795 #if HAVE_AFINET6
1796 printf( "IPv6/");
1797 #endif
1798 printf( _("IPv4 Group Memberships\n") );
1799 printf( _("Interface RefCnt Group\n") );
1800 printf( "--------------- ------ ---------------------\n" );
1801 i = igmp_info();
1802 if (i)
1803 return (i);
1805 #endif
1807 if (!flag_arg || flag_unx) {
1808 #if HAVE_AFUNIX
1809 prg_cache_load();
1810 i = unix_info();
1811 if (i)
1812 return (i);
1813 #else
1814 if (flag_arg) {
1815 i = 1;
1816 ENOSUPP("netstat", "AF UNIX");
1818 #endif
1820 if (!flag_arg || flag_ipx) {
1821 #if HAVE_AFIPX
1822 i = ipx_info();
1823 if (i)
1824 return (i);
1825 #else
1826 if (flag_arg) {
1827 i = 1;
1828 ENOSUPP("netstat", "AF IPX");
1830 #endif
1832 if (!flag_arg || flag_ax25) {
1833 #if HAVE_AFAX25
1834 i = ax25_info();
1835 if (i)
1836 return (i);
1837 #else
1838 if (flag_arg) {
1839 i = 1;
1840 ENOSUPP("netstat", "AF AX25");
1842 #endif
1844 if(!flag_arg || flag_x25) {
1845 #if HAVE_AFX25
1846 /* FIXME */
1847 i = x25_info();
1848 if (i)
1849 return(i);
1850 #else
1851 if (flag_arg) {
1852 i = 1;
1853 ENOSUPP("netstat", "AF X25");
1855 #endif
1857 if (!flag_arg || flag_netrom) {
1858 #if HAVE_AFNETROM
1859 i = netrom_info();
1860 if (i)
1861 return (i);
1862 #else
1863 if (flag_arg) {
1864 i = 1;
1865 ENOSUPP("netstat", "AF NETROM");
1867 #endif
1869 if (!flag_cnt || i)
1870 break;
1871 sleep(1);
1872 prg_cache_clear();
1874 return (i);