897b6bfa11813882327f9a36f1a5e32ca7713bdf
[platform/upstream/net-tools.git] / netstat.c
1 /*
2  * netstat    This file contains an implementation of the command
3  *              that helps in debugging the networking modules.
4  *
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.
8  *
9  * Version:     $Id: netstat.c,v 1.73 2011-04-20 01:35:22 ecki Exp $
10  *
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>
18  *
19  * Tuned for NET3 by:
20  *              Alan Cox, <A.Cox@swansea.ac.uk>
21  *              Copyright (c) 1993  Fred Baumgarten
22  *
23  * Modified:
24  *
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
40  *
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
58  *
59  *990420 {1.38} Tuan Hoang              removed a useless assignment from igmp_do_one()
60  *20010404 {1.39} Arnaldo Carvalho de Melo - use setlocale
61  *20081201 {1.42} Brian Micek           added -L|--udplite options for RFC 3828 
62  *20020722 {1.51} Thomas Preusser       added SCTP over IPv4 support
63  *
64  *              This program is free software; you can redistribute it
65  *              and/or  modify it under  the terms of  the GNU General
66  *              Public  License as  published  by  the  Free  Software
67  *              Foundation;  either  version 2 of the License, or  (at
68  *              your option) any later version.
69  *
70  */
71 #include <errno.h>
72 #include <stdio.h>
73 #include <stdlib.h>
74 #include <string.h>
75 #include <strings.h>
76 #include <unistd.h>
77 #include <ctype.h>
78 #include <fcntl.h>
79 #include <netdb.h>
80 #include <paths.h>
81 #include <pwd.h>
82 #include <getopt.h>
83 #include <sys/param.h>
84 #include <sys/socket.h>
85 #include <arpa/inet.h>
86 #include <netinet/in.h>
87 #include <sys/ioctl.h>
88 #include <sys/stat.h>
89 #include <net/if.h>
90 #include <dirent.h>
91 #include <attr/xattr.h>
92
93 #if HAVE_SELINUX
94 #include <selinux/selinux.h>
95 #endif
96 #include "net-support.h"
97 #include "pathnames.h"
98 #include "version.h"
99 #include "config.h"
100 #include "intl.h"
101 #include "sockets.h"
102 #include "interface.h"
103 #include "util.h"
104 #include "proc.h"
105
106 #if HAVE_AFBLUETOOTH
107 #include <bluetooth/bluetooth.h>
108 #endif
109
110 #define PROGNAME_WIDTH 20
111 #define SELINUX_WIDTH 50
112
113 #define SMK_WIDTH 27
114 #define SMK_BANNER_IN "IPIN"
115 #define SMK_BANNER_OUT "IPOUT"
116 #define SMK_LABELLEN 256
117 #define SMK_ATTR_IN "security.SMACK64IPIN"
118 #define SMK_ATTR_OUT "security.SMACK64IPOUT"
119
120 #if !defined(s6_addr32) && defined(in6a_words)
121 #define s6_addr32 in6a_words    /* libinet6                     */
122 #endif
123
124 /* prototypes for statistics.c */
125 void parsesnmp(int, int, int);
126 void inittab(void);
127 void parsesnmp6(int, int, int);
128 void inittab6(void);
129
130 typedef enum {
131     SS_FREE = 0,                /* not allocated                */
132     SS_UNCONNECTED,             /* unconnected to any socket    */
133     SS_CONNECTING,              /* in process of connecting     */
134     SS_CONNECTED,               /* connected to socket          */
135     SS_DISCONNECTING            /* in process of disconnecting  */
136 } socket_state;
137
138 #define SO_ACCEPTCON    (1<<16) /* performed a listen           */
139 #define SO_WAITDATA     (1<<17) /* wait data to read            */
140 #define SO_NOSPACE      (1<<18) /* no space to write            */
141
142 #define DFLT_AF "inet"
143
144 #define FEATURE_NETSTAT
145 #include "lib/net-features.h"
146
147 char *Release = RELEASE, *Version = "netstat 1.42 (2001-04-15)", *Signature = "Fred Baumgarten, Alan Cox, Bernd Eckenfels, Phil Blundell, Tuan Hoang, Brian Micek and others";
148
149
150 #define E_READ  -1
151 #define E_IOCTL -3
152
153 int flag_int = 0;
154 int flag_rou = 0;
155 int flag_mas = 0;
156 int flag_sta = 0;
157
158 int flag_all = 0;
159 int flag_lst = 0;
160 int flag_cnt = 0;
161 int flag_deb = 0;
162 int flag_not = 0;
163 int flag_cf  = 0;
164 int flag_opt = 0;
165 int flag_raw = 0;
166 int flag_tcp = 0;
167 int flag_sctp= 0;
168 int flag_udp = 0;
169 int flag_udplite = 0;
170 int flag_igmp= 0;
171 int flag_rom = 0;
172 int flag_exp = 1;
173 int flag_wide= 0;
174 int flag_prg = 0;
175 int flag_arg = 0;
176 int flag_ver = 0;
177 int flag_l2cap = 0;
178 int flag_rfcomm = 0;
179 int flag_selinux = 0;
180 int flag_smack = 0;
181
182 FILE *procinfo;
183
184 #define INFO_GUTS1(file,name,proc,prot)                 \
185   procinfo = proc_fopen((file));                        \
186   if (procinfo == NULL) {                               \
187     if (errno != ENOENT) {                              \
188       perror((file));                                   \
189       return -1;                                        \
190     }                                                   \
191     if (flag_arg || flag_ver)                           \
192       ESYSNOT("netstat", (name));                       \
193     if (flag_arg)                                       \
194       rc = 1;                                           \
195   } else {                                              \
196     do {                                                \
197       if (fgets(buffer, sizeof(buffer), procinfo))      \
198         (proc)(lnr++, buffer,prot);                     \
199     } while (!feof(procinfo));                          \
200     fclose(procinfo);                                   \
201   }
202
203 #if HAVE_AFINET6
204 #define INFO_GUTS2(file,proc,prot)                      \
205   lnr = 0;                                              \
206   procinfo = proc_fopen((file));                        \
207   if (procinfo != NULL) {                               \
208     do {                                                \
209       if (fgets(buffer, sizeof(buffer), procinfo))      \
210         (proc)(lnr++, buffer,prot);                     \
211     } while (!feof(procinfo));                          \
212     fclose(procinfo);                                   \
213   }
214 #else
215 #define INFO_GUTS2(file,proc,prot)
216 #endif
217
218 #define INFO_GUTS3                                      \
219  return rc;
220
221 #define INFO_GUTS6(file,file6,name,proc,prot4,prot6)    \
222  char buffer[8192];                                     \
223  int rc = 0;                                            \
224  int lnr = 0;                                           \
225  if (!flag_arg || flag_inet) {                          \
226     INFO_GUTS1(file,name,proc,prot4)                    \
227  }                                                      \
228  if (!flag_arg || flag_inet6) {                         \
229     INFO_GUTS2(file6,proc,prot6)                        \
230  }                                                      \
231  INFO_GUTS3
232
233 #define INFO_GUTS(file,name,proc,prot)                  \
234  char buffer[8192];                                     \
235  int rc = 0;                                            \
236  int lnr = 0;                                           \
237  INFO_GUTS1(file,name,proc,prot)                        \
238  INFO_GUTS3
239
240 #define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)
241 #define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)
242 #define PROGNAME_WIDTH2(s) #s
243
244 #define SELINUX_WIDTHs SELINUX_WIDTH1(SELINUX_WIDTH)
245 #define SELINUX_WIDTH1(s) SELINUX_WIDTH2(s)
246 #define SELINUX_WIDTH2(s) #s
247
248 #define SMK_WIDTHs SMK_WIDTH1(SMK_WIDTH)
249 #define SMK_WIDTH1(s) SMK_WIDTH2(s)
250 #define SMK_WIDTH2(s) #s
251
252 #define PRG_HASH_SIZE 211
253
254 static struct smk {
255     char in[SMK_LABELLEN];
256     char out[SMK_LABELLEN];
257 };
258
259 static struct prg_node {
260     struct prg_node *next;
261     unsigned long inode;
262     char name[PROGNAME_WIDTH];
263     char scon[SELINUX_WIDTH];
264     struct smk smk_labels;
265 } *prg_hash[PRG_HASH_SIZE];
266
267 static char prg_cache_loaded = 0;
268
269 #define PRG_HASHIT(x) ((x) % PRG_HASH_SIZE)
270
271 #define PROGNAME_BANNER "PID/Program name"
272 #define SELINUX_BANNER "Security Context"
273
274 #define print_progname_banner() do { if (flag_prg) printf(" %-" PROGNAME_WIDTHs "s",PROGNAME_BANNER); } while (0)
275
276 #define print_selinux_banner() do { if (flag_selinux) printf("%-" SELINUX_WIDTHs "s"," " SELINUX_BANNER); } while (0)
277
278 #define print_smack_banner() do { if (flag_smack) printf(" %-" SMK_WIDTHs "s" " " "%-" SMK_WIDTHs "s", SMK_BANNER_IN, SMK_BANNER_OUT); } while (0)
279
280 #define PRG_LOCAL_ADDRESS "local_address"
281 #define PRG_INODE        "inode"
282 #define PRG_SOCKET_PFX    "socket:["
283 #define PRG_SOCKET_PFXl (strlen(PRG_SOCKET_PFX))
284 #define PRG_SOCKET_PFX2   "[0000]:"
285 #define PRG_SOCKET_PFX2l  (strlen(PRG_SOCKET_PFX2))
286
287
288 #ifndef LINE_MAX
289 #define LINE_MAX 4096
290 #endif
291
292 #define PATH_PROC          "/proc"
293 #define PATH_FD_SUFF    "fd"
294 #define PATH_FD_SUFFl       strlen(PATH_FD_SUFF)
295 #define PATH_PROC_X_FD      PATH_PROC "/%s/" PATH_FD_SUFF
296 #define PATH_CMDLINE    "cmdline"
297 #define PATH_CMDLINEl       strlen(PATH_CMDLINE)
298
299 static void prg_cache_add(unsigned long inode, char *name, const char *scon, struct smk *const smk_labels)
300 {
301     unsigned hi = PRG_HASHIT(inode);
302     struct prg_node **pnp,*pn;
303
304     prg_cache_loaded = 2;
305     for (pnp = prg_hash + hi; (pn = *pnp); pnp = &pn->next) {
306         if (pn->inode == inode) {
307             /* Some warning should be appropriate here
308                as we got multiple processes for one i-node */
309             return;
310         }
311     }
312     if (!(*pnp = malloc(sizeof(**pnp)))) 
313         return;
314     pn = *pnp;
315     pn->next = NULL;
316     pn->inode = inode;
317     if (strlen(name) > sizeof(pn->name) - 1) 
318         name[sizeof(pn->name) - 1] = '\0';
319     strcpy(pn->name, name);
320
321     {
322         int len = (strlen(scon) - sizeof(pn->scon)) + 1;
323         if (len > 0) 
324             strcpy(pn->scon, &scon[len + 1]);
325         else
326             strcpy(pn->scon, scon);
327     }
328
329     strncpy(pn->smk_labels.in, smk_labels->in, SMK_LABELLEN);
330     strncpy(pn->smk_labels.out, smk_labels->out, SMK_LABELLEN);
331 }
332
333 static const char *prg_cache_get(unsigned long inode)
334 {
335     unsigned hi = PRG_HASHIT(inode);
336     struct prg_node *pn;
337
338     for (pn = prg_hash[hi]; pn; pn = pn->next)
339         if (pn->inode == inode)
340             return (pn->name);
341     return ("-");
342 }
343
344 static const char *prg_cache_get_con(unsigned long inode)
345 {
346     unsigned hi = PRG_HASHIT(inode);
347     struct prg_node *pn;
348
349     for (pn = prg_hash[hi]; pn; pn = pn->next)
350         if (pn->inode == inode)
351             return (pn->scon);
352     return ("-");
353 }
354
355 static const char *prg_cache_get_smkin(unsigned long inode)
356 {
357     unsigned hi = PRG_HASHIT(inode);
358     struct prg_node *pn;
359
360     for (pn = prg_hash[hi]; pn; pn = pn->next)
361         if (pn->inode == inode)
362             return pn->smk_labels.in;
363     return ("-");
364 }
365
366 static const char *prg_cache_get_smkout(unsigned long inode)
367 {
368     unsigned hi = PRG_HASHIT(inode);
369     struct prg_node *pn;
370
371     for (pn = prg_hash[hi]; pn; pn = pn->next)
372         if (pn->inode == inode)
373             return pn->smk_labels.out;
374     return ("-");
375 }
376
377 static void prg_cache_clear(void)
378 {
379     struct prg_node **pnp,*pn;
380
381     if (prg_cache_loaded == 2)
382         for (pnp = prg_hash; pnp < prg_hash + PRG_HASH_SIZE; pnp++)
383             while ((pn = *pnp)) {
384                 *pnp = pn->next;
385                 free(pn);
386             }
387     prg_cache_loaded = 0;
388 }
389
390 static void wait_continous(void)
391 {
392     fflush(stdout);
393     sleep(1);
394 }
395
396 static int extract_type_1_socket_inode(const char lname[], unsigned long * inode_p) {
397
398     /* If lname is of the form "socket:[12345]", extract the "12345"
399        as *inode_p.  Otherwise, return -1 as *inode_p.
400        */
401
402     if (strlen(lname) < PRG_SOCKET_PFXl+3) return(-1);
403     
404     if (memcmp(lname, PRG_SOCKET_PFX, PRG_SOCKET_PFXl)) return(-1);
405     if (lname[strlen(lname)-1] != ']') return(-1);
406
407     {
408         char inode_str[strlen(lname + 1)];  /* e.g. "12345" */
409         const int inode_str_len = strlen(lname) - PRG_SOCKET_PFXl - 1;
410         char *serr;
411
412         strncpy(inode_str, lname+PRG_SOCKET_PFXl, inode_str_len);
413         inode_str[inode_str_len] = '\0';
414         *inode_p = strtoul(inode_str, &serr, 0);
415         if (!serr || *serr || *inode_p == ~0)
416             return(-1);
417     }
418     return(0);
419 }
420
421
422
423 static int extract_type_2_socket_inode(const char lname[], unsigned long * inode_p) {
424
425     /* If lname is of the form "[0000]:12345", extract the "12345"
426        as *inode_p.  Otherwise, return -1 as *inode_p.
427        */
428
429     if (strlen(lname) < PRG_SOCKET_PFX2l+1) return(-1);
430     if (memcmp(lname, PRG_SOCKET_PFX2, PRG_SOCKET_PFX2l)) return(-1);
431
432     {
433         char *serr;
434
435         *inode_p = strtoul(lname + PRG_SOCKET_PFX2l, &serr, 0);
436         if (!serr || *serr || *inode_p == ~0)
437             return(-1);
438     }
439     return(0);
440 }
441
442
443 static void get_smack_labels(const char *line, struct smk *smk_labels) {
444     int ret;
445
446     ret = getxattr(line, SMK_ATTR_OUT, smk_labels->out, SMK_LABELLEN);
447     if (ret == -1)
448         smk_labels->out[0] = '\0';
449     else
450         smk_labels->out[ret] = '\0';
451
452     ret = getxattr(line, SMK_ATTR_IN, smk_labels->in, SMK_LABELLEN);
453     if (ret == -1)
454         smk_labels->in[0] = '\0';
455     else
456         smk_labels->in[ret] = '\0';
457 }
458
459 static void prg_cache_load(void)
460 {
461     char line[LINE_MAX], eacces=0;
462     int procfdlen, fd, cmdllen, lnamelen;
463     char lname[30], cmdlbuf[512], finbuf[PROGNAME_WIDTH];
464     unsigned long inode;
465     const char *cs, *cmdlp;
466     DIR *dirproc = NULL, *dirfd = NULL;
467     struct dirent *direproc, *direfd;
468 #if HAVE_SELINUX
469     security_context_t scon = NULL;
470 #endif
471     struct smk smk_labels;
472
473     if (prg_cache_loaded || !flag_prg) return;
474     prg_cache_loaded = 1;
475     cmdlbuf[sizeof(cmdlbuf) - 1] = '\0';
476     if (!(dirproc=opendir(PATH_PROC))) goto fail;
477     while (errno = 0, direproc = readdir(dirproc)) {
478         for (cs = direproc->d_name; *cs; cs++)
479             if (!isdigit(*cs)) 
480                 break;
481         if (*cs) 
482             continue;
483         procfdlen = snprintf(line,sizeof(line),PATH_PROC_X_FD,direproc->d_name);
484         if (procfdlen <= 0 || procfdlen >= sizeof(line) - 5) 
485             continue;
486         errno = 0;
487         dirfd = opendir(line);
488         if (! dirfd) {
489             if (errno == EACCES) 
490                 eacces = 1;
491             continue;
492         }
493         line[procfdlen] = '/';
494         cmdlp = NULL;
495         while ((direfd = readdir(dirfd))) {
496            /* Skip . and .. */
497            if (!isdigit(direfd->d_name[0]))
498                continue;
499             if (procfdlen + 1 + strlen(direfd->d_name) + 1 > sizeof(line)) 
500                 continue;
501             memcpy(line + procfdlen - PATH_FD_SUFFl, PATH_FD_SUFF "/",
502                    PATH_FD_SUFFl + 1);
503             strcpy(line + procfdlen + 1, direfd->d_name);
504             lnamelen = readlink(line, lname, sizeof(lname) - 1);
505             if (lnamelen == -1)
506                 continue;
507             lname[lnamelen] = '\0';  /*make it a null-terminated string*/
508
509             if (extract_type_1_socket_inode(lname, &inode) < 0)
510                 if (extract_type_2_socket_inode(lname, &inode) < 0)
511                     continue;
512
513             get_smack_labels(line, &smk_labels);
514
515             if (!cmdlp) {
516                 if (procfdlen - PATH_FD_SUFFl + PATH_CMDLINEl >= 
517                     sizeof(line) - 5) 
518                     continue;
519                 strcpy(line + procfdlen-PATH_FD_SUFFl, PATH_CMDLINE);
520                 fd = open(line, O_RDONLY);
521                 if (fd < 0) 
522                     continue;
523                 cmdllen = read(fd, cmdlbuf, sizeof(cmdlbuf) - 1);
524                 if (close(fd)) 
525                     continue;
526                 if (cmdllen == -1) 
527                     continue;
528                 if (cmdllen < sizeof(cmdlbuf) - 1) 
529                     cmdlbuf[cmdllen]='\0';
530                 if (cmdlbuf[0] == '/' && (cmdlp = strrchr(cmdlbuf, '/'))) 
531                     cmdlp++;
532                 else 
533                     cmdlp = cmdlbuf;
534             }
535
536             snprintf(finbuf, sizeof(finbuf), "%s/%s", direproc->d_name, cmdlp);
537 #if HAVE_SELINUX
538             if (getpidcon(atoi(direproc->d_name), &scon) == -1) {
539                     scon=strdup("-");
540             }
541             prg_cache_add(inode, finbuf, scon, &smk_labels);
542             freecon(scon);
543 #else
544             prg_cache_add(inode, finbuf, "-", &smk_labels);
545 #endif
546             smk_labels.in[0] = '\0';
547             smk_labels.out[0] = '\0';
548         }
549         closedir(dirfd); 
550         dirfd = NULL;
551     }
552     if (dirproc) 
553         closedir(dirproc);
554     if (dirfd) 
555         closedir(dirfd);
556     if (!eacces) 
557         return;
558     if (prg_cache_loaded == 1) {
559     fail:
560         fprintf(stderr,_("(No info could be read for \"-p\": geteuid()=%d but you should be root.)\n"),
561                 geteuid());
562     }
563     else
564         fprintf(stderr, _("(Not all processes could be identified, non-owned process info\n"
565                          " will not be shown, you would have to be root to see it all.)\n"));
566 }
567
568 #if HAVE_AFNETROM
569 static const char *netrom_state[] =
570 {
571     N_("LISTENING"),
572     N_("CONN SENT"),
573     N_("DISC SENT"),
574     N_("ESTABLISHED")
575 };
576
577 static int netrom_info(void)
578 {
579     FILE *f;
580     char buffer[256], dev[16];
581     int st, vs, vr, sendq, recvq, ret;
582
583     f = proc_fopen(_PATH_PROCNET_NR);
584     if (f == NULL) {
585         if (errno != ENOENT) {
586             perror(_PATH_PROCNET_NR);
587             return (-1);
588         }
589         if (flag_arg || flag_ver)
590             ESYSNOT("netstat", "AF NETROM");
591         if (flag_arg)
592             return (1);
593         else
594             return (0);
595     }
596     printf(_("Active NET/ROM sockets\n"));
597     printf(_("User       Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q\n"));
598     if (fgets(buffer, 256, f))
599         /* eat line */;
600
601     while (fgets(buffer, 256, f)) {
602         buffer[9] = 0;
603         buffer[19] = 0;
604         buffer[29] = 0;
605         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",
606                dev, &st, &vs, &vr, &sendq, &recvq);
607         if (ret != 6) {
608             printf(_("Problem reading data from %s\n"), _PATH_PROCNET_NR);
609             continue;
610         }
611         printf("%-9s  %-9s  %-9s  %-6s  %-11s  %03d/%03d  %-6d  %-6d\n",
612                buffer, buffer + 10, buffer + 20,
613                dev,
614                _(netrom_state[st]),
615                vr, vs, sendq, recvq);
616     }
617     fclose(f);
618     return 0;
619 }
620 #endif
621
622 /* These enums are used by IPX too. :-( */
623 enum {
624     TCP_ESTABLISHED = 1,
625     TCP_SYN_SENT,
626     TCP_SYN_RECV,
627     TCP_FIN_WAIT1,
628     TCP_FIN_WAIT2,
629     TCP_TIME_WAIT,
630     TCP_CLOSE,
631     TCP_CLOSE_WAIT,
632     TCP_LAST_ACK,
633     TCP_LISTEN,
634     TCP_CLOSING                 /* now a valid state */
635 };
636
637 #if HAVE_AFINET || HAVE_AFINET6
638
639 static const char *tcp_state[] =
640 {
641     "",
642     N_("ESTABLISHED"),
643     N_("SYN_SENT"),
644     N_("SYN_RECV"),
645     N_("FIN_WAIT1"),
646     N_("FIN_WAIT2"),
647     N_("TIME_WAIT"),
648     N_("CLOSE"),
649     N_("CLOSE_WAIT"),
650     N_("LAST_ACK"),
651     N_("LISTEN"),
652     N_("CLOSING")
653 };
654
655 static void finish_this_one(int uid, unsigned long inode, const char *timers)
656 {
657     struct passwd *pw;
658
659     if (flag_exp > 1) {
660         if (!(flag_not & FLAG_NUM_USER) && ((pw = getpwuid(uid)) != NULL))
661             printf(" %-10s ", pw->pw_name);
662         else
663             printf(" %-10d ", uid);
664         printf("%-10lu",inode);
665     }
666     if (flag_prg)
667         printf(" %-" PROGNAME_WIDTHs "s",prg_cache_get(inode));
668     if (flag_selinux)
669         printf(" %-" SELINUX_WIDTHs "s",prg_cache_get_con(inode));
670
671     if (flag_opt)
672         printf(" %s", timers);
673     putchar('\n');
674 }
675
676 static void igmp_do_one(int lnr, const char *line,const char *prot)
677 {
678     char mcast_addr[128];
679 #if HAVE_AFINET6
680     struct sockaddr_in6 mcastaddr;
681     char addr6[INET6_ADDRSTRLEN];
682     struct in6_addr in6;
683     extern struct aftype inet6_aftype;
684 #else
685     struct sockaddr_in mcastaddr;
686 #endif
687     struct aftype *ap;
688     static int idx_flag = 0;
689     static int igmp6_flag = 0;
690     static char device[16];
691     int num, idx, refcnt;
692
693     if (lnr == 0) {
694         /* IPV6 ONLY */
695         /* igmp6 file does not have any comments on first line */
696         if ( strstr( line, "Device" ) == NULL ) {
697             igmp6_flag = 1;
698         } else {
699             /* IPV4 ONLY */
700             /* 2.1.x kernels and up have Idx field */
701             /* 2.0.x and below do not have Idx field */
702             if ( strncmp( line, "Idx", strlen("Idx") ) == 0 )
703                 idx_flag = 1;
704             else
705                 idx_flag = 0;
706             return;
707         }
708     }
709
710     if (igmp6_flag) {    /* IPV6 */
711 #if HAVE_AFINET6
712         num = sscanf( line, "%d %15s %64[0-9A-Fa-f] %d", &idx, device, mcast_addr, &refcnt );
713         if (num == 4) {
714             /* Demangle what the kernel gives us */
715             sscanf(mcast_addr, "%08X%08X%08X%08X",
716                    &in6.s6_addr32[0], &in6.s6_addr32[1],
717            &in6.s6_addr32[2], &in6.s6_addr32[3]);
718             in6.s6_addr32[0] = htonl(in6.s6_addr32[0]);
719             in6.s6_addr32[1] = htonl(in6.s6_addr32[1]);
720             in6.s6_addr32[2] = htonl(in6.s6_addr32[2]);
721             in6.s6_addr32[3] = htonl(in6.s6_addr32[3]);
722         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
723             inet6_aftype.input(1, addr6, (struct sockaddr *) &mcastaddr);
724             mcastaddr.sin6_family = AF_INET6;
725         } else {
726             fprintf(stderr, _("warning, got bogus igmp6 line %d.\n"), lnr);
727             return;
728         }
729
730         if ((ap = get_afntype(((struct sockaddr *) &mcastaddr)->sa_family)) == NULL) {
731             fprintf(stderr, _("netstat: unsupported address family %d !\n"),
732                     ((struct sockaddr *) &mcastaddr)->sa_family);
733             return;
734         }
735         safe_strncpy(mcast_addr, ap->sprint((struct sockaddr *) &mcastaddr, 
736                                       flag_not & FLAG_NUM_HOST), sizeof(mcast_addr));
737         printf("%-15s %-6d %s\n", device, refcnt, mcast_addr);
738 #endif
739     } else {    /* IPV4 */
740 #if HAVE_AFINET
741         if (line[0] != '\t') {
742             if (idx_flag) {
743                 if ((num = sscanf( line, "%d\t%10c", &idx, device)) < 2) {
744                     fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
745                     return;
746                 }
747             } else {
748                 if ( (num = sscanf( line, "%10c", device )) < 1 ) {
749                     fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
750                     return;
751                 }
752             }
753             device[10] = '\0';
754             return;
755         } else if ( line[0] == '\t' ) {
756             if ( (num = sscanf(line, "\t%8[0-9A-Fa-f] %d", mcast_addr, &refcnt)) < 2 ) {
757                 fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
758                 return;
759             }
760             sscanf( mcast_addr, "%X",
761                     &((struct sockaddr_in *) &mcastaddr)->sin_addr.s_addr );
762             ((struct sockaddr *) &mcastaddr)->sa_family = AF_INET;
763         } else {
764             fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
765             return;
766         }
767         
768         if ((ap = get_afntype(((struct sockaddr *) &mcastaddr)->sa_family)) == NULL) {
769             fprintf(stderr, _("netstat: unsupported address family %d !\n"),
770                     ((struct sockaddr *) &mcastaddr)->sa_family);
771             return;
772         }
773         safe_strncpy(mcast_addr, ap->sprint((struct sockaddr *) &mcastaddr, 
774                                       flag_not & FLAG_NUM_HOST), sizeof(mcast_addr));
775         printf("%-15s %-6d %s\n", device, refcnt, mcast_addr );
776 #endif
777     }    /* IPV4 */
778 }
779
780 #if HAVE_AFX25
781 static int x25_info(void)
782 {
783        FILE *f=proc_fopen(_PATH_PROCNET_X25);
784        char buffer[256],dev[16];
785        int st,vs,vr,sendq,recvq,lci;
786        static char *x25_state[5]=
787        {
788                "LISTENING",
789                "SABM_SENT",
790                "DISC_SENT",
791                "ESTABLISHED",
792                "RECOVERY"
793        };
794        if(!f)
795        {
796                if (errno != ENOENT) {
797                        perror(_PATH_PROCNET_X25);
798                        return(-1);
799                }
800                if (flag_arg || flag_ver)
801                        ESYSNOT("netstat","AF X25");
802                if (flag_arg)
803                        return(1);
804                else
805                        return(0);
806        }
807        printf( _("Active X.25 sockets\n"));
808        /* IMHO, Vr/Vs is not very usefull --SF */
809        printf( _("Dest         Source          Device  LCI  State        Vr/Vs  Send-Q  Recv-Q\n"));
810        if (fgets(buffer,256,f))
811                /* eat line */;
812        while(fgets(buffer,256,f))
813        {
814                buffer[10]=0;
815                buffer[20]=0;
816                sscanf(buffer+22,"%s %d %d %d %d %*d %*d %*d %*d %*d %*d %d %d %*d",
817                        dev,&lci,&st,&vs,&vr,&sendq,&recvq);
818                if (!(flag_all || lci))
819                        continue;
820                printf("%-15s %-15s %-7s %-3d  %-11s  %02d/%02d  %-6d  %-6d\n",
821                        buffer,buffer+11,
822                        dev,
823                        lci,
824                        x25_state[st],
825                        vr,vs,sendq,recvq);
826        }
827        fclose(f);
828        return 0;               
829 }
830 #endif
831
832 static int igmp_info(void)
833 {
834     INFO_GUTS6(_PATH_PROCNET_IGMP, _PATH_PROCNET_IGMP6, "AF INET (igmp)",
835                igmp_do_one, "igmp", "igmp6");
836 }
837
838 static int ip_parse_dots(uint32_t *addr, char const *src) {
839   unsigned  a, b, c, d;
840   unsigned  ret = 4-sscanf(src, "%u.%u.%u.%u", &a, &b, &c, &d);
841   *addr = htonl((a << 24)|(b << 16)|(c << 8)|d);
842   return  ret;
843 }
844
845 static void print_ip_service(struct sockaddr_in *addr, char const *protname,
846                              char *buf, unsigned size) {
847   struct aftype *ap;
848
849   if(size == 0)  return;
850
851   /* print host */
852   if((ap = get_afntype(addr->sin_family)) == NULL) {
853     fprintf(stderr, _("netstat: unsupported address family %d !\n"),
854             addr->sin_family);
855     return;
856   }
857   safe_strncpy(buf, ap->sprint((struct sockaddr*)addr, flag_not), size);
858
859   /* print service */
860   if(flag_all || (flag_lst && !addr->sin_port) || (!flag_lst && addr->sin_port)) {
861     char  bfs[32];
862
863     snprintf(bfs, sizeof(bfs), "%s",
864              get_sname(addr->sin_port, (char*)protname, flag_not & FLAG_NUM_PORT));
865
866     /* check if we must cut on host and/or service name */
867     {
868       unsigned const  bufl = strlen(buf);
869       unsigned const  bfsl = strlen(bfs);
870
871       if(bufl+bfsl+2 > size) {
872         unsigned const  half = (size-2)>>1;
873         if(bufl > half) {
874           if(bfsl > half) {
875             buf[size-2-half] = '\0';
876             bfs[half+1]      = '\0';
877           }
878           else  buf[size-2-bfsl] = '\0';
879         }
880         else  bfs[size-2-bufl] = '\0';
881       }  
882     }
883     strcat(buf, ":");
884     strcat(buf, bfs);
885   }
886 }
887
888 /* process single SCTP endpoint */
889 static void sctp_do_ept(int lnr, char const *line, const char *prot)
890 {
891   struct sockaddr_in  laddr, raddr;
892   unsigned            uid, inode;
893
894   char        l_addr[23], r_addr[23];
895
896   /* fill sockaddr_in structures */
897   {
898     unsigned  lport;
899     unsigned  ate;
900
901     if(lnr == 0)  return;
902     if(sscanf(line, "%*X %*X %*u %*u %*u %u %u %u %n",
903               &lport, &uid, &inode, &ate) < 3)  goto err;
904
905     /* decode IP address */
906     if(ip_parse_dots(&laddr.sin_addr.s_addr, line+ate))  goto err;
907     raddr.sin_addr.s_addr = htonl(0);
908     laddr.sin_family = raddr.sin_family = AF_INET;
909     laddr.sin_port = htons(lport);
910     raddr.sin_port = htons(0);
911   }
912
913   /* print IP:service to l_addr and r_addr */
914   print_ip_service(&laddr, prot, l_addr, sizeof(l_addr));
915   print_ip_service(&raddr, prot, r_addr, sizeof(r_addr));
916
917   /* Print line */
918   printf("%-4s  %6d %6d %-*s %-*s %-11s",
919          prot, 0, 0,
920          (int)netmax(23,strlen(l_addr)), l_addr,
921          (int)netmax(23,strlen(r_addr)), r_addr,
922          _(tcp_state[TCP_LISTEN]));
923   finish_this_one(uid, inode, "");
924   return;
925  err:
926   fprintf(stderr, "SCTP error in line: %d\n", lnr);
927 }
928
929 /* process single SCTP association */
930 static void sctp_do_assoc(int lnr, char const *line, const char *prot)
931 {
932   struct sockaddr_in  laddr, raddr;
933   unsigned long       rxq, txq;
934   unsigned            uid, inode;
935
936   char        l_addr[23], r_addr[23];
937
938   /* fill sockaddr_in structures */
939   {
940     unsigned    lport, rport;
941     unsigned    ate;
942     char const *addr;
943
944     if(lnr == 0)  return;
945     if(sscanf(line, "%*X %*X %*u %*u %*u %*u %*u %lu %lu %u %u %u %u %n",
946               &txq, &rxq, &uid, &inode, &lport, &rport, &ate) < 6)  goto err;
947
948     /* decode IP addresses */
949     addr = strchr(line+ate, '*');
950     if(addr == 0)  goto err;
951     if(ip_parse_dots(&laddr.sin_addr.s_addr, ++addr))  goto err;
952     addr = strchr(addr, '*');
953     if(addr == 0)  goto err;
954     if(ip_parse_dots(&raddr.sin_addr.s_addr, ++addr))  goto err;
955
956     /* complete sockaddr_in structures */
957     laddr.sin_family = raddr.sin_family = AF_INET;
958     laddr.sin_port = htons(lport);
959     raddr.sin_port = htons(rport);
960   }
961
962   /* print IP:service to l_addr and r_addr */
963   print_ip_service(&laddr, prot, l_addr, sizeof(l_addr));
964   print_ip_service(&raddr, prot, r_addr, sizeof(r_addr));
965
966   /* Print line */
967   printf("%-4s  %6ld %6ld %-*s %-*s %-11s",
968          prot, rxq, txq,
969          (int)netmax(23,strlen(l_addr)), l_addr,
970          (int)netmax(23,strlen(r_addr)), r_addr,
971          _(tcp_state[TCP_ESTABLISHED]));
972   finish_this_one(uid, inode, "");
973   return;
974  err:
975   fprintf(stderr, "SCTP error in line: %d\n", lnr);
976 }
977
978 static int sctp_info_epts(void) {
979   INFO_GUTS6(_PATH_PROCNET_SCTPEPTS, _PATH_PROCNET_SCTP6EPTS, "AF INET (sctp)",
980              sctp_do_ept, "sctp", "sctp6");
981 }
982
983 static int sctp_info_assocs(void) {
984   INFO_GUTS6(_PATH_PROCNET_SCTPASSOCS, _PATH_PROCNET_SCTP6ASSOCS, "AF INET (sctp)",
985              sctp_do_assoc, "sctp", "sctp6");
986 }
987
988 static int sctp_info(void) {
989   int  res;
990   res = sctp_info_epts();
991   if(res)  return  res;
992   return  sctp_info_assocs();
993 }
994
995 static void addr_do_one(char *buf, size_t buf_len, size_t short_len, struct aftype *ap,
996 #if HAVE_AFINET6
997                         struct sockaddr_in6 *addr,
998 #else
999                         struct sockaddr_in *addr,
1000 #endif
1001                         int port, const char *proto
1002 )
1003 {
1004     const char *sport, *saddr;
1005     size_t port_len, addr_len;
1006
1007     saddr = ap->sprint((struct sockaddr *)addr, flag_not & FLAG_NUM_HOST);
1008     sport = get_sname(htons(port), proto, flag_not & FLAG_NUM_PORT);
1009     addr_len = strlen(saddr);
1010     port_len = strlen(sport);
1011     if (!flag_wide && (addr_len + port_len > short_len)) {
1012         /* Assume port name is short */
1013         port_len = netmin(port_len, short_len - 4);
1014         addr_len = short_len - port_len;
1015         strncpy(buf, saddr, addr_len);
1016         buf[addr_len] = '\0';
1017         strcat(buf, ":");
1018         strncat(buf, sport, port_len);
1019     } else
1020         snprintf(buf, buf_len, "%s:%s", saddr, sport);
1021 }
1022
1023 static void tcp_do_one(int lnr, const char *line, const char *prot)
1024 {
1025     unsigned long rxq, txq, time_len, retr, inode;
1026     int num, local_port, rem_port, d, state, uid, timer_run, timeout;
1027     char rem_addr[128], local_addr[128], timers[64], more[512];
1028     struct aftype *ap;
1029 #if HAVE_AFINET6
1030     struct sockaddr_in6 localaddr, remaddr;
1031     char addr6[INET6_ADDRSTRLEN];
1032     struct in6_addr in6;
1033     extern struct aftype inet6_aftype;
1034 #else
1035     struct sockaddr_in localaddr, remaddr;
1036 #endif
1037
1038     if (lnr == 0)
1039         return;
1040
1041     num = sscanf(line,
1042     "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %512s\n",
1043                  &d, local_addr, &local_port, rem_addr, &rem_port, &state,
1044                  &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
1045
1046     if (!flag_all && ((flag_lst && rem_port) || (!flag_lst && !rem_port)))
1047       return;
1048
1049     if (strlen(local_addr) > 8) {
1050 #if HAVE_AFINET6
1051         /* Demangle what the kernel gives us */
1052         sscanf(local_addr, "%08X%08X%08X%08X",
1053                &in6.s6_addr32[0], &in6.s6_addr32[1],
1054            &in6.s6_addr32[2], &in6.s6_addr32[3]);
1055         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1056         inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
1057         sscanf(rem_addr, "%08X%08X%08X%08X",
1058                &in6.s6_addr32[0], &in6.s6_addr32[1],
1059                &in6.s6_addr32[2], &in6.s6_addr32[3]);
1060         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1061         inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
1062         localaddr.sin6_family = AF_INET6;
1063         remaddr.sin6_family = AF_INET6;
1064 #endif
1065     } else {
1066         sscanf(local_addr, "%X",
1067                &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
1068         sscanf(rem_addr, "%X",
1069                &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
1070         ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
1071         ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
1072     }
1073
1074     if (num < 11) {
1075         fprintf(stderr, _("warning, got bogus tcp line.\n"));
1076         return;
1077     }
1078     if ((ap = get_afntype(((struct sockaddr *) &localaddr)->sa_family)) == NULL) {
1079         fprintf(stderr, _("netstat: unsupported address family %d !\n"),
1080                 ((struct sockaddr *) &localaddr)->sa_family);
1081         return;
1082     }
1083
1084         addr_do_one(local_addr, sizeof(local_addr), 22, ap, &localaddr, local_port, "tcp");
1085         addr_do_one(rem_addr, sizeof(rem_addr), 22, ap, &remaddr, rem_port, "tcp");
1086
1087         timers[0] = '\0';
1088         if (flag_opt)
1089             switch (timer_run) {
1090             case 0:
1091                 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
1092                 break;
1093
1094             case 1:
1095                 snprintf(timers, sizeof(timers), _("on (%2.2f/%ld/%d)"),
1096                          (double) time_len / HZ, retr, timeout);
1097                 break;
1098
1099             case 2:
1100                 snprintf(timers, sizeof(timers), _("keepalive (%2.2f/%ld/%d)"),
1101                          (double) time_len / HZ, retr, timeout);
1102                 break;
1103
1104             case 3:
1105                 snprintf(timers, sizeof(timers), _("timewait (%2.2f/%ld/%d)"),
1106                          (double) time_len / HZ, retr, timeout);
1107                 break;
1108
1109             default:
1110                 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
1111                          timer_run, (double) time_len / HZ, retr, timeout);
1112                 break;
1113             }
1114
1115         printf("%-4s  %6ld %6ld %-*s %-*s %-11s",
1116                prot, rxq, txq, (int)netmax(23,strlen(local_addr)), local_addr, (int)netmax(23,strlen(rem_addr)), rem_addr, _(tcp_state[state]));
1117
1118         finish_this_one(uid,inode,timers);
1119 }
1120
1121 static int tcp_info(void)
1122 {
1123     INFO_GUTS6(_PATH_PROCNET_TCP, _PATH_PROCNET_TCP6, "AF INET (tcp)",
1124                tcp_do_one, "tcp", "tcp6");
1125 }
1126
1127 static void udp_do_one(int lnr, const char *line,const char *prot)
1128 {
1129     char local_addr[64], rem_addr[64];
1130     char *udp_state, timers[64], more[512];
1131     int num, local_port, rem_port, d, state, timer_run, uid, timeout;
1132 #if HAVE_AFINET6
1133     struct sockaddr_in6 localaddr, remaddr;
1134     char addr6[INET6_ADDRSTRLEN];
1135     struct in6_addr in6;
1136     extern struct aftype inet6_aftype;
1137 #else
1138     struct sockaddr_in localaddr, remaddr;
1139 #endif
1140     struct aftype *ap;
1141     unsigned long rxq, txq, time_len, retr, inode;
1142
1143     if (lnr == 0)
1144         return;
1145
1146     more[0] = '\0';
1147     num = sscanf(line,
1148                  "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %511s\n",
1149                  &d, local_addr, &local_port,
1150                  rem_addr, &rem_port, &state,
1151           &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
1152
1153     if (strlen(local_addr) > 8) {
1154 #if HAVE_AFINET6
1155         sscanf(local_addr, "%08X%08X%08X%08X",
1156                &in6.s6_addr32[0], &in6.s6_addr32[1],
1157                &in6.s6_addr32[2], &in6.s6_addr32[3]);
1158         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1159         inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
1160         sscanf(rem_addr, "%08X%08X%08X%08X",
1161                &in6.s6_addr32[0], &in6.s6_addr32[1],
1162                &in6.s6_addr32[2], &in6.s6_addr32[3]);
1163         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1164         inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
1165         localaddr.sin6_family = AF_INET6;
1166         remaddr.sin6_family = AF_INET6;
1167 #endif
1168     } else {
1169         sscanf(local_addr, "%X",
1170                &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
1171         sscanf(rem_addr, "%X",
1172                &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
1173         ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
1174         ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
1175     }
1176
1177     retr = 0L;
1178     if (!flag_opt)
1179         more[0] = '\0';
1180
1181     if (num < 10) {
1182         fprintf(stderr, _("warning, got bogus udp line.\n"));
1183         return;
1184     }
1185     if ((ap = get_afntype(((struct sockaddr *) &localaddr)->sa_family)) == NULL) {
1186         fprintf(stderr, _("netstat: unsupported address family %d !\n"),
1187                 ((struct sockaddr *) &localaddr)->sa_family);
1188         return;
1189     }
1190     switch (state) {
1191     case TCP_ESTABLISHED:
1192         udp_state = _("ESTABLISHED");
1193         break;
1194
1195     case TCP_CLOSE:
1196         udp_state = "";
1197         break;
1198
1199     default:
1200         udp_state = _("UNKNOWN");
1201         break;
1202     }
1203
1204 #if HAVE_AFINET6
1205 #define notnull(A) (((A.sin6_family == AF_INET6) && \
1206          ((A.sin6_addr.s6_addr32[0]) ||            \
1207           (A.sin6_addr.s6_addr32[1]) ||            \
1208           (A.sin6_addr.s6_addr32[2]) ||            \
1209           (A.sin6_addr.s6_addr32[3]))) ||          \
1210         ((A.sin6_family == AF_INET) &&             \
1211          ((struct sockaddr_in *) &A)->sin_addr.s_addr))
1212 #else
1213 #define notnull(A) (A.sin_addr.s_addr)
1214 #endif
1215
1216     if (flag_all || (notnull(remaddr) && !flag_lst) || (!notnull(remaddr) && flag_lst))
1217     {
1218         addr_do_one(local_addr, sizeof(local_addr), 22, ap, &localaddr, local_port, "udp");
1219         addr_do_one(rem_addr, sizeof(rem_addr), 22, ap, &remaddr, rem_port, "udp");
1220
1221         timers[0] = '\0';
1222         if (flag_opt)
1223             switch (timer_run) {
1224             case 0:
1225                 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
1226                 break;
1227
1228             case 1:
1229             case 2:
1230                 snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100, retr, timeout);
1231                 break;
1232
1233             default:
1234                 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
1235                          retr, timeout);
1236                 break;
1237             }
1238         printf("%-5s %6ld %6ld %-23s %-23s %-11s",
1239                prot, rxq, txq, local_addr, rem_addr, udp_state);
1240
1241         finish_this_one(uid,inode,timers);
1242     }
1243 }
1244
1245 static int udp_info(void)
1246 {
1247     INFO_GUTS6(_PATH_PROCNET_UDP, _PATH_PROCNET_UDP6, "AF INET (udp)",
1248                udp_do_one, "udp", "udp6");
1249 }
1250
1251 static int udplite_info(void)
1252 {
1253     INFO_GUTS6(_PATH_PROCNET_UDPLITE, _PATH_PROCNET_UDPLITE6, 
1254                "AF INET (udplite)", udp_do_one, "udpl", "udpl6" );
1255 }
1256
1257 static void raw_do_one(int lnr, const char *line,const char *prot)
1258 {
1259     char local_addr[64], rem_addr[64];
1260     char timers[64], more[512];
1261     int num, local_port, rem_port, d, state, timer_run, uid, timeout;
1262 #if HAVE_AFINET6
1263     struct sockaddr_in6 localaddr, remaddr;
1264     char addr6[INET6_ADDRSTRLEN];
1265     struct in6_addr in6;
1266     extern struct aftype inet6_aftype;
1267 #else
1268     struct sockaddr_in localaddr, remaddr;
1269 #endif
1270     struct aftype *ap;
1271     unsigned long rxq, txq, time_len, retr, inode;
1272
1273     if (lnr == 0)
1274         return;
1275
1276     more[0] = '\0';
1277     num = sscanf(line,
1278                  "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %511s\n",
1279                  &d, local_addr, &local_port, rem_addr, &rem_port, &state,
1280           &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
1281
1282     if (strlen(local_addr) > 8) {
1283 #if HAVE_AFINET6
1284         sscanf(local_addr, "%08X%08X%08X%08X",
1285                &in6.s6_addr32[0], &in6.s6_addr32[1],
1286            &in6.s6_addr32[2], &in6.s6_addr32[3]);
1287     inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1288         inet6_aftype.input(1, addr6, (struct sockaddr *) &localaddr);
1289         sscanf(rem_addr, "%08X%08X%08X%08X",
1290                &in6.s6_addr32[0], &in6.s6_addr32[1],
1291            &in6.s6_addr32[2], &in6.s6_addr32[3]);
1292     inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
1293         inet6_aftype.input(1, addr6, (struct sockaddr *) &remaddr);
1294         localaddr.sin6_family = AF_INET6;
1295         remaddr.sin6_family = AF_INET6;
1296 #endif
1297     } else {
1298         sscanf(local_addr, "%X",
1299                &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
1300         sscanf(rem_addr, "%X",
1301                &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
1302         ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
1303         ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
1304     }
1305 #if HAVE_AFINET6
1306     if ((ap = get_afntype(localaddr.sin6_family)) == NULL) {
1307         fprintf(stderr, _("netstat: unsupported address family %d !\n"), localaddr.sin6_family);
1308         return;
1309     }
1310 #else
1311     if ((ap = get_afntype(localaddr.sin_family)) == NULL) {
1312         fprintf(stderr, _("netstat: unsupported address family %d !\n"), localaddr.sin_family);
1313         return;
1314     }
1315 #endif
1316
1317     if (!flag_opt)
1318         more[0] = '\0';
1319
1320     if (num < 10) {
1321         fprintf(stderr, _("warning, got bogus raw line.\n"));
1322         return;
1323     }
1324
1325     if (flag_all || (notnull(remaddr) && !flag_lst) || (!notnull(remaddr) && flag_lst))
1326     {
1327         addr_do_one(local_addr, sizeof(local_addr), 22, ap, &localaddr, local_port, "raw");
1328         addr_do_one(rem_addr, sizeof(rem_addr), 22, ap, &remaddr, rem_port, "raw");
1329
1330         timers[0] = '\0';
1331         if (flag_opt)
1332             switch (timer_run) {
1333             case 0:
1334                 snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
1335                 break;
1336
1337             case 1:
1338             case 2:
1339                 snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
1340                          retr, timeout);
1341                 break;
1342
1343             default:
1344                 snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
1345                          timer_run, (double) time_len / 100,
1346                          retr, timeout);
1347                 break;
1348             }
1349         printf("%-4s  %6ld %6ld %-23s %-23s %-11d",
1350                prot, rxq, txq, local_addr, rem_addr, state);
1351
1352         finish_this_one(uid,inode,timers);
1353     }
1354 }
1355
1356 static int raw_info(void)
1357 {
1358     INFO_GUTS6(_PATH_PROCNET_RAW, _PATH_PROCNET_RAW6, "AF INET (raw)",
1359                raw_do_one, "raw", "raw6");
1360 }
1361
1362 #endif
1363
1364
1365 #if HAVE_AFUNIX
1366
1367 #define HAS_INODE 1
1368
1369 static void unix_do_one(int nr, const char *line, const char *prot)
1370 {
1371     static int has = 0;
1372     char path[MAXPATHLEN], ss_flags[32];
1373     char *ss_proto, *ss_state, *ss_type;
1374     int num, state, type;
1375     void *d;
1376     unsigned long refcnt, proto, flags, inode;
1377
1378     if (nr == 0) {
1379         if (strstr(line, "Inode"))
1380             has |= HAS_INODE;
1381         return;
1382     }
1383     path[0] = '\0';
1384     num = sscanf(line, "%p: %lX %lX %lX %X %X %lu %s",
1385                  &d, &refcnt, &proto, &flags, &type, &state, &inode, path);
1386     if (num < 6) {
1387         fprintf(stderr, _("warning, got bogus unix line.\n"));
1388         return;
1389     }
1390     if (!(has & HAS_INODE))
1391         snprintf(path,sizeof(path),"%lu",inode);
1392
1393     if (!flag_all) {
1394         if ((state == SS_UNCONNECTED) && (flags & SO_ACCEPTCON)) {
1395                 if (!flag_lst)
1396                         return;
1397         } else {
1398                 if (flag_lst)
1399                         return;
1400         }
1401     }
1402
1403     switch (proto) {
1404     case 0:
1405         ss_proto = "unix";
1406         break;
1407
1408     default:
1409         ss_proto = "??";
1410     }
1411
1412     switch (type) {
1413     case SOCK_STREAM:
1414         ss_type = _("STREAM");
1415         break;
1416
1417     case SOCK_DGRAM:
1418         ss_type = _("DGRAM");
1419         break;
1420
1421     case SOCK_RAW:
1422         ss_type = _("RAW");
1423         break;
1424
1425     case SOCK_RDM:
1426         ss_type = _("RDM");
1427         break;
1428
1429     case SOCK_SEQPACKET:
1430         ss_type = _("SEQPACKET");
1431         break;
1432
1433     default:
1434         ss_type = _("UNKNOWN");
1435     }
1436
1437     switch (state) {
1438     case SS_FREE:
1439         ss_state = _("FREE");
1440         break;
1441
1442     case SS_UNCONNECTED:
1443         /*
1444          * Unconnected sockets may be listening
1445          * for something.
1446          */
1447         if (flags & SO_ACCEPTCON) {
1448             ss_state = _("LISTENING");
1449         } else {
1450             ss_state = "";
1451         }
1452         break;
1453
1454     case SS_CONNECTING:
1455         ss_state = _("CONNECTING");
1456         break;
1457
1458     case SS_CONNECTED:
1459         ss_state = _("CONNECTED");
1460         break;
1461
1462     case SS_DISCONNECTING:
1463         ss_state = _("DISCONNECTING");
1464         break;
1465
1466     default:
1467         ss_state = _("UNKNOWN");
1468     }
1469
1470     strcpy(ss_flags, "[ ");
1471     if (flags & SO_ACCEPTCON)
1472         strcat(ss_flags, "ACC ");
1473     if (flags & SO_WAITDATA)
1474         strcat(ss_flags, "W ");
1475     if (flags & SO_NOSPACE)
1476         strcat(ss_flags, "N ");
1477
1478     strcat(ss_flags, "]");
1479
1480     printf("%-5s %-6ld %-11s %-10s %-13s ",
1481            ss_proto, refcnt, ss_flags, ss_type, ss_state);
1482     if (has & HAS_INODE)
1483         printf("%-8lu",inode);
1484     else
1485         printf("-       ");
1486     if (flag_prg)
1487         printf(" %-" PROGNAME_WIDTHs "s",(has & HAS_INODE?prg_cache_get(inode):"-"));
1488     if (flag_selinux)
1489         printf(" %-" SELINUX_WIDTHs "s",(has & HAS_INODE?prg_cache_get_con(inode):"-"));
1490     if (flag_smack) {
1491         printf(" %-" SMK_WIDTHs "s",
1492                 (has & HAS_INODE ? prg_cache_get_smkin(inode) : "-"));
1493         printf(" %-" SMK_WIDTHs "s",
1494                 (has & HAS_INODE ? prg_cache_get_smkout(inode) : "-"));
1495     }
1496
1497     printf(" %s\n", path);
1498 }
1499
1500 static int unix_info(void)
1501 {
1502
1503     printf(_("Active UNIX domain sockets "));
1504     if (flag_all)
1505         printf(_("(servers and established)"));
1506     else {
1507       if (flag_lst)
1508         printf(_("(only servers)"));
1509       else
1510         printf(_("(w/o servers)"));
1511     }
1512
1513     printf(_("\nProto RefCnt Flags       Type       State         I-Node  "));
1514     print_progname_banner();
1515     print_selinux_banner();
1516     print_smack_banner();
1517     printf(_(" Path\n"));       /* xxx */
1518
1519     {
1520         INFO_GUTS(_PATH_PROCNET_UNIX, "AF UNIX", unix_do_one, "unix");
1521     }
1522 }
1523 #endif
1524
1525
1526 #if HAVE_AFAX25
1527 static int ax25_info(void)
1528 {
1529     FILE *f;
1530     char buffer[256], buf[16];
1531     char *src, *dst, *dev, *p;
1532     int st, vs, vr, sendq, recvq, ret;
1533     int new = -1;               /* flag for new (2.1.x) kernels */
1534     static char *ax25_state[5] =
1535     {
1536         N_("LISTENING"),
1537         N_("SABM SENT"),
1538         N_("DISC SENT"),
1539         N_("ESTABLISHED"),
1540         N_("RECOVERY")
1541     };
1542     if (!(f = proc_fopen(_PATH_PROCNET_AX25))) {
1543         if (errno != ENOENT) {
1544             perror(_PATH_PROCNET_AX25);
1545             return (-1);
1546         }
1547         if (flag_arg || flag_ver)
1548             ESYSNOT("netstat", "AF AX25");
1549         if (flag_arg)
1550             return (1);
1551         else
1552             return (0);
1553     }
1554     printf(_("Active AX.25 sockets\n"));
1555     printf(_("Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q\n"));
1556     while (fgets(buffer, 256, f)) {
1557         if (new == -1) {
1558             if (!strncmp(buffer, "dest_addr", 9)) {
1559                 new = 0;
1560                 continue;       /* old kernels have a header line */
1561             } else
1562                 new = 1;
1563         }
1564         /*
1565          * In a network connection with no user socket the Snd-Q, Rcv-Q
1566          * and Inode fields are empty in 2.0.x and '*' in 2.1.x
1567          */
1568         sendq = 0;
1569         recvq = 0;
1570         if (new == 0) {
1571             dst = buffer;
1572             src = buffer + 10;
1573             dst[9] = 0;
1574             src[9] = 0;
1575             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",
1576                    buf, &st, &vs, &vr, &sendq, &recvq);
1577             if (ret != 4 && ret != 6) {
1578                 printf(_("Problem reading data from %s\n"), _PATH_PROCNET_AX25);
1579                 continue;
1580             }
1581             dev = buf;
1582         } else {
1583             p = buffer;
1584             while (*p != ' ') p++;
1585             p++;
1586             dev = p;
1587             while (*p != ' ') p++;
1588             *p++ = 0;
1589             src = p;
1590             while (*p != ' ') p++;
1591             *p++ = 0;
1592             dst = p;
1593             while (*p != ' ') p++;
1594             *p++ = 0;
1595             ret = sscanf(p, "%d %d %d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d %*d",
1596                    &st, &vs, &vr, &sendq, &recvq);
1597             if (ret != 3 && ret != 5) {
1598                     printf(_("problem reading data from %s\n"), _PATH_PROCNET_AX25);
1599                     continue;
1600             }
1601             /*
1602              * FIXME: digipeaters should be handled somehow.
1603              * For now we just strip them.
1604              */
1605             p = dst;
1606             while (*p && *p != ',') p++;
1607             *p = 0;
1608         }
1609         printf("%-9s  %-9s  %-6s  %-11s  %03d/%03d  %-6d  %-6d\n",
1610                dst, src,
1611                dev,
1612                _(ax25_state[st]),
1613                vr, vs, sendq, recvq);
1614     }
1615     fclose(f);
1616     return 0;
1617 }
1618 #endif
1619
1620
1621 #if HAVE_AFIPX
1622 static int ipx_info(void)
1623 {
1624     FILE *f;
1625     char buf[256];
1626     unsigned long txq, rxq;
1627     unsigned int state;
1628     unsigned int uid;
1629     char *st;
1630     int nc;
1631     struct aftype *ap;
1632     struct passwd *pw;
1633     char sad[50], dad[50];
1634     struct sockaddr sa;
1635     unsigned sport = 0, dport = 0;
1636     struct stat s;
1637     
1638     f = proc_fopen(_PATH_PROCNET_IPX_SOCKET1);
1639     if (!f) {
1640         if (errno != ENOENT) {
1641             perror(_PATH_PROCNET_IPX_SOCKET1);
1642             return (-1);
1643         }
1644         f = proc_fopen(_PATH_PROCNET_IPX_SOCKET2);
1645
1646         /* We need to check for directory */
1647         if (f) {
1648             fstat(fileno(f), &s);
1649             if (!S_ISREG(s.st_mode)) {
1650                 fclose(f);
1651                 f=NULL;
1652             }
1653         }
1654
1655         if (!f) {
1656             if (errno != ENOENT) {
1657                 perror(_PATH_PROCNET_IPX_SOCKET2);
1658                 return (-1);
1659             }
1660             if (flag_arg || flag_ver)
1661                 ESYSNOT("netstat", "AF IPX");
1662             if (flag_arg)
1663                 return (1);
1664             else
1665                 return (0);
1666         }
1667     }
1668     printf(_("Active IPX sockets\nProto Recv-Q Send-Q Local Address              Foreign Address            State"));   /* xxx */
1669     if (flag_exp > 1)
1670         printf(_(" User"));     /* xxx */
1671     printf("\n");
1672     if ((ap = get_afntype(AF_IPX)) == NULL) {
1673         EINTERN("netstat.c", "AF_IPX missing");
1674         fclose(f);
1675         return (-1);
1676     }
1677     if (fgets(buf, 255, f))
1678         /* eat line */;
1679
1680     while (fgets(buf, 255, f) != NULL) {
1681         sscanf(buf, "%s %s %lX %lX %d %d",
1682                sad, dad, &txq, &rxq, &state, &uid);
1683         if ((st = rindex(sad, ':'))) {
1684             *st++ = '\0';
1685             sscanf(st, "%X", &sport);   /* net byt order */
1686             sport = ntohs(sport);
1687         } else {
1688             EINTERN("netstat.c", "ipx socket format error in source port");
1689             fclose(f);
1690             return (-1);
1691         }
1692         nc = 0;
1693         if (strcmp(dad, "Not_Connected") != 0) {
1694             if ((st = rindex(dad, ':'))) {
1695                 *st++ = '\0';
1696                 sscanf(st, "%X", &dport);       /* net byt order */
1697                 dport = ntohs(dport);
1698             } else {
1699                 EINTERN("netstat.c", "ipx soket format error in destination port");
1700                 fclose(f);
1701                 return (-1);
1702             }
1703         } else
1704             nc = 1;
1705
1706         switch (state) {
1707         case TCP_ESTABLISHED:
1708             st = _("ESTAB");
1709             break;
1710
1711         case TCP_CLOSE:
1712             st = "";
1713             break;
1714
1715         default:
1716             st = _("UNK.");
1717             break;
1718         }
1719
1720         /* Fetch and resolve the Source */
1721         (void) ap->input(4, sad, &sa);
1722         safe_strncpy(buf, ap->sprint(&sa, flag_not & FLAG_NUM_HOST), sizeof(buf));
1723         snprintf(sad, sizeof(sad), "%s:%04X", buf, sport);
1724
1725         if (!nc) {
1726             /* Fetch and resolve the Destination */
1727             (void) ap->input(4, dad, &sa);
1728             safe_strncpy(buf, ap->sprint(&sa, flag_not & FLAG_NUM_HOST), sizeof(buf));
1729             snprintf(dad, sizeof(dad), "%s:%04X", buf, dport);
1730         } else
1731             strcpy(dad, "-");
1732
1733         printf("IPX   %6ld %6ld %-26s %-26s %-5s", txq, rxq, sad, dad, st);
1734         if (flag_exp > 1) {
1735             if (!(flag_not & FLAG_NUM_USER) && ((pw = getpwuid(uid)) != NULL))
1736                 printf(" %-10s", pw->pw_name);
1737             else
1738                 printf(" %-10d", uid);
1739         }
1740         printf("\n");
1741     }
1742     fclose(f);
1743     return 0;
1744 }
1745 #endif
1746
1747 #if HAVE_AFBLUETOOTH
1748 const char *bluetooth_state(int state)
1749 {
1750     switch (state) {
1751         case BT_CONNECTED:
1752             return _("CONNECTED");
1753         case BT_OPEN:
1754             return _("OPEN");
1755         case BT_BOUND:
1756             return _("BOUND");
1757         case BT_LISTEN:
1758             return _("LISTEN");
1759         case BT_CONNECT:
1760             return _("CONNECT");
1761         case BT_CONNECT2:
1762             return _("CONNECT2");
1763         case BT_CONFIG:
1764             return _("CONFIG");
1765         case BT_DISCONN:
1766             return _("DISCONN");
1767         case BT_CLOSED:
1768             return _("CLOSED");
1769         default:
1770             return _("UNKNOWN");
1771     }
1772 }
1773
1774 static void l2cap_do_one(int nr, const char *line, const char *prot)
1775 {
1776     char daddr[18], saddr[18];
1777     unsigned state, psm, dcid, scid, imtu, omtu, sec_level;
1778     int num;
1779     const char *bt_state, *bt_sec_level;
1780
1781     num = sscanf(line, "%17s %17s %d %d 0x%04x 0x%04x %d %d %d",
1782         daddr, saddr, &state, &psm, &dcid, &scid, &imtu, &omtu, &sec_level);
1783
1784     if (num < 9) {
1785         fprintf(stderr, _("warning, got bogus l2cap line.\n"));
1786         return;
1787     }
1788
1789     if (flag_lst && !(state == BT_LISTEN || state == BT_BOUND))
1790         return;
1791     if (!(flag_all || flag_lst) && (state == BT_LISTEN || state == BT_BOUND))
1792         return;
1793
1794     bt_state = bluetooth_state(state);
1795     switch (sec_level) {
1796         case BT_SECURITY_SDP:
1797             bt_sec_level = _("SDP");
1798             break;
1799         case BT_SECURITY_LOW:
1800             bt_sec_level = _("LOW");
1801             break;
1802         case BT_SECURITY_MEDIUM:
1803             bt_sec_level = _("MEDIUM");
1804             break;
1805         case BT_SECURITY_HIGH:
1806             bt_sec_level = _("HIGH");
1807             break;
1808         default:
1809             bt_sec_level = _("UNKNOWN");
1810     }
1811
1812     printf("l2cap  %-17s %-17s %-9s %7d 0x%04x 0x%04x %7d %7d %-7s\n",
1813         (strcmp (daddr, "00:00:00:00:00:00") == 0 ? "*" : daddr),
1814         (strcmp (saddr, "00:00:00:00:00:00") == 0 ? "*" : saddr),
1815         bt_state, psm, dcid, scid, imtu, omtu, bt_sec_level);
1816 }
1817
1818 static int l2cap_info(void)
1819 {
1820     printf("%-6s %-17s %-17s %-9s %7s %-6s %-6s %7s %7s %-7s\n",
1821         "Proto", "Destination", "Source", "State", "PSM", "DCID", "SCID", "IMTU", "OMTU", "Security");
1822     INFO_GUTS(_PATH_SYS_BLUETOOTH_L2CAP, "AF BLUETOOTH", l2cap_do_one, "l2cap");
1823 }
1824
1825 static void rfcomm_do_one(int nr, const char *line, const char *prot)
1826 {
1827     char daddr[18], saddr[18];
1828     unsigned state, channel;
1829     int num;
1830     const char *bt_state;
1831
1832     num = sscanf(line, "%17s %17s %d %d", daddr, saddr, &state, &channel);
1833     if (num < 4) {
1834         fprintf(stderr, _("warning, got bogus rfcomm line.\n"));
1835         return;
1836     }
1837
1838     if (flag_lst && !(state == BT_LISTEN || state == BT_BOUND))
1839         return;
1840     if (!(flag_all || flag_lst) && (state == BT_LISTEN || state == BT_BOUND))
1841         return;
1842
1843     bt_state = bluetooth_state(state);
1844     printf("rfcomm %-17s %-17s %-9s %7d\n",
1845         (strcmp (daddr, "00:00:00:00:00:00") == 0 ? "*" : daddr),
1846         (strcmp (saddr, "00:00:00:00:00:00") == 0 ? "*" : saddr),
1847         bt_state, channel);
1848 }
1849
1850 static int rfcomm_info(void)
1851 {
1852     printf("%-6s %-17s %-17s %-9s %7s\n", "Proto", "Destination", "Source", "State", "Channel");
1853     INFO_GUTS(_PATH_SYS_BLUETOOTH_RFCOMM, "AF BLUETOOTH", rfcomm_do_one, "rfcomm");
1854 }
1855 #endif
1856
1857 static int iface_info(void)
1858 {
1859     if (skfd < 0) {
1860         if ((skfd = sockets_open(0)) < 0) {
1861             perror("socket");
1862             exit(1);
1863         }
1864         printf(_("Kernel Interface table\n"));
1865     }
1866     if (flag_exp < 2) {
1867         ife_short = 1;
1868         printf(_("Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg\n"));
1869     }
1870
1871     if (for_all_interfaces(do_if_print, &flag_all) < 0) {
1872         perror(_("missing interface information"));
1873         exit(1);
1874     }
1875     if (flag_cnt)
1876         if_cache_free();
1877     else {
1878         close(skfd);
1879         skfd = -1;
1880     }
1881
1882     return 0;
1883 }
1884
1885
1886 static void version(void)
1887 {
1888     printf("%s\n%s\n%s\n%s\n", Release, Version, Signature, Features);
1889     exit(E_VERSION);
1890 }
1891
1892
1893 static void usage(void)
1894 {
1895     fprintf(stderr, _("usage: netstat [-vWeenNcCF] [<Af>] -r         netstat {-V|--version|-h|--help}\n"));
1896     fprintf(stderr, _("       netstat [-vWnNcaeol] [<Socket> ...]\n"));
1897     fprintf(stderr, _("       netstat { [-vWeenNac] -i | [-cnNe] -M | -s [-6tuw] }\n\n"));
1898
1899     fprintf(stderr, _("        -r, --route              display routing table\n"));
1900     fprintf(stderr, _("        -i, --interfaces         display interface table\n"));
1901     fprintf(stderr, _("        -g, --groups             display multicast group memberships\n"));
1902     fprintf(stderr, _("        -s, --statistics         display networking statistics (like SNMP)\n"));
1903 #if HAVE_FW_MASQUERADE
1904     fprintf(stderr, _("        -M, --masquerade         display masqueraded connections\n\n"));
1905 #endif
1906
1907     fprintf(stderr, _("        -v, --verbose            be verbose\n"));
1908     fprintf(stderr, _("        -W, --wide               don't truncate IP addresses\n"));
1909     fprintf(stderr, _("        -n, --numeric            don't resolve names\n"));
1910     fprintf(stderr, _("        --numeric-hosts          don't resolve host names\n"));
1911     fprintf(stderr, _("        --numeric-ports          don't resolve port names\n"));
1912     fprintf(stderr, _("        --numeric-users          don't resolve user names\n"));
1913     fprintf(stderr, _("        -N, --symbolic           resolve hardware names\n"));
1914     fprintf(stderr, _("        -e, --extend             display other/more information\n"));
1915     fprintf(stderr, _("        -p, --programs           display PID/Program name for sockets\n"));
1916     fprintf(stderr, _("        -o, --timers             display timers\n"));
1917     fprintf(stderr, _("        -c, --continuous         continuous listing\n\n"));
1918     fprintf(stderr, _("        -l, --listening          display listening server sockets\n"));
1919     fprintf(stderr, _("        -a, --all                display all sockets (default: connected)\n"));
1920     fprintf(stderr, _("        -F, --fib                display Forwarding Information Base (default)\n"));
1921     fprintf(stderr, _("        -C, --cache              display routing cache instead of FIB\n"));
1922 #if HAVE_SELINUX
1923     fprintf(stderr, _("        -Z, --context            display SELinux security context for sockets\n"));
1924 #endif
1925
1926     fprintf(stderr, _("        -X, --smack              display Smack labels for sockets\n"));
1927     fprintf(stderr, _("\n  <Socket>={-t|--tcp} {-u|--udp} {-U|--udplite} {-w|--raw} {-x|--unix}\n"));
1928     fprintf(stderr, _("           --ax25 --ipx --netrom\n"));
1929     fprintf(stderr, _("  <AF>=Use '-6|-4' or '-A <af>' or '--<af>'; default: %s\n"), DFLT_AF);
1930     fprintf(stderr, _("  List of possible address families (which support routing):\n"));
1931     print_aflist(1); /* 1 = routeable */
1932     exit(E_USAGE);
1933 }
1934
1935
1936 int main
1937  (int argc, char *argv[]) {
1938     int i;
1939     int lop;
1940     static struct option longopts[] =
1941     {
1942         AFTRANS_OPTS,
1943         {"version", 0, 0, 'V'},
1944         {"interfaces", 0, 0, 'i'},
1945         {"help", 0, 0, 'h'},
1946         {"route", 0, 0, 'r'},
1947 #if HAVE_FW_MASQUERADE
1948         {"masquerade", 0, 0, 'M'},
1949 #endif
1950         {"protocol", 1, 0, 'A'},
1951         {"tcp", 0, 0, 't'},
1952         {"sctp", 0, 0, 'S'},
1953         {"udp", 0, 0, 'u'},
1954         {"udplite", 0, 0, 'U'},
1955         {"raw", 0, 0, 'w'},
1956         {"unix", 0, 0, 'x'},
1957         {"l2cap", 0, 0, '2'},
1958         {"rfcomm", 0, 0, 'f'},
1959         {"listening", 0, 0, 'l'},
1960         {"all", 0, 0, 'a'},
1961         {"timers", 0, 0, 'o'},
1962         {"continuous", 0, 0, 'c'},
1963         {"extend", 0, 0, 'e'},
1964         {"programs", 0, 0, 'p'},
1965         {"verbose", 0, 0, 'v'},
1966         {"statistics", 0, 0, 's'},
1967         {"wide", 0, 0, 'W'},
1968         {"numeric", 0, 0, 'n'},
1969         {"numeric-hosts", 0, 0, '!'},
1970         {"numeric-ports", 0, 0, '@'},
1971         {"numeric-users", 0, 0, '#'},
1972         {"symbolic", 0, 0, 'N'},
1973         {"cache", 0, 0, 'C'},
1974         {"fib", 0, 0, 'F'},
1975         {"groups", 0, 0, 'g'},
1976         {"context", 0, 0, 'Z'},
1977         {"smack", 0 , 0, 'X'},
1978         {NULL, 0, 0, 0}
1979     };
1980
1981 #if I18N
1982     setlocale (LC_ALL, "");
1983     bindtextdomain("net-tools", "/usr/share/locale");
1984     textdomain("net-tools");
1985 #endif
1986     getroute_init();            /* Set up AF routing support */
1987
1988     afname[0] = '\0';
1989     while ((i = getopt_long(argc, argv, "A:CFMacdeghilnNoprsStuUvVWwx64?ZX", longopts, &lop)) != EOF)
1990         switch (i) {
1991         case -1:
1992             break;
1993         case 1:
1994             if (lop < 0 || lop >= AFTRANS_CNT) {
1995                 EINTERN("netstat.c", "longopts 1 range");
1996                 break;
1997             }
1998             if (aftrans_opt(longopts[lop].name))
1999                 exit(1);
2000             break;
2001         case 'A':
2002             if (aftrans_opt(optarg))
2003                 exit(1);
2004             break;
2005         case 'M':
2006             flag_mas++;
2007             break;
2008         case 'a':
2009             flag_all++;
2010             break;
2011         case 'l':
2012             flag_lst++;
2013             break;
2014         case 'c':
2015             flag_cnt++;
2016             break;
2017
2018         case 'd':
2019             flag_deb++;
2020             break;
2021         case 'g':
2022             flag_igmp++;
2023             break;
2024         case 'e':
2025             flag_exp++;
2026             break;
2027         case 'p':
2028             flag_prg++;
2029             break;
2030         case 'i':
2031             flag_int++;
2032             break;
2033         case 'W':
2034             flag_wide++;
2035             break;
2036         case 'n':
2037             flag_not |= FLAG_NUM;
2038             break;
2039         case '!':
2040             flag_not |= FLAG_NUM_HOST;
2041             break;
2042         case '@':
2043             flag_not |= FLAG_NUM_PORT;
2044             break;
2045         case '#':
2046             flag_not |= FLAG_NUM_USER;
2047             break;
2048         case 'N':
2049             flag_not |= FLAG_SYM;
2050             break;
2051         case 'C':
2052             flag_cf |= FLAG_CACHE;
2053             break;
2054         case 'F':
2055             flag_cf |= FLAG_FIB;
2056             break;
2057         case 'o':
2058             flag_opt++;
2059             break;
2060         case '6':
2061             if (aftrans_opt("inet6"))
2062                 exit(1);
2063             break;
2064         case '4':
2065             if (aftrans_opt("inet"))
2066                 exit(1);
2067             break;
2068         case 'V':
2069             version();
2070             /*NOTREACHED */
2071         case 'v':
2072             flag_ver |= FLAG_VERBOSE;
2073             break;
2074         case 'r':
2075             flag_rou++;
2076             break;
2077         case 't':
2078             flag_tcp++;
2079             break;
2080         case 'S':
2081             flag_sctp++;
2082             break;
2083         case 'u':
2084             flag_udp++;
2085             break;
2086         case 'U':
2087             flag_udplite++;
2088             break;
2089         case 'w':
2090             flag_raw++;
2091             break;
2092         case '2':
2093             flag_l2cap++;
2094             break;
2095         case 'f':
2096             flag_rfcomm++;
2097             break;
2098         case 'x':
2099             if (aftrans_opt("unix"))
2100                 exit(1);
2101             break;
2102         case 'Z':
2103 #if HAVE_SELINUX
2104             if (is_selinux_enabled() <= 0) {
2105                 fprintf(stderr, _("SELinux is not enabled on this machine.\n"));
2106                 exit(1);
2107             }
2108             flag_prg++;
2109             flag_selinux++;
2110 #else
2111             fprintf(stderr, _("SELinux is not enabled for this application.\n"));
2112             exit(1);
2113 #endif
2114
2115             break;
2116         case 'X':
2117                 flag_smack++;
2118                 flag_prg++;
2119                 break;
2120         case '?':
2121         case 'h':
2122             usage();
2123         case 's':
2124             flag_sta++;
2125         }
2126
2127     if (flag_int + flag_rou + flag_mas + flag_sta > 1)
2128         usage();
2129
2130     if ((flag_inet || flag_inet6 || flag_sta) && 
2131         !(flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw))
2132            flag_tcp = flag_sctp = flag_udp = flag_udplite = flag_raw = 1;
2133
2134     if ((flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw || flag_igmp) && 
2135         !(flag_inet || flag_inet6))
2136         flag_inet = flag_inet6 = 1;
2137
2138     if (flag_bluetooth && !(flag_l2cap || flag_rfcomm))
2139            flag_l2cap = flag_rfcomm = 1;
2140
2141     flag_arg = flag_tcp + flag_sctp + flag_udplite + flag_udp + flag_raw + flag_unx 
2142         + flag_ipx + flag_ax25 + flag_netrom + flag_igmp + flag_x25 + flag_rose
2143         + flag_l2cap + flag_rfcomm;
2144
2145     if (flag_mas) {
2146 #if HAVE_FW_MASQUERADE && HAVE_AFINET
2147 #if MORE_THAN_ONE_MASQ_AF
2148         if (!afname[0])
2149             strcpy(afname, DFLT_AF);
2150 #endif
2151         for (;;) {
2152             i = ip_masq_info(flag_not & FLAG_NUM_HOST,
2153                              flag_not & FLAG_NUM_PORT, flag_exp);
2154             if (i || !flag_cnt)
2155                 break;
2156             wait_continous();
2157         }
2158 #else
2159         ENOSUPP("netstat", "FW_MASQUERADE");
2160         i = -1;
2161 #endif
2162         return (i);
2163     }
2164
2165     if (flag_sta) {
2166         if (!afname[0])
2167             strcpy(afname, DFLT_AF);
2168             
2169         if (!strcmp(afname, "inet")) {
2170 #if HAVE_AFINET
2171             inittab();
2172             parsesnmp(flag_raw, flag_tcp, flag_udp);
2173 #else
2174             ENOSUPP("netstat", "AF INET");
2175 #endif
2176         } else if(!strcmp(afname, "inet6")) {
2177 #if HAVE_AFINET6
2178             inittab6();
2179             parsesnmp6(flag_raw, flag_tcp, flag_udp);
2180 #else
2181             ENOSUPP("netstat", "AF INET6");
2182 #endif
2183         } else {
2184           printf(_("netstat: No statistics support for specified address family: %s\n"), afname);
2185           exit(1);
2186         }
2187         exit(0);
2188     }
2189     
2190     if (flag_rou) {
2191         int options = 0;
2192
2193         if (!afname[0])
2194             strcpy(afname, DFLT_AF);
2195
2196         if (flag_exp == 2)
2197             flag_exp = 1;
2198         else if (flag_exp == 1)
2199             flag_exp = 2;
2200
2201         options = (flag_exp & FLAG_EXT) | flag_not | flag_cf | flag_ver;
2202         if (!flag_cf)
2203             options |= FLAG_FIB;
2204
2205         for (;;) {
2206             i = route_info(afname, options);
2207             if (i || !flag_cnt)
2208                 break;
2209             wait_continous();
2210         }
2211         return (i);
2212     }
2213     if (flag_int) {
2214         for (;;) {
2215             i = iface_info();
2216             if (!flag_cnt || i)
2217                 break;
2218             wait_continous();
2219         }
2220         return (i);
2221     }
2222     for (;;) {
2223         if (!flag_arg || flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw) {
2224 #if HAVE_AFINET
2225             prg_cache_load();
2226             printf(_("Active Internet connections "));  /* xxx */
2227
2228             if (flag_all)
2229                 printf(_("(servers and established)"));
2230             else {
2231               if (flag_lst)
2232                 printf(_("(only servers)"));
2233               else
2234                 printf(_("(w/o servers)"));
2235             }
2236             printf(_("\nProto Recv-Q Send-Q Local Address           Foreign Address         State      "));     /* xxx */
2237             if (flag_exp > 1)
2238                 printf(_(" User       Inode     "));
2239             print_progname_banner();
2240             print_selinux_banner();
2241             if (flag_opt)
2242                 printf(_(" Timer"));    /* xxx */
2243             printf("\n");
2244 #else
2245             if (flag_arg) {
2246                 i = 1;
2247                 ENOSUPP("netstat", "AF INET");
2248             }
2249 #endif
2250         }
2251 #if HAVE_AFINET
2252         if (!flag_arg || flag_tcp) {
2253             i = tcp_info();
2254             if (i)
2255                 return (i);
2256         }
2257
2258         if (!flag_arg || flag_sctp) {
2259             i = sctp_info();
2260             if (i)
2261                 return (i);
2262         }
2263
2264         if (!flag_arg || flag_udp) {
2265             i = udp_info();
2266             if (i)
2267                 return (i);
2268         }
2269
2270         if (!flag_arg || flag_udplite) {
2271             i = udplite_info();
2272             if (i)
2273                 return (i);
2274         }
2275
2276         if (!flag_arg || flag_raw) {
2277             i = raw_info();
2278             if (i)
2279                 return (i);
2280         }
2281
2282         if (flag_igmp) {
2283 #if HAVE_AFINET6
2284             printf( "IPv6/");
2285 #endif
2286             printf( _("IPv4 Group Memberships\n") );
2287             printf( _("Interface       RefCnt Group\n") );
2288             printf( "--------------- ------ ---------------------\n" );
2289             i = igmp_info();
2290             if (i)
2291                 return (i);
2292         }
2293 #endif
2294
2295         if (!flag_arg || flag_unx) {
2296 #if HAVE_AFUNIX
2297             prg_cache_load();
2298             i = unix_info();
2299             if (i)
2300                 return (i);
2301 #else
2302             if (flag_arg) {
2303                 i = 1;
2304                 ENOSUPP("netstat", "AF UNIX");
2305             }
2306 #endif
2307         }
2308         if (!flag_arg || flag_ipx) {
2309 #if HAVE_AFIPX
2310             i = ipx_info();
2311             if (i)
2312                 return (i);
2313 #else
2314             if (flag_arg) {
2315                 i = 1;
2316                 ENOSUPP("netstat", "AF IPX");
2317             }
2318 #endif
2319         }
2320         if (!flag_arg || flag_ax25) {
2321 #if HAVE_AFAX25
2322             i = ax25_info();
2323             if (i)
2324                 return (i);
2325 #else
2326             if (flag_arg) {
2327                 i = 1;
2328                 ENOSUPP("netstat", "AF AX25");
2329             }
2330 #endif
2331         }
2332         if(!flag_arg || flag_x25) {
2333 #if HAVE_AFX25
2334             /* FIXME */
2335             i = x25_info();
2336             if (i)
2337                 return(i);
2338 #else
2339             if (flag_arg) {
2340                 i = 1;
2341                 ENOSUPP("netstat", "AF X25");
2342             }
2343 #endif
2344         }
2345         if (!flag_arg || flag_netrom) {
2346 #if HAVE_AFNETROM
2347             i = netrom_info();
2348             if (i)
2349                 return (i);
2350 #else
2351             if (flag_arg) {
2352                 i = 1;
2353                 ENOSUPP("netstat", "AF NETROM");
2354             }
2355 #endif
2356         }
2357         if (!flag_arg || flag_rose) {
2358 #if 0 && HAVE_AFROSE
2359           i = rose_info();
2360           if (i)
2361             return (i);
2362 #else
2363           if (flag_arg) {
2364             i = 1;
2365             ENOSUPP("netstat", "AF ROSE");
2366           }
2367 #endif
2368         }
2369
2370         if (!flag_arg || flag_l2cap || flag_rfcomm) {
2371 #if HAVE_AFBLUETOOTH
2372             printf(_("Active Bluetooth connections ")); /* xxx */
2373
2374             if (flag_all)
2375                 printf(_("(servers and established)"));
2376             else {
2377               if (flag_lst)
2378                 printf(_("(only servers)"));
2379               else
2380                 printf(_("(w/o servers)"));
2381             }
2382             printf("\n");
2383 #else
2384             if (flag_arg) {
2385                 i = 1;
2386                 ENOSUPP("netstat", "AF BLUETOOTH");
2387             }
2388 #endif
2389         }
2390 #if HAVE_AFBLUETOOTH
2391         if (!flag_arg || flag_l2cap) {
2392             i = l2cap_info();
2393             if (i)
2394                 return (i);
2395         }
2396         if (!flag_arg || flag_rfcomm) {
2397             i = rfcomm_info();
2398             if (i)
2399                 return (i);
2400         }
2401 #endif
2402
2403         if (!flag_cnt || i)
2404             break;
2405         wait_continous();
2406         prg_cache_clear();
2407     }
2408     return (i);
2409 }