fixed compile warning for NULL instead of 0 in "suppress_null_addr" (who did
[oss-qm-packages.git] / netstat.c
blobe14da30d0dcdd4ff82e532b31bd7c74da9d75227
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.32 2000/02/20 17:50:01 philip 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 *980411 {1.34} Arnaldo Carvalho i18n: catgets -> gnu gettext, substitution
47 * of sprintf for snprintf
48 *10/1998 Andi Kleen Use new interface primitives.
49 *990101 {1.36} Bernd Eckenfels usage updated to include -s and -C -F,
50 * fixed netstat -rC output (lib/inet_gr.c)
51 * removed broken NETLINK Support
52 * fixed format for /proc/net/udp|tcp|raw
53 * added -w,-t,-u TcpExt support to -s
54 *990131 {1.37} Jan Kratochvil added -p for prg_cache() & friends
55 * Flames to <short@ucw.cz>.
56 * Tuan Hoang added IGMP support for IPv4 and IPv6
58 *990420 {1.38} Tuan Hoang removed a useless assignment from igmp_do_one()
60 * This program is free software; you can redistribute it
61 * and/or modify it under the terms of the GNU General
62 * Public License as published by the Free Software
63 * Foundation; either version 2 of the License, or (at
64 * your option) any later version.
67 #include <errno.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <strings.h>
72 #include <unistd.h>
73 #include <ctype.h>
74 #include <fcntl.h>
75 #include <netdb.h>
76 #include <paths.h>
77 #include <pwd.h>
78 #include <getopt.h>
79 #include <sys/param.h>
80 #include <sys/socket.h>
81 #include <netinet/in.h>
82 #include <sys/ioctl.h>
83 #include <net/if.h>
84 #include <dirent.h>
86 #include "net-support.h"
87 #include "pathnames.h"
88 #include "version.h"
89 #include "config.h"
90 #include "intl.h"
91 #include "sockets.h"
92 #include "interface.h"
93 #include "util.h"
95 #define PROGNAME_WIDTH 20
97 #if !defined(s6_addr32) && defined(in6a_words)
98 #define s6_addr32 in6a_words /* libinet6 */
99 #endif
101 /* prototypes for statistics.c */
102 void parsesnmp(int, int, int);
103 void inittab(void);
105 typedef enum {
106 SS_FREE = 0, /* not allocated */
107 SS_UNCONNECTED, /* unconnected to any socket */
108 SS_CONNECTING, /* in process of connecting */
109 SS_CONNECTED, /* connected to socket */
110 SS_DISCONNECTING /* in process of disconnecting */
111 } socket_state;
113 #define SO_ACCEPTCON (1<<16) /* performed a listen */
114 #define SO_WAITDATA (1<<17) /* wait data to read */
115 #define SO_NOSPACE (1<<18) /* no space to write */
117 #define DFLT_AF "inet"
119 #define FEATURE_NETSTAT
120 #include "lib/net-features.h"
122 char *Release = RELEASE, *Version = "netstat 1.38 (1999-04-20)", *Signature = "Fred Baumgarten, Alan Cox, Bernd Eckenfels, Phil Blundell, Tuan Hoang and others";
125 #define E_READ -1
126 #define E_IOCTL -3
128 int flag_int = 0;
129 int flag_rou = 0;
130 int flag_mas = 0;
131 int flag_sta = 0;
133 int flag_all = 0;
134 int flag_lst = 0;
135 int flag_cnt = 0;
136 int flag_deb = 0;
137 int flag_not = 0;
138 int flag_cf = 0;
139 int flag_opt = 0;
140 int flag_raw = 0;
141 int flag_tcp = 0;
142 int flag_udp = 0;
143 int flag_igmp= 0;
144 int flag_rom = 0;
145 int flag_exp = 1;
146 int flag_prg = 0;
147 int flag_arg = 0;
148 int flag_ver = 0;
150 FILE *procinfo;
152 #define INFO_GUTS1(file,name,proc) \
153 procinfo = fopen((file), "r"); \
154 if (procinfo == NULL) { \
155 if (errno != ENOENT) { \
156 perror((file)); \
157 return -1; \
159 if (flag_arg || flag_ver) \
160 ESYSNOT("netstat", (name)); \
161 if (flag_arg) \
162 rc = 1; \
163 } else { \
164 do { \
165 if (fgets(buffer, sizeof(buffer), procinfo)) \
166 (proc)(lnr++, buffer); \
167 } while (!feof(procinfo)); \
168 fclose(procinfo); \
171 #if HAVE_AFINET6
172 #define INFO_GUTS2(file,proc) \
173 lnr = 0; \
174 procinfo = fopen((file), "r"); \
175 if (procinfo != NULL) { \
176 do { \
177 if (fgets(buffer, sizeof(buffer), procinfo)) \
178 (proc)(lnr++, buffer); \
179 } while (!feof(procinfo)); \
180 fclose(procinfo); \
182 #else
183 #define INFO_GUTS2(file,proc)
184 #endif
186 #define INFO_GUTS3 \
187 return rc;
189 #define INFO_GUTS6(file,file6,name,proc) \
190 char buffer[8192]; \
191 int rc = 0; \
192 int lnr = 0; \
193 if (!flag_arg || flag_inet) { \
194 INFO_GUTS1(file,name,proc) \
196 if (!flag_arg || flag_inet6) { \
197 INFO_GUTS2(file6,proc) \
199 INFO_GUTS3
201 #define INFO_GUTS(file,name,proc) \
202 char buffer[8192]; \
203 int rc = 0; \
204 int lnr = 0; \
205 INFO_GUTS1(file,name,proc) \
206 INFO_GUTS3
208 #define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)
209 #define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)
210 #define PROGNAME_WIDTH2(s) #s
212 #define PRG_HASH_SIZE 211
214 static struct prg_node {
215 struct prg_node *next;
216 int inode;
217 char name[PROGNAME_WIDTH];
218 } *prg_hash[PRG_HASH_SIZE];
220 static char prg_cache_loaded = 0;
222 #define PRG_HASHIT(x) ((x) % PRG_HASH_SIZE)
224 #define PROGNAME_BANNER "PID/Program name"
226 #define print_progname_banner() do { if (flag_prg) printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER); } while (0)
228 #define PRG_LOCAL_ADDRESS "local_address"
229 #define PRG_INODE "inode"
230 #define PRG_SOCKET_PFX "socket:["
231 #define PRG_SOCKET_PFXl (strlen(PRG_SOCKET_PFX))
233 #ifndef LINE_MAX
234 #define LINE_MAX 4096
235 #endif
237 #define PATH_PROC "/proc"
238 #define PATH_FD_SUFF "fd"
239 #define PATH_FD_SUFFl strlen(PATH_FD_SUFF)
240 #define PATH_PROC_X_FD PATH_PROC "/%s/" PATH_FD_SUFF
241 #define PATH_CMDLINE "cmdline"
242 #define PATH_CMDLINEl strlen(PATH_CMDLINE)
243 /* NOT working as of glibc-2.0.7: */
244 #undef DIRENT_HAVE_D_TYPE_WORKS
246 static void prg_cache_add(int inode, char *name)
248 unsigned hi = PRG_HASHIT(inode);
249 struct prg_node **pnp,*pn;
251 prg_cache_loaded=2;
252 for (pnp=prg_hash+hi;(pn=*pnp);pnp=&pn->next) {
253 if (pn->inode==inode) {
254 /* Some warning should be appropriate here
255 as we got multiple processes for one i-node */
256 return;
259 if (!(*pnp=malloc(sizeof(**pnp))))
260 return;
261 pn=*pnp;
262 pn->next=NULL;
263 pn->inode=inode;
264 if (strlen(name)>sizeof(pn->name)-1)
265 name[sizeof(pn->name)-1]='\0';
266 strcpy(pn->name,name);
269 static const char *prg_cache_get(int inode)
271 unsigned hi=PRG_HASHIT(inode);
272 struct prg_node *pn;
274 for (pn=prg_hash[hi];pn;pn=pn->next)
275 if (pn->inode==inode) return(pn->name);
276 return("-");
279 static void prg_cache_clear(void)
281 struct prg_node **pnp,*pn;
283 if (prg_cache_loaded == 2)
284 for (pnp=prg_hash;pnp<prg_hash+PRG_HASH_SIZE;pnp++)
285 while ((pn=*pnp)) {
286 *pnp=pn->next;
287 free(pn);
289 prg_cache_loaded=0;
292 static void prg_cache_load(void)
294 char line[LINE_MAX],*serr,eacces=0;
295 int procfdlen,fd,cmdllen,lnamelen;
296 char lname[30],cmdlbuf[512],finbuf[PROGNAME_WIDTH];
297 long inode;
298 const char *cs,*cmdlp;
299 DIR *dirproc=NULL,*dirfd=NULL;
300 struct dirent *direproc,*direfd;
302 if (prg_cache_loaded || !flag_prg) return;
303 prg_cache_loaded=1;
304 cmdlbuf[sizeof(cmdlbuf)-1]='\0';
305 if (!(dirproc=opendir(PATH_PROC))) goto fail;
306 while (errno=0,direproc=readdir(dirproc)) {
307 #ifdef DIRENT_HAVE_D_TYPE_WORKS
308 if (direproc->d_type!=DT_DIR) continue;
309 #endif
310 for (cs=direproc->d_name;*cs;cs++)
311 if (!isdigit(*cs))
312 break;
313 if (*cs)
314 continue;
315 procfdlen=snprintf(line,sizeof(line),PATH_PROC_X_FD,direproc->d_name);
316 if (procfdlen<=0 || procfdlen>=sizeof(line)-5)
317 continue;
318 errno=0;
319 dirfd=opendir(line);
320 if (! dirfd) {
321 if (errno==EACCES)
322 eacces=1;
323 continue;
325 line[procfdlen] = '/';
326 cmdlp = NULL;
327 while ((direfd = readdir(dirfd))) {
328 #ifdef DIRENT_HAVE_D_TYPE_WORKS
329 if (direfd->d_type!=DT_LNK)
330 continue;
331 #endif
332 if (procfdlen+1+strlen(direfd->d_name)+1>sizeof(line))
333 continue;
334 memcpy(line + procfdlen - PATH_FD_SUFFl, PATH_FD_SUFF "/",
335 PATH_FD_SUFFl+1);
336 strcpy(line + procfdlen + 1, direfd->d_name);
337 lnamelen=readlink(line,lname,sizeof(lname));
338 if (lnamelen < strlen(PRG_SOCKET_PFX+2))
339 continue;
340 if (memcmp(lname, PRG_SOCKET_PFX, PRG_SOCKET_PFXl)
341 || lname[lnamelen-1]!=']')
342 continue;
343 lname[lnamelen-1]='\0';
344 inode = strtol(lname+PRG_SOCKET_PFXl,&serr,0);
345 if (!serr || *serr || inode < 0 || inode >= INT_MAX)
346 continue;
348 if (!cmdlp) {
349 if (procfdlen - PATH_FD_SUFFl + PATH_CMDLINEl >=
350 sizeof(line) - 5)
351 continue;
352 strcpy(line + procfdlen-PATH_FD_SUFFl, PATH_CMDLINE);
353 fd = open(line, O_RDONLY);
354 if (fd < 0)
355 continue;
356 cmdllen = read(fd, cmdlbuf, sizeof(cmdlbuf) - 1);
357 if (close(fd))
358 continue;
359 if (cmdllen == -1)
360 continue;
361 if (cmdllen < sizeof(cmdlbuf) - 1)
362 cmdlbuf[cmdllen]='\0';
363 if ((cmdlp = strrchr(cmdlbuf, '/')))
364 cmdlp++;
365 else
366 cmdlp = cmdlbuf;
369 snprintf(finbuf, sizeof(finbuf), "%s/%s", direproc->d_name, cmdlp);
370 prg_cache_add(inode, finbuf);
372 closedir(dirfd);
373 dirfd = NULL;
375 if (dirproc)
376 closedir(dirproc);
377 if (dirfd)
378 closedir(dirfd);
379 if (!eacces)
380 return;
381 if (prg_cache_loaded == 1) {
382 fail:
383 fprintf(stderr,_("(No info could be read for \"-p\": geteuid()=%d but you should be root.)\n"),
384 geteuid());
386 else
387 fprintf(stderr, _("(Not all processes could be identified, non-owned process info\n"
388 " will not be shown, you would have to be root to see it all.)\n"));
391 #if HAVE_AFNETROM
392 static const char *netrom_state[] =
394 N_("LISTENING"),
395 N_("CONN SENT"),
396 N_("DISC SENT"),
397 N_("ESTABLISHED")
400 static int netrom_info(void)
402 FILE *f;
403 char buffer[256], dev[16];
404 int st, vs, vr, sendq, recvq, ret;
406 f = fopen(_PATH_PROCNET_NR, "r");
407 if (f == NULL) {
408 if (errno != ENOENT) {
409 perror(_PATH_PROCNET_NR);
410 return (-1);
412 if (flag_arg || flag_ver)
413 ESYSNOT("netstat", "AF NETROM");
414 if (flag_arg)
415 return (1);
416 else
417 return (0);
419 printf(_("Active NET/ROM sockets\n"));
420 printf(_("User Dest Source Device State Vr/Vs Send-Q Recv-Q\n"));
421 fgets(buffer, 256, f);
423 while (fgets(buffer, 256, f)) {
424 buffer[9] = 0;
425 buffer[19] = 0;
426 buffer[29] = 0;
427 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",
428 dev, &st, &vs, &vr, &sendq, &recvq);
429 if (ret != 6) {
430 printf(_("Problem reading data from %s\n"), _PATH_PROCNET_NR);
431 continue;
433 printf("%-9s %-9s %-9s %-6s %-11s %03d/%03d %-6d %-6d\n",
434 buffer, buffer + 10, buffer + 20,
435 dev,
436 _(netrom_state[st]),
437 vr, vs, sendq, recvq);
439 fclose(f);
440 return 0;
442 #endif
444 /* These enums are used by IPX too. :-( */
445 enum {
446 TCP_ESTABLISHED = 1,
447 TCP_SYN_SENT,
448 TCP_SYN_RECV,
449 TCP_FIN_WAIT1,
450 TCP_FIN_WAIT2,
451 TCP_TIME_WAIT,
452 TCP_CLOSE,
453 TCP_CLOSE_WAIT,
454 TCP_LAST_ACK,
455 TCP_LISTEN,
456 TCP_CLOSING /* now a valid state */
459 #if HAVE_AFINET || HAVE_AFINET6
461 static const char *tcp_state[] =
464 N_("ESTABLISHED"),
465 N_("SYN_SENT"),
466 N_("SYN_RECV"),
467 N_("FIN_WAIT1"),
468 N_("FIN_WAIT2"),
469 N_("TIME_WAIT"),
470 N_("CLOSE"),
471 N_("CLOSE_WAIT"),
472 N_("LAST_ACK"),
473 N_("LISTEN"),
474 N_("CLOSING")
477 static void finish_this_one(int uid, unsigned long inode, const char *timers)
479 struct passwd *pw;
481 if (flag_exp > 1) {
482 if (!flag_not && ((pw = getpwuid(uid)) != NULL))
483 printf("%-10s ", pw->pw_name);
484 else
485 printf("%-10d ", uid);
486 printf("%-10ld ",inode);
488 if (flag_prg)
489 printf("%-" PROGNAME_WIDTHs "s",prg_cache_get(inode));
490 if (flag_opt)
491 printf("%s", timers);
492 putchar('\n');
495 static void igmp_do_one(int lnr, const char *line)
497 char mcast_addr[128];
498 #if HAVE_AFINET6
499 struct sockaddr_in6 mcastaddr;
500 char addr6p[8][5];
501 char addr6[128];
502 extern struct aftype inet6_aftype;
503 #else
504 struct sockaddr_in mcastaddr;
505 #endif
506 struct aftype *ap;
507 static int idx_flag = 0;
508 static int igmp6_flag = 0;
509 static char device[16];
510 int num, idx, refcnt;
512 if (lnr == 0) {
513 /* IPV6 ONLY */
514 /* igmp6 file does not have any comments on first line */
515 if ( strstr( line, "Device" ) == NULL ) {
516 igmp6_flag = 1;
517 } else {
518 /* IPV4 ONLY */
519 /* 2.1.x kernels and up have Idx field */
520 /* 2.0.x and below do not have Idx field */
521 if ( strncmp( line, "Idx", strlen("Idx") ) == 0 )
522 idx_flag = 1;
523 else
524 idx_flag = 0;
525 return;
529 if (igmp6_flag) { /* IPV6 */
530 #if HAVE_AFINET6
531 num = sscanf( line, "%d %15s %64[0-9A-Fa-f] %d", &idx, device, mcast_addr, &refcnt );
532 if (num == 4) {
533 /* Demangle what the kernel gives us */
534 sscanf(mcast_addr,
535 "%4s%4s%4s%4s%4s%4s%4s%4s",
536 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
537 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
538 snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
539 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
540 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
541 inet6_aftype.input(1, addr6, (struct sockaddr *) &mcastaddr);
542 mcastaddr.sin6_family = AF_INET6;
543 } else {
544 fprintf(stderr, _("warning, got bogus igmp6 line %d.\n"), lnr);
545 return;
548 if ((ap = get_afntype(((struct sockaddr *) &mcastaddr)->sa_family)) == NULL) {
549 fprintf(stderr, _("netstat: unsupported address family %d !\n"),
550 ((struct sockaddr *) &mcastaddr)->sa_family);
551 return;
553 safe_strncpy(mcast_addr, ap->sprint((struct sockaddr *) &mcastaddr,
554 flag_not), sizeof(mcast_addr));
555 printf("%-15s %-6d %s\n", device, refcnt, mcast_addr);
556 #endif
557 } else { /* IPV4 */
558 #if HAVE_AFINET
559 if (line[0] != '\t') {
560 if (idx_flag) {
561 if ((num = sscanf( line, "%d\t%10c", &idx, device)) < 2) {
562 fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
563 return;
565 } else {
566 if ( (num = sscanf( line, "%10c", device )) < 1 ) {
567 fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
568 return;
571 device[10] = '\0';
572 return;
573 } else if ( line[0] == '\t' ) {
574 if ( (num = sscanf(line, "\t%8[0-9A-Fa-f] %d", mcast_addr, &refcnt)) < 2 ) {
575 fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
576 return;
578 sscanf( mcast_addr, "%X",
579 &((struct sockaddr_in *) &mcastaddr)->sin_addr.s_addr );
580 ((struct sockaddr *) &mcastaddr)->sa_family = AF_INET;
581 } else {
582 fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
583 return;
586 if ((ap = get_afntype(((struct sockaddr *) &mcastaddr)->sa_family)) == NULL) {
587 fprintf(stderr, _("netstat: unsupported address family %d !\n"),
588 ((struct sockaddr *) &mcastaddr)->sa_family);
589 return;
591 safe_strncpy(mcast_addr, ap->sprint((struct sockaddr *) &mcastaddr,
592 flag_not), sizeof(mcast_addr));
593 printf("%-15s %-6d %s\n", device, refcnt, mcast_addr );
594 #endif
595 } /* IPV4 */
598 static int igmp_info(void)
600 INFO_GUTS6(_PATH_PROCNET_IGMP, _PATH_PROCNET_IGMP6, "AF INET (igmp)",
601 igmp_do_one);
604 static void tcp_do_one(int lnr, const char *line)
606 unsigned long rxq, txq, time_len, retr, inode;
607 int num, local_port, rem_port, d, state, uid, timer_run, timeout;
608 char rem_addr[128], local_addr[128], timers[64], buffer[1024], more[512];
609 struct aftype *ap;
610 #if HAVE_AFINET6
611 struct sockaddr_in6 localaddr, remaddr;
612 char addr6p[16][3], addr6[128];
613 extern struct aftype inet6_aftype;
614 #else
615 struct sockaddr_in localaddr, remaddr;
616 #endif
618 if (lnr == 0)
619 return;
621 num = sscanf(line,
622 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
623 &d, local_addr, &local_port, rem_addr, &rem_port, &state,
624 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
626 if (strlen(local_addr) > 8) {
627 #if HAVE_AFINET6
628 /* Demangle what the kernel gives us */
629 sscanf(local_addr,
630 "%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s",
631 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
632 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
633 addr6p[8], addr6p[9], addr6p[10], addr6p[11],
634 addr6p[12], addr6p[13], addr6p[14], addr6p[15]);
635 snprintf(addr6, sizeof(addr6), "%s%s:%s%s:%s%s:%s%s:%s%s:%s%s:%s%s:%s%s",
636 addr6p[3], addr6p[2], addr6p[1], addr6p[0],
637 addr6p[7], addr6p[6], addr6p[5], addr6p[4],
638 addr6p[11], addr6p[10], addr6p[9], addr6p[8],
639 addr6p[15], addr6p[14], addr6p[13], addr6p[12]);
640 inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
641 sscanf(rem_addr,
642 "%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s%2s",
643 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
644 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
645 addr6p[8], addr6p[9], addr6p[10], addr6p[11],
646 addr6p[12], addr6p[13], addr6p[14], addr6p[15]);
647 snprintf(addr6, sizeof(addr6), "%s%s:%s%s:%s%s:%s%s:%s%s:%s%s:%s%s:%s%s",
648 addr6p[3], addr6p[2], addr6p[1], addr6p[0],
649 addr6p[7], addr6p[6], addr6p[5], addr6p[4],
650 addr6p[11], addr6p[10], addr6p[9], addr6p[8],
651 addr6p[15], addr6p[14], addr6p[13], addr6p[12]);
652 inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
653 localaddr.sin6_family = AF_INET6;
654 remaddr.sin6_family = AF_INET6;
655 #endif
656 } else {
657 sscanf(local_addr, "%X",
658 &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
659 sscanf(rem_addr, "%X",
660 &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
661 ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
662 ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
665 if (num < 11) {
666 fprintf(stderr, _("warning, got bogus tcp line.\n"));
667 return;
669 if ((ap = get_afntype(((struct sockaddr *) &localaddr)->sa_family)) == NULL) {
670 fprintf(stderr, _("netstat: unsupported address family %d !\n"),
671 ((struct sockaddr *) &localaddr)->sa_family);
672 return;
674 if (state == TCP_LISTEN) {
675 time_len = 0;
676 retr = 0L;
677 rxq = 0L;
678 txq = 0L;
680 safe_strncpy(local_addr, ap->sprint((struct sockaddr *) &localaddr,
681 flag_not), sizeof(local_addr));
682 safe_strncpy(rem_addr, ap->sprint((struct sockaddr *) &remaddr, flag_not),
683 sizeof(rem_addr));
684 if (flag_all || (flag_lst && !rem_port) || (!flag_lst && rem_port)) {
685 snprintf(buffer, sizeof(buffer), "%s", get_sname(htons(local_port), "tcp", flag_not));
687 if ((strlen(local_addr) + strlen(buffer)) > 22)
688 local_addr[22 - strlen(buffer)] = '\0';
690 strcat(local_addr, ":");
691 strcat(local_addr, buffer);
692 snprintf(buffer, sizeof(buffer), "%s", get_sname(htons(rem_port), "tcp", flag_not));
694 if ((strlen(rem_addr) + strlen(buffer)) > 22)
695 rem_addr[22 - strlen(buffer)] = '\0';
697 strcat(rem_addr, ":");
698 strcat(rem_addr, buffer);
699 timers[0] = '\0';
701 if (flag_opt)
702 switch (timer_run) {
703 case 0:
704 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
705 break;
707 case 1:
708 snprintf(timers, sizeof(timers), _("on (%2.2f/%ld/%d)"),
709 (double) time_len / HZ, retr, timeout);
710 break;
712 case 2:
713 snprintf(timers, sizeof(timers), _("keepalive (%2.2f/%ld/%d)"),
714 (double) time_len / HZ, retr, timeout);
715 break;
717 case 3:
718 snprintf(timers, sizeof(timers), _("timewait (%2.2f/%ld/%d)"),
719 (double) time_len / HZ, retr, timeout);
720 break;
722 default:
723 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
724 timer_run, (double) time_len / HZ, retr, timeout);
725 break;
727 printf("tcp %6ld %6ld %-23s %-23s %-12s",
728 rxq, txq, local_addr, rem_addr, _(tcp_state[state]));
730 finish_this_one(uid,inode,timers);
734 static int tcp_info(void)
736 INFO_GUTS6(_PATH_PROCNET_TCP, _PATH_PROCNET_TCP6, "AF INET (tcp)",
737 tcp_do_one);
740 static void udp_do_one(int lnr, const char *line)
742 char buffer[8192], local_addr[64], rem_addr[64];
743 char *udp_state, timers[64], more[512];
744 int num, local_port, rem_port, d, state, timer_run, uid, timeout;
745 #if HAVE_AFINET6
746 struct sockaddr_in6 localaddr, remaddr;
747 char addr6p[8][5];
748 char addr6[128];
749 extern struct aftype inet6_aftype;
750 #else
751 struct sockaddr_in localaddr, remaddr;
752 #endif
753 struct aftype *ap;
754 unsigned long rxq, txq, time_len, retr, inode;
756 if (lnr == 0)
757 return;
759 more[0] = '\0';
760 num = sscanf(line,
761 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
762 &d, local_addr, &local_port,
763 rem_addr, &rem_port, &state,
764 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
766 if (strlen(local_addr) > 8) {
767 #if HAVE_AFINET6
768 sscanf(local_addr, "%4s%4s%4s%4s%4s%4s%4s%4s",
769 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
770 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
771 snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
772 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
773 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
774 inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
775 sscanf(rem_addr, "%4s%4s%4s%4s%4s%4s%4s%4s",
776 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
777 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
778 snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
779 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
780 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
781 inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
782 localaddr.sin6_family = AF_INET6;
783 remaddr.sin6_family = AF_INET6;
784 #endif
785 } else {
786 sscanf(local_addr, "%X",
787 &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
788 sscanf(rem_addr, "%X",
789 &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
790 ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
791 ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
794 retr = 0L;
795 if (!flag_opt)
796 more[0] = '\0';
798 if (num < 10) {
799 fprintf(stderr, _("warning, got bogus udp line.\n"));
800 return;
802 if ((ap = get_afntype(((struct sockaddr *) &localaddr)->sa_family)) == NULL) {
803 fprintf(stderr, _("netstat: unsupported address family %d !\n"),
804 ((struct sockaddr *) &localaddr)->sa_family);
805 return;
807 switch (state) {
808 case TCP_ESTABLISHED:
809 udp_state = _("ESTABLISHED");
810 break;
812 case TCP_CLOSE:
813 udp_state = "";
814 break;
816 default:
817 udp_state = _("UNKNOWN");
818 break;
821 #if HAVE_AFINET6
822 #define notnull(A) (((A.sin6_family == AF_INET6) && \
823 ((A.sin6_addr.s6_addr32[0]) || \
824 (A.sin6_addr.s6_addr32[1]) || \
825 (A.sin6_addr.s6_addr32[2]) || \
826 (A.sin6_addr.s6_addr32[3]))) || \
827 ((A.sin6_family == AF_INET) && \
828 ((struct sockaddr_in *) &A)->sin_addr.s_addr))
829 #else
830 #define notnull(A) (A.sin_addr.s_addr)
831 #endif
833 if (flag_all || (notnull(remaddr) && !flag_lst) || (!notnull(remaddr) && flag_lst))
835 safe_strncpy(local_addr, ap->sprint((struct sockaddr *) &localaddr,
836 flag_not), sizeof(local_addr));
837 snprintf(buffer, sizeof(buffer), "%s", get_sname(htons(local_port), "udp", flag_not));
838 if ((strlen(local_addr) + strlen(buffer)) > 22)
839 local_addr[22 - strlen(buffer)] = '\0';
840 strcat(local_addr, ":");
841 strcat(local_addr, buffer);
843 snprintf(buffer, sizeof(buffer), "%s", get_sname(htons(rem_port), "udp", flag_not));
844 safe_strncpy(rem_addr, ap->sprint((struct sockaddr *) &remaddr,
845 flag_not), sizeof(rem_addr));
846 if ((strlen(rem_addr) + strlen(buffer)) > 22)
847 rem_addr[22 - strlen(buffer)] = '\0';
848 strcat(rem_addr, ":");
849 strcat(rem_addr, buffer);
851 timers[0] = '\0';
852 if (flag_opt)
853 switch (timer_run) {
854 case 0:
855 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
856 break;
858 case 1:
859 case 2:
860 snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100, retr, timeout);
861 break;
863 default:
864 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
865 retr, timeout);
866 break;
868 printf("udp %6ld %6ld %-23s %-23s %-12s",
869 rxq, txq, local_addr, rem_addr, udp_state);
871 finish_this_one(uid,inode,timers);
875 static int udp_info(void)
877 INFO_GUTS6(_PATH_PROCNET_UDP, _PATH_PROCNET_UDP6, "AF INET (udp)",
878 udp_do_one);
881 static void raw_do_one(int lnr, const char *line)
883 char buffer[8192], local_addr[64], rem_addr[64];
884 char timers[64], more[512];
885 int num, local_port, rem_port, d, state, timer_run, uid, timeout;
886 #if HAVE_AFINET6
887 struct sockaddr_in6 localaddr, remaddr;
888 char addr6p[8][5];
889 char addr6[128];
890 extern struct aftype inet6_aftype;
891 #else
892 struct sockaddr_in localaddr, remaddr;
893 #endif
894 struct aftype *ap;
895 unsigned long rxq, txq, time_len, retr, inode;
897 if (lnr == 0)
898 return;
900 more[0] = '\0';
901 num = sscanf(line,
902 "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
903 &d, local_addr, &local_port, rem_addr, &rem_port, &state,
904 &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
906 if (strlen(local_addr) > 8) {
907 #if HAVE_AFINET6
908 sscanf(local_addr, "%4s%4s%4s%4s%4s%4s%4s%4s",
909 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
910 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
911 snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
912 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
913 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
914 inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
915 sscanf(rem_addr, "%4s%4s%4s%4s%4s%4s%4s%4s",
916 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
917 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
918 snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
919 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
920 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
921 inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
922 localaddr.sin6_family = AF_INET6;
923 remaddr.sin6_family = AF_INET6;
924 #endif
925 } else {
926 sscanf(local_addr, "%X",
927 &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
928 sscanf(rem_addr, "%X",
929 &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
930 ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
931 ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
933 #if HAVE_AFINET6
934 if ((ap = get_afntype(localaddr.sin6_family)) == NULL) {
935 fprintf(stderr, _("netstat: unsupported address family %d !\n"), localaddr.sin6_family);
936 return;
938 #else
939 if ((ap = get_afntype(localaddr.sin_family)) == NULL) {
940 fprintf(stderr, _("netstat: unsupported address family %d !\n"), localaddr.sin_family);
941 return;
943 #endif
945 if (!flag_opt)
946 more[0] = '\0';
948 if (num < 10) {
949 fprintf(stderr, _("warning, got bogus raw line.\n"));
950 return;
953 if (flag_all || (notnull(remaddr) && !flag_lst) || (!notnull(remaddr) && flag_lst))
955 snprintf(buffer, sizeof(buffer), "%s", get_sname(htons(local_port), "raw", flag_not));
956 safe_strncpy(local_addr, ap->sprint((struct sockaddr *) &localaddr,
957 flag_not), sizeof(local_addr));
958 if ((strlen(local_addr) + strlen(buffer)) > 22)
959 local_addr[22 - strlen(buffer)] = '\0';
960 strcat(local_addr, ":");
961 strcat(local_addr, buffer);
963 snprintf(buffer, sizeof(buffer), "%s", get_sname(htons(rem_port), "raw", flag_not));
964 safe_strncpy(rem_addr, ap->sprint((struct sockaddr *) &remaddr,
965 flag_not), sizeof(rem_addr));
966 if ((strlen(rem_addr) + strlen(buffer)) > 22)
967 rem_addr[22 - strlen(buffer)] = '\0';
968 strcat(rem_addr, ":");
969 strcat(rem_addr, buffer);
971 timers[0] = '\0';
972 if (flag_opt)
973 switch (timer_run) {
974 case 0:
975 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
976 break;
978 case 1:
979 case 2:
980 snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
981 retr, timeout);
982 break;
984 default:
985 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
986 timer_run, (double) time_len / 100,
987 retr, timeout);
988 break;
990 printf("raw %6ld %6ld %-23s %-23s %-12d",
991 rxq, txq, local_addr, rem_addr, state);
993 finish_this_one(uid,inode,timers);
997 static int raw_info(void)
999 INFO_GUTS6(_PATH_PROCNET_RAW, _PATH_PROCNET_RAW6, "AF INET (raw)",
1000 raw_do_one);
1003 #endif
1006 #if HAVE_AFUNIX
1008 #define HAS_INODE 1
1010 static void unix_do_one(int nr, const char *line)
1012 static int has = 0;
1013 char path[MAXPATHLEN], ss_flags[32];
1014 char *ss_proto, *ss_state, *ss_type;
1015 int num, state, type, inode;
1016 void *d;
1017 unsigned long refcnt, proto, flags;
1019 if (nr == 0) {
1020 if (strstr(line, "Inode"))
1021 has |= HAS_INODE;
1022 return;
1024 path[0] = '\0';
1025 num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s",
1026 &d, &refcnt, &proto, &flags, &type, &state, &inode, path);
1027 if (num < 6) {
1028 fprintf(stderr, _("warning, got bogus unix line.\n"));
1029 return;
1031 if (!(has & HAS_INODE))
1032 snprintf(path,sizeof(path),"%d",inode);
1034 if (!flag_all) {
1035 if ((state == SS_UNCONNECTED) && (flags & SO_ACCEPTCON)) {
1036 if (!flag_lst)
1037 return;
1038 } else {
1039 if (flag_lst)
1040 return;
1044 switch (proto) {
1045 case 0:
1046 ss_proto = "unix";
1047 break;
1049 default:
1050 ss_proto = "??";
1053 switch (type) {
1054 case SOCK_STREAM:
1055 ss_type = _("STREAM");
1056 break;
1058 case SOCK_DGRAM:
1059 ss_type = _("DGRAM");
1060 break;
1062 case SOCK_RAW:
1063 ss_type = _("RAW");
1064 break;
1066 case SOCK_RDM:
1067 ss_type = _("RDM");
1068 break;
1070 case SOCK_SEQPACKET:
1071 ss_type = _("SEQPACKET");
1072 break;
1074 default:
1075 ss_type = _("UNKNOWN");
1078 switch (state) {
1079 case SS_FREE:
1080 ss_state = _("FREE");
1081 break;
1083 case SS_UNCONNECTED:
1085 * Unconnected sockets may be listening
1086 * for something.
1088 if (flags & SO_ACCEPTCON) {
1089 ss_state = _("LISTENING");
1090 } else {
1091 ss_state = "";
1093 break;
1095 case SS_CONNECTING:
1096 ss_state = _("CONNECTING");
1097 break;
1099 case SS_CONNECTED:
1100 ss_state = _("CONNECTED");
1101 break;
1103 case SS_DISCONNECTING:
1104 ss_state = _("DISCONNECTING");
1105 break;
1107 default:
1108 ss_state = _("UNKNOWN");
1111 strcpy(ss_flags, "[ ");
1112 if (flags & SO_ACCEPTCON)
1113 strcat(ss_flags, "ACC ");
1114 if (flags & SO_WAITDATA)
1115 strcat(ss_flags, "W ");
1116 if (flags & SO_NOSPACE)
1117 strcat(ss_flags, "N ");
1119 strcat(ss_flags, "]");
1121 printf("%-5s %-6ld %-11s %-10s %-13s ",
1122 ss_proto, refcnt, ss_flags, ss_type, ss_state);
1123 if (has & HAS_INODE)
1124 printf("%-6d ",inode);
1125 else
1126 printf("- ");
1127 if (flag_prg)
1128 printf("%-" PROGNAME_WIDTHs "s",(has & HAS_INODE?prg_cache_get(inode):"-"));
1129 puts(path);
1132 static int unix_info(void)
1135 printf(_("Active UNIX domain sockets "));
1136 if (flag_all)
1137 printf(_("(servers and established)"));
1138 else {
1139 if (flag_lst)
1140 printf(_("(only servers)"));
1141 else
1142 printf(_("(w/o servers)"));
1145 printf(_("\nProto RefCnt Flags Type State I-Node"));
1146 print_progname_banner();
1147 printf(_(" Path\n")); /* xxx */
1150 INFO_GUTS(_PATH_PROCNET_UNIX, "AF UNIX", unix_do_one);
1153 #endif
1156 #if HAVE_AFAX25
1157 static int ax25_info(void)
1159 FILE *f;
1160 char buffer[256], buf[16];
1161 char *src, *dst, *dev, *p;
1162 int st, vs, vr, sendq, recvq, ret;
1163 int new = -1; /* flag for new (2.1.x) kernels */
1164 static char *ax25_state[5] =
1166 N_("LISTENING"),
1167 N_("SABM SENT"),
1168 N_("DISC SENT"),
1169 N_("ESTABLISHED"),
1170 N_("RECOVERY")
1172 if (!(f = fopen(_PATH_PROCNET_AX25, "r"))) {
1173 if (errno != ENOENT) {
1174 perror(_PATH_PROCNET_AX25);
1175 return (-1);
1177 if (flag_arg || flag_ver)
1178 ESYSNOT("netstat", "AF AX25");
1179 if (flag_arg)
1180 return (1);
1181 else
1182 return (0);
1184 printf(_("Active AX.25 sockets\n"));
1185 printf(_("Dest Source Device State Vr/Vs Send-Q Recv-Q\n"));
1186 while (fgets(buffer, 256, f)) {
1187 if (new == -1) {
1188 if (!strncmp(buffer, "dest_addr", 9)) {
1189 new = 0;
1190 continue; /* old kernels have a header line */
1191 } else
1192 new = 1;
1195 * In a network connection with no user socket the Snd-Q, Rcv-Q
1196 * and Inode fields are empty in 2.0.x and '*' in 2.1.x
1198 sendq = 0;
1199 recvq = 0;
1200 if (new == 0) {
1201 dst = buffer;
1202 src = buffer + 10;
1203 dst[9] = 0;
1204 src[9] = 0;
1205 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",
1206 buf, &st, &vs, &vr, &sendq, &recvq);
1207 if (ret != 4 && ret != 6) {
1208 printf(_("Problem reading data from %s\n"), _PATH_PROCNET_AX25);
1209 continue;
1211 dev = buf;
1212 } else {
1213 p = buffer;
1214 while (*p != ' ') p++;
1215 p++;
1216 dev = p;
1217 while (*p != ' ') p++;
1218 *p++ = 0;
1219 src = p;
1220 while (*p != ' ') p++;
1221 *p++ = 0;
1222 dst = p;
1223 while (*p != ' ') p++;
1224 *p++ = 0;
1225 ret = sscanf(p, "%d %d %d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d %*d",
1226 &st, &vs, &vr, &sendq, &recvq);
1227 if (ret != 3 && ret != 5) {
1228 printf(_("problem reading data from %s\n"), _PATH_PROCNET_AX25);
1229 continue;
1232 * FIXME: digipeaters should be handled somehow.
1233 * For now we just strip them.
1235 p = dst;
1236 while (*p && *p != ',') p++;
1237 *p = 0;
1239 printf("%-9s %-9s %-6s %-11s %03d/%03d %-6d %-6d\n",
1240 dst, src,
1241 dev,
1242 _(ax25_state[st]),
1243 vr, vs, sendq, recvq);
1245 fclose(f);
1246 return 0;
1248 #endif
1251 #if HAVE_AFIPX
1252 static int ipx_info(void)
1254 FILE *f;
1255 char buf[256];
1256 unsigned long txq, rxq;
1257 unsigned int state;
1258 unsigned int uid;
1259 char *st;
1260 int nc;
1261 struct aftype *ap;
1262 struct passwd *pw;
1263 char sad[50], dad[50];
1264 struct sockaddr sa;
1265 unsigned sport = 0, dport = 0;
1267 if (!(f = fopen(_PATH_PROCNET_IPX, "r"))) {
1268 if (errno != ENOENT) {
1269 perror(_PATH_PROCNET_IPX);
1270 return (-1);
1272 if (flag_arg || flag_ver)
1273 ESYSNOT("netstat", "AF IPX");
1274 if (flag_arg)
1275 return (1);
1276 else
1277 return (0);
1279 printf(_("Active IPX sockets\nProto Recv-Q Send-Q Local Address Foreign Address State")); /* xxx */
1280 if (flag_exp > 1)
1281 printf(_(" User")); /* xxx */
1282 printf("\n");
1283 if ((ap = get_afntype(AF_IPX)) == NULL) {
1284 EINTERN("netstat.c", "AF_IPX missing");
1285 return (-1);
1287 fgets(buf, 255, f);
1289 while (fgets(buf, 255, f) != NULL) {
1290 sscanf(buf, "%s %s %lX %lX %d %d",
1291 sad, dad, &txq, &rxq, &state, &uid);
1292 if ((st = rindex(sad, ':'))) {
1293 *st++ = '\0';
1294 sscanf(st, "%X", &sport); /* net byt order */
1295 sport = ntohs(sport);
1296 } else {
1297 EINTERN("netstat.c", _PATH_PROCNET_IPX " sport format error");
1298 return (-1);
1300 nc = 0;
1301 if (strcmp(dad, "Not_Connected") != 0) {
1302 if ((st = rindex(dad, ':'))) {
1303 *st++ = '\0';
1304 sscanf(st, "%X", &dport); /* net byt order */
1305 dport = ntohs(dport);
1306 } else {
1307 EINTERN("netstat.c", _PATH_PROCNET_IPX " dport format error");
1308 return (-1);
1310 } else
1311 nc = 1;
1313 switch (state) {
1314 case TCP_ESTABLISHED:
1315 st = _("ESTAB");
1316 break;
1318 case TCP_CLOSE:
1319 st = "";
1320 break;
1322 default:
1323 st = _("UNK.");
1324 break;
1327 /* Fetch and resolve the Source */
1328 (void) ap->input(4, sad, &sa);
1329 safe_strncpy(buf, ap->sprint(&sa, flag_not), sizeof(buf));
1330 snprintf(sad, sizeof(sad), "%s:%04X", buf, sport);
1332 if (!nc) {
1333 /* Fetch and resolve the Destination */
1334 (void) ap->input(4, dad, &sa);
1335 safe_strncpy(buf, ap->sprint(&sa, flag_not), sizeof(buf));
1336 snprintf(dad, sizeof(dad), "%s:%04X", buf, dport);
1337 } else
1338 strcpy(dad, "-");
1340 printf("IPX %6ld %6ld %-26s %-26s %-5s", txq, rxq, sad, dad, st);
1341 if (flag_exp > 1) {
1342 if (!flag_not && ((pw = getpwuid(uid)) != NULL))
1343 printf(" %-10s", pw->pw_name);
1344 else
1345 printf(" %-10d", uid);
1347 printf("\n");
1349 fclose(f);
1350 return 0;
1352 #endif
1354 void ife_print(struct interface *ptr)
1356 printf("%-5.5s ", ptr->name);
1357 printf("%5d %3d ", ptr->mtu, ptr->metric);
1358 /* If needed, display the interface statistics. */
1359 if (ptr->statistics_valid) {
1360 printf("%8lu %6lu %6lu %6lu ",
1361 ptr->stats.rx_packets, ptr->stats.rx_errors,
1362 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors);
1363 printf("%8lu %6lu %6lu %6lu ",
1364 ptr->stats.tx_packets, ptr->stats.tx_errors,
1365 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors);
1366 } else {
1367 printf("%-56s", _(" - no statistics available -"));
1369 if (ptr->flags == 0)
1370 printf(_("[NO FLAGS]"));
1371 if (ptr->flags & IFF_ALLMULTI)
1372 printf("A");
1373 if (ptr->flags & IFF_BROADCAST)
1374 printf("B");
1375 if (ptr->flags & IFF_DEBUG)
1376 printf("D");
1377 if (ptr->flags & IFF_LOOPBACK)
1378 printf("L");
1379 if (ptr->flags & IFF_PROMISC)
1380 printf("M");
1381 if (ptr->flags & IFF_NOTRAILERS)
1382 printf("N");
1383 if (ptr->flags & IFF_NOARP)
1384 printf("O");
1385 if (ptr->flags & IFF_POINTOPOINT)
1386 printf("P");
1387 if (ptr->flags & IFF_RUNNING)
1388 printf("R");
1389 if (ptr->flags & IFF_UP)
1390 printf("U");
1391 printf("\n");
1394 static int iface_info(void)
1396 if (skfd < 0) {
1397 if ((skfd = sockets_open(0)) < 0) {
1398 perror("socket");
1399 exit(1);
1401 printf(_("Kernel Interface table\n"));
1403 printf(_("Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg\n"));
1405 if (for_all_interfaces(do_if_print, &flag_all) < 0) {
1406 perror(_("missing interface information"));
1407 exit(1);
1409 if (flag_cnt)
1410 free_interface_list();
1411 else {
1412 close(skfd);
1413 skfd = -1;
1416 return 0;
1420 static void version(void)
1422 printf("%s\n%s\n%s\n%s\n", Release, Version, Signature, Features);
1423 exit(E_VERSION);
1427 static void usage(void)
1429 fprintf(stderr, _("usage: netstat [-veenNcCF] [<Af>] -r netstat {-V|--version|-h|--help}\n"));
1430 fprintf(stderr, _(" netstat [-vnNcaeol] [<Socket> ...]\n"));
1431 fprintf(stderr, _(" netstat { [-veenNac] -i | [-cnNe] -M | -s }\n\n"));
1433 fprintf(stderr, _(" -r, --route display routing table\n"));
1434 fprintf(stderr, _(" -i, --interfaces display interface table\n"));
1435 fprintf(stderr, _(" -g, --groups display multicast group memberships\n"));
1436 fprintf(stderr, _(" -s, --statistics display networking statistics (like SNMP)\n"));
1437 #if HAVE_FW_MASQUERADE
1438 fprintf(stderr, _(" -M, --masquerade display masqueraded connections\n\n"));
1439 #endif
1440 fprintf(stderr, _(" -v, --verbose be verbose\n"));
1441 fprintf(stderr, _(" -n, --numeric dont resolve names\n"));
1442 fprintf(stderr, _(" -N, --symbolic resolve hardware names\n"));
1443 fprintf(stderr, _(" -e, --extend display other/more information\n"));
1444 fprintf(stderr, _(" -p, --programs display PID/Program name for sockets\n"));
1445 fprintf(stderr, _(" -c, --continuous continuous listing\n\n"));
1446 fprintf(stderr, _(" -l, --listening display listening server sockets\n"));
1447 fprintf(stderr, _(" -a, --all, --listening display all sockets (default: connected)\n"));
1448 fprintf(stderr, _(" -o, --timers display timers\n"));
1449 fprintf(stderr, _(" -F, --fib display Forwarding Information Base (default)\n"));
1450 fprintf(stderr, _(" -C, --cache display routing cache instead of FIB\n\n"));
1452 fprintf(stderr, _(" <Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom\n"));
1453 fprintf(stderr, _(" <AF>=Use '-A <af>' or '--<af>' Default: %s\n"), DFLT_AF);
1454 fprintf(stderr, _(" List of possible address families (which support routing):\n"));
1455 print_aflist(1); /* 1 = routeable */
1456 exit(E_USAGE);
1460 int main
1461 (int argc, char *argv[]) {
1462 int i;
1463 int lop;
1464 struct option longopts[] =
1466 AFTRANS_OPTS,
1467 {"version", 0, 0, 'V'},
1468 {"interfaces", 0, 0, 'i'},
1469 {"help", 0, 0, 'h'},
1470 {"route", 0, 0, 'r'},
1471 {"netlink", 2, 0, 'L'},
1472 #if HAVE_FW_MASQUERADE
1473 {"masquerade", 0, 0, 'M'},
1474 #endif
1475 {"protocol", 1, 0, 'A'},
1476 {"tcp", 0, 0, 't'},
1477 {"udp", 0, 0, 'u'},
1478 {"raw", 0, 0, 'w'},
1479 {"unix", 0, 0, 'x'},
1480 {"listening", 0, 0, 'l'},
1481 {"all", 0, 0, 'a'},
1482 {"timers", 0, 0, 'o'},
1483 {"continuous", 0, 0, 'c'},
1484 {"extend", 0, 0, 'e'},
1485 {"programs", 0, 0, 'p'},
1486 {"verbose", 0, 0, 'v'},
1487 {"statistics", 0, 0, 's'},
1488 {"numeric", 0, 0, 'n'},
1489 {"symbolic", 0, 0, 'N'},
1490 {"cache", 0, 0, 'C'},
1491 {"fib", 0, 0, 'F'},
1492 {"groups", 0, 0, 'g'},
1493 {NULL, 0, 0, 0}
1496 #if I18N
1497 bindtextdomain("net-tools", "/usr/share/locale");
1498 textdomain("net-tools");
1499 #endif
1500 getroute_init(); /* Set up AF routing support */
1502 afname[0] = '\0';
1503 while ((i = getopt_long(argc, argv, "MCFA:acdegphinNorstuVv?wxl", longopts, &lop)) != EOF)
1504 switch (i) {
1505 case -1:
1506 break;
1507 case 1:
1508 if (lop < 0 || lop >= AFTRANS_CNT) {
1509 EINTERN("netstat.c", "longopts 1 range");
1510 break;
1512 if (aftrans_opt(longopts[lop].name))
1513 exit(1);
1514 break;
1515 case 'A':
1516 if (aftrans_opt(optarg))
1517 exit(1);
1518 break;
1519 case 'M':
1520 flag_mas++;
1521 break;
1522 case 'a':
1523 flag_all++;
1524 break;
1525 case 'l':
1526 flag_lst++;
1527 break;
1528 case 'c':
1529 flag_cnt++;
1530 break;
1532 case 'd':
1533 flag_deb++;
1534 break;
1535 case 'g':
1536 flag_igmp++;
1537 break;
1538 case 'e':
1539 flag_exp++;
1540 break;
1541 case 'p':
1542 flag_prg++;
1543 break;
1544 case 'i':
1545 flag_int++;
1546 break;
1548 case 'n':
1549 flag_not |= FLAG_NUM;
1550 break;
1551 case 'N':
1552 flag_not |= FLAG_SYM;
1553 break;
1554 case 'C':
1555 flag_cf |= FLAG_CACHE;
1556 break;
1557 case 'F':
1558 flag_cf |= FLAG_FIB;
1559 break;
1560 case 'o':
1561 flag_opt++;
1562 break;
1563 case 'V':
1564 version();
1565 /*NOTREACHED */
1566 case 'v':
1567 flag_ver |= FLAG_VERBOSE;
1568 break;
1569 case 'r':
1570 flag_rou++;
1571 break;
1573 case 't':
1574 flag_tcp++;
1575 break;
1577 case 'u':
1578 flag_udp++;
1579 break;
1580 case 'w':
1581 flag_raw++;
1582 break;
1583 case 'x':
1584 if (aftrans_opt("unix"))
1585 exit(1);
1586 break;
1587 case '?':
1588 case 'h':
1589 usage();
1590 case 's':
1591 flag_sta++;
1594 if (flag_int + flag_rou + flag_mas + flag_sta > 1)
1595 usage();
1597 if ((flag_inet || flag_inet6 || flag_sta) && !(flag_tcp || flag_udp || flag_raw))
1598 flag_tcp = flag_udp = flag_raw = 1;
1600 if ((flag_tcp || flag_udp || flag_raw || flag_igmp) && !(flag_inet || flag_inet6))
1601 flag_inet = flag_inet6 = 1;
1603 flag_arg = flag_tcp + flag_udp + flag_raw + flag_unx + flag_ipx
1604 + flag_ax25 + flag_netrom + flag_igmp;
1606 if (flag_mas) {
1607 #if HAVE_FW_MASQUERADE && HAVE_AFINET
1608 #if MORE_THAN_ONE_MASQ_AF
1609 if (!afname[0])
1610 strcpy(afname, DFLT_AF);
1611 #endif
1612 for (;;) {
1613 i = ip_masq_info(flag_not, flag_exp);
1614 if (i || !flag_cnt)
1615 break;
1616 sleep(1);
1618 #else
1619 ENOSUPP("netstat.c", "FW_MASQUERADE");
1620 i = -1;
1621 #endif
1622 return (i);
1625 if (flag_sta) {
1626 inittab();
1627 parsesnmp(flag_raw, flag_tcp, flag_udp);
1628 exit(0);
1631 if (flag_rou) {
1632 int options = 0;
1634 if (!afname[0])
1635 strcpy(afname, DFLT_AF);
1637 if (flag_exp == 2)
1638 flag_exp = 1;
1639 else if (flag_exp == 1)
1640 flag_exp = 2;
1642 options = (flag_exp & FLAG_EXT) | flag_not | flag_cf | flag_ver;
1643 if (!flag_cf)
1644 options |= FLAG_FIB;
1646 for (;;) {
1647 i = route_info(afname, options);
1648 if (i || !flag_cnt)
1649 break;
1650 sleep(1);
1652 return (i);
1654 if (flag_int) {
1655 for (;;) {
1656 i = iface_info();
1657 if (!flag_cnt || i)
1658 break;
1659 sleep(1);
1661 return (i);
1663 for (;;) {
1664 if (!flag_arg || flag_tcp || flag_udp || flag_raw) {
1665 #if HAVE_AFINET
1666 prg_cache_load();
1667 printf(_("Active Internet connections ")); /* xxx */
1669 if (flag_all)
1670 printf(_("(servers and established)"));
1671 else {
1672 if (flag_lst)
1673 printf(_("(only servers)"));
1674 else
1675 printf(_("(w/o servers)"));
1677 printf(_("\nProto Recv-Q Send-Q Local Address Foreign Address State ")); /* xxx */
1678 if (flag_exp > 1)
1679 printf(_(" User Inode "));
1680 print_progname_banner();
1681 if (flag_opt)
1682 printf(_(" Timer")); /* xxx */
1683 printf("\n");
1684 #else
1685 if (flag_arg) {
1686 i = 1;
1687 ENOSUPP("netstat", "AF INET");
1689 #endif
1691 #if HAVE_AFINET
1692 if (!flag_arg || flag_tcp) {
1693 i = tcp_info();
1694 if (i)
1695 return (i);
1697 if (!flag_arg || flag_udp) {
1698 i = udp_info();
1699 if (i)
1700 return (i);
1702 if (!flag_arg || flag_raw) {
1703 i = raw_info();
1704 if (i)
1705 return (i);
1708 if (flag_igmp) {
1709 #if HAVE_AFINET6
1710 printf( "IPv6/");
1711 #endif
1712 printf( _("IPv4 Group Memberships\n") );
1713 printf( _("Interface RefCnt Group\n") );
1714 printf( "--------------- ------ ---------------------\n" );
1715 i = igmp_info();
1716 if (i)
1717 return (i);
1719 #endif
1721 if (!flag_arg || flag_unx) {
1722 #if HAVE_AFUNIX
1723 prg_cache_load();
1724 i = unix_info();
1725 if (i)
1726 return (i);
1727 #else
1728 if (flag_arg) {
1729 i = 1;
1730 ENOSUPP("netstat", "AF UNIX");
1732 #endif
1734 if (!flag_arg || flag_ipx) {
1735 #if HAVE_AFIPX
1736 i = ipx_info();
1737 if (i)
1738 return (i);
1739 #else
1740 if (flag_arg) {
1741 i = 1;
1742 ENOSUPP("netstat", "AF IPX");
1744 #endif
1746 if (!flag_arg || flag_ax25) {
1747 #if HAVE_AFAX25
1748 i = ax25_info();
1749 if (i)
1750 return (i);
1751 #else
1752 if (flag_arg) {
1753 i = 1;
1754 ENOSUPP("netstat", "AF AX25");
1756 #endif
1758 if (!flag_arg || flag_netrom) {
1759 #if HAVE_AFNETROM
1760 i = netrom_info();
1761 if (i)
1762 return (i);
1763 #else
1764 if (flag_arg) {
1765 i = 1;
1766 ENOSUPP("netstat", "AF NETROM");
1768 #endif
1770 if (!flag_cnt || i)
1771 break;
1772 sleep(1);
1773 prg_cache_clear();
1775 return (i);