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