5 kx /*
5 kx * netstat This file contains an implementation of the command
5 kx * that helps in debugging the networking modules.
5 kx *
5 kx * NET-TOOLS A collection of programs that form the base set of the
5 kx * NET-3 Networking Distribution for the LINUX operating
5 kx * system.
5 kx *
5 kx * Version: $Id: netstat.c,v 1.73 2011-04-20 01:35:22 ecki Exp $
5 kx *
5 kx * Authors: Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
5 kx * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
5 kx * Phil Packer, <pep@wicked.demon.co.uk>
5 kx * Johannes Stille, <johannes@titan.os.open.de>
5 kx * Bernd Eckenfels, <net-tools@lina.inka.de>
5 kx * Phil Blundell <philb@gnu.org>
5 kx * Tuan Hoang <tqhoang@bigfoot.com>
5 kx *
5 kx * Tuned for NET3 by:
5 kx * Alan Cox, <A.Cox@swansea.ac.uk>
5 kx * Copyright (c) 1993 Fred Baumgarten
5 kx *
5 kx * Modified:
5 kx *
5 kx *960116 {1.01} Bernd Eckenfels: verbose, cleanups
5 kx *960204 {1.10} Bernd Eckenfels: aftrans, usage, new route_info,
5 kx * DLFT_AF
5 kx *960204 {1.11} Bernd Eckenfels: netlink support
5 kx *960204 {1.12} Bernd Eckenfels: route_init()
5 kx *960215 {1.13} Bernd Eckenfels: netlink_print honors HAVE_
5 kx *960217 {1.14} Bernd Eckenfels: masq_info from Jos Vos and
5 kx * ax25_info from Jonathan Naylor.
5 kx *960218 {1.15} Bernd Eckenfels: ipx_info rewritten, -e for tcp/ipx
5 kx *960220 {1.16} Bernd Eckenfels: minor output reformats, -a for -x
5 kx *960221 {1.17} Bernd Eckenfels: route_init->getroute_init
5 kx *960426 {1.18} Bernd Eckenfels: new RTACTION, SYM/NUM, FIB/CACHE
5 kx *960517 {1.19} Bernd Eckenfels: usage() spelling fix and --unix inode,
5 kx * ':' is part of sock_addr for --inet
5 kx *960822 {x.xx} Frank Strauss: INET6 support
5 kx *
5 kx *970406 {1.33} Philip Copeland Added snmp reporting support module -s
5 kx * code provided by Andi Kleen
5 kx * (relly needs to be kernel hooked but
5 kx * this will do in the meantime)
5 kx * minor header file misplacement tidy up.
5 kx *980815 {1.xx} Stephane Fillod: X.25 support
5 kx *980411 {1.34} Arnaldo Carvalho i18n: catgets -> gnu gettext, substitution
5 kx * of sprintf for snprintf
5 kx *10/1998 Andi Kleen Use new interface primitives.
5 kx *990101 {1.36} Bernd Eckenfels usage updated to include -s and -C -F,
5 kx * fixed netstat -rC output (lib/inet_gr.c)
5 kx * removed broken NETLINK Support
5 kx * fixed format for /proc/net/udp|tcp|raw
5 kx * added -w,-t,-u TcpExt support to -s
5 kx *990131 {1.37} Jan Kratochvil added -p for prg_cache() & friends
5 kx * Flames to <short@ucw.cz>.
5 kx * Tuan Hoang added IGMP support for IPv4 and IPv6
5 kx *
5 kx *990420 {1.38} Tuan Hoang removed a useless assignment from igmp_do_one()
5 kx *20010404 {1.39} Arnaldo Carvalho de Melo - use setlocale
5 kx *20081201 {1.42} Brian Micek added -L|--udplite options for RFC 3828
5 kx *20020722 {1.51} Thomas Preusser added SCTP over IPv4 support
5 kx *
5 kx * This program is free software; you can redistribute it
5 kx * and/or modify it under the terms of the GNU General
5 kx * Public License as published by the Free Software
5 kx * Foundation; either version 2 of the License, or (at
5 kx * your option) any later version.
5 kx *
5 kx */
5 kx #include <errno.h>
5 kx #include <stdio.h>
5 kx #include <stdlib.h>
5 kx #include <string.h>
5 kx #include <strings.h>
5 kx #include <unistd.h>
5 kx #include <ctype.h>
5 kx #include <fcntl.h>
5 kx #include <netdb.h>
5 kx #include <paths.h>
5 kx #include <pwd.h>
5 kx #include <getopt.h>
5 kx #include <sys/param.h>
5 kx #include <sys/socket.h>
5 kx #include <arpa/inet.h>
5 kx #include <netinet/in.h>
5 kx #include <sys/ioctl.h>
5 kx #include <sys/stat.h>
5 kx #include <net/if.h>
5 kx #include <dirent.h>
5 kx
5 kx #include "net-support.h"
5 kx #include "pathnames.h"
5 kx #include "version.h"
5 kx #include "config.h"
5 kx #include "intl.h"
5 kx #include "sockets.h"
5 kx #include "interface.h"
5 kx #include "util.h"
5 kx #include "proc.h"
5 kx
5 kx #if HAVE_SELINUX
5 kx #include <selinux/selinux.h>
5 kx #endif
5 kx
5 kx #if HAVE_AFBLUETOOTH
5 kx /*
5 kx Only following stuff is needed from
5 kx kernel: net/bluetooth/bluetooth.h
5 kx or bluez: bluetooth/bluetooth.h
5 kx */
5 kx #define BT_SECURITY_SDP 0
5 kx #define BT_SECURITY_LOW 1
5 kx #define BT_SECURITY_MEDIUM 2
5 kx #define BT_SECURITY_HIGH 3
5 kx #define BT_SECURITY_FIPS 4
5 kx
5 kx /* Connection and socket states */
5 kx enum {
5 kx BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
5 kx BT_OPEN,
5 kx BT_BOUND,
5 kx BT_LISTEN,
5 kx BT_CONNECT,
5 kx BT_CONNECT2,
5 kx BT_CONFIG,
5 kx BT_DISCONN,
5 kx BT_CLOSED
5 kx };
5 kx #endif
5 kx
5 kx #define PROGNAME_WIDTH 20
5 kx #define SELINUX_WIDTH 50
5 kx
5 kx #if !defined(s6_addr32) && defined(in6a_words)
5 kx #define s6_addr32 in6a_words /* libinet6 */
5 kx #endif
5 kx
5 kx /* prototypes for statistics.c */
5 kx void parsesnmp(int, int, int, int);
5 kx void parsesnmp6(int, int, int);
5 kx
5 kx typedef enum {
5 kx SS_FREE = 0, /* not allocated */
5 kx SS_UNCONNECTED, /* unconnected to any socket */
5 kx SS_CONNECTING, /* in process of connecting */
5 kx SS_CONNECTED, /* connected to socket */
5 kx SS_DISCONNECTING /* in process of disconnecting */
5 kx } socket_state;
5 kx
5 kx #define SO_ACCEPTCON (1<<16) /* performed a listen */
5 kx #define SO_WAITDATA (1<<17) /* wait data to read */
5 kx #define SO_NOSPACE (1<<18) /* no space to write */
5 kx
5 kx #define DFLT_AF "inet"
5 kx
5 kx #define FEATURE_NETSTAT
5 kx #include "lib/net-features.h"
5 kx
5 kx static char *Release = RELEASE, *Signature = "Fred Baumgarten, Alan Cox, Bernd Eckenfels, Phil Blundell, Tuan Hoang, Brian Micek and others";
5 kx
5 kx
5 kx #define E_READ -1
5 kx #define E_IOCTL -3
5 kx
5 kx int flag_int = 0;
5 kx int flag_rou = 0;
5 kx int flag_mas = 0;
5 kx int flag_sta = 0;
5 kx
5 kx int flag_all = 0;
5 kx int flag_lst = 0;
5 kx int flag_cnt = 0;
5 kx int flag_deb = 0;
5 kx int flag_not = 0;
5 kx int flag_cf = 0;
5 kx int flag_opt = 0;
5 kx int flag_raw = 0;
5 kx int flag_tcp = 0;
5 kx int flag_sctp= 0;
5 kx int flag_udp = 0;
5 kx int flag_udplite = 0;
5 kx int flag_igmp= 0;
5 kx int flag_rom = 0;
5 kx int flag_exp = 1;
5 kx int flag_wide= 0;
5 kx int flag_prg = 0;
5 kx int flag_arg = 0;
5 kx int flag_noprot = 0;
5 kx int flag_ver = 0;
5 kx int flag_l2cap = 0;
5 kx int flag_rfcomm = 0;
5 kx int flag_selinux = 0;
5 kx
5 kx FILE *procinfo;
5 kx
5 kx #define INFO_GUTS1(file,name,proc,prot) \
5 kx procinfo = proc_fopen((file)); \
5 kx if (procinfo == NULL) { \
5 kx if (errno != ENOENT && errno != EACCES) { \
5 kx perror((file)); \
5 kx return -1; \
5 kx } \
5 kx if (!flag_noprot && (flag_arg || flag_ver)) \
5 kx ESYSNOT("netstat", (name)); \
5 kx if (!flag_noprot && flag_arg) \
5 kx rc = 1; \
5 kx } else { \
5 kx do { \
5 kx if (fgets(buffer, sizeof(buffer), procinfo)) \
5 kx (proc)(lnr++, buffer,prot); \
5 kx } while (!feof(procinfo)); \
5 kx fclose(procinfo); \
5 kx }
5 kx
5 kx #if HAVE_AFINET6
5 kx #define INFO_GUTS2(file,proc,prot) \
5 kx lnr = 0; \
5 kx procinfo = proc_fopen((file)); \
5 kx if (procinfo != NULL) { \
5 kx do { \
5 kx if (fgets(buffer, sizeof(buffer), procinfo)) \
5 kx (proc)(lnr++, buffer,prot); \
5 kx } while (!feof(procinfo)); \
5 kx fclose(procinfo); \
5 kx }
5 kx #else
5 kx #define INFO_GUTS2(file,proc,prot)
5 kx #endif
5 kx
5 kx #define INFO_GUTS3 \
5 kx return rc;
5 kx
5 kx #define INFO_GUTS6(file,file6,name,proc,prot4,prot6) \
5 kx char buffer[8192]; \
5 kx int rc = 0; \
5 kx int lnr = 0; \
5 kx if (!flag_arg || flag_inet) { \
5 kx INFO_GUTS1(file,name,proc,prot4) \
5 kx } \
5 kx if (!flag_arg || flag_inet6) { \
5 kx INFO_GUTS2(file6,proc,prot6) \
5 kx } \
5 kx INFO_GUTS3
5 kx
5 kx #define INFO_GUTS(file,name,proc,prot) \
5 kx char buffer[8192]; \
5 kx int rc = 0; \
5 kx int lnr = 0; \
5 kx INFO_GUTS1(file,name,proc,prot) \
5 kx INFO_GUTS3
5 kx
5 kx #define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)
5 kx #define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)
5 kx #define PROGNAME_WIDTH2(s) #s
5 kx
5 kx #define SELINUX_WIDTHs SELINUX_WIDTH1(SELINUX_WIDTH)
5 kx #define SELINUX_WIDTH1(s) SELINUX_WIDTH2(s)
5 kx #define SELINUX_WIDTH2(s) #s
5 kx
5 kx #define PRG_HASH_SIZE 211
5 kx
5 kx static struct prg_node {
5 kx struct prg_node *next;
5 kx unsigned long inode;
5 kx char name[PROGNAME_WIDTH];
5 kx char scon[SELINUX_WIDTH];
5 kx } *prg_hash[PRG_HASH_SIZE];
5 kx
5 kx static char prg_cache_loaded = 0;
5 kx
5 kx #define PRG_HASHIT(x) ((x) % PRG_HASH_SIZE)
5 kx
5 kx #define PROGNAME_BANNER "PID/Program name"
5 kx #define SELINUX_BANNER "Security Context"
5 kx
5 kx #define print_progname_banner() do { if (flag_prg) printf(" %-" PROGNAME_WIDTHs "s",PROGNAME_BANNER); } while (0)
5 kx
5 kx #define print_selinux_banner() do { if (flag_selinux) printf("%-" SELINUX_WIDTHs "s"," " SELINUX_BANNER); } while (0)
5 kx
5 kx #define PRG_LOCAL_ADDRESS "local_address"
5 kx #define PRG_INODE "inode"
5 kx #define PRG_SOCKET_PFX "socket:["
5 kx #define PRG_SOCKET_PFXl (strlen(PRG_SOCKET_PFX))
5 kx #define PRG_SOCKET_PFX2 "[0000]:"
5 kx #define PRG_SOCKET_PFX2l (strlen(PRG_SOCKET_PFX2))
5 kx
5 kx
5 kx #ifndef LINE_MAX
5 kx #define LINE_MAX 4096
5 kx #endif
5 kx
5 kx #define PATH_PROC "/proc"
5 kx #define PATH_FD_SUFF "fd"
5 kx #define PATH_FD_SUFFl strlen(PATH_FD_SUFF)
5 kx #define PATH_PROC_X_FD PATH_PROC "/%s/" PATH_FD_SUFF
5 kx #define PATH_CMDLINE "cmdline"
5 kx #define PATH_CMDLINEl strlen(PATH_CMDLINE)
5 kx
5 kx static void prg_cache_add(unsigned long inode, char *name, const char *scon)
5 kx {
5 kx unsigned hi = PRG_HASHIT(inode);
5 kx struct prg_node **pnp,*pn;
5 kx
5 kx prg_cache_loaded = 2;
5 kx for (pnp = prg_hash + hi; (pn = *pnp); pnp = &pn->next) {
5 kx if (pn->inode == inode) {
5 kx /* Some warning should be appropriate here
5 kx as we got multiple processes for one i-node */
5 kx return;
5 kx }
5 kx }
5 kx if (!(*pnp = malloc(sizeof(**pnp))))
5 kx return;
5 kx pn = *pnp;
5 kx pn->next = NULL;
5 kx pn->inode = inode;
5 kx safe_strncpy(pn->name, name, sizeof(pn->name));
5 kx
5 kx {
5 kx int len = (strlen(scon) - sizeof(pn->scon)) + 1;
5 kx if (len > 0)
5 kx safe_strncpy(pn->scon, &scon[len + 1], sizeof(pn->scon));
5 kx else
5 kx safe_strncpy(pn->scon, scon, sizeof(pn->scon));
5 kx }
5 kx
5 kx }
5 kx
5 kx static const char *prg_cache_get(unsigned long inode)
5 kx {
5 kx unsigned hi = PRG_HASHIT(inode);
5 kx struct prg_node *pn;
5 kx
5 kx for (pn = prg_hash[hi]; pn; pn = pn->next)
5 kx if (pn->inode == inode)
5 kx return (pn->name);
5 kx return ("-");
5 kx }
5 kx
5 kx static const char *prg_cache_get_con(unsigned long inode)
5 kx {
5 kx unsigned hi = PRG_HASHIT(inode);
5 kx struct prg_node *pn;
5 kx
5 kx for (pn = prg_hash[hi]; pn; pn = pn->next)
5 kx if (pn->inode == inode)
5 kx return (pn->scon);
5 kx return ("-");
5 kx }
5 kx
5 kx static void prg_cache_clear(void)
5 kx {
5 kx struct prg_node **pnp,*pn;
5 kx
5 kx if (prg_cache_loaded == 2)
5 kx for (pnp = prg_hash; pnp < prg_hash + PRG_HASH_SIZE; pnp++)
5 kx while ((pn = *pnp)) {
5 kx *pnp = pn->next;
5 kx free(pn);
5 kx }
5 kx prg_cache_loaded = 0;
5 kx }
5 kx
5 kx static void wait_continous(void)
5 kx {
5 kx fflush(stdout);
5 kx sleep(1);
5 kx }
5 kx
5 kx static int extract_type_1_socket_inode(const char lname[], unsigned long * inode_p) {
5 kx
5 kx /* If lname is of the form "socket:[12345]", extract the "12345"
5 kx as *inode_p. Otherwise, return -1 as *inode_p.
5 kx */
5 kx
5 kx if (strlen(lname) < PRG_SOCKET_PFXl+3) return(-1);
5 kx
5 kx if (memcmp(lname, PRG_SOCKET_PFX, PRG_SOCKET_PFXl)) return(-1);
5 kx if (lname[strlen(lname)-1] != ']') return(-1);
5 kx
5 kx {
5 kx char inode_str[strlen(lname + 1)]; /* e.g. "12345" */
5 kx const int inode_str_len = strlen(lname) - PRG_SOCKET_PFXl - 1;
5 kx char *serr;
5 kx
5 kx strncpy(inode_str, lname+PRG_SOCKET_PFXl, inode_str_len);
5 kx inode_str[inode_str_len] = '\0';
5 kx *inode_p = strtoul(inode_str, &serr, 0);
5 kx if (!serr || *serr || *inode_p == ~0)
5 kx return(-1);
5 kx }
5 kx return(0);
5 kx }
5 kx
5 kx
5 kx
5 kx static int extract_type_2_socket_inode(const char lname[], unsigned long * inode_p) {
5 kx
5 kx /* If lname is of the form "[0000]:12345", extract the "12345"
5 kx as *inode_p. Otherwise, return -1 as *inode_p.
5 kx */
5 kx
5 kx if (strlen(lname) < PRG_SOCKET_PFX2l+1) return(-1);
5 kx if (memcmp(lname, PRG_SOCKET_PFX2, PRG_SOCKET_PFX2l)) return(-1);
5 kx
5 kx {
5 kx char *serr;
5 kx
5 kx *inode_p = strtoul(lname + PRG_SOCKET_PFX2l, &serr, 0);
5 kx if (!serr || *serr || *inode_p == ~0)
5 kx return(-1);
5 kx }
5 kx return(0);
5 kx }
5 kx
5 kx
5 kx
5 kx
5 kx static void prg_cache_load(void)
5 kx {
5 kx char line[LINE_MAX], eacces=0;
5 kx int procfdlen, fd, cmdllen, lnamelen;
5 kx char lname[30], cmdlbuf[512], finbuf[PROGNAME_WIDTH];
5 kx unsigned long inode;
5 kx const char *cs, *cmdlp;
5 kx DIR *dirproc = NULL, *dirfd = NULL;
5 kx struct dirent *direproc, *direfd;
5 kx #if HAVE_SELINUX
5 kx security_context_t scon = NULL;
5 kx #endif
5 kx
5 kx if (prg_cache_loaded || !flag_prg) return;
5 kx prg_cache_loaded = 1;
5 kx cmdlbuf[sizeof(cmdlbuf) - 1] = '\0';
5 kx if (!(dirproc=opendir(PATH_PROC))) goto fail;
5 kx while (errno = 0, direproc = readdir(dirproc)) {
5 kx for (cs = direproc->d_name; *cs; cs++)
5 kx if (!isdigit(*cs))
5 kx break;
5 kx if (*cs)
5 kx continue;
5 kx procfdlen = snprintf(line,sizeof(line),PATH_PROC_X_FD,direproc->d_name);
5 kx if (procfdlen <= 0 || procfdlen >= sizeof(line) - 5)
5 kx continue;
5 kx errno = 0;
5 kx dirfd = opendir(line);
5 kx if (! dirfd) {
5 kx if (errno == EACCES)
5 kx eacces = 1;
5 kx continue;
5 kx }
5 kx line[procfdlen] = '/';
5 kx cmdlp = NULL;
5 kx while ((direfd = readdir(dirfd))) {
5 kx /* Skip . and .. */
5 kx if (!isdigit(direfd->d_name[0]))
5 kx continue;
5 kx if (procfdlen + 1 + strlen(direfd->d_name) + 1 > sizeof(line))
5 kx continue;
5 kx memcpy(line + procfdlen - PATH_FD_SUFFl, PATH_FD_SUFF "/",
5 kx PATH_FD_SUFFl + 1);
5 kx safe_strncpy(line + procfdlen + 1, direfd->d_name,
5 kx sizeof(line) - procfdlen - 1);
5 kx lnamelen = readlink(line, lname, sizeof(lname) - 1);
5 kx if (lnamelen == -1)
5 kx continue;
5 kx lname[lnamelen] = '\0'; /*make it a null-terminated string*/
5 kx
5 kx if (extract_type_1_socket_inode(lname, &inode) < 0)
5 kx if (extract_type_2_socket_inode(lname, &inode) < 0)
5 kx continue;
5 kx
5 kx if (!cmdlp) {
5 kx if (procfdlen - PATH_FD_SUFFl + PATH_CMDLINEl >=
5 kx sizeof(line) - 5)
5 kx continue;
5 kx safe_strncpy(line + procfdlen - PATH_FD_SUFFl, PATH_CMDLINE,
5 kx sizeof(line) - procfdlen + PATH_FD_SUFFl);
5 kx fd = open(line, O_RDONLY);
5 kx if (fd < 0)
5 kx continue;
5 kx cmdllen = read(fd, cmdlbuf, sizeof(cmdlbuf) - 1);
5 kx if (close(fd))
5 kx continue;
5 kx if (cmdllen == -1)
5 kx continue;
5 kx if (cmdllen < sizeof(cmdlbuf) - 1)
5 kx cmdlbuf[cmdllen]='\0';
5 kx if (cmdlbuf[0] == '/' && (cmdlp = strrchr(cmdlbuf, '/')))
5 kx cmdlp++;
5 kx else
5 kx cmdlp = cmdlbuf;
5 kx }
5 kx
5 kx snprintf(finbuf, sizeof(finbuf), "%s/%s", direproc->d_name, cmdlp);
5 kx #if HAVE_SELINUX
5 kx if (getpidcon(atoi(direproc->d_name), &scon) == -1) {
5 kx scon=xstrdup("-");
5 kx }
5 kx prg_cache_add(inode, finbuf, scon);
5 kx freecon(scon);
5 kx #else
5 kx prg_cache_add(inode, finbuf, "-");
5 kx #endif
5 kx }
5 kx closedir(dirfd);
5 kx dirfd = NULL;
5 kx }
5 kx if (dirproc)
5 kx closedir(dirproc);
5 kx if (dirfd)
5 kx closedir(dirfd);
5 kx if (!eacces)
5 kx return;
5 kx if (prg_cache_loaded == 1) {
5 kx fail:
5 kx fprintf(stderr,_("(No info could be read for \"-p\": geteuid()=%d but you should be root.)\n"),
5 kx geteuid());
5 kx }
5 kx else
5 kx fprintf(stderr, _("(Not all processes could be identified, non-owned process info\n"
5 kx " will not be shown, you would have to be root to see it all.)\n"));
5 kx }
5 kx
5 kx #if HAVE_AFNETROM
5 kx static const char *netrom_state[] =
5 kx {
5 kx N_("LISTENING"),
5 kx N_("CONN SENT"),
5 kx N_("DISC SENT"),
5 kx N_("ESTABLISHED")
5 kx };
5 kx
5 kx static int netrom_info(void)
5 kx {
5 kx FILE *f;
5 kx char buffer[256], dev[16];
5 kx int st, vs, vr, sendq, recvq, ret;
5 kx
5 kx f = proc_fopen(_PATH_PROCNET_NR);
5 kx if (f == NULL) {
5 kx if (errno != ENOENT) {
5 kx perror(_PATH_PROCNET_NR);
5 kx return (-1);
5 kx }
5 kx if (flag_arg || flag_ver)
5 kx ESYSNOT("netstat", "AF NETROM");
5 kx if (flag_arg)
5 kx return (1);
5 kx else
5 kx return (0);
5 kx }
5 kx printf(_("Active NET/ROM sockets\n"));
5 kx printf(_("User Dest Source Device State Vr/Vs Send-Q Recv-Q\n"));
5 kx if (fgets(buffer, 256, f))
5 kx /* eat line */;
5 kx
5 kx while (fgets(buffer, 256, f)) {
5 kx buffer[9] = 0;
5 kx buffer[19] = 0;
5 kx buffer[29] = 0;
5 kx 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",
5 kx dev, &st, &vs, &vr, &sendq, &recvq);
5 kx if (ret != 6) {
5 kx printf(_("Problem reading data from %s\n"), _PATH_PROCNET_NR);
5 kx continue;
5 kx }
5 kx printf("%-9s %-9s %-9s %-6s %-11s %03d/%03d %-6d %-6d\n",
5 kx buffer, buffer + 10, buffer + 20,
5 kx dev,
5 kx _(netrom_state[st]),
5 kx vr, vs, sendq, recvq);
5 kx }
5 kx fclose(f);
5 kx return 0;
5 kx }
5 kx #endif
5 kx
5 kx #if HAVE_AFROSE
5 kx static const char * const rose_state[] =
5 kx {
5 kx N_("LISTENING"),
5 kx N_("CONN SENT"),
5 kx N_("DISC SENT"),
5 kx N_("ESTABLISHED"),
5 kx };
5 kx
5 kx static int rose_info(void)
5 kx {
5 kx FILE *f;
5 kx char buffer[256], dev[6];
5 kx int ret, st, lci, neigh;
5 kx char src_addr[10], src_call[9], dest_addr[10], dest_call[9];
5 kx
5 kx f = fopen(_PATH_PROCNET_ROSE, "r");
5 kx if (f == NULL) {
5 kx if (errno != ENOENT) {
5 kx perror(_PATH_PROCNET_ROSE);
5 kx return (-1);
5 kx }
5 kx if (flag_arg || flag_ver)
5 kx ESYSNOT("netstat", "AF ROSE");
5 kx if (flag_arg)
5 kx return (1);
5 kx else
5 kx return (0);
5 kx }
5 kx printf(_("Active ROSE sockets\n"));
5 kx printf(_("dest_addr dest_call src_addr src_call dev lci neigh state\n"));
5 kx if (fgets(buffer, 256, f))
5 kx /* eat line */;
5 kx
5 kx while (fgets(buffer, 256, f)) {
5 kx ret = sscanf(buffer, "%s %s %s %s %s %d %d %d",
5 kx dest_addr, dest_call, src_addr, src_call, dev, &lci, &neigh, &st);
5 kx if (ret != 8) {
5 kx printf(_("Problem reading data from %s\n"), _PATH_PROCNET_ROSE);
5 kx continue;
5 kx }
5 kx printf("%-10s %-9s %-10s %-9s %-5s %3d %5d %s\n",
5 kx dest_addr, dest_call, src_addr, src_call, dev, lci, neigh, _(rose_state[st]));
5 kx }
5 kx fclose(f);
5 kx return 0;
5 kx }
5 kx #endif
5 kx
5 kx /* These enums are used by IPX too. :-( */
5 kx enum {
5 kx TCP_ESTABLISHED = 1,
5 kx TCP_SYN_SENT,
5 kx TCP_SYN_RECV,
5 kx TCP_FIN_WAIT1,
5 kx TCP_FIN_WAIT2,
5 kx TCP_TIME_WAIT,
5 kx TCP_CLOSE,
5 kx TCP_CLOSE_WAIT,
5 kx TCP_LAST_ACK,
5 kx TCP_LISTEN,
5 kx TCP_CLOSING /* now a valid state */
5 kx };
5 kx
5 kx #if HAVE_AFINET || HAVE_AFINET6
5 kx
5 kx static const char *tcp_state[] =
5 kx {
5 kx "",
5 kx N_("ESTABLISHED"),
5 kx N_("SYN_SENT"),
5 kx N_("SYN_RECV"),
5 kx N_("FIN_WAIT1"),
5 kx N_("FIN_WAIT2"),
5 kx N_("TIME_WAIT"),
5 kx N_("CLOSE"),
5 kx N_("CLOSE_WAIT"),
5 kx N_("LAST_ACK"),
5 kx N_("LISTEN"),
5 kx N_("CLOSING")
5 kx };
5 kx
5 kx static void finish_this_one(int uid, unsigned long inode, const char *timers)
5 kx {
5 kx struct passwd *pw;
5 kx
5 kx if (flag_exp > 1) {
5 kx if (!(flag_not & FLAG_NUM_USER) && ((pw = getpwuid(uid)) != NULL))
5 kx printf(" %-10s ", pw->pw_name);
5 kx else
5 kx printf(" %-10d ", uid);
5 kx printf("%-10lu",inode);
5 kx }
5 kx if (flag_prg)
5 kx printf(" %-" PROGNAME_WIDTHs "s",prg_cache_get(inode));
5 kx if (flag_selinux)
5 kx printf(" %-" SELINUX_WIDTHs "s",prg_cache_get_con(inode));
5 kx
5 kx if (flag_opt)
5 kx printf(" %s", timers);
5 kx putchar('\n');
5 kx }
5 kx
5 kx static void igmp_do_one(int lnr, const char *line,const char *prot)
5 kx {
5 kx char mcast_addr[128];
5 kx struct sockaddr_storage sas;
5 kx struct sockaddr_in *sin = (struct sockaddr_in *)&sas;
5 kx #if HAVE_AFINET6
5 kx char addr6[INET6_ADDRSTRLEN];
5 kx struct in6_addr in6;
5 kx extern struct aftype inet6_aftype;
5 kx #endif
5 kx const struct aftype *ap;
5 kx static int idx_flag = 0;
5 kx static int igmp6_flag = 0;
5 kx static char device[16];
5 kx int num, idx, refcnt;
5 kx char* offset;
5 kx
5 kx if (lnr == 0) {
5 kx /* IPV6 ONLY */
5 kx /* igmp6 file does not have any comments on first line */
5 kx if ( strstr( line, "Device" ) == NULL ) {
5 kx igmp6_flag = 1;
5 kx } else {
5 kx /* IPV4 ONLY */
5 kx /* 2.1.x kernels and up have Idx field */
5 kx /* 2.0.x and below do not have Idx field */
5 kx if ( strncmp( line, "Idx", strlen("Idx") ) == 0 )
5 kx idx_flag = 1;
5 kx else
5 kx idx_flag = 0;
5 kx return;
5 kx }
5 kx }
5 kx
5 kx if (igmp6_flag) { /* IPV6 */
5 kx #if HAVE_AFINET6
5 kx num = sscanf( line, "%d %15s %64[0-9A-Fa-f] %d", &idx, device, mcast_addr, &refcnt );
5 kx if (num == 4) {
5 kx /* Demangle what the kernel gives us */
5 kx sscanf(mcast_addr, "%08X%08X%08X%08X",
5 kx &in6.s6_addr32[0], &in6.s6_addr32[1],
5 kx &in6.s6_addr32[2], &in6.s6_addr32[3]);
5 kx in6.s6_addr32[0] = htonl(in6.s6_addr32[0]);
5 kx in6.s6_addr32[1] = htonl(in6.s6_addr32[1]);
5 kx in6.s6_addr32[2] = htonl(in6.s6_addr32[2]);
5 kx in6.s6_addr32[3] = htonl(in6.s6_addr32[3]);
5 kx inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
5 kx inet6_aftype.input(1, addr6, &sas);
5 kx sas.ss_family = AF_INET6;
5 kx } else {
5 kx fprintf(stderr, _("warning, got bogus igmp6 line %d.\n"), lnr);
5 kx return;
5 kx }
5 kx
5 kx if ((ap = get_afntype(sas.ss_family)) == NULL) {
5 kx fprintf(stderr, _("netstat: unsupported address family %d !\n"),
5 kx sas.ss_family);
5 kx return;
5 kx }
5 kx safe_strncpy(mcast_addr, ap->sprint(&sas, flag_not & FLAG_NUM_HOST),
5 kx sizeof(mcast_addr));
5 kx printf("%-15s %-6d %s\n", device, refcnt, mcast_addr);
5 kx #endif
5 kx } else { /* IPV4 */
5 kx #if HAVE_AFINET
5 kx if (line[0] != '\t') {
5 kx if (idx_flag) {
5 kx if ((num = sscanf(line, "%d\t%15c", &idx, device)) < 2) {
5 kx fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
5 kx return;
5 kx }
5 kx } else {
5 kx if ((num = sscanf(line, "%15c", device)) < 1 ) {
5 kx fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
5 kx return;
5 kx }
5 kx }
5 kx
5 kx offset = strrchr(device, ':');
5 kx if (offset)
5 kx *offset = 0;
5 kx
5 kx return;
5 kx } else if ( line[0] == '\t' ) {
5 kx if ( (num = sscanf(line, "\t%8[0-9A-Fa-f] %d", mcast_addr, &refcnt)) < 2 ) {
5 kx fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
5 kx return;
5 kx }
5 kx sscanf(mcast_addr, "%X", &sin->sin_addr.s_addr);
5 kx sas.ss_family = AF_INET;
5 kx } else {
5 kx fprintf(stderr, _("warning, got bogus igmp line %d.\n"), lnr);
5 kx return;
5 kx }
5 kx
5 kx if ((ap = get_afntype(sas.ss_family)) == NULL) {
5 kx fprintf(stderr, _("netstat: unsupported address family %d !\n"),
5 kx sas.ss_family);
5 kx return;
5 kx }
5 kx safe_strncpy(mcast_addr, ap->sprint(&sas, flag_not & FLAG_NUM_HOST),
5 kx sizeof(mcast_addr));
5 kx printf("%-15s %-6d %s\n", device, refcnt, mcast_addr );
5 kx #endif
5 kx } /* IPV4 */
5 kx }
5 kx
5 kx #if HAVE_AFX25
5 kx static int x25_info(void)
5 kx {
5 kx FILE *f=proc_fopen(_PATH_PROCNET_X25);
5 kx char buffer[256],dev[16];
5 kx int st,vs,vr,sendq,recvq,lci;
5 kx static char *x25_state[5]=
5 kx {
5 kx "LISTENING",
5 kx "SABM_SENT",
5 kx "DISC_SENT",
5 kx "ESTABLISHED",
5 kx "RECOVERY"
5 kx };
5 kx if(!f)
5 kx {
5 kx if (errno != ENOENT) {
5 kx perror(_PATH_PROCNET_X25);
5 kx return(-1);
5 kx }
5 kx if (flag_arg || flag_ver)
5 kx ESYSNOT("netstat","AF X25");
5 kx if (flag_arg)
5 kx return(1);
5 kx else
5 kx return(0);
5 kx }
5 kx printf( _("Active X.25 sockets\n"));
5 kx /* IMHO, Vr/Vs is not very usefull --SF */
5 kx printf( _("Dest Source Device LCI State Vr/Vs Send-Q Recv-Q\n"));
5 kx if (fgets(buffer,256,f))
5 kx /* eat line */;
5 kx while(fgets(buffer,256,f))
5 kx {
5 kx buffer[10]=0;
5 kx buffer[20]=0;
5 kx sscanf(buffer+22,"%s %d %d %d %d %*d %*d %*d %*d %*d %*d %d %d %*d",
5 kx dev,&lci,&st,&vs,&vr,&sendq,&recvq);
5 kx if (!(flag_all || lci))
5 kx continue;
5 kx printf("%-15s %-15s %-7s %-3d %-11s %02d/%02d %-6d %-6d\n",
5 kx buffer,buffer+11,
5 kx dev,
5 kx lci,
5 kx x25_state[st],
5 kx vr,vs,sendq,recvq);
5 kx }
5 kx fclose(f);
5 kx return 0;
5 kx }
5 kx #endif
5 kx
5 kx static int igmp_info(void)
5 kx {
5 kx INFO_GUTS6(_PATH_PROCNET_IGMP, _PATH_PROCNET_IGMP6, "AF INET (igmp)",
5 kx igmp_do_one, "igmp", "igmp6");
5 kx }
5 kx
5 kx static const char *sctp_socket_state_str(int state)
5 kx {
5 kx if (state >= 0 && state < ARRAY_SIZE(tcp_state))
5 kx return tcp_state[state];
5 kx else {
5 kx static char state_str_buf[64];
5 kx sprintf(state_str_buf, "UNKNOWN(%d)", state);
5 kx return state_str_buf;
5 kx }
5 kx }
5 kx
5 kx static const struct aftype *process_sctp_addr_str(const char *addr_str, struct sockaddr_storage *sas)
5 kx {
5 kx if (strchr(addr_str,':')) {
5 kx #if HAVE_AFINET6
5 kx extern struct aftype inet6_aftype;
5 kx /* Demangle what the kernel gives us */
5 kx struct in6_addr in6;
5 kx char addr6_str[INET6_ADDRSTRLEN];
5 kx unsigned u0, u1, u2, u3, u4, u5, u6, u7;
5 kx sscanf(addr_str, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
5 kx &u0, &u1, &u2, &u3, &u4, &u5, &u6, &u7);
5 kx in6.s6_addr16[0] = htons(u0);
5 kx in6.s6_addr16[1] = htons(u1);
5 kx in6.s6_addr16[2] = htons(u2);
5 kx in6.s6_addr16[3] = htons(u3);
5 kx in6.s6_addr16[4] = htons(u4);
5 kx in6.s6_addr16[5] = htons(u5);
5 kx in6.s6_addr16[6] = htons(u6);
5 kx in6.s6_addr16[7] = htons(u7);
5 kx
5 kx inet_ntop(AF_INET6, &in6, addr6_str, sizeof(addr6_str));
5 kx inet6_aftype.input(1, addr6_str, sas);
5 kx sas->ss_family = AF_INET6;
5 kx #endif
5 kx } else {
5 kx struct sockaddr_in *sin = (struct sockaddr_in *)sas;
5 kx sin->sin_addr.s_addr = inet_addr(addr_str);
5 kx sas->ss_family = AF_INET;
5 kx }
5 kx return get_afntype(sas->ss_family);
5 kx }
5 kx
5 kx static void sctp_eps_do_one(int lnr, char *line, const char *proto)
5 kx {
5 kx char buffer[1024];
5 kx int state, port;
5 kx int uid;
5 kx unsigned long inode;
5 kx const struct aftype *ap;
5 kx struct sockaddr_storage localsas;
5 kx const char *sst_str;
5 kx const char *lport_str;
5 kx const char *uid_str;
5 kx const char *inode_str;
5 kx char *laddrs_str;
5 kx
5 kx if (lnr == 0) {
5 kx /* ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS */
5 kx return;
5 kx }
5 kx strtok(line, " \t\n"); /* skip endpt */
5 kx strtok(0, " \t\n"); /* skip sock */
5 kx strtok(0, " \t\n"); /* skip sty */
5 kx sst_str = strtok(0, " \t\n");
5 kx strtok(0, " \t\n"); /* skip hash bucket */
5 kx lport_str = strtok(0, " \t\n");
5 kx uid_str = strtok(0, " \t\n");
5 kx inode_str = strtok(0, " \t\n");
5 kx laddrs_str = strtok(0, "\t\n");
5 kx
5 kx if (!sst_str || !lport_str || !uid_str || !inode_str) {
5 kx fprintf(stderr, _("warning, got bogus sctp eps line.\n"));
5 kx return;
5 kx }
5 kx state = atoi(sst_str);
5 kx port = atoi(lport_str);
5 kx uid = atoi(uid_str);
5 kx inode = strtoul(inode_str,0,0);
5 kx
5 kx const char *this_local_addr;
5 kx int first = 1;
5 kx char local_port[16];
5 kx snprintf(local_port, sizeof(local_port), "%s",
5 kx get_sname(htons(port), proto, flag_not & FLAG_NUM_PORT));
5 kx for (this_local_addr = strtok(laddrs_str, " \t\n");
5 kx this_local_addr;
5 kx this_local_addr = strtok(0, " \t\n")) {
5 kx char local_addr[64];
5 kx ap = process_sctp_addr_str(this_local_addr, &localsas);
5 kx if (ap)
5 kx safe_strncpy(local_addr, ap->sprint(&localsas, flag_not), sizeof(local_addr));
5 kx else
5 kx sprintf(local_addr, _("unsupported address family %d"), localsas.ss_family);
5 kx
5 kx if (first)
5 kx printf("sctp ");
5 kx else
5 kx printf("\n ");
5 kx sprintf(buffer, "%s:%s", local_addr, local_port);
5 kx printf("%-47s", buffer);
5 kx printf(" %-11s", first ? sctp_socket_state_str(state) : "");
5 kx first = 0;
5 kx }
5 kx finish_this_one(uid, inode, "");
5 kx }
5 kx
5 kx static void sctp_assoc_do_one(int lnr, char *line, const char *proto)
5 kx {
5 kx char buffer[1024];
5 kx int state, lport,rport;
5 kx int uid;
5 kx unsigned rxqueue,txqueue;
5 kx unsigned long inode;
5 kx
5 kx const struct aftype *ap;
5 kx struct sockaddr_storage localsas, remotesas;
5 kx const char *sst_str;
5 kx const char *txqueue_str;
5 kx const char *rxqueue_str;
5 kx const char *lport_str, *rport_str;
5 kx const char *uid_str;
5 kx const char *inode_str;
5 kx char *laddrs_str;
5 kx char *raddrs_str;
5 kx
5 kx if (lnr == 0) {
5 kx /* ASSOC SOCK STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT RPORT LADDRS <-> RADDRS */
5 kx return;
5 kx }
5 kx
5 kx strtok(line, " \t\n"); /* skip assoc */
5 kx strtok(0, " \t\n"); /* skip sock */
5 kx strtok(0, " \t\n"); /* skip sty */
5 kx sst_str = strtok(0, " \t\n");
5 kx strtok(0, " \t\n");
5 kx strtok(0, " \t\n"); /* skip hash bucket */
5 kx strtok(0, " \t\n"); /* skip hash assoc-id */
5 kx txqueue_str = strtok(0, " \t\n");
5 kx rxqueue_str = strtok(0, " \t\n");
5 kx uid_str = strtok(0, " \t\n");
5 kx inode_str = strtok(0, " \t\n");
5 kx lport_str = strtok(0, " \t\n");
5 kx rport_str = strtok(0, " \t\n");
5 kx laddrs_str = strtok(0, "<->\t\n");
5 kx raddrs_str = strtok(0, "<->\t\n");
5 kx
5 kx if (!sst_str || !txqueue_str || !rxqueue_str || !uid_str ||
5 kx !inode_str || !lport_str || !rport_str) {
5 kx fprintf(stderr, _("warning, got bogus sctp assoc line.\n"));
5 kx return;
5 kx }
5 kx
5 kx state = atoi(sst_str);
5 kx txqueue = atoi(txqueue_str);
5 kx rxqueue = atoi(rxqueue_str);
5 kx uid = atoi(uid_str);
5 kx inode = strtoul(inode_str, 0, 0);
5 kx lport = atoi(lport_str);
5 kx rport = atoi(rport_str);
5 kx
5 kx /*print all addresses*/
5 kx const char *this_local_addr;
5 kx const char *this_remote_addr;
5 kx char *ss1, *ss2;
5 kx int first = 1;
5 kx char local_port[16];
5 kx char remote_port[16];
5 kx snprintf(local_port, sizeof(local_port), "%s",
5 kx get_sname(htons(lport), proto,
5 kx flag_not & FLAG_NUM_PORT));
5 kx snprintf(remote_port, sizeof(remote_port), "%s",
5 kx get_sname(htons(rport), proto,
5 kx flag_not & FLAG_NUM_PORT));
5 kx
5 kx this_local_addr = strtok_r(laddrs_str, " \t\n", &ss1);
5 kx this_remote_addr = strtok_r(raddrs_str, " \t\n", &ss2);
5 kx while (this_local_addr || this_remote_addr) {
5 kx char local_addr[64];
5 kx char remote_addr[64];
5 kx
5 kx if (this_local_addr) {
5 kx if (this_local_addr[0] == '*') {
5 kx /* skip * */
5 kx this_local_addr++;
5 kx }
5 kx ap = process_sctp_addr_str(this_local_addr, &localsas);
5 kx if (ap)
5 kx safe_strncpy(local_addr,
5 kx ap->sprint(&localsas, flag_not), sizeof(local_addr));
5 kx else
5 kx sprintf(local_addr, _("unsupported address family %d"), localsas.ss_family);
5 kx }
5 kx if (this_remote_addr) {
5 kx if (this_remote_addr[0] == '*') {
5 kx /* skip * */
5 kx this_remote_addr++;
5 kx }
5 kx ap = process_sctp_addr_str(this_remote_addr, &remotesas);
5 kx if (ap)
5 kx safe_strncpy(remote_addr,
5 kx ap->sprint(&remotesas, flag_not), sizeof(remote_addr));
5 kx else
5 kx sprintf(remote_addr, _("unsupported address family %d"), remotesas.ss_family);
5 kx }
5 kx
5 kx if (first)
5 kx printf("sctp %6u %6u ", rxqueue, txqueue);
5 kx else
5 kx printf("\n ");
5 kx if (this_local_addr) {
5 kx if (first)
5 kx sprintf(buffer, "%s:%s", local_addr, local_port);
5 kx else
5 kx sprintf(buffer, "%s", local_addr);
5 kx printf("%-23s", buffer);
5 kx } else
5 kx printf("%-23s", "");
5 kx printf(" ");
5 kx if (this_remote_addr) {
5 kx if (first)
5 kx sprintf(buffer, "%s:%s", remote_addr, remote_port);
5 kx else
5 kx sprintf(buffer, "%s", remote_addr);
5 kx printf("%-23s", buffer);
5 kx } else
5 kx printf("%-23s", "");
5 kx
5 kx printf(" %-11s", first ? sctp_socket_state_str(state) : "");
5 kx
5 kx first = 0;
5 kx this_local_addr = strtok_r(0, " \t\n", &ss1);
5 kx this_remote_addr = strtok_r(0, " \t\n", &ss2);
5 kx }
5 kx finish_this_one(uid, inode, "");
5 kx }
5 kx
5 kx static int sctp_info_eps(void)
5 kx {
5 kx INFO_GUTS6(_PATH_PROCNET_SCTPEPTS, _PATH_PROCNET_SCTP6EPTS, "AF INET (sctp)",
5 kx sctp_eps_do_one, "sctp", "sctp6");
5 kx }
5 kx
5 kx static int sctp_info_assocs(void)
5 kx {
5 kx INFO_GUTS6(_PATH_PROCNET_SCTPASSOCS, _PATH_PROCNET_SCTP6ASSOCS, "AF INET (sctp)",
5 kx sctp_assoc_do_one, "sctp", "sctp6");
5 kx }
5 kx
5 kx static int sctp_info(void)
5 kx {
5 kx int res;
5 kx
5 kx if (flag_all || flag_lst) {
5 kx res = sctp_info_eps();
5 kx if (res)
5 kx return res;
5 kx }
5 kx
5 kx if (flag_all || !flag_lst) {
5 kx res = sctp_info_assocs();
5 kx }
5 kx
5 kx return res;
5 kx }
5 kx
5 kx static void addr_do_one(char *buf, size_t buf_len, size_t short_len, const struct aftype *ap,
5 kx const struct sockaddr_storage *addr,
5 kx int port, const char *proto
5 kx )
5 kx {
5 kx const char *sport, *saddr;
5 kx size_t port_len, addr_len;
5 kx
5 kx saddr = ap->sprint(addr, flag_not & FLAG_NUM_HOST);
5 kx sport = get_sname(htons(port), proto, flag_not & FLAG_NUM_PORT);
5 kx addr_len = strlen(saddr);
5 kx port_len = strlen(sport);
5 kx if (!flag_wide && (addr_len + port_len > short_len)) {
5 kx /* Assume port name is short */
5 kx port_len = netmin(port_len, short_len - 4);
5 kx addr_len = short_len - port_len;
5 kx strncpy(buf, saddr, addr_len);
5 kx buf[addr_len] = '\0';
5 kx strcat(buf, ":");
5 kx strncat(buf, sport, port_len);
5 kx } else
5 kx snprintf(buf, buf_len, "%s:%s", saddr, sport);
5 kx }
5 kx
5 kx static void tcp_do_one(int lnr, const char *line, const char *prot)
5 kx {
5 kx unsigned long rxq, txq, time_len, retr, inode;
5 kx int num, local_port, rem_port, d, state, uid, timer_run, timeout;
5 kx char rem_addr[128], local_addr[128], timers[64];
5 kx const struct aftype *ap;
5 kx struct sockaddr_storage localsas, remsas;
5 kx struct sockaddr_in *localaddr = (struct sockaddr_in *)&localsas;
5 kx struct sockaddr_in *remaddr = (struct sockaddr_in *)&remsas;
5 kx #if HAVE_AFINET6
5 kx char addr6[INET6_ADDRSTRLEN];
5 kx struct in6_addr in6;
5 kx extern struct aftype inet6_aftype;
5 kx #endif
5 kx long clk_tck = ticks_per_second();
5 kx
5 kx if (lnr == 0)
5 kx return;
5 kx
5 kx num = sscanf(line,
5 kx "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %*s\n",
5 kx &d, local_addr, &local_port, rem_addr, &rem_port, &state,
5 kx &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode);
5 kx
5 kx if (num < 11) {
5 kx fprintf(stderr, _("warning, got bogus tcp line.\n"));
5 kx return;
5 kx }
5 kx
5 kx if (!flag_all && ((flag_lst && rem_port) || (!flag_lst && !rem_port)))
5 kx return;
5 kx
5 kx if (strlen(local_addr) > 8) {
5 kx #if HAVE_AFINET6
5 kx /* Demangle what the kernel gives us */
5 kx sscanf(local_addr, "%08X%08X%08X%08X",
5 kx &in6.s6_addr32[0], &in6.s6_addr32[1],
5 kx &in6.s6_addr32[2], &in6.s6_addr32[3]);
5 kx inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
5 kx inet6_aftype.input(1, addr6, &localsas);
5 kx sscanf(rem_addr, "%08X%08X%08X%08X",
5 kx &in6.s6_addr32[0], &in6.s6_addr32[1],
5 kx &in6.s6_addr32[2], &in6.s6_addr32[3]);
5 kx inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
5 kx inet6_aftype.input(1, addr6, &remsas);
5 kx localsas.ss_family = AF_INET6;
5 kx remsas.ss_family = AF_INET6;
5 kx #endif
5 kx } else {
5 kx sscanf(local_addr, "%X", &localaddr->sin_addr.s_addr);
5 kx sscanf(rem_addr, "%X", &remaddr->sin_addr.s_addr);
5 kx localsas.ss_family = AF_INET;
5 kx remsas.ss_family = AF_INET;
5 kx }
5 kx
5 kx if ((ap = get_afntype(localsas.ss_family)) == NULL) {
5 kx fprintf(stderr, _("netstat: unsupported address family %d !\n"),
5 kx localsas.ss_family);
5 kx return;
5 kx }
5 kx
5 kx addr_do_one(local_addr, sizeof(local_addr), 22, ap, &localsas, local_port, "tcp");
5 kx addr_do_one(rem_addr, sizeof(rem_addr), 22, ap, &remsas, rem_port, "tcp");
5 kx
5 kx timers[0] = '\0';
5 kx if (flag_opt)
5 kx switch (timer_run) {
5 kx case 0:
5 kx snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
5 kx break;
5 kx
5 kx case 1:
5 kx snprintf(timers, sizeof(timers), _("on (%2.2f/%ld/%d)"),
5 kx (double) time_len / clk_tck, retr, timeout);
5 kx break;
5 kx
5 kx case 2:
5 kx snprintf(timers, sizeof(timers), _("keepalive (%2.2f/%ld/%d)"),
5 kx (double) time_len / clk_tck, retr, timeout);
5 kx break;
5 kx
5 kx case 3:
5 kx snprintf(timers, sizeof(timers), _("timewait (%2.2f/%ld/%d)"),
5 kx (double) time_len / clk_tck, retr, timeout);
5 kx break;
5 kx
5 kx case 4:
5 kx snprintf(timers, sizeof(timers), _("probe (%2.2f/%ld/%d)"),
5 kx (double) time_len / clk_tck, retr, timeout);
5 kx break;
5 kx
5 kx default:
5 kx snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
5 kx timer_run, (double) time_len / clk_tck, retr, timeout);
5 kx break;
5 kx }
5 kx
5 kx printf("%-4s %6ld %6ld %-*s %-*s %-11s",
5 kx prot, rxq, txq, (int)netmax(23,strlen(local_addr)), local_addr, (int)netmax(23,strlen(rem_addr)), rem_addr, _(tcp_state[state]));
5 kx
5 kx finish_this_one(uid,inode,timers);
5 kx }
5 kx
5 kx static int tcp_info(void)
5 kx {
5 kx INFO_GUTS6(_PATH_PROCNET_TCP, _PATH_PROCNET_TCP6, "AF INET (tcp)",
5 kx tcp_do_one, "tcp", "tcp6");
5 kx }
5 kx
5 kx static int notnull(const struct sockaddr_storage *sas)
5 kx {
5 kx const struct sockaddr_in *sin = (const struct sockaddr_in *)sas;
5 kx
5 kx #if HAVE_AFINET6
5 kx const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sas;
5 kx
5 kx if (sin6->sin6_family == AF_INET6) {
5 kx return sin6->sin6_addr.s6_addr32[0] ||
5 kx sin6->sin6_addr.s6_addr32[1] ||
5 kx sin6->sin6_addr.s6_addr32[2] ||
5 kx sin6->sin6_addr.s6_addr32[3];
5 kx }
5 kx #endif
5 kx
5 kx return sin->sin_addr.s_addr;
5 kx }
5 kx
5 kx static void udp_do_one(int lnr, const char *line,const char *prot)
5 kx {
5 kx char local_addr[128], rem_addr[128];
5 kx char *udp_state, timers[64];
5 kx int num, local_port, rem_port, d, state, timer_run, uid, timeout;
5 kx struct sockaddr_storage localsas, remsas;
5 kx struct sockaddr_in *localaddr = (struct sockaddr_in *)&localsas;
5 kx struct sockaddr_in *remaddr = (struct sockaddr_in *)&remsas;
5 kx #if HAVE_AFINET6
5 kx char addr6[INET6_ADDRSTRLEN];
5 kx struct in6_addr in6;
5 kx extern struct aftype inet6_aftype;
5 kx #endif
5 kx const struct aftype *ap;
5 kx unsigned long rxq, txq, time_len, retr, inode;
5 kx
5 kx if (lnr == 0)
5 kx return;
5 kx
5 kx num = sscanf(line,
5 kx "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %*s\n",
5 kx &d, local_addr, &local_port,
5 kx rem_addr, &rem_port, &state,
5 kx &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode);
5 kx
5 kx if (num < 10) {
5 kx fprintf(stderr, _("warning, got bogus udp line.\n"));
5 kx return;
5 kx }
5 kx
5 kx if (strlen(local_addr) > 8) {
5 kx #if HAVE_AFINET6
5 kx sscanf(local_addr, "%08X%08X%08X%08X",
5 kx &in6.s6_addr32[0], &in6.s6_addr32[1],
5 kx &in6.s6_addr32[2], &in6.s6_addr32[3]);
5 kx inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
5 kx inet6_aftype.input(1, addr6, &localsas);
5 kx sscanf(rem_addr, "%08X%08X%08X%08X",
5 kx &in6.s6_addr32[0], &in6.s6_addr32[1],
5 kx &in6.s6_addr32[2], &in6.s6_addr32[3]);
5 kx inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
5 kx inet6_aftype.input(1, addr6, &remsas);
5 kx localsas.ss_family = AF_INET6;
5 kx remsas.ss_family = AF_INET6;
5 kx #endif
5 kx } else {
5 kx sscanf(local_addr, "%X", &localaddr->sin_addr.s_addr);
5 kx sscanf(rem_addr, "%X", &remaddr->sin_addr.s_addr);
5 kx localsas.ss_family = AF_INET;
5 kx remsas.ss_family = AF_INET;
5 kx }
5 kx
5 kx retr = 0L;
5 kx
5 kx if ((ap = get_afntype(localsas.ss_family)) == NULL) {
5 kx fprintf(stderr, _("netstat: unsupported address family %d !\n"),
5 kx localsas.ss_family);
5 kx return;
5 kx }
5 kx switch (state) {
5 kx case TCP_ESTABLISHED:
5 kx udp_state = _("ESTABLISHED");
5 kx break;
5 kx
5 kx case TCP_CLOSE:
5 kx udp_state = "";
5 kx break;
5 kx
5 kx default:
5 kx udp_state = _("UNKNOWN");
5 kx break;
5 kx }
5 kx
5 kx if (flag_all || (notnull(&remsas) && !flag_lst) || (!notnull(&remsas) && flag_lst))
5 kx {
5 kx addr_do_one(local_addr, sizeof(local_addr), 22, ap, &localsas, local_port, "udp");
5 kx addr_do_one(rem_addr, sizeof(rem_addr), 22, ap, &remsas, rem_port, "udp");
5 kx
5 kx timers[0] = '\0';
5 kx if (flag_opt)
5 kx switch (timer_run) {
5 kx case 0:
5 kx snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
5 kx break;
5 kx
5 kx case 1:
5 kx case 2:
5 kx snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100, retr, timeout);
5 kx break;
5 kx
5 kx default:
5 kx snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
5 kx retr, timeout);
5 kx break;
5 kx }
5 kx printf("%-5s %6ld %6ld %-23s %-23s %-11s",
5 kx prot, rxq, txq, local_addr, rem_addr, udp_state);
5 kx
5 kx finish_this_one(uid,inode,timers);
5 kx }
5 kx }
5 kx
5 kx static int udp_info(void)
5 kx {
5 kx INFO_GUTS6(_PATH_PROCNET_UDP, _PATH_PROCNET_UDP6, "AF INET (udp)",
5 kx udp_do_one, "udp", "udp6");
5 kx }
5 kx
5 kx static int udplite_info(void)
5 kx {
5 kx INFO_GUTS6(_PATH_PROCNET_UDPLITE, _PATH_PROCNET_UDPLITE6,
5 kx "AF INET (udplite)", udp_do_one, "udpl", "udpl6" );
5 kx }
5 kx
5 kx static void raw_do_one(int lnr, const char *line,const char *prot)
5 kx {
5 kx char local_addr[128], rem_addr[128];
5 kx char timers[64];
5 kx int num, local_port, rem_port, d, state, timer_run, uid, timeout;
5 kx struct sockaddr_storage localsas, remsas;
5 kx struct sockaddr_in *localaddr = (struct sockaddr_in *)&localsas;
5 kx struct sockaddr_in *remaddr = (struct sockaddr_in *)&remsas;
5 kx #if HAVE_AFINET6
5 kx char addr6[INET6_ADDRSTRLEN];
5 kx struct in6_addr in6;
5 kx extern struct aftype inet6_aftype;
5 kx #endif
5 kx const struct aftype *ap;
5 kx unsigned long rxq, txq, time_len, retr, inode;
5 kx
5 kx if (lnr == 0)
5 kx return;
5 kx
5 kx num = sscanf(line,
5 kx "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %lu %*s\n",
5 kx &d, local_addr, &local_port, rem_addr, &rem_port, &state,
5 kx &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode);
5 kx
5 kx if (num < 10) {
5 kx fprintf(stderr, _("warning, got bogus raw line.\n"));
5 kx return;
5 kx }
5 kx
5 kx if (strlen(local_addr) > 8) {
5 kx #if HAVE_AFINET6
5 kx sscanf(local_addr, "%08X%08X%08X%08X",
5 kx &in6.s6_addr32[0], &in6.s6_addr32[1],
5 kx &in6.s6_addr32[2], &in6.s6_addr32[3]);
5 kx inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
5 kx inet6_aftype.input(1, addr6, &localsas);
5 kx sscanf(rem_addr, "%08X%08X%08X%08X",
5 kx &in6.s6_addr32[0], &in6.s6_addr32[1],
5 kx &in6.s6_addr32[2], &in6.s6_addr32[3]);
5 kx inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
5 kx inet6_aftype.input(1, addr6, &remsas);
5 kx localsas.ss_family = AF_INET6;
5 kx remsas.ss_family = AF_INET6;
5 kx #endif
5 kx } else {
5 kx sscanf(local_addr, "%X", &localaddr->sin_addr.s_addr);
5 kx sscanf(rem_addr, "%X", &remaddr->sin_addr.s_addr);
5 kx localsas.ss_family = AF_INET;
5 kx remsas.ss_family = AF_INET;
5 kx }
5 kx
5 kx if ((ap = get_afntype(localsas.ss_family)) == NULL) {
5 kx fprintf(stderr, _("netstat: unsupported address family %d !\n"), localsas.ss_family);
5 kx return;
5 kx }
5 kx
5 kx if (flag_all || (notnull(&remsas) && !flag_lst) || (!notnull(&remsas) && flag_lst))
5 kx {
5 kx addr_do_one(local_addr, sizeof(local_addr), 22, ap, &localsas, local_port, "raw");
5 kx addr_do_one(rem_addr, sizeof(rem_addr), 22, ap, &remsas, rem_port, "raw");
5 kx
5 kx timers[0] = '\0';
5 kx if (flag_opt)
5 kx switch (timer_run) {
5 kx case 0:
5 kx snprintf(timers, sizeof(timers), _("off (0.00/%ld/%d)"), retr, timeout);
5 kx break;
5 kx
5 kx case 1:
5 kx case 2:
5 kx snprintf(timers, sizeof(timers), _("on%d (%2.2f/%ld/%d)"), timer_run, (double) time_len / 100,
5 kx retr, timeout);
5 kx break;
5 kx
5 kx default:
5 kx snprintf(timers, sizeof(timers), _("unkn-%d (%2.2f/%ld/%d)"),
5 kx timer_run, (double) time_len / 100,
5 kx retr, timeout);
5 kx break;
5 kx }
5 kx printf("%-4s %6ld %6ld %-23s %-23s %-11d",
5 kx prot, rxq, txq, local_addr, rem_addr, state);
5 kx
5 kx finish_this_one(uid,inode,timers);
5 kx }
5 kx }
5 kx
5 kx static int raw_info(void)
5 kx {
5 kx INFO_GUTS6(_PATH_PROCNET_RAW, _PATH_PROCNET_RAW6, "AF INET (raw)",
5 kx raw_do_one, "raw", "raw6");
5 kx }
5 kx
5 kx #endif
5 kx
5 kx
5 kx #if HAVE_AFUNIX
5 kx
5 kx #define HAS_INODE 1
5 kx
5 kx static void unix_do_one(int nr, const char *line, const char *prot)
5 kx {
5 kx static int has = 0;
5 kx char path[MAXPATHLEN], ss_flags[32];
5 kx char *ss_proto, *ss_state, *ss_type;
5 kx int num, state, type;
5 kx void *d;
5 kx unsigned long refcnt, proto, flags, inode;
5 kx
5 kx if (nr == 0) {
5 kx if (strstr(line, "Inode"))
5 kx has |= HAS_INODE;
5 kx return;
5 kx }
5 kx path[0] = '\0';
5 kx num = sscanf(line, "%p: %lX %lX %lX %X %X %lu %s",
5 kx &d, &refcnt, &proto, &flags, &type, &state, &inode, path);
5 kx if (num < 6) {
5 kx fprintf(stderr, _("warning, got bogus unix line.\n"));
5 kx return;
5 kx }
5 kx if (!(has & HAS_INODE))
5 kx snprintf(path,sizeof(path),"%lu",inode);
5 kx
5 kx if (!flag_all) {
5 kx if ((state == SS_UNCONNECTED) && (flags & SO_ACCEPTCON)) {
5 kx if (!flag_lst)
5 kx return;
5 kx } else {
5 kx if (flag_lst)
5 kx return;
5 kx }
5 kx }
5 kx
5 kx switch (proto) {
5 kx case 0:
5 kx ss_proto = "unix";
5 kx break;
5 kx
5 kx default:
5 kx ss_proto = "??";
5 kx }
5 kx
5 kx switch (type) {
5 kx case SOCK_STREAM:
5 kx ss_type = _("STREAM");
5 kx break;
5 kx
5 kx case SOCK_DGRAM:
5 kx ss_type = _("DGRAM");
5 kx break;
5 kx
5 kx case SOCK_RAW:
5 kx ss_type = _("RAW");
5 kx break;
5 kx
5 kx case SOCK_RDM:
5 kx ss_type = _("RDM");
5 kx break;
5 kx
5 kx case SOCK_SEQPACKET:
5 kx ss_type = _("SEQPACKET");
5 kx break;
5 kx
5 kx default:
5 kx ss_type = _("UNKNOWN");
5 kx }
5 kx
5 kx switch (state) {
5 kx case SS_FREE:
5 kx ss_state = _("FREE");
5 kx break;
5 kx
5 kx case SS_UNCONNECTED:
5 kx /*
5 kx * Unconnected sockets may be listening
5 kx * for something.
5 kx */
5 kx if (flags & SO_ACCEPTCON) {
5 kx ss_state = _("LISTENING");
5 kx } else {
5 kx ss_state = "";
5 kx }
5 kx break;
5 kx
5 kx case SS_CONNECTING:
5 kx ss_state = _("CONNECTING");
5 kx break;
5 kx
5 kx case SS_CONNECTED:
5 kx ss_state = _("CONNECTED");
5 kx break;
5 kx
5 kx case SS_DISCONNECTING:
5 kx ss_state = _("DISCONNECTING");
5 kx break;
5 kx
5 kx default:
5 kx ss_state = _("UNKNOWN");
5 kx }
5 kx
5 kx safe_strncpy(ss_flags, "[ ", sizeof(ss_flags));
5 kx if (flags & SO_ACCEPTCON)
5 kx strcat(ss_flags, "ACC ");
5 kx if (flags & SO_WAITDATA)
5 kx strcat(ss_flags, "W ");
5 kx if (flags & SO_NOSPACE)
5 kx strcat(ss_flags, "N ");
5 kx
5 kx strcat(ss_flags, "]");
5 kx
5 kx printf("%-5s %-6ld %-11s %-10s %-13s ",
5 kx ss_proto, refcnt, ss_flags, ss_type, ss_state);
5 kx if (has & HAS_INODE)
5 kx printf("%-8lu",inode);
5 kx else
5 kx printf("- ");
5 kx if (flag_prg)
5 kx printf(" %-" PROGNAME_WIDTHs "s",(has & HAS_INODE?prg_cache_get(inode):"-"));
5 kx if (flag_selinux)
5 kx printf(" %-" SELINUX_WIDTHs "s",(has & HAS_INODE?prg_cache_get_con(inode):"-"));
5 kx
5 kx printf(" %s\n", path);
5 kx }
5 kx
5 kx static int unix_info(void)
5 kx {
5 kx
5 kx printf(_("Active UNIX domain sockets "));
5 kx if (flag_all)
5 kx printf(_("(servers and established)"));
5 kx else {
5 kx if (flag_lst)
5 kx printf(_("(only servers)"));
5 kx else
5 kx printf(_("(w/o servers)"));
5 kx }
5 kx
5 kx printf(_("\nProto RefCnt Flags Type State I-Node "));
5 kx print_progname_banner();
5 kx print_selinux_banner();
5 kx printf(_(" Path\n")); /* xxx */
5 kx
5 kx {
5 kx INFO_GUTS(_PATH_PROCNET_UNIX, "AF UNIX", unix_do_one, "unix");
5 kx }
5 kx }
5 kx #endif
5 kx
5 kx
5 kx #if HAVE_AFAX25
5 kx static int ax25_info(void)
5 kx {
5 kx FILE *f;
5 kx char buffer[256], buf[16];
5 kx char *src, *dst, *dev, *p;
5 kx int st, vs, vr, sendq, recvq, ret;
5 kx int new = -1; /* flag for new (2.1.x) kernels */
5 kx static char *ax25_state[5] =
5 kx {
5 kx N_("LISTENING"),
5 kx N_("SABM SENT"),
5 kx N_("DISC SENT"),
5 kx N_("ESTABLISHED"),
5 kx N_("RECOVERY")
5 kx };
5 kx if (!(f = proc_fopen(_PATH_PROCNET_AX25))) {
5 kx if (errno != ENOENT) {
5 kx perror(_PATH_PROCNET_AX25);
5 kx return (-1);
5 kx }
5 kx if (flag_arg || flag_ver)
5 kx ESYSNOT("netstat", "AF AX25");
5 kx if (flag_arg)
5 kx return (1);
5 kx else
5 kx return (0);
5 kx }
5 kx printf(_("Active AX.25 sockets\n"));
5 kx printf(_("Dest Source Device State Vr/Vs Send-Q Recv-Q\n"));
5 kx while (fgets(buffer, 256, f)) {
5 kx if (new == -1) {
5 kx if (!strncmp(buffer, "dest_addr", 9)) {
5 kx new = 0;
5 kx continue; /* old kernels have a header line */
5 kx } else
5 kx new = 1;
5 kx }
5 kx /*
5 kx * In a network connection with no user socket the Snd-Q, Rcv-Q
5 kx * and Inode fields are empty in 2.0.x and '*' in 2.1.x
5 kx */
5 kx sendq = 0;
5 kx recvq = 0;
5 kx if (new == 0) {
5 kx dst = buffer;
5 kx src = buffer + 10;
5 kx dst[9] = 0;
5 kx src[9] = 0;
5 kx 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",
5 kx buf, &st, &vs, &vr, &sendq, &recvq);
5 kx if (ret != 4 && ret != 6) {
5 kx printf(_("Problem reading data from %s\n"), _PATH_PROCNET_AX25);
5 kx continue;
5 kx }
5 kx dev = buf;
5 kx } else {
5 kx p = buffer;
5 kx while (*p != ' ') p++;
5 kx p++;
5 kx dev = p;
5 kx while (*p != ' ') p++;
5 kx *p++ = 0;
5 kx src = p;
5 kx while (*p != ' ') p++;
5 kx *p++ = 0;
5 kx dst = p;
5 kx while (*p != ' ') p++;
5 kx *p++ = 0;
5 kx ret = sscanf(p, "%d %d %d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d %*d",
5 kx &st, &vs, &vr, &sendq, &recvq);
5 kx if (ret != 3 && ret != 5) {
5 kx printf(_("problem reading data from %s\n"), _PATH_PROCNET_AX25);
5 kx continue;
5 kx }
5 kx /*
5 kx * FIXME: digipeaters should be handled somehow.
5 kx * For now we just strip them.
5 kx */
5 kx p = dst;
5 kx while (*p && *p != ',') p++;
5 kx *p = 0;
5 kx }
5 kx printf("%-9s %-9s %-6s %-11s %03d/%03d %-6d %-6d\n",
5 kx dst, src,
5 kx dev,
5 kx _(ax25_state[st]),
5 kx vr, vs, sendq, recvq);
5 kx }
5 kx fclose(f);
5 kx return 0;
5 kx }
5 kx #endif
5 kx
5 kx
5 kx #if HAVE_AFIPX
5 kx static int ipx_info(void)
5 kx {
5 kx FILE *f;
5 kx char buf[256];
5 kx unsigned long txq, rxq;
5 kx unsigned int state;
5 kx unsigned int uid;
5 kx char *st;
5 kx int nc;
5 kx const struct aftype *ap;
5 kx struct passwd *pw;
5 kx char sad[50], dad[50];
5 kx struct sockaddr_storage sa;
5 kx unsigned sport = 0, dport = 0;
5 kx struct stat s;
5 kx
5 kx f = proc_fopen(_PATH_PROCNET_IPX_SOCKET1);
5 kx if (!f) {
5 kx if (errno != ENOENT) {
5 kx perror(_PATH_PROCNET_IPX_SOCKET1);
5 kx return (-1);
5 kx }
5 kx f = proc_fopen(_PATH_PROCNET_IPX_SOCKET2);
5 kx
5 kx /* We need to check for directory */
5 kx if (f) {
5 kx if (fstat (fileno(f), &s) == -1 ||
5 kx !S_ISREG(s.st_mode)) {
5 kx fclose(f);
5 kx f=NULL;
5 kx }
5 kx }
5 kx
5 kx if (!f) {
5 kx if (errno != ENOENT) {
5 kx perror(_PATH_PROCNET_IPX_SOCKET2);
5 kx return (-1);
5 kx }
5 kx if (flag_arg || flag_ver)
5 kx ESYSNOT("netstat", "AF IPX");
5 kx if (flag_arg)
5 kx return (1);
5 kx else
5 kx return (0);
5 kx }
5 kx }
5 kx printf(_("Active IPX sockets\nProto Recv-Q Send-Q Local Address Foreign Address State")); /* xxx */
5 kx if (flag_exp > 1)
5 kx printf(_(" User")); /* xxx */
5 kx printf("\n");
5 kx if ((ap = get_afntype(AF_IPX)) == NULL) {
5 kx EINTERN("netstat.c", "AF_IPX missing");
5 kx fclose(f);
5 kx return (-1);
5 kx }
5 kx if (fgets(buf, 255, f))
5 kx /* eat line */;
5 kx
5 kx while (fgets(buf, 255, f) != NULL) {
5 kx sscanf(buf, "%s %s %lX %lX %u %u",
5 kx sad, dad, &txq, &rxq, &state, &uid);
5 kx if ((st = rindex(sad, ':'))) {
5 kx *st++ = '\0';
5 kx sscanf(st, "%X", &sport); /* net byt order */
5 kx sport = ntohs(sport);
5 kx } else {
5 kx EINTERN("netstat.c", "ipx socket format error in source port");
5 kx fclose(f);
5 kx return (-1);
5 kx }
5 kx nc = 0;
5 kx if (strcmp(dad, "Not_Connected") != 0) {
5 kx if ((st = rindex(dad, ':'))) {
5 kx *st++ = '\0';
5 kx sscanf(st, "%X", &dport); /* net byt order */
5 kx dport = ntohs(dport);
5 kx } else {
5 kx EINTERN("netstat.c", "ipx socket format error in destination port");
5 kx fclose(f);
5 kx return (-1);
5 kx }
5 kx } else
5 kx nc = 1;
5 kx
5 kx switch (state) {
5 kx case TCP_ESTABLISHED:
5 kx st = _("ESTAB");
5 kx break;
5 kx
5 kx case TCP_CLOSE:
5 kx st = "";
5 kx break;
5 kx
5 kx default:
5 kx st = _("UNK.");
5 kx break;
5 kx }
5 kx
5 kx /* Fetch and resolve the Source */
5 kx (void) ap->input(0, sad, &sa);
5 kx safe_strncpy(buf, ap->sprint(&sa, flag_not & FLAG_NUM_HOST), sizeof(buf));
5 kx snprintf(sad, sizeof(sad), "%s:%04X", buf, sport);
5 kx
5 kx if (!nc) {
5 kx /* Fetch and resolve the Destination */
5 kx (void) ap->input(0, dad, &sa);
5 kx safe_strncpy(buf, ap->sprint(&sa, flag_not & FLAG_NUM_HOST), sizeof(buf));
5 kx snprintf(dad, sizeof(dad), "%s:%04X", buf, dport);
5 kx } else
5 kx safe_strncpy(dad, "-", sizeof(dad));
5 kx
5 kx printf("IPX %6ld %6ld %-26s %-26s %-5s", txq, rxq, sad, dad, st);
5 kx if (flag_exp > 1) {
5 kx if (!(flag_not & FLAG_NUM_USER) && ((pw = getpwuid(uid)) != NULL))
5 kx printf(" %-10s", pw->pw_name);
5 kx else
5 kx printf(" %-10d", uid);
5 kx }
5 kx printf("\n");
5 kx }
5 kx fclose(f);
5 kx return 0;
5 kx }
5 kx #endif
5 kx
5 kx #if HAVE_AFBLUETOOTH
5 kx const char *bluetooth_state(int state)
5 kx {
5 kx switch (state) {
5 kx case BT_CONNECTED:
5 kx return _("CONNECTED");
5 kx case BT_OPEN:
5 kx return _("OPEN");
5 kx case BT_BOUND:
5 kx return _("BOUND");
5 kx case BT_LISTEN:
5 kx return _("LISTEN");
5 kx case BT_CONNECT:
5 kx return _("CONNECT");
5 kx case BT_CONNECT2:
5 kx return _("CONNECT2");
5 kx case BT_CONFIG:
5 kx return _("CONFIG");
5 kx case BT_DISCONN:
5 kx return _("DISCONN");
5 kx case BT_CLOSED:
5 kx return _("CLOSED");
5 kx default:
5 kx return _("UNKNOWN");
5 kx }
5 kx }
5 kx
5 kx static void l2cap_do_one(int nr, const char *line, const char *prot)
5 kx {
5 kx char daddr[18], saddr[18];
5 kx unsigned dtype, stype, state, psm, dcid, scid, imtu, omtu, sec_level;
5 kx int num;
5 kx const char *bt_state, *bt_sec_level;
5 kx
5 kx num = sscanf(line, "%17s (%u) %17s (%u) %d %d 0x%04x 0x%04x %d %d %d",
5 kx daddr, &dtype, saddr, &stype, &state, &psm, &dcid, &scid, &imtu, &omtu, &sec_level);
5 kx
5 kx if (num != 11) {
5 kx num = sscanf(line, "%17s %17s %d %d 0x%04x 0x%04x %d %d %d",
5 kx daddr, saddr, &state, &psm, &dcid, &scid, &imtu, &omtu, &sec_level);
5 kx
5 kx if (num != 9) {
5 kx fprintf(stderr, _("warning, got bogus l2cap line.\n"));
5 kx return;
5 kx }
5 kx }
5 kx
5 kx if (flag_lst && !(state == BT_LISTEN || state == BT_BOUND))
5 kx return;
5 kx if (!(flag_all || flag_lst) && (state == BT_LISTEN || state == BT_BOUND))
5 kx return;
5 kx
5 kx bt_state = bluetooth_state(state);
5 kx switch (sec_level) {
5 kx case BT_SECURITY_SDP:
5 kx bt_sec_level = _("SDP");
5 kx break;
5 kx case BT_SECURITY_LOW:
5 kx bt_sec_level = _("LOW");
5 kx break;
5 kx case BT_SECURITY_MEDIUM:
5 kx bt_sec_level = _("MEDIUM");
5 kx break;
5 kx case BT_SECURITY_HIGH:
5 kx bt_sec_level = _("HIGH");
5 kx break;
5 kx default:
5 kx bt_sec_level = _("UNKNOWN");
5 kx }
5 kx
5 kx printf("l2cap %-17s %-17s %-9s %7d 0x%04x 0x%04x %7d %7d %-7s\n",
5 kx (strcmp (daddr, "00:00:00:00:00:00") == 0 ? "*" : daddr),
5 kx (strcmp (saddr, "00:00:00:00:00:00") == 0 ? "*" : saddr),
5 kx bt_state, psm, dcid, scid, imtu, omtu, bt_sec_level);
5 kx }
5 kx
5 kx static int l2cap_info(void)
5 kx {
5 kx printf("%-6s %-17s %-17s %-9s %7s %-6s %-6s %7s %7s %-7s\n",
5 kx "Proto", "Destination", "Source", "State", "PSM", "DCID", "SCID", "IMTU", "OMTU", "Security");
5 kx INFO_GUTS(_PATH_SYS_BLUETOOTH_L2CAP, "BTPROTO L2CAP", l2cap_do_one, "l2cap");
5 kx }
5 kx
5 kx static void rfcomm_do_one(int nr, const char *line, const char *prot)
5 kx {
5 kx char daddr[18], saddr[18];
5 kx unsigned state, channel;
5 kx int num;
5 kx const char *bt_state;
5 kx
5 kx num = sscanf(line, "%17s %17s %d %d", daddr, saddr, &state, &channel);
5 kx if (num < 4) {
5 kx fprintf(stderr, _("warning, got bogus rfcomm line.\n"));
5 kx return;
5 kx }
5 kx
5 kx if (flag_lst && !(state == BT_LISTEN || state == BT_BOUND))
5 kx return;
5 kx if (!(flag_all || flag_lst) && (state == BT_LISTEN || state == BT_BOUND))
5 kx return;
5 kx
5 kx bt_state = bluetooth_state(state);
5 kx printf("rfcomm %-17s %-17s %-9s %7d\n",
5 kx (strcmp (daddr, "00:00:00:00:00:00") == 0 ? "*" : daddr),
5 kx (strcmp (saddr, "00:00:00:00:00:00") == 0 ? "*" : saddr),
5 kx bt_state, channel);
5 kx }
5 kx
5 kx static int rfcomm_info(void)
5 kx {
5 kx printf("%-6s %-17s %-17s %-9s %7s\n", "Proto", "Destination", "Source", "State", "Channel");
5 kx INFO_GUTS(_PATH_SYS_BLUETOOTH_RFCOMM, "BTPROTO RFCOMM", rfcomm_do_one, "rfcomm");
5 kx }
5 kx #endif
5 kx
5 kx static int iface_info(void)
5 kx {
5 kx if (skfd < 0) {
5 kx if ((skfd = sockets_open(0)) < 0) {
5 kx perror("socket");
5 kx exit(1);
5 kx }
5 kx printf(_("Kernel Interface table\n"));
5 kx }
5 kx if (flag_exp < 2) {
5 kx ife_short = 1;
5 kx printf(_("Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg\n"));
5 kx }
5 kx
5 kx if (for_all_interfaces(do_if_print, &flag_all) < 0) {
5 kx perror(_("missing interface information"));
5 kx exit(1);
5 kx }
5 kx if (flag_cnt)
5 kx if_cache_free();
5 kx else {
5 kx close(skfd);
5 kx skfd = -1;
5 kx }
5 kx
5 kx return 0;
5 kx }
5 kx
5 kx
5 kx static void version(void)
5 kx {
5 kx printf("%s\n%s\n%s\n", Release, Signature, Features);
5 kx exit(E_VERSION);
5 kx }
5 kx
5 kx
5 kx static void usage(int rc)
5 kx {
5 kx FILE *fp = rc ? stderr : stdout;
5 kx fprintf(fp, _("usage: netstat [-vWeenNcCF] [<Af>] -r netstat {-V|--version|-h|--help}\n"));
5 kx fprintf(fp, _(" netstat [-vWnNcaeol] [<Socket> ...]\n"));
5 kx fprintf(fp, _(" netstat { [-vWeenNac] -i | [-cnNe] -M | -s [-6tuw] }\n\n"));
5 kx
5 kx fprintf(fp, _(" -r, --route display routing table\n"));
5 kx fprintf(fp, _(" -i, --interfaces display interface table\n"));
5 kx fprintf(fp, _(" -g, --groups display multicast group memberships\n"));
5 kx fprintf(fp, _(" -s, --statistics display networking statistics (like SNMP)\n"));
5 kx #if HAVE_FW_MASQUERADE
5 kx fprintf(fp, _(" -M, --masquerade display masqueraded connections\n\n"));
5 kx #endif
5 kx
5 kx fprintf(fp, _(" -v, --verbose be verbose\n"));
5 kx fprintf(fp, _(" -W, --wide don't truncate IP addresses\n"));
5 kx fprintf(fp, _(" -n, --numeric don't resolve names\n"));
5 kx fprintf(fp, _(" --numeric-hosts don't resolve host names\n"));
5 kx fprintf(fp, _(" --numeric-ports don't resolve port names\n"));
5 kx fprintf(fp, _(" --numeric-users don't resolve user names\n"));
5 kx fprintf(fp, _(" -N, --symbolic resolve hardware names\n"));
5 kx fprintf(fp, _(" -e, --extend display other/more information\n"));
5 kx fprintf(fp, _(" -p, --programs display PID/Program name for sockets\n"));
5 kx fprintf(fp, _(" -o, --timers display timers\n"));
5 kx fprintf(fp, _(" -c, --continuous continuous listing\n\n"));
5 kx fprintf(fp, _(" -l, --listening display listening server sockets\n"));
5 kx fprintf(fp, _(" -a, --all display all sockets (default: connected)\n"));
5 kx fprintf(fp, _(" -F, --fib display Forwarding Information Base (default)\n"));
5 kx fprintf(fp, _(" -C, --cache display routing cache instead of FIB\n"));
5 kx #if HAVE_SELINUX
5 kx fprintf(fp, _(" -Z, --context display SELinux security context for sockets\n"));
5 kx #endif
5 kx
5 kx fprintf(fp, _("\n <Socket>={-t|--tcp} {-u|--udp} {-U|--udplite} {-S|--sctp} {-w|--raw}\n"));
5 kx fprintf(fp, _(" {-x|--unix} --ax25 --ipx --netrom\n"));
5 kx fprintf(fp, _(" <AF>=Use '-6|-4' or '-A <af>' or '--<af>'; default: %s\n"), DFLT_AF);
5 kx fprintf(fp, _(" List of possible address families (which support routing):\n"));
5 kx print_aflist(1); /* 1 = routeable */
5 kx exit(rc);
5 kx }
5 kx
5 kx
5 kx int main
5 kx (int argc, char *argv[]) {
5 kx int i;
5 kx int lop;
5 kx static struct option longopts[] =
5 kx {
5 kx AFTRANS_OPTS,
5 kx {"version", 0, 0, 'V'},
5 kx {"interfaces", 0, 0, 'i'},
5 kx {"help", 0, 0, 'h'},
5 kx {"route", 0, 0, 'r'},
5 kx #if HAVE_FW_MASQUERADE
5 kx {"masquerade", 0, 0, 'M'},
5 kx #endif
5 kx {"protocol", 1, 0, 'A'},
5 kx {"tcp", 0, 0, 't'},
5 kx {"sctp", 0, 0, 'S'},
5 kx {"udp", 0, 0, 'u'},
5 kx {"udplite", 0, 0, 'U'},
5 kx {"raw", 0, 0, 'w'},
5 kx {"unix", 0, 0, 'x'},
5 kx {"l2cap", 0, 0, '2'},
5 kx {"rfcomm", 0, 0, 'f'},
5 kx {"listening", 0, 0, 'l'},
5 kx {"all", 0, 0, 'a'},
5 kx {"timers", 0, 0, 'o'},
5 kx {"continuous", 0, 0, 'c'},
5 kx {"extend", 0, 0, 'e'},
5 kx {"programs", 0, 0, 'p'},
5 kx {"verbose", 0, 0, 'v'},
5 kx {"statistics", 0, 0, 's'},
5 kx {"wide", 0, 0, 'W'},
5 kx {"numeric", 0, 0, 'n'},
5 kx {"numeric-hosts", 0, 0, '!'},
5 kx {"numeric-ports", 0, 0, '@'},
5 kx {"numeric-users", 0, 0, '#'},
5 kx {"symbolic", 0, 0, 'N'},
5 kx {"cache", 0, 0, 'C'},
5 kx {"fib", 0, 0, 'F'},
5 kx {"groups", 0, 0, 'g'},
5 kx {"context", 0, 0, 'Z'},
5 kx {NULL, 0, 0, 0}
5 kx };
5 kx
5 kx #if I18N
5 kx setlocale (LC_ALL, "");
5 kx bindtextdomain("net-tools", "/usr/share/locale");
5 kx textdomain("net-tools");
5 kx #endif
5 kx getroute_init(); /* Set up AF routing support */
5 kx
5 kx afname[0] = '\0';
5 kx while ((i = getopt_long(argc, argv, "A:CFMacdeghilnNoprsStuUvVWw2fx64?Z", longopts, &lop)) != EOF)
5 kx switch (i) {
5 kx case -1:
5 kx break;
5 kx case 1:
5 kx if (lop < 0 || lop >= AFTRANS_CNT) {
5 kx EINTERN("netstat.c", "longopts 1 range");
5 kx break;
5 kx }
5 kx if (aftrans_opt(longopts[lop].name))
5 kx exit(1);
5 kx break;
5 kx case 'A':
5 kx if (aftrans_opt(optarg))
5 kx exit(1);
5 kx break;
5 kx case 'M':
5 kx flag_mas++;
5 kx break;
5 kx case 'a':
5 kx flag_all++;
5 kx break;
5 kx case 'l':
5 kx flag_lst++;
5 kx break;
5 kx case 'c':
5 kx flag_cnt++;
5 kx break;
5 kx
5 kx case 'd':
5 kx flag_deb++;
5 kx break;
5 kx case 'g':
5 kx flag_igmp++;
5 kx break;
5 kx case 'e':
5 kx flag_exp++;
5 kx break;
5 kx case 'p':
5 kx flag_prg++;
5 kx break;
5 kx case 'i':
5 kx flag_int++;
5 kx break;
5 kx case 'W':
5 kx flag_wide++;
5 kx break;
5 kx case 'n':
5 kx flag_not |= FLAG_NUM;
5 kx break;
5 kx case '!':
5 kx flag_not |= FLAG_NUM_HOST;
5 kx break;
5 kx case '@':
5 kx flag_not |= FLAG_NUM_PORT;
5 kx break;
5 kx case '#':
5 kx flag_not |= FLAG_NUM_USER;
5 kx break;
5 kx case 'N':
5 kx flag_not |= FLAG_SYM;
5 kx break;
5 kx case 'C':
5 kx flag_cf |= FLAG_CACHE;
5 kx break;
5 kx case 'F':
5 kx flag_cf |= FLAG_FIB;
5 kx break;
5 kx case 'o':
5 kx flag_opt++;
5 kx break;
5 kx case '6':
5 kx if (aftrans_opt("inet6"))
5 kx exit(1);
5 kx break;
5 kx case '4':
5 kx if (aftrans_opt("inet"))
5 kx exit(1);
5 kx break;
5 kx case 'V':
5 kx version();
5 kx /*NOTREACHED */
5 kx case 'v':
5 kx flag_ver |= FLAG_VERBOSE;
5 kx break;
5 kx case 'r':
5 kx flag_rou++;
5 kx break;
5 kx case 't':
5 kx flag_tcp++;
5 kx break;
5 kx case 'S':
5 kx flag_sctp++;
5 kx break;
5 kx case 'u':
5 kx flag_udp++;
5 kx break;
5 kx case 'U':
5 kx flag_udplite++;
5 kx break;
5 kx case 'w':
5 kx flag_raw++;
5 kx break;
5 kx case '2':
5 kx flag_l2cap++;
5 kx break;
5 kx case 'f':
5 kx flag_rfcomm++;
5 kx break;
5 kx case 'x':
5 kx if (aftrans_opt("unix"))
5 kx exit(1);
5 kx break;
5 kx case 'Z':
5 kx #if HAVE_SELINUX
5 kx if (is_selinux_enabled() <= 0) {
5 kx fprintf(stderr, _("SELinux is not enabled on this machine.\n"));
5 kx exit(1);
5 kx }
5 kx flag_prg++;
5 kx flag_selinux++;
5 kx #else
5 kx fprintf(stderr, _("SELinux is not enabled for this application.\n"));
5 kx exit(1);
5 kx #endif
5 kx
5 kx break;
5 kx case '?':
5 kx usage(E_OPTERR);
5 kx case 'h':
5 kx usage(E_USAGE);
5 kx case 's':
5 kx flag_sta++;
5 kx }
5 kx
5 kx if (flag_int + flag_rou + flag_mas + flag_sta > 1)
5 kx usage(E_OPTERR);
5 kx
5 kx if ((flag_inet || flag_inet6 || flag_sta) &&
5 kx !(flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw))
5 kx flag_noprot = flag_tcp = flag_sctp = flag_udp = flag_udplite = flag_raw = 1;
5 kx
5 kx if ((flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw || flag_igmp) &&
5 kx !(flag_inet || flag_inet6))
5 kx flag_inet = flag_inet6 = 1;
5 kx
5 kx if (flag_bluetooth && !(flag_l2cap || flag_rfcomm))
5 kx flag_l2cap = flag_rfcomm = 1;
5 kx
5 kx flag_arg = flag_tcp + flag_sctp + flag_udplite + flag_udp + flag_raw + flag_unx
5 kx + flag_ipx + flag_ax25 + flag_netrom + flag_igmp + flag_x25 + flag_rose
5 kx + flag_l2cap + flag_rfcomm;
5 kx
5 kx if (flag_mas) {
5 kx #if HAVE_FW_MASQUERADE && HAVE_AFINET
5 kx #if MORE_THAN_ONE_MASQ_AF
5 kx if (!afname[0])
5 kx safe_strncpy(afname, DFLT_AF, sizeof(afname));
5 kx #endif
5 kx for (;;) {
5 kx i = ip_masq_info(flag_not & FLAG_NUM_HOST,
5 kx flag_not & FLAG_NUM_PORT, flag_exp);
5 kx if (i || !flag_cnt)
5 kx break;
5 kx wait_continous();
5 kx }
5 kx #else
5 kx ENOSUPP("netstat", "FW_MASQUERADE");
5 kx i = -1;
5 kx #endif
5 kx return (i);
5 kx }
5 kx
5 kx if (flag_sta) {
5 kx if (!afname[0])
5 kx safe_strncpy(afname, DFLT_AF, sizeof(afname));
5 kx
5 kx if (!strcmp(afname, "inet")) {
5 kx #if HAVE_AFINET
5 kx parsesnmp(flag_raw, flag_tcp, flag_udp, flag_sctp);
5 kx #else
5 kx ENOSUPP("netstat", "AF INET");
5 kx exit(1);
5 kx #endif
5 kx } else if(!strcmp(afname, "inet6")) {
5 kx #if HAVE_AFINET6
5 kx parsesnmp6(flag_raw, flag_tcp, flag_udp);
5 kx #else
5 kx ENOSUPP("netstat", "AF INET6");
5 kx exit(1);
5 kx #endif
5 kx } else {
5 kx printf(_("netstat: No statistics support for specified address family: %s\n"), afname);
5 kx exit(1);
5 kx }
5 kx exit(0);
5 kx }
5 kx
5 kx if (flag_rou) {
5 kx int options = 0;
5 kx
5 kx if (!afname[0])
5 kx safe_strncpy(afname, DFLT_AF, sizeof(afname));
5 kx
5 kx if (flag_exp == 2)
5 kx flag_exp = 1;
5 kx else if (flag_exp == 1)
5 kx flag_exp = 2;
5 kx
5 kx options = (flag_exp & FLAG_EXT) | flag_not | flag_cf | flag_ver;
5 kx if (!flag_cf)
5 kx options |= FLAG_FIB;
5 kx
5 kx for (;;) {
5 kx i = route_info(afname, options);
5 kx if (i || !flag_cnt)
5 kx break;
5 kx wait_continous();
5 kx }
5 kx return (i);
5 kx }
5 kx if (flag_int) {
5 kx for (;;) {
5 kx i = iface_info();
5 kx if (!flag_cnt || i)
5 kx break;
5 kx wait_continous();
5 kx }
5 kx return (i);
5 kx }
5 kx for (;;) {
5 kx if (!flag_arg || flag_tcp || flag_sctp || flag_udp || flag_udplite || flag_raw) {
5 kx #if HAVE_AFINET
5 kx prg_cache_load();
5 kx printf(_("Active Internet connections ")); /* xxx */
5 kx
5 kx if (flag_all)
5 kx printf(_("(servers and established)"));
5 kx else {
5 kx if (flag_lst)
5 kx printf(_("(only servers)"));
5 kx else
5 kx printf(_("(w/o servers)"));
5 kx }
5 kx printf(_("\nProto Recv-Q Send-Q Local Address Foreign Address State ")); /* xxx */
5 kx if (flag_exp > 1)
5 kx printf(_(" User Inode "));
5 kx print_progname_banner();
5 kx print_selinux_banner();
5 kx if (flag_opt)
5 kx printf(_(" Timer")); /* xxx */
5 kx printf("\n");
5 kx #else
5 kx if (flag_arg) {
5 kx i = 1;
5 kx ENOSUPP("netstat", "AF INET");
5 kx }
5 kx #endif
5 kx }
5 kx #if HAVE_AFINET
5 kx if (!flag_arg || flag_tcp) {
5 kx i = tcp_info();
5 kx if (i)
5 kx return (i);
5 kx }
5 kx
5 kx if (!flag_arg || flag_sctp) {
5 kx i = sctp_info();
5 kx if (i)
5 kx return (i);
5 kx }
5 kx
5 kx if (!flag_arg || flag_udp) {
5 kx i = udp_info();
5 kx if (i)
5 kx return (i);
5 kx }
5 kx
5 kx if (!flag_arg || flag_udplite) {
5 kx i = udplite_info();
5 kx if (i)
5 kx return (i);
5 kx }
5 kx
5 kx if (!flag_arg || flag_raw) {
5 kx i = raw_info();
5 kx if (i)
5 kx return (i);
5 kx }
5 kx
5 kx if (flag_igmp) {
5 kx #if HAVE_AFINET6
5 kx printf( "IPv6/");
5 kx #endif
5 kx printf( _("IPv4 Group Memberships\n") );
5 kx printf( _("Interface RefCnt Group\n") );
5 kx printf( "--------------- ------ ---------------------\n" );
5 kx i = igmp_info();
5 kx if (i)
5 kx return (i);
5 kx }
5 kx #endif
5 kx
5 kx if (!flag_arg || flag_unx) {
5 kx #if HAVE_AFUNIX
5 kx prg_cache_load();
5 kx i = unix_info();
5 kx if (i)
5 kx return (i);
5 kx #else
5 kx if (flag_arg) {
5 kx i = 1;
5 kx ENOSUPP("netstat", "AF UNIX");
5 kx }
5 kx #endif
5 kx }
5 kx if (!flag_arg || flag_ipx) {
5 kx #if HAVE_AFIPX
5 kx i = ipx_info();
5 kx if (i)
5 kx return (i);
5 kx #else
5 kx if (flag_arg) {
5 kx i = 1;
5 kx ENOSUPP("netstat", "AF IPX");
5 kx }
5 kx #endif
5 kx }
5 kx if (!flag_arg || flag_ax25) {
5 kx #if HAVE_AFAX25
5 kx i = ax25_info();
5 kx if (i)
5 kx return (i);
5 kx #else
5 kx if (flag_arg) {
5 kx i = 1;
5 kx ENOSUPP("netstat", "AF AX25");
5 kx }
5 kx #endif
5 kx }
5 kx if(!flag_arg || flag_x25) {
5 kx #if HAVE_AFX25
5 kx /* FIXME */
5 kx i = x25_info();
5 kx if (i)
5 kx return(i);
5 kx #else
5 kx if (flag_arg) {
5 kx i = 1;
5 kx ENOSUPP("netstat", "AF X25");
5 kx }
5 kx #endif
5 kx }
5 kx if (!flag_arg || flag_netrom) {
5 kx #if HAVE_AFNETROM
5 kx i = netrom_info();
5 kx if (i)
5 kx return (i);
5 kx #else
5 kx if (flag_arg) {
5 kx i = 1;
5 kx ENOSUPP("netstat", "AF NETROM");
5 kx }
5 kx #endif
5 kx }
5 kx if (!flag_arg || flag_rose) {
5 kx #if HAVE_AFROSE
5 kx i = rose_info();
5 kx if (i)
5 kx return (i);
5 kx #else
5 kx if (flag_arg) {
5 kx i = 1;
5 kx ENOSUPP("netstat", "AF ROSE");
5 kx }
5 kx #endif
5 kx }
5 kx
5 kx if (!flag_arg || flag_l2cap || flag_rfcomm) {
5 kx #if HAVE_AFBLUETOOTH
5 kx printf(_("Active Bluetooth connections ")); /* xxx */
5 kx
5 kx if (flag_all)
5 kx printf(_("(servers and established)"));
5 kx else {
5 kx if (flag_lst)
5 kx printf(_("(only servers)"));
5 kx else
5 kx printf(_("(w/o servers)"));
5 kx }
5 kx printf("\n");
5 kx #else
5 kx if (flag_arg) {
5 kx i = 1;
5 kx ENOSUPP("netstat", "AF BLUETOOTH");
5 kx }
5 kx #endif
5 kx }
5 kx #if HAVE_AFBLUETOOTH
5 kx if (!flag_arg || flag_l2cap) {
5 kx i = l2cap_info();
5 kx if (i)
5 kx return (i);
5 kx }
5 kx if (!flag_arg || flag_rfcomm) {
5 kx i = rfcomm_info();
5 kx if (i)
5 kx return (i);
5 kx }
5 kx #endif
5 kx
5 kx if (!flag_cnt || i)
5 kx break;
5 kx wait_continous();
5 kx prg_cache_clear();
5 kx }
5 kx return (i);
5 kx }