summaryrefslogtreecommitdiff
path: root/dialects/linux/dsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'dialects/linux/dsock.c')
-rw-r--r--dialects/linux/dsock.c3946
1 files changed, 3946 insertions, 0 deletions
diff --git a/dialects/linux/dsock.c b/dialects/linux/dsock.c
new file mode 100644
index 0000000..9109b2f
--- /dev/null
+++ b/dialects/linux/dsock.c
@@ -0,0 +1,3946 @@
+/*
+ * dsock.c - Linux socket processing functions for /proc-based lsof
+ */
+
+
+/*
+ * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
+ * 47907. All rights reserved.
+ *
+ * Written by Victor A. Abell
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ *
+ * 1. Neither the authors nor Purdue University are responsible for any
+ * consequences of the use of this software.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Credit to the authors and Purdue
+ * University must appear in documentation and sources.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 4. This notice may not be removed or altered.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: dsock.c,v 1.39 2013/01/02 17:02:36 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+#include <sys/xattr.h>
+
+
+/*
+ * Local definitions
+ */
+
+#define INOBUCKS 128 /* inode hash bucket count -- must be
+ * a power of two */
+#define INOHASH(ino) ((int)((ino * 31415) >> 3) & (INOBUCKS - 1))
+#define TCPUDPHASH(ino) ((int)((ino * 31415) >> 3) & (TcpUdp_bucks - 1))
+#define TCPUDP6HASH(ino) ((int)((ino * 31415) >> 3) & (TcpUdp6_bucks - 1))
+
+
+/*
+ * Local structures
+ */
+
+struct ax25sin { /* AX25 socket information */
+ char *da; /* destination address */
+ char *dev_ch; /* device characters */
+ char *sa; /* source address */
+ INODETYPE inode;
+ unsigned long sq, rq; /* send and receive queue values */
+ unsigned char sqs, rqs; /* send and receive queue states */
+ int state;
+ struct ax25sin *next;
+};
+
+struct icmpin {
+ INODETYPE inode; /* node number */
+ char *la; /* local address */
+ char *ra; /* remote address */
+ MALLOC_S lal; /* strlen(la) */
+ MALLOC_S ral; /* strlen(ra) */
+ struct icmpin *next;
+};
+
+struct ipxsin { /* IPX socket information */
+ INODETYPE inode;
+ char *la; /* local address */
+ char *ra; /* remote address */
+ int state;
+ unsigned long txq, rxq; /* transmit and receive queue values */
+ struct ipxsin *next;
+};
+
+struct nlksin { /* Netlink socket information */
+ INODETYPE inode; /* node number */
+ unsigned int pr; /* protocol */
+ struct nlksin *next;
+};
+
+struct packin { /* packet information */
+ INODETYPE inode;
+ int ty; /* socket type */
+ int pr; /* protocol */
+ struct packin *next;
+};
+
+struct rawsin { /* raw socket information */
+ INODETYPE inode;
+ char *la; /* local address */
+ char *ra; /* remote address */
+ char *sp; /* state characters */
+ MALLOC_S lal; /* strlen(la) */
+ MALLOC_S ral; /* strlen(ra) */
+ MALLOC_S spl; /* strlen(sp) */
+ struct rawsin *next;
+};
+
+struct sctpsin { /* SCTP socket information */
+ INODETYPE inode;
+ int type; /* type: 0 = assoc
+ * 1 = eps
+ * 2 assoc and eps */
+ char *addr; /* association or endpoint address */
+ char *assocID; /* association ID */
+ char *lport; /* local port */
+ char *rport; /* remote port */
+ char *laddrs; /* local address */
+ char *raddrs; /* remote address */
+ struct sctpsin *next;
+};
+
+struct tcp_udp { /* IPv4 TCP and UDP socket
+ * information */
+ INODETYPE inode;
+ unsigned long faddr, laddr; /* foreign & local IPv6 addresses */
+ int fport, lport; /* foreign & local ports */
+ unsigned long txq, rxq; /* transmit & receive queue values */
+ int proto; /* 0 = TCP, 1 = UDP, 2 = UDPLITE */
+ int state; /* protocol state */
+ struct tcp_udp *next;
+};
+
+#if defined(HASIPv6)
+struct tcp_udp6 { /* IPv6 TCP and UDP socket
+ * information */
+ INODETYPE inode;
+ struct in6_addr faddr, laddr; /* foreign and local IPv6 addresses */
+ int fport, lport; /* foreign & local ports */
+ unsigned long txq, rxq; /* transmit & receive queue values */
+ int proto; /* 0 = TCP, 1 = UDP, 2 = UDPLITE */
+ int state; /* protocol state */
+ struct tcp_udp6 *next;
+};
+#endif /* defined(HASIPv6) */
+
+struct uxsin { /* UNIX socket information */
+ INODETYPE inode; /* node number */
+ char *pcb; /* protocol control block */
+ char *path; /* file path */
+ unsigned char sb_def; /* stat(2) buffer definitions */
+ dev_t sb_dev; /* stat(2) buffer device */
+ INODETYPE sb_ino; /* stat(2) buffer node number */
+ dev_t sb_rdev; /* stat(2) raw device number */
+ struct uxsin *next;
+};
+
+
+/*
+ * Local static values
+ */
+
+static char *AX25path = (char *)NULL; /* path to AX25 /proc information */
+static struct ax25sin **AX25sin = (struct ax25sin **)NULL;
+ /* AX25 socket info, hashed by inode */
+static char *ax25st[] = {
+ "LISTENING", /* 0 */
+ "SABM SENT", /* 1 */
+ "DISC SENT", /* 2 */
+ "ESTABLISHED", /* 3 */
+ "RECOVERY" /* 4 */
+};
+#define NAX25ST (sizeof(ax25st) / sizeof(char *))
+static char *ICMPpath = (char *)NULL; /* path to ICMP /proc information */
+static struct icmpin **Icmpin = (struct icmpin **)NULL;
+ /* ICMP socket info, hashed by inode */
+static char *Ipxpath = (char *)NULL; /* path to IPX /proc information */
+static struct ipxsin **Ipxsin = (struct ipxsin **)NULL;
+ /* IPX socket info, hashed by inode */
+static char *Nlkpath = (char *)NULL; /* path to Netlink /proc information */
+static struct nlksin **Nlksin = (struct nlksin **)NULL;
+ /* Netlink socket info, hashed by
+ * inode */
+static struct packin **Packin = (struct packin **)NULL;
+ /* packet info, hashed by inode */
+static char *Packpath = (char *)NULL; /* path to packet /proc information */
+static char *Rawpath = (char *)NULL; /* path to raw socket /proc
+ * information */
+static struct rawsin **Rawsin = (struct rawsin **)NULL;
+ /* raw socket info, hashed by inode */
+static char *SCTPPath[] = { /* paths to /proc/net STCP info */
+ (char *)NULL, /* 0 = /proc/net/sctp/assocs */
+ (char *)NULL /* 1 = /proc/net/sctp/eps */
+};
+#define NSCTPPATHS sizeof(SCTPPath)/sizeof(char *)
+static char *SCTPSfx[] = { /* /proc/net suffixes */
+ "sctp/assocs", /* 0 = /proc/net/sctp/assocs */
+ "sctp/eps" /* 1 = /proc/net/sctp/eps */
+};
+static struct sctpsin **SCTPsin = (struct sctpsin **)NULL;
+ /* SCTP info, hashed by inode */
+static char *SockStatPath = (char *)NULL;
+ /* path to /proc/net socket status */
+static char *TCPpath = (char *)NULL; /* path to TCP /proc information */
+static struct tcp_udp **TcpUdp = (struct tcp_udp **)NULL;
+ /* IPv4 TCP & UDP info, hashed by
+ * inode */
+static int TcpUdp_bucks = 0; /* dynamically sized hash bucket
+ * count for TCP and UDP -- will
+ * be a power of two */
+
+#if defined(HASIPv6)
+static char *Raw6path = (char *)NULL; /* path to raw IPv6 /proc information */
+static struct rawsin **Rawsin6 = (struct rawsin **)NULL;
+ /* IPv6 raw socket info, hashed by
+ * inode */
+static char *SockStatPath6 = (char *)NULL;
+ /* path to /proc/net IPv6 socket
+ * status */
+static char *TCP6path = (char *)NULL; /* path to IPv6 TCP /proc information */
+static struct tcp_udp6 **TcpUdp6 = (struct tcp_udp6 **)NULL;
+ /* IPv6 TCP & UDP info, hashed by
+ * inode */
+static int TcpUdp6_bucks = 0; /* dynamically sized hash bucket
+ * count for IPv6 TCP and UDP -- will
+ * be a power of two */
+static char *UDP6path = (char *)NULL; /* path to IPv6 UDP /proc information */
+static char *UDPLITE6path = (char *)NULL;
+ /* path to IPv6 UDPLITE /proc
+ * information */
+#endif /* defined(HASIPv6) */
+
+static char *UDPpath = (char *)NULL; /* path to UDP /proc information */
+static char *UDPLITEpath = (char *)NULL;
+ /* path to UDPLITE /proc information */
+static char *UNIXpath = (char *)NULL; /* path to UNIX /proc information */
+static struct uxsin **Uxsin = (struct uxsin **)NULL;
+ /* UNIX socket info, hashed by inode */
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static struct ax25sin *check_ax25,(INODETYPE i));
+_PROTOTYPE(static struct icmpin *check_icmp,(INODETYPE i));
+_PROTOTYPE(static struct ipxsin *check_ipx,(INODETYPE i));
+_PROTOTYPE(static struct nlksin *check_netlink,(INODETYPE i));
+_PROTOTYPE(static struct packin *check_pack,(INODETYPE i));
+_PROTOTYPE(static struct rawsin *check_raw,(INODETYPE i));
+_PROTOTYPE(static struct sctpsin *check_sctp,(INODETYPE i));
+_PROTOTYPE(static struct tcp_udp *check_tcpudp,(INODETYPE i, char **p));
+_PROTOTYPE(static struct uxsin *check_unix,(INODETYPE i));
+_PROTOTYPE(static void get_ax25,(char *p));
+_PROTOTYPE(static void get_icmp,(char *p));
+_PROTOTYPE(static void get_ipx,(char *p));
+_PROTOTYPE(static void get_netlink,(char *p));
+_PROTOTYPE(static void get_pack,(char *p));
+_PROTOTYPE(static void get_raw,(char *p));
+_PROTOTYPE(static void get_sctp,(void));
+_PROTOTYPE(static char *get_sctpaddrs,(char **fp, int i, int nf, int *x));
+_PROTOTYPE(static void get_tcpudp,(char *p, int pr, int clr));
+_PROTOTYPE(static void get_unix,(char *p));
+_PROTOTYPE(static int isainb,(char *a, char *b));
+_PROTOTYPE(static void print_ax25info,(struct ax25sin *ap));
+_PROTOTYPE(static void print_ipxinfo,(struct ipxsin *ip));
+
+#if defined(HASIPv6)
+_PROTOTYPE(static struct rawsin *check_raw6,(INODETYPE i));
+_PROTOTYPE(static struct tcp_udp6 *check_tcpudp6,(INODETYPE i, char **p));
+_PROTOTYPE(static void get_raw6,(char *p));
+_PROTOTYPE(static void get_tcpudp6,(char *p, int pr, int clr));
+_PROTOTYPE(static int net6a2in6,(char *as, struct in6_addr *ad));
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * build_IPstates() -- build the TCP and UDP state tables
+ */
+
+void
+build_IPstates()
+{
+ if (!TcpSt) {
+ (void) enter_IPstate("TCP", "ESTABLISHED", TCP_ESTABLISHED);
+ (void) enter_IPstate("TCP", "SYN_SENT", TCP_SYN_SENT);
+ (void) enter_IPstate("TCP", "SYN_RECV", TCP_SYN_RECV);
+ (void) enter_IPstate("TCP", "FIN_WAIT1", TCP_FIN_WAIT1);
+ (void) enter_IPstate("TCP", "FIN_WAIT2", TCP_FIN_WAIT2);
+ (void) enter_IPstate("TCP", "TIME_WAIT", TCP_TIME_WAIT);
+ (void) enter_IPstate("TCP", "CLOSE", TCP_CLOSE);
+ (void) enter_IPstate("TCP", "CLOSE_WAIT", TCP_CLOSE_WAIT);
+ (void) enter_IPstate("TCP", "LAST_ACK", TCP_LAST_ACK);
+ (void) enter_IPstate("TCP", "LISTEN", TCP_LISTEN);
+ (void) enter_IPstate("TCP", "CLOSING", TCP_CLOSING);
+ (void) enter_IPstate("TCP", "CLOSED", 0);
+ (void) enter_IPstate("TCP", (char *)NULL, 0);
+ }
+}
+
+
+/*
+ * check_ax25() - check for AX25 socket file
+ */
+
+static struct ax25sin *
+check_ax25(i)
+ INODETYPE i; /* socket file's inode number */
+{
+ struct ax25sin *ap;
+ int h;
+
+ h = INOHASH(i);
+ for (ap = AX25sin[h]; ap; ap = ap->next) {
+ if (i == ap->inode)
+ return(ap);
+ }
+ return((struct ax25sin *)NULL);
+}
+
+
+
+/*
+ * check_icmp() - check for ICMP socket
+ */
+
+static struct icmpin *
+check_icmp(i)
+ INODETYPE i; /* socket file's inode number */
+{
+ int h;
+ struct icmpin *icmpp;
+
+ h = INOHASH(i);
+ for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
+ if (i == icmpp->inode)
+ return(icmpp);
+ }
+ return((struct icmpin *)NULL);
+}
+
+
+/*
+ * check_ipx() - check for IPX socket file
+ */
+
+static struct ipxsin *
+check_ipx(i)
+ INODETYPE i; /* socket file's inode number */
+{
+ int h;
+ struct ipxsin *ip;
+
+ h = INOHASH(i);
+ for (ip = Ipxsin[h]; ip; ip = ip->next) {
+ if (i == ip->inode)
+ return(ip);
+ }
+ return((struct ipxsin *)NULL);
+}
+
+
+/*
+ * check_netlink() - check for Netlink socket file
+ */
+
+static struct nlksin *
+check_netlink(i)
+ INODETYPE i; /* socket file's inode number */
+{
+ int h;
+ struct nlksin *lp;
+
+ h = INOHASH(i);
+ for (lp = Nlksin[h]; lp; lp = lp->next) {
+ if (i == lp->inode)
+ return(lp);
+ }
+ return((struct nlksin *)NULL);
+}
+
+
+/*
+ * check_pack() - check for packet file
+ */
+
+static struct packin *
+check_pack(i)
+ INODETYPE i; /* packet file's inode number */
+{
+ int h;
+ struct packin *pp;
+
+ h = INOHASH(i);
+ for (pp = Packin[h]; pp; pp = pp->next) {
+ if (i == pp->inode)
+ return(pp);
+ }
+ return((struct packin *)NULL);
+}
+
+
+/*
+ * check_raw() - check for raw socket file
+ */
+
+static struct rawsin *
+check_raw(i)
+ INODETYPE i; /* socket file's inode number */
+{
+ int h;
+ struct rawsin *rp;
+
+ h = INOHASH(i);
+ for (rp = Rawsin[h]; rp; rp = rp->next) {
+ if (i == rp->inode)
+ return(rp);
+ }
+ return((struct rawsin *)NULL);
+}
+
+
+/*
+ * check_sctp() - check for SCTP socket file
+ */
+
+static struct sctpsin *
+check_sctp(i)
+ INODETYPE i; /* socket file's inode number */
+{
+ int h;
+ struct sctpsin *sp;
+
+ h = INOHASH(i);
+ for (sp = SCTPsin[h]; sp; sp = sp->next) {
+ if (i == sp->inode)
+ return(sp);
+ }
+ return((struct sctpsin *)NULL);
+}
+
+
+/*
+ * check_tcpudp() - check for IPv4 TCP or UDP socket file
+ */
+
+static struct tcp_udp *
+check_tcpudp(i, p)
+ INODETYPE i; /* socket file's inode number */
+ char **p; /* protocol return */
+{
+ int h;
+ struct tcp_udp *tp;
+
+ h = TCPUDPHASH(i);
+ for (tp = TcpUdp[h]; tp; tp = tp->next) {
+ if (i == tp->inode) {
+ switch (tp->proto) {
+ case 0:
+ *p = "TCP";
+ break;
+ case 1:
+ *p = "UDP";
+ break;
+ case 2:
+ *p = "UDPLITE";
+ break;
+ default:
+ *p = "unknown";
+ }
+ return(tp);
+ }
+ }
+ return((struct tcp_udp *)NULL);
+}
+
+
+#if defined(HASIPv6)
+/*
+ * check_raw6() - check for raw IPv6 socket file
+ */
+
+static struct rawsin *
+check_raw6(i)
+ INODETYPE i; /* socket file's inode number */
+{
+ int h;
+ struct rawsin *rp;
+
+ h = INOHASH(i);
+ for (rp = Rawsin6[h]; rp; rp = rp->next) {
+ if (i == rp->inode)
+ return(rp);
+ }
+ return((struct rawsin *)NULL);
+}
+
+
+/*
+ * check_tcpudp6() - check for IPv6 TCP or UDP socket file
+ */
+
+static struct tcp_udp6 *
+check_tcpudp6(i, p)
+ INODETYPE i; /* socket file's inode number */
+ char **p; /* protocol return */
+{
+ int h;
+ struct tcp_udp6 *tp6;
+
+ h = TCPUDP6HASH(i);
+ for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
+ if (i == tp6->inode) {
+ switch (tp6->proto) {
+ case 0:
+ *p = "TCP";
+ break;
+ case 1:
+ *p = "UDP";
+ break;
+ case 2:
+ *p = "UDPLITE";
+ break;
+ default:
+ *p = "unknown";
+ }
+ return(tp6);
+ }
+ }
+ return((struct tcp_udp6 *)NULL);
+}
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * check_unix() - check for UNIX domain socket
+ */
+
+static struct uxsin *
+check_unix(i)
+ INODETYPE i; /* socket file's inode number */
+{
+ int h;
+ struct uxsin *up;
+
+ h = INOHASH(i);
+ for (up = Uxsin[h]; up; up = up->next) {
+ if (i == up->inode)
+ return(up);
+ }
+ return((struct uxsin *)NULL);
+}
+
+
+/*
+ * get_ax25() - get /proc/net/ax25 info
+ */
+
+static void
+get_ax25(p)
+ char *p; /* /proc/net/ipx path */
+{
+ struct ax25sin *ap, *np;
+ FILE *as;
+ char buf[MAXPATHLEN], *da, *dev_ch, *ep, **fp, *sa;
+ int h, nf;
+ INODETYPE inode;
+ unsigned long rq, sq, state;
+ MALLOC_S len;
+ unsigned char rqs, sqs;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (AX25sin) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (ap = AX25sin[h]; ap; ap = np) {
+ np = ap->next;
+ if (ap->da)
+ (void) free((FREE_P *)ap->da);
+ if (ap->dev_ch)
+ (void) free((FREE_P *)ap->dev_ch);
+ if (ap->sa)
+ (void) free((FREE_P *)ap->sa);
+ (void) free((FREE_P *)ap);
+ }
+ AX25sin[h] = (struct ax25sin *)NULL;
+ }
+ } else {
+ AX25sin = (struct ax25sin **)calloc(INOBUCKS,
+ sizeof(struct ax25sin *));
+ if (!AX25sin) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d AX25 hash pointer bytes\n",
+ Pn, (int)(INOBUCKS * sizeof(struct ax25sin *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net/ax25 file, assign a page size buffer to the stream,
+ * and read it. Store AX25 socket info in the AX25sin[] hash buckets.
+ */
+ if (!(as = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ while (fgets(buf, sizeof(buf) - 1, as)) {
+ if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0)) < 24)
+ continue;
+ /*
+ * /proc/net/ax25 has no title line, a very poor deficiency in its
+ * implementation.
+ *
+ * The ax25_get_info() function in kern module .../net/ax25/af_ax25.c
+ * says the format of the lines in the file is:
+ *
+ * magic dev src_addr dest_addr,digi1,digi2,.. st vs vr va t1 t1 \
+ * t2 t2 t3 t3 idle idle n2 n2 rtt window paclen Snd-Q Rcv-Q \
+ * inode
+ *
+ * The code in this function is forced to assume that format is in
+ * effect..
+ */
+
+ /*
+ * Assemble the inode number and see if it has already been recorded.
+ * If it has, skip this line.
+ */
+ ep = (char *)NULL;
+ if (!fp[23] || !*fp[23]
+ || (inode = strtoull(fp[23], &ep, 0)) == ULONG_MAX
+ || !ep || *ep)
+ continue;
+ h = INOHASH((INODETYPE)inode);
+ for (ap = AX25sin[h]; ap; ap = ap->next) {
+ if (inode == ap->inode)
+ break;
+ }
+ if (ap)
+ continue;
+ /*
+ * Assemble the send and receive queue values and the state.
+ */
+ rq = sq = (unsigned long)0;
+ rqs = sqs = (unsigned char)0;
+ ep = (char *)NULL;
+ if (!fp[21] || !*fp[21]
+ || (sq = strtoul(fp[21], &ep, 0)) == ULONG_MAX || !ep || *ep)
+ continue;
+ sqs = (unsigned char)1;
+ ep = (char *)NULL;
+ if (!fp[22] || !*fp[22]
+ || (rq = strtoul(fp[22], &ep, 0)) == ULONG_MAX || !ep || *ep)
+ continue;
+ rqs = (unsigned char)1;
+ ep = (char *)NULL;
+ if (!fp[4] || !*fp[4]
+ || (state = strtoul(fp[4], &ep, 0)) == ULONG_MAX || !ep || *ep)
+ continue;
+ /*
+ * Allocate space for the destination address.
+ */
+ if (!fp[3] || !*fp[3])
+ da = (char *)NULL;
+ else if ((len = strlen(fp[3]))) {
+ if (!(da = (char *)malloc(len + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d destination AX25 addr bytes: %s\n",
+ Pn, (int)(len + 1), fp[3]);
+ Exit(1);
+ }
+ (void) snpf(da, len + 1, "%s", fp[3]);
+ } else
+ da = (char *)NULL;
+ /*
+ * Allocate space for the source address.
+ */
+ if (!fp[2] || !*fp[2])
+ sa = (char *)NULL;
+ else if ((len = strlen(fp[2]))) {
+ if (!(sa = (char *)malloc(len + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d source AX25 address bytes: %s\n",
+ Pn, (int)(len + 1), fp[2]);
+ Exit(1);
+ }
+ (void) snpf(sa, len + 1, "%s", fp[2]);
+ } else
+ sa = (char *)NULL;
+ /*
+ * Allocate space for the device characters.
+ */
+ if (!fp[1] || !*fp[1])
+ dev_ch = (char *)NULL;
+ else if ((len = strlen(fp[1]))) {
+ if (!(dev_ch = (char *)malloc(len + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d destination AX25 dev bytes: %s\n",
+ Pn, (int)(len + 1), fp[1]);
+ Exit(1);
+ }
+ (void) snpf(dev_ch, len + 1, "%s", fp[1]);
+ } else
+ dev_ch = (char *)NULL;
+ /*
+ * Allocate space for an ax25sin entry, fill it, and link it to its
+ * hash bucket.
+ */
+ if (!(ap = (struct ax25sin *)malloc(sizeof(struct ax25sin)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte ax25sin structure\n",
+ Pn, (int)sizeof(struct ax25sin));
+ Exit(1);
+ }
+ ap->da = da;
+ ap->dev_ch = dev_ch;
+ ap->inode = inode;
+ ap->rq = rq;
+ ap->rqs = rqs;
+ ap->sa = sa;
+ ap->sq = sq;
+ ap->sqs = sqs;
+ ap->state = (int)state;
+ ap->next = AX25sin[h];
+ AX25sin[h] = ap;
+ }
+ (void) fclose(as);
+}
+
+
+/*
+ * get_icmp() - get ICMP net info
+ */
+
+static void
+get_icmp(p)
+ char *p; /* /proc/net/icmp path */
+{
+ char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
+ int fl = 1;
+ int h;
+ INODETYPE inode;
+ struct icmpin *np, *icmpp;
+ unsigned long pr;
+ MALLOC_S lal, ral, spl;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+ FILE *xs;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (Icmpin) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (icmpp = Icmpin[h]; icmpp; icmpp = np) {
+ np = icmpp->next;
+ (void) free((FREE_P *)icmpp);
+ }
+ Icmpin[h] = (struct icmpin *)NULL;
+ }
+ } else {
+ Icmpin = (struct icmpin **)calloc(INOBUCKS,
+ sizeof(struct icmpin *));
+ if (!Icmpin) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d icmp hash pointer bytes\n",
+ Pn, (int)(INOBUCKS * sizeof(struct icmpin *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net/icmp file, assign a page size buffer to its stream,
+ * and read the file. Store icmp info in the Icmpin[] hash buckets.
+ */
+ if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ while (fgets(buf, sizeof(buf) - 1, xs)) {
+ if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 11)
+ continue;
+ if (fl) {
+
+ /*
+ * Check the column labels in the first line.
+ *
+ * NOTE:
+ * In column header, "inode" is at the 11th column.
+ * However, in data rows, inode appears at the 9th column.
+ *
+ * In column header, "tx_queue" and "rx_queue" are separated
+ * by a space. It is the same for "tr" and "tm->when"; in
+ * data rows they are connected with ":".
+ */
+ if (!fp[1] || strcmp(fp[1], "local_address")
+ || !fp[2] || strcmp(fp[2], "rem_address")
+ || !fp[11] || strcmp(fp[11], "inode"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ fl = 0;
+ continue;
+ }
+ /*
+ * Assemble the inode number and see if the inode is already
+ * recorded.
+ */
+ ep = (char *)NULL;
+ if (!fp[9] || !*fp[9]
+ || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
+ || !ep || *ep)
+ continue;
+ h = INOHASH(inode);
+ for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
+ if (inode == icmpp->inode)
+ break;
+ }
+ if (icmpp)
+ continue;
+ /*
+ * Save the local address, and remote address.
+ */
+ if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
+ la = (char *)NULL;
+ lal = (MALLOC_S)0;
+ } else {
+ if (!(la = (char *)malloc(lal + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d local icmp address bytes: %s\n",
+ Pn, (int)(lal + 1), fp[1]);
+ Exit(1);
+ }
+ (void) snpf(la, lal + 1, "%s", fp[1]);
+ }
+ if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
+ ra = (char *)NULL;
+ ral = (MALLOC_S)0;
+ } else {
+ if (!(ra = (char *)malloc(ral + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d remote icmp address bytes: %s\n",
+ Pn, (int)(ral + 1), fp[2]);
+ Exit(1);
+ }
+ (void) snpf(ra, ral + 1, "%s", fp[2]);
+ }
+ /*
+ * Allocate space for a icmpin entry, fill it, and link it to its
+ * hash bucket.
+ */
+ if (!(icmpp = (struct icmpin *)malloc(sizeof(struct icmpin)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte icmp structure\n",
+ Pn, (int)sizeof(struct icmpin));
+ Exit(1);
+ }
+ icmpp->inode = inode;
+ icmpp->la = la;
+ icmpp->lal = lal;
+ icmpp->ra = ra;
+ icmpp->ral = ral;
+ icmpp->next = Icmpin[h];
+ Icmpin[h] = icmpp;
+ }
+ (void) fclose(xs);
+}
+
+
+
+/*
+ * get_ipx() - get /proc/net/ipx info
+ */
+
+static void
+get_ipx(p)
+ char *p; /* /proc/net/ipx path */
+{
+ char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
+ int fl = 1;
+ int h;
+ INODETYPE inode;
+ unsigned long rxq, state, txq;
+ struct ipxsin *ip, *np;
+ MALLOC_S len;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+ FILE *xs;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (Ipxsin) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (ip = Ipxsin[h]; ip; ip = np) {
+ np = ip->next;
+ if (ip->la)
+ (void) free((FREE_P *)ip->la);
+ if (ip->ra)
+ (void) free((FREE_P *)ip->ra);
+ (void) free((FREE_P *)ip);
+ }
+ Ipxsin[h] = (struct ipxsin *)NULL;
+ }
+ } else {
+ Ipxsin = (struct ipxsin **)calloc(INOBUCKS,
+ sizeof(struct ipxsin *));
+ if (!Ipxsin) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d IPX hash pointer bytes\n",
+ Pn, (int)(INOBUCKS * sizeof(struct ipxsin *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net/ipx file, assign a page size buffer to the stream,
+ * and read it. Store IPX socket info in the Ipxsin[] hash buckets.
+ */
+ if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ while (fgets(buf, sizeof(buf) - 1, xs)) {
+ if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 7)
+ continue;
+ if (fl) {
+
+ /*
+ * Check the column labels in the first line.
+ */
+ if (!fp[0] || strcmp(fp[0], "Local_Address")
+ || !fp[1] || strcmp(fp[1], "Remote_Address")
+ || !fp[2] || strcmp(fp[2], "Tx_Queue")
+ || !fp[3] || strcmp(fp[3], "Rx_Queue")
+ || !fp[4] || strcmp(fp[4], "State")
+ || !fp[5] || strcmp(fp[5], "Uid")
+ || !fp[6] || strcmp(fp[6], "Inode"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ fl = 0;
+ continue;
+ }
+ /*
+ * Assemble the inode number and see if the inode is already
+ * recorded.
+ */
+ ep = (char *)NULL;
+ if (!fp[6] || !*fp[6]
+ || (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX
+ || !ep || *ep)
+ continue;
+ h = INOHASH(inode);
+ for (ip = Ipxsin[h]; ip; ip = ip->next) {
+ if (inode == ip->inode)
+ break;
+ }
+ if (ip)
+ continue;
+ /*
+ * Assemble the transmit and receive queue values and the state.
+ */
+ ep = (char *)NULL;
+ if (!fp[2] || !*fp[2]
+ || (txq = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[3] || !*fp[3]
+ || (rxq = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[4] || !*fp[4]
+ || (state = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ /*
+ * Allocate space for the local address, unless it is "Not_Connected".
+ */
+ if (!fp[0] || !*fp[0] || strcmp(fp[0], "Not_Connected") == 0)
+ la = (char *)NULL;
+ else if ((len = strlen(fp[0]))) {
+ if (!(la = (char *)malloc(len + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d local IPX address bytes: %s\n",
+ Pn, (int)(len + 1), fp[0]);
+ Exit(1);
+ }
+ (void) snpf(la, len + 1, "%s", fp[0]);
+ } else
+ la = (char *)NULL;
+ /*
+ * Allocate space for the remote address, unless it is "Not_Connected".
+ */
+ if (!fp[1] || !*fp[1] || strcmp(fp[1], "Not_Connected") == 0)
+ ra = (char *)NULL;
+ else if ((len = strlen(fp[1]))) {
+ if (!(ra = (char *)malloc(len + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d remote IPX address bytes: %s\n",
+ Pn, (int)(len + 1), fp[1]);
+ Exit(1);
+ }
+ (void) snpf(ra, len + 1, "%s", fp[1]);
+ } else
+ ra = (char *)NULL;
+ /*
+ * Allocate space for an ipxsin entry, fill it, and link it to its
+ * hash bucket.
+ */
+ if (!(ip = (struct ipxsin *)malloc(sizeof(struct ipxsin)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte ipxsin structure\n",
+ Pn, (int)sizeof(struct ipxsin));
+ Exit(1);
+ }
+ ip->inode = inode;
+ ip->la = la;
+ ip->ra = ra;
+ ip->txq = txq;
+ ip->rxq = rxq;
+ ip->state = (int)state;
+ ip->next = Ipxsin[h];
+ Ipxsin[h] = ip;
+ }
+ (void) fclose(xs);
+}
+
+
+/*
+ * get_netlink() - get /proc/net/netlink info
+ */
+
+static void
+get_netlink(p)
+ char *p; /* /proc/net/netlink path */
+{
+ char buf[MAXPATHLEN], *ep, **fp;
+ int fr = 1;
+ int h, pr;
+ INODETYPE inode;
+ struct nlksin *np, *lp;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+ FILE *xs;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (Nlksin) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (lp = Nlksin[h]; lp; lp = np) {
+ np = lp->next;
+ (void) free((FREE_P *)lp);
+ }
+ Nlksin[h] = (struct nlksin *)NULL;
+ }
+ } else {
+ Nlksin = (struct nlksin **)calloc(INOBUCKS,sizeof(struct nlksin *));
+ if (!Nlksin) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d netlink hash pointer bytes\n",
+ Pn, (int)(INOBUCKS * sizeof(struct nlksin *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net/netlink file, assign a page size buffer to its stream,
+ * and read the file. Store Netlink info in the Nlksin[] hash buckets.
+ */
+ if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ while (fgets(buf, sizeof(buf) - 1, xs)) {
+ if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 10)
+ continue;
+ if (fr) {
+
+ /*
+ * Check the column labels in the first line.
+ */
+ if (!fp[1] || strcmp(fp[1], "Eth")
+ || !fp[9] || strcmp(fp[9], "Inode"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ fr = 0;
+ continue;
+ }
+ /*
+ * Assemble the inode number and see if the inode is already
+ * recorded.
+ */
+ ep = (char *)NULL;
+ if (!fp[9] || !*fp[9]
+ || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
+ || !ep || *ep)
+ continue;
+ h = INOHASH(inode);
+ for (lp = Nlksin[h]; lp; lp = lp->next) {
+ if (inode == lp->inode)
+ break;
+ }
+ if (lp)
+ continue;
+ /*
+ * Save the protocol from the Eth column.
+ */
+ if (!fp[1] || !*fp[1] || (strlen(fp[1])) < 1)
+ continue;
+ pr = atoi(fp[1]);
+ /*
+ * Allocate space for a nlksin entry, fill it, and link it to its
+ * hash bucket.
+ */
+ if (!(lp = (struct nlksin *)malloc(sizeof(struct nlksin)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte Netlink structure\n",
+ Pn, (int)sizeof(struct nlksin));
+ Exit(1);
+ }
+ lp->inode = inode;
+ lp->pr = pr;
+ lp->next = Nlksin[h];
+ Nlksin[h] = lp;
+ }
+ (void) fclose(xs);
+}
+
+
+/*
+ * get_pack() - get /proc/net/packet info
+ */
+
+static void
+get_pack(p)
+ char *p; /* /proc/net/raw path */
+{
+ char buf[MAXPATHLEN], *ep, **fp;
+ int fl = 1;
+ int h, ty;
+ INODETYPE inode;
+ struct packin *np, *pp;
+ unsigned long pr;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+ FILE *xs;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (Packin) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (pp = Packin[h]; pp; pp = np) {
+ np = pp->next;
+ (void) free((FREE_P *)pp);
+ }
+ Packin[h] = (struct packin *)NULL;
+ }
+ } else {
+ Packin = (struct packin **)calloc(INOBUCKS,
+ sizeof(struct packin *));
+ if (!Packin) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d packet hash pointer bytes\n",
+ Pn, (int)(INOBUCKS * sizeof(struct packin *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net/packet file, assign a page size buffer to its stream,
+ * and read the file. Store packet info in the Packin[] hash buckets.
+ */
+ if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ while (fgets(buf, sizeof(buf) - 1, xs)) {
+ if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 9)
+ continue;
+ if (fl) {
+
+ /*
+ * Check the column labels in the first line.
+ */
+ if (!fp[2] || strcmp(fp[2], "Type")
+ || !fp[3] || strcmp(fp[3], "Proto")
+ || !fp[8] || strcmp(fp[8], "Inode"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ fl = 0;
+ continue;
+ }
+ /*
+ * Assemble the inode number and see if the inode is already
+ * recorded.
+ */
+ ep = (char *)NULL;
+ if (!fp[8] || !*fp[8]
+ || (inode = strtoull(fp[8], &ep, 0)) == ULONG_MAX
+ || !ep || *ep)
+ continue;
+ h = INOHASH(inode);
+ for (pp = Packin[h]; pp; pp = pp->next) {
+ if (inode == pp->inode)
+ break;
+ }
+ if (pp)
+ continue;
+ /*
+ * Save the socket type and protocol.
+ */
+ if (!fp[2] || !*fp[2] || (strlen(fp[2])) < 1)
+ continue;
+ ty = atoi(fp[2]);
+ ep = (char *)NULL;
+ if (!fp[3] || !*fp[3] || (strlen(fp[3]) < 1)
+ || ((pr = strtoul(fp[3], &ep, 16)) == ULONG_MAX) || !ep || *ep)
+ continue;
+ /*
+ * Allocate space for a packin entry, fill it, and link it to its
+ * hash bucket.
+ */
+ if (!(pp = (struct packin *)malloc(sizeof(struct packin)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte packet structure\n",
+ Pn, (int)sizeof(struct packin));
+ Exit(1);
+ }
+ pp->inode = inode;
+ pp->pr = (int)pr;
+ pp->ty = ty;
+ pp->next = Packin[h];
+ Packin[h] = pp;
+ }
+ (void) fclose(xs);
+}
+
+
+/*
+ * get_raw() - get /proc/net/raw info
+ */
+
+static void
+get_raw(p)
+ char *p; /* /proc/net/raw path */
+{
+ char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
+ int h;
+ INODETYPE inode;
+ int nf = 12;
+ struct rawsin *np, *rp;
+ MALLOC_S lal, ral, spl;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+ FILE *xs;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (Rawsin) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (rp = Rawsin[h]; rp; rp = np) {
+ np = rp->next;
+ if (rp->la)
+ (void) free((FREE_P *)rp->la);
+ if (rp->ra)
+ (void) free((FREE_P *)rp->ra);
+ (void) free((FREE_P *)rp);
+ }
+ Rawsin[h] = (struct rawsin *)NULL;
+ }
+ } else {
+ Rawsin = (struct rawsin **)calloc(INOBUCKS,
+ sizeof(struct rawsin *));
+ if (!Rawsin) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d raw hash pointer bytes\n",
+ Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net/raw file, assign a page size buffer to its stream,
+ * and read the file. Store raw socket info in the Rawsin[] hash buckets.
+ */
+ if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ while (fgets(buf, sizeof(buf) - 1, xs)) {
+ if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
+ continue;
+ if (nf == 12) {
+
+ /*
+ * Check the column labels in the first line.
+ */
+ if (!fp[1] || strcmp(fp[1], "local_address")
+ || !fp[2] || strcmp(fp[2], "rem_address")
+ || !fp[3] || strcmp(fp[3], "st")
+ || !fp[11] || strcmp(fp[11], "inode"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ nf = 10;
+ continue;
+ }
+ /*
+ * Assemble the inode number and see if the inode is already
+ * recorded.
+ */
+ ep = (char *)NULL;
+ if (!fp[9] || !*fp[9]
+ || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
+ || !ep || *ep)
+ continue;
+ h = INOHASH(inode);
+ for (rp = Rawsin[h]; rp; rp = rp->next) {
+ if (inode == rp->inode)
+ break;
+ }
+ if (rp)
+ continue;
+ /*
+ * Save the local address, remote address, and state.
+ */
+ if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
+ la = (char *)NULL;
+ lal = (MALLOC_S)0;
+ } else {
+ if (!(la = (char *)malloc(lal + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d local raw address bytes: %s\n",
+ Pn, (int)(lal + 1), fp[1]);
+ Exit(1);
+ }
+ (void) snpf(la, lal + 1, "%s", fp[1]);
+ }
+ if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
+ ra = (char *)NULL;
+ ral = (MALLOC_S)0;
+ } else {
+ if (!(ra = (char *)malloc(ral + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d remote raw address bytes: %s\n",
+ Pn, (int)(ral + 1), fp[2]);
+ Exit(1);
+ }
+ (void) snpf(ra, ral + 1, "%s", fp[2]);
+ }
+ if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
+ sp = (char *)NULL;
+ spl = (MALLOC_S)0;
+ } else {
+ if (!(sp = (char *)malloc(spl + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d remote raw state bytes: %s\n",
+ Pn, (int)(spl + 1), fp[2]);
+ Exit(1);
+ }
+ (void) snpf(sp, spl + 1, "%s", fp[3]);
+ }
+ /*
+ * Allocate space for an rawsin entry, fill it, and link it to its
+ * hash bucket.
+ */
+ if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte rawsin structure\n",
+ Pn, (int)sizeof(struct rawsin));
+ Exit(1);
+ }
+ rp->inode = inode;
+ rp->la = la;
+ rp->lal = lal;
+ rp->ra = ra;
+ rp->ral = ral;
+ rp->sp = sp;
+ rp->spl = spl;
+ rp->next = Rawsin[h];
+ Rawsin[h] = rp;
+ }
+ (void) fclose(xs);
+}
+
+
+/*
+ * get_sctp() - get /proc/net/sctp/assocs info
+ */
+
+static void
+get_sctp()
+{
+ char buf[MAXPATHLEN], *a, *ep, **fp, *id, *la, *lp, *ra, *rp, *ta;
+ int d, err, fl, h, i, j, nf, ty, x;
+ INODETYPE inode;
+ MALLOC_S len, plen;
+ struct sctpsin *sp, *np;
+ FILE *ss;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (SCTPsin) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (sp = SCTPsin[h]; sp; sp = np) {
+ np = sp->next;
+ if (sp->addr)
+ (void) free((FREE_P *)sp->addr);
+ if (sp->assocID)
+ (void) free((FREE_P *)sp->assocID);
+ if (sp->lport)
+ (void) free((FREE_P *)sp->lport);
+ if (sp->rport)
+ (void) free((FREE_P *)sp->rport);
+ if (sp->laddrs)
+ (void) free((FREE_P *)sp->laddrs);
+ if (sp->raddrs)
+ (void) free((FREE_P *)sp->raddrs);
+ (void) free((FREE_P *)sp);
+ }
+ SCTPsin[h] = (struct sctpsin *)NULL;
+ }
+ } else {
+ SCTPsin = (struct sctpsin **)calloc(INOBUCKS,
+ sizeof(struct sctpsin *));
+ if (!SCTPsin) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d SCTP hash pointer bytes\n",
+ Pn, (int)(INOBUCKS * sizeof(struct sctpsin *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net/sctp files, assign a page size buffer to the streams,
+ * and read them. Store SCTP socket info in the SCTPsin[] hash buckets.
+ */
+ for (i = 0; i < NSCTPPATHS; i++ ) {
+ if (!(ss = open_proc_stream(SCTPPath[i], "r", &vbuf, &vsz, 0)))
+ continue;
+ fl = 1;
+ while (fgets(buf, sizeof(buf) - 1, ss)) {
+ if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0))
+ < (i ? 9 : 16)
+ ) {
+ continue;
+ }
+ if (fl) {
+
+ /*
+ * Check the column labels in the first line.
+ */
+ err = 0;
+ switch (i) {
+ case 0:
+ if (!fp[0] || strcmp(fp[0], "ASSOC")
+ || !fp[6] || strcmp(fp[6], "ASSOC-ID")
+ || !fp[10] || strcmp(fp[10], "INODE")
+ || !fp[11] || strcmp(fp[11], "LPORT")
+ || !fp[12] || strcmp(fp[12], "RPORT")
+ || !fp[13] || strcmp(fp[13], "LADDRS")
+ || !fp[14] || strcmp(fp[14], "<->")
+ || !fp[15] || strcmp(fp[15], "RADDRS")
+ ) {
+ err = 1;
+ }
+ break;
+ case 1:
+ if (!fp[0] || strcmp(fp[0], "ENDPT")
+ || !fp[5] || strcmp(fp[5], "LPORT")
+ || !fp[7] || strcmp(fp[7], "INODE")
+ || !fp[8] || strcmp(fp[8], "LADDRS")
+ ) {
+ err = 1;
+ }
+ }
+ if (err) {
+ if (!Fwarn)
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, SCTPPath[i]);
+ break;
+ }
+ fl = 0;
+ continue;
+ }
+ /*
+ * Assemble the inode number and see if it has already been
+ * recorded.
+ */
+ ep = (char *)NULL;
+ j = i ? 7 : 10;
+ if (!fp[j] || !*fp[j]
+ || (inode = strtoull(fp[j], &ep, 0)) == ULONG_MAX
+ || !ep || *ep)
+ continue;
+ h = INOHASH((INODETYPE)inode);
+ for (sp = SCTPsin[h]; sp; sp = sp->next) {
+ if (inode == sp->inode)
+ break;
+ }
+ /*
+ * Set the entry type.
+ */
+ if (sp)
+ ty = (sp->type == i) ? i : 3;
+ else
+ ty = i;
+ /*
+ * Allocate space for this line's sctpsin members.
+ *
+ * The association or endpoint address is in the first field.
+ */
+ a = sp ? sp->addr : (char *)NULL;
+ if (fp[0] && *fp[0] && (len = strlen(fp[0]))) {
+ if (a) {
+ if (isainb(fp[0], a)) {
+ plen = strlen(a);
+ a = (char *)realloc((MALLOC_P *)a, plen + len + 2);
+ d = 0;
+ } else
+ d = 1;
+ } else {
+ plen = (MALLOC_S)0;
+ a = (char *)malloc(len + 1);
+ d = 0;
+ }
+ if (!a) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d SCTP ASSOC bytes: %s\n",
+ Pn, (int)(len + 1), fp[0]);
+ Exit(1);
+ }
+ if (!d) {
+ if (plen)
+ (void) snpf((a + plen), len + 2, ",%s", fp[0]);
+ else
+ (void) snpf(a, len + 1, "%s", fp[0]);
+ }
+ }
+ /*
+ * The association ID is in the seventh field.
+ */
+ id = sp ? sp->assocID : (char *)NULL;
+ if (!i && fp[6] && *fp[6] && (len = strlen(fp[6]))) {
+ if (id) {
+ if (isainb(fp[6], id)) {
+ plen = strlen(id);
+ id = (char *)realloc((MALLOC_P *)id,plen+len+2);
+ d = 0;
+ } else
+ d = 1;
+ } else {
+ plen = (MALLOC_S)0;
+ id = (char *)malloc(len + 1);
+ d = 0;
+ }
+ if (!id) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d SCTP ASSOC-ID bytes: %s\n",
+ Pn, (int)(len + 1), fp[6]);
+ Exit(1);
+ }
+ if (!d) {
+ if (plen)
+ (void) snpf((id + plen), len + 2, ",%s", fp[6]);
+ else
+ (void) snpf(id, len + 1, "%s", fp[6]);
+ }
+ }
+ /*
+ * The field number for the local port depends on the entry type.
+ */
+ j = i ? 5 : 11;
+ lp = sp ? sp->lport : (char *)NULL;
+ if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
+ if (lp) {
+ if (isainb(fp[j], lp)) {
+ plen = strlen(lp);
+ lp = (char *)realloc((MALLOC_P *)lp,plen+len+2);
+ d = 0;
+ } else
+ d = 1;
+ } else {
+ plen = (MALLOC_S)0;
+ lp = (char *)malloc(len + 1);
+ d = 0;
+ }
+ if (!lp) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d SCTP LPORT bytes: %s\n",
+ Pn, (int)(len + 1), fp[j]);
+ Exit(1);
+ }
+ if (!d) {
+ if (plen)
+ (void) snpf((lp + plen), len + 2, ",%s", fp[j]);
+ else
+ (void) snpf(lp, len + 1, "%s", fp[j]);
+ }
+ }
+ /*
+ * The field number for the remote port depends on the entry type.
+ */
+ rp = sp ? sp->rport : (char *)NULL;
+ if (!i && fp[12] && *fp[12] && (len = strlen(fp[12]))) {
+ if (rp) {
+ if (isainb(fp[12], rp)) {
+ plen = strlen(rp);
+ rp = (char *)realloc((MALLOC_P *)rp,plen+len+2);
+ d = 0;
+ } else
+ d = 1;
+ } else {
+ plen = (MALLOC_S)0;
+ rp = (char *)malloc(len + 1);
+ d = 0;
+ }
+ if (!rp) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d SCTP RPORT bytes: %s\n",
+ Pn, (int)(len + 1), fp[12]);
+ Exit(1);
+ }
+ if (!d) {
+ if (plen)
+ (void) snpf((rp + plen), len + 2, ",%s", fp[12]);
+ else
+ (void) snpf(rp, len + 1, "%s", fp[12]);
+ }
+ }
+ /*
+ * The local addresses begin in a field whose number depends on
+ * the entry type.
+ */
+ j = i ? 8 : 13;
+ la = sp ? sp->laddrs : (char *)NULL;
+ if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
+ if (!(ta = get_sctpaddrs(fp, j, nf, &x))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d SCTP LADDRS bytes\n",
+ Pn, (int)len);
+ Exit(1);
+ }
+ if (la) {
+ if (isainb(ta, la)) {
+ len = strlen(ta);
+ plen = strlen(la);
+ if (!(la=(char *)realloc((MALLOC_P *)la,plen+len+2))
+ ) {
+ (void) fprintf(stderr,
+ "%s: can't reallocate %d SCTP LADDRS bytes\n",
+ Pn, (int)len);
+ Exit(1);
+ }
+ (void) snpf(la + plen, len + 2, ",%s", ta);
+ (void) free((FREE_P *)ta);
+ }
+ } else
+ la = ta;
+ }
+ /*
+ * The remote addresses begin after the local addresses, but only
+ * for the ASSOC type.
+ */
+ ra = sp ? sp->raddrs : (char *)NULL;
+ if (!i && x && fp[x+1] && *fp[x+1] && (len = strlen(fp[x+1]))) {
+ if (!(ta = get_sctpaddrs(fp, x + 1, nf, &x))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d SCTP RADDRS bytes\n",
+ Pn, (int)len);
+ Exit(1);
+ }
+ if (ra) {
+ if (isainb(ta, ra)) {
+ len = strlen(ta);
+ plen = strlen(ra);
+ if (!(ra=(char *)realloc((MALLOC_P *)ra,plen+len+2))
+ ) {
+ (void) fprintf(stderr,
+ "%s: can't reallocate %d SCTP RADDRS bytes\n",
+ Pn, (int)len);
+ Exit(1);
+ }
+ (void) snpf(ra + plen, len + 2, ",%s", ta);
+ (void) free((FREE_P *)ta);
+ }
+ } else
+ ra = ta;
+ }
+ /*
+ * If no matching sctpsin entry was found for this inode, allocate
+ * space for a new sctpsin entry, fill it, and link it to its hash
+ * bucket. Update a matching entry.
+ */
+ if (!sp) {
+ if (!(sp = (struct sctpsin *)malloc(sizeof(struct sctpsin))) ) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte sctpsin structure\n",
+ Pn, (int)sizeof(struct sctpsin));
+ Exit(1);
+ }
+ sp->inode = inode;
+ sp->next = SCTPsin[h];
+ SCTPsin[h] = sp;
+ }
+ sp->addr = a;
+ sp->assocID = id;
+ sp->lport = lp;
+ sp->rport = rp;
+ sp->laddrs = la;
+ sp->raddrs = ra;
+ sp->type = ty;
+ }
+ (void) fclose(ss);
+ }
+}
+
+
+static char *
+get_sctpaddrs(fp, i, nf, x)
+ char **fp; /* field pointers */
+ int i; /* first address field index in fp */
+ int nf; /* number of fields */
+ int *x; /* index of first "<->" field entry */
+{
+ MALLOC_S al = (MALLOC_S)0;
+ char *cp = (char *)NULL;
+ MALLOC_S tl;
+
+ *x = 0;
+ do {
+ if ((i >= nf) || !fp[i] || !*fp[i] || !(tl = strlen(fp[i])))
+ break;
+ if (!strcmp(fp[i], "<->")) {
+ *x = i;
+ break;
+ }
+ if (!strchr(fp[i], (int)'.') && !strchr(fp[i], (int)':'))
+ break;
+ if (cp)
+ cp = (char *)realloc((MALLOC_P *)cp, al + tl + 1);
+ else
+ cp = (char *)malloc(al + tl + 1);
+ if (!cp)
+ break;
+ if (al)
+ *(cp + al - 1) = ',';
+ (void) strncpy(al ? (cp + al) : cp, fp[i], tl);
+ al += (tl + 1);
+ *(cp + al - 1) = '\0';
+ } while (++i < nf);
+ return(cp);
+}
+
+
+/*
+ * get_tcpudp() - get IPv4 TCP, UDP or UDPLITE net info
+ */
+
+static void
+get_tcpudp(p, pr, clr)
+ char *p; /* /proc/net/{tcp,udp} path */
+ int pr; /* protocol: 0 = TCP, 1 = UDP,
+ * 2 = UDPLITE */
+ int clr; /* 1 == clear the table */
+{
+ char buf[MAXPATHLEN], *ep, **fp;
+ unsigned long faddr, fport, laddr, lport, rxq, state, txq;
+ FILE *fs;
+ int h, nf;
+ INODETYPE inode;
+ struct tcp_udp *np, *tp;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+/*
+ * Delete previous table contents.
+ */
+ if (TcpUdp) {
+ if (clr) {
+ for (h = 0; h < TcpUdp_bucks; h++) {
+ for (tp = TcpUdp[h]; tp; tp = np) {
+ np = tp->next;
+ (void) free((FREE_P *)tp);
+ }
+ TcpUdp[h] = (struct tcp_udp *)NULL;
+ }
+ }
+/*
+ * If no hash buckets have been allocated, do so now.
+ */
+ } else {
+
+ /*
+ * Open the /proc/net/sockstat file and establish the hash bucket
+ * count from its "sockets: used" line.
+ */
+ TcpUdp_bucks = INOBUCKS;
+ if ((fs = fopen(SockStatPath, "r"))) {
+ while(fgets(buf, sizeof(buf) - 1, fs)) {
+ if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) != 3)
+ continue;
+ if (!fp[0] || strcmp(fp[0], "sockets:")
+ || !fp[1] || strcmp(fp[1], "used")
+ || !fp[2] || !*fp[2])
+ continue;
+ if ((h = atoi(fp[2])) < 1)
+ h = INOBUCKS;
+ while (TcpUdp_bucks < h)
+ TcpUdp_bucks *= 2;
+ break;
+ }
+ (void) fclose(fs);
+ }
+ if (!(TcpUdp = (struct tcp_udp **)calloc(TcpUdp_bucks,
+ sizeof(struct tcp_udp *))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for TCP&UDP hash buckets\n",
+ Pn, (int)(TcpUdp_bucks * sizeof(struct tcp_udp *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net file, assign a page size buffer to the stream, and
+ * read it.
+ */
+ if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ nf = 12;
+ while(fgets(buf, sizeof(buf) - 1, fs)) {
+ if (get_fields(buf,
+ (nf == 12) ? (char *)NULL : ":",
+ &fp, (int *)NULL, 0)
+ < nf)
+ continue;
+ if (nf == 12) {
+ if (!fp[1] || strcmp(fp[1], "local_address")
+ || !fp[2] || strcmp(fp[2], "rem_address")
+ || !fp[3] || strcmp(fp[3], "st")
+ || !fp[4] || strcmp(fp[4], "tx_queue")
+ || !fp[5] || strcmp(fp[5], "rx_queue")
+ || !fp[11] || strcmp(fp[11], "inode"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ nf = 14;
+ continue;
+ }
+ /*
+ * Get the local and remote addresses.
+ */
+ ep = (char *)NULL;
+ if (!fp[1] || !*fp[1]
+ || (laddr = strtoul(fp[1], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[2] || !*fp[2]
+ || (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[3] || !*fp[3]
+ || (faddr = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[4] || !*fp[4]
+ || (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ /*
+ * Get the state and queue sizes.
+ */
+ ep = (char *)NULL;
+ if (!fp[5] || !*fp[5]
+ || (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[6] || !*fp[6]
+ || (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[7] || !*fp[7]
+ || (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ /*
+ * Get the inode and use it for hashing and searching.
+ */
+ ep = (char *)NULL;
+ if (!fp[13] || !*fp[13]
+ || (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
+ continue;
+ h = TCPUDPHASH(inode);
+ for (tp = TcpUdp[h]; tp; tp = tp->next) {
+ if (tp->inode == inode)
+ break;
+ }
+ if (tp)
+ continue;
+ /*
+ * Create a new entry and link it to its hash bucket.
+ */
+ if (!(tp = (struct tcp_udp *)malloc(sizeof(struct tcp_udp)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for tcp_udp struct\n",
+ Pn, (int)sizeof(struct tcp_udp));
+ Exit(1);
+ }
+ tp->inode = inode;
+ tp->faddr = faddr;
+ tp->fport = (int)(fport & 0xffff);
+ tp->laddr = laddr;
+ tp->lport = (int)(lport & 0xffff);
+ tp->txq = txq;
+ tp->rxq = rxq;
+ tp->proto = pr;
+ tp->state = (int)state;
+ tp->next = TcpUdp[h];
+ TcpUdp[h] = tp;
+ }
+ (void) fclose(fs);
+}
+
+
+#if defined(HASIPv6)
+/*
+ * get_raw6() - get /proc/net/raw6 info
+ */
+
+static void
+get_raw6(p)
+ char *p; /* /proc/net/raw path */
+{
+ char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
+ int h;
+ INODETYPE inode;
+ int nf = 12;
+ struct rawsin *np, *rp;
+ MALLOC_S lal, ral, spl;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+ FILE *xs;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (Rawsin6) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (rp = Rawsin6[h]; rp; rp = np) {
+ np = rp->next;
+ if (rp->la)
+ (void) free((FREE_P *)rp->la);
+ if (rp->ra)
+ (void) free((FREE_P *)rp->ra);
+ (void) free((FREE_P *)rp);
+ }
+ Rawsin6[h] = (struct rawsin *)NULL;
+ }
+ } else {
+ Rawsin6 = (struct rawsin **)calloc(INOBUCKS,
+ sizeof(struct rawsin *));
+ if (!Rawsin6) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d raw6 hash pointer bytes\n",
+ Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net/raw6 file, assign a page size buffer to the stream,
+ * and read it. Store raw6 socket info in the Rawsin6[] hash buckets.
+ */
+ if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ while (fgets(buf, sizeof(buf) - 1, xs)) {
+ if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
+ continue;
+ if (nf == 12) {
+
+ /*
+ * Check the column labels in the first line.
+ */
+ if (!fp[1] || strcmp(fp[1], "local_address")
+ || !fp[2] || strcmp(fp[2], "remote_address")
+ || !fp[3] || strcmp(fp[3], "st")
+ || !fp[11] || strcmp(fp[11], "inode"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ nf = 10;
+ continue;
+ }
+ /*
+ * Assemble the inode number and see if the inode is already
+ * recorded.
+ */
+ ep = (char *)NULL;
+ if (!fp[9] || !*fp[9]
+ || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
+ || !ep || *ep)
+ continue;
+ h = INOHASH(inode);
+ for (rp = Rawsin6[h]; rp; rp = rp->next) {
+ if (inode == rp->inode)
+ break;
+ }
+ if (rp)
+ continue;
+ /*
+ * Save the local address, remote address, and state.
+ */
+ if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
+ la = (char *)NULL;
+ lal = (MALLOC_S)0;
+ } else {
+ if (!(la = (char *)malloc(lal + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d local raw6 address bytes: %s\n",
+ Pn, (int)(lal + 1), fp[1]);
+ Exit(1);
+ }
+ (void) snpf(la, lal + 1, "%s", fp[1]);
+ }
+ if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
+ ra = (char *)NULL;
+ ral = (MALLOC_S)0;
+ } else {
+ if (!(ra = (char *)malloc(ral + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d remote raw6 address bytes: %s\n",
+ Pn, (int)(ral + 1), fp[2]);
+ Exit(1);
+ }
+ (void) snpf(ra, ral + 1, "%s", fp[2]);
+ }
+ if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
+ sp = (char *)NULL;
+ spl = (MALLOC_S)0;
+ } else {
+ if (!(sp = (char *)malloc(spl + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d remote raw6 state bytes: %s\n",
+ Pn, (int)(spl + 1), fp[2]);
+ Exit(1);
+ }
+ (void) snpf(sp, spl + 1, "%s", fp[3]);
+ }
+ /*
+ * Allocate space for an rawsin entry, fill it, and link it to its
+ * hash bucket.
+ */
+ if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d byte rawsin structure for IPv6\n",
+ Pn, (int)sizeof(struct rawsin));
+ Exit(1);
+ }
+ rp->inode = inode;
+ rp->la = la;
+ rp->lal = lal;
+ rp->ra = ra;
+ rp->ral = ral;
+ rp->sp = sp;
+ rp->spl = spl;
+ rp->next = Rawsin6[h];
+ Rawsin6[h] = rp;
+ }
+ (void) fclose(xs);
+}
+
+
+/*
+ * get_tcpudp6() - get IPv6 TCP, UDP or UDPLITE net info
+ */
+
+static void
+get_tcpudp6(p, pr, clr)
+ char *p; /* /proc/net/{tcp,udp} path */
+ int pr; /* protocol: 0 = TCP, 1 = UDP */
+ int clr; /* 1 == clear the table */
+{
+ char buf[MAXPATHLEN], *ep, **fp;
+ struct in6_addr faddr, laddr;
+ unsigned long fport, lport, rxq, state, txq;
+ FILE *fs;
+ int h, i, nf;
+ INODETYPE inode;
+ struct tcp_udp6 *np6, *tp6;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+/*
+ * Delete previous table contents. Allocate a table for the first time.
+ */
+ if (TcpUdp6) {
+ if (clr) {
+ for (h = 0; h < TcpUdp6_bucks; h++) {
+ for (tp6 = TcpUdp6[h]; tp6; tp6 = np6) {
+ np6 = tp6->next;
+ (void) free((FREE_P *)tp6);
+ }
+ TcpUdp6[h] = (struct tcp_udp6 *)NULL;
+ }
+ }
+ } else {
+
+ /*
+ * Open the /proc/net/sockstat6 file and establish the hash bucket
+ * count from its "TCP6: inuse" and "UDP6: inuse" lines.
+ */
+ TcpUdp6_bucks = INOBUCKS;
+ h = i = nf = 0;
+ if ((fs = fopen(SockStatPath6, "r"))) {
+ while(fgets(buf, sizeof(buf) - 1, fs)) {
+ if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) != 3)
+ continue;
+ if (!fp[0]
+ || !fp[1] || strcmp(fp[1], "inuse")
+ || !fp[2] || !*fp[2])
+ continue;
+ if (!strcmp(fp[0], "TCP6:")) {
+ nf |= 1;
+ if ((h = atoi(fp[2])) < 1)
+ h = INOBUCKS;
+ i += h;
+ } else if (!strcmp(fp[0], "UDP6:")) {
+ nf |= 2;
+ if ((h = atoi(fp[2])) < 1)
+ h = INOBUCKS;
+ i += h;
+ } else
+ continue;
+ if (nf == 3) {
+ while (TcpUdp6_bucks < i)
+ TcpUdp6_bucks *= 2;
+ break;
+ }
+ }
+ (void) fclose(fs);
+ }
+ if (!(TcpUdp6 = (struct tcp_udp6 **)calloc(TcpUdp6_bucks,
+ sizeof(struct tcp_udp6 *))))
+ {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for TCP6&UDP6 hash buckets\n",
+ Pn, (int)(TcpUdp6_bucks * sizeof(struct tcp_udp6 *)));
+ Exit(1);
+ }
+ }
+/*
+ * Open the /proc/net file, assign a page size buffer to the stream,
+ * and read it.
+ */
+ if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ nf = 12;
+ while(fgets(buf, sizeof(buf) - 1, fs)) {
+ if (get_fields(buf,
+ (nf == 12) ? (char *)NULL : ":",
+ &fp, (int *)NULL, 0)
+ < nf)
+ continue;
+ if (nf == 12) {
+ if (!fp[1] || strcmp(fp[1], "local_address")
+ || !fp[2] || strcmp(fp[2], "remote_address")
+ || !fp[3] || strcmp(fp[3], "st")
+ || !fp[4] || strcmp(fp[4], "tx_queue")
+ || !fp[5] || strcmp(fp[5], "rx_queue")
+ || !fp[11] || strcmp(fp[11], "inode"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ nf = 14;
+ continue;
+ }
+ /*
+ * Get the local and remote addresses.
+ */
+ if (!fp[1] || !*fp[1] || net6a2in6(fp[1], &laddr))
+ continue;
+ ep = (char *)NULL;
+ if (!fp[2] || !*fp[2]
+ || (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ if (!fp[3] || !*fp[3] || net6a2in6(fp[3], &faddr))
+ continue;
+ ep = (char *)NULL;
+ if (!fp[4] || !*fp[4]
+ || (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ /*
+ * Get the state and queue sizes.
+ */
+ ep = (char *)NULL;
+ if (!fp[5] || !*fp[5]
+ || (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[6] || !*fp[6]
+ || (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ ep = (char *)NULL;
+ if (!fp[7] || !*fp[7]
+ || (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
+ continue;
+ /*
+ * Get the inode and use it for hashing and searching.
+ */
+ ep = (char *)NULL;
+ if (!fp[13] || !*fp[13]
+ || (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
+ continue;
+ h = TCPUDP6HASH(inode);
+ for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
+ if (tp6->inode == inode)
+ break;
+ }
+ if (tp6)
+ continue;
+ /*
+ * Create a new entry and link it to its hash bucket.
+ */
+ if (!(tp6 = (struct tcp_udp6 *)malloc(sizeof(struct tcp_udp6)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for tcp_udp6 struct\n",
+ Pn, (int)sizeof(struct tcp_udp6));
+ Exit(1);
+ }
+ tp6->inode = inode;
+ tp6->faddr = faddr;
+ tp6->fport = (int)(fport & 0xffff);
+ tp6->laddr = laddr;
+ tp6->lport = (int)(lport & 0xffff);
+ tp6->txq = txq;
+ tp6->rxq = rxq;
+ tp6->proto = pr;
+ tp6->state = (int)state;
+ tp6->next = TcpUdp6[h];
+ TcpUdp6[h] = tp6;
+ }
+ (void) fclose(fs);
+}
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * get_unix() - get UNIX net info
+ */
+
+static void
+get_unix(p)
+ char *p; /* /proc/net/unix path */
+{
+ char buf[MAXPATHLEN], *ep, **fp, *path, *pcb;
+ int fl = 1;
+ int h, nf;
+ INODETYPE inode;
+ MALLOC_S len;
+ struct uxsin *np, *up;
+ FILE *us;
+ static char *vbuf = (char *)NULL;
+ static size_t vsz = (size_t)0;
+/*
+ * Do second time cleanup or first time setup.
+ */
+ if (Uxsin) {
+ for (h = 0; h < INOBUCKS; h++) {
+ for (up = Uxsin[h]; up; up = np) {
+ np = up->next;
+ if (up->path)
+ (void) free((FREE_P *)up->path);
+ if (up->pcb)
+ (void) free((FREE_P *)up->pcb);
+ (void) free((FREE_P *)up);
+ }
+ Uxsin[h] = (struct uxsin *)NULL;
+ }
+ } else {
+ Uxsin = (struct uxsin **)calloc(INOBUCKS, sizeof(struct uxsin *));
+ if (!Uxsin) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for Unix socket info\n",
+ Pn, (int)(INOBUCKS * sizeof(struct uxsin *)));
+ }
+ }
+/*
+ * Open the /proc/net/unix file, assign a page size buffer to the stream,
+ * read the file's contents, and add them to the Uxsin hash buckets.
+ */
+ if (!(us = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
+ return;
+ while (fgets(buf, sizeof(buf) - 1, us)) {
+ if ((nf = get_fields(buf, ":", &fp, (int *)NULL, 0)) < 7)
+ continue;
+ if (fl) {
+
+ /*
+ * Check the first line for header words.
+ */
+ if (!fp[0] || strcmp(fp[0], "Num")
+ || !fp[1] || strcmp(fp[1], "RefCount")
+ || !fp[2] || strcmp(fp[2], "Protocol")
+ || !fp[3] || strcmp(fp[3], "Flags")
+ || !fp[4] || strcmp(fp[4], "Type")
+ || !fp[5] || strcmp(fp[5], "St")
+ || !fp[6] || strcmp(fp[6], "Inode")
+ || nf < 8
+ || !fp[7] || strcmp(fp[7], "Path"))
+ {
+ if (!Fwarn) {
+ (void) fprintf(stderr,
+ "%s: WARNING: unsupported format: %s\n",
+ Pn, p);
+ }
+ break;
+ }
+ fl = 0;
+ continue;
+ }
+ /*
+ * Assemble PCB address, inode number, and path name. If this
+ * inode is already represented in Uxsin, skip it.
+ */
+ ep = (char *)NULL;
+ if (!fp[6] || !*fp[6]
+ || (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX || !ep || *ep)
+ continue;
+ h = INOHASH(inode);
+ for (up = Uxsin[h]; up; up = up->next) {
+ if (inode == up->inode)
+ break;
+ }
+ if (up)
+ continue;
+ if (!fp[0] || !*fp[0])
+ pcb = (char *)NULL;
+ else {
+ len = strlen(fp[0]) + 2;
+ if (!(pcb = (char *)malloc(len + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for UNIX PCB: %s\n",
+ Pn, (int)(len + 1), fp[0]);
+ Exit(1);
+ }
+ (void) snpf(pcb, len + 1, "0x%s", fp[0]);
+ }
+ if (nf >= 8 && fp[7] && *fp[7] && (len = strlen(fp[7]))) {
+ if (!(path = (char *)malloc(len + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for UNIX path \"%s\"\n",
+ Pn, (int)(len + 1), fp[7]);
+ Exit(1);
+ }
+ (void) snpf(path, len + 1, "%s", fp[7]);
+ } else
+ path = (char *)NULL;
+ /*
+ * Allocate and fill a Unix socket info structure; link it to its
+ * hash bucket.
+ */
+ if (!(up = (struct uxsin *)malloc(sizeof(struct uxsin)))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for uxsin struct\n",
+ Pn, (int)sizeof(struct uxsin));
+ Exit(1);
+ }
+ up->inode = inode;
+ up->pcb = pcb;
+ up->sb_def = 0;
+ if ((up->path = path) && (*path == '/')) {
+
+ /*
+ * If an absolute path (i.e., one that begins with a '/') exists
+ * for the line, attempt to stat(2) it and save the device and
+ * node numbers reported in the stat buffer.
+ */
+ struct stat sb;
+ int sr;
+
+ if (HasNFS)
+ sr = statsafely(path, &sb);
+ else
+ sr = stat(path, &sb);
+ if (sr && ((sb.st_mode & S_IFMT) == S_IFSOCK)) {
+ up->sb_def = 1;
+ up->sb_dev = sb.st_dev;
+ up->sb_ino = (INODETYPE)sb.st_ino;
+ up->sb_rdev = sb.st_rdev;
+ }
+ }
+ up->next = Uxsin[h];
+ Uxsin[h] = up;
+ }
+ (void) fclose(us);
+}
+
+
+#if defined(HASIPv6)
+/*
+ * net6a2in6() - convert ASCII IPv6 address in /proc/net/{tcp,udp} form to
+ * an in6_addr
+ */
+
+static int
+net6a2in6(as, ad)
+ char *as; /* address source */
+ struct in6_addr *ad; /* address destination */
+{
+ char buf[9], *ep;
+ int i;
+ size_t len;
+/*
+ * Assemble four uint32_t's from 4 X 8 hex digits into s6_addr32[].
+ */
+ for (i = 0, len = strlen(as);
+ (i < 4) && (len >= 8);
+ as += 8, i++, len -= 8)
+ {
+ (void) strncpy(buf, as, 8);
+ buf[8] = '\0';
+ ep = (char *)NULL;
+ if ((ad->s6_addr32[i] = (uint32_t)strtoul(buf, &ep, 16))
+ == (uint32_t)UINT32_MAX || !ep || *ep)
+ break;
+ }
+ return((*as || (i != 4) || len) ? 1 : 0);
+}
+#endif /* defined(HASIPv6) */
+
+
+/*
+ * isainb(a,b) is string a in string b
+ */
+
+static int
+isainb(a, b)
+ char *a; /*string a */
+ char *b; /* string b */
+{
+ char *cp, *pp;
+ MALLOC_S la, lb, lt;
+
+ if (!a || !b)
+ return(1);
+ if (!(la = strlen(a)) || !(lb = strlen(b)))
+ return(1);
+ if (!(cp = strchr(b, (int)','))) {
+ if (la != lb)
+ return(1);
+ return(strcmp(a, b));
+ }
+ for (pp = b; pp && *pp; ) {
+ lt = (MALLOC_S)(cp - pp);
+ if ((la == lt) && !strncmp(a, pp, lt))
+ return(0);
+ if (*cp) {
+ pp = cp + 1;
+ if (!(cp = strchr(pp, (int)',')))
+ cp = b + lb;
+ } else
+ pp = cp;
+ }
+ return(1);
+}
+
+
+/*
+ * print_ax25info() - print AX25 socket info
+ */
+
+static void
+print_ax25info(ap)
+ struct ax25sin *ap; /* AX25 socket info */
+{
+ char *cp, pbuf[1024];
+ int ds;
+ MALLOC_S pl = (MALLOC_S)0;
+
+ if (Lf->nma)
+ return;
+ if (ap->sa) {
+ ds = (ap->da && strcmp(ap->da, "*")) ? 1 : 0;
+ (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s%s ", ap->sa,
+ ds ? "->" : "",
+ ds ? ap->da : "");
+ pl = strlen(pbuf);
+ }
+ if (ap->sqs) {
+ (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "(Sq=%lu ", ap->sq);
+ pl = strlen(pbuf);
+ cp = "";
+ } else
+ cp = "(";
+ if (ap->rqs) {
+ (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sRq=%lu ", cp, ap->rq);
+ pl = strlen(pbuf);
+ cp = "";
+ }
+ (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sState=%d", cp, ap->state);
+ pl = strlen(pbuf);
+ if ((ap->state >= 0) && (ap->state < NAX25ST))
+ cp = ax25st[ap->state];
+ else
+ cp = NULL;
+ (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s)",
+ cp ? ", " : "",
+ cp ? cp : "");
+ pl = strlen(pbuf);
+ if (!(cp = (char *)malloc(pl + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for AX25 sock state, PID: %d\n",
+ Pn, (int)(pl + 1), Lp->pid);
+ Exit(1);
+ }
+ (void) snpf(cp, pl + 1, "%s", pbuf);
+ Lf->nma = cp;
+}
+
+
+/*
+ * print_ipxinfo() - print IPX socket info
+ */
+
+static void
+print_ipxinfo(ip)
+ struct ipxsin *ip; /* IPX socket info */
+{
+ char *cp, pbuf[256];
+ MALLOC_S pl;
+
+ if (Lf->nma)
+ return;
+ (void) snpf(pbuf, sizeof(pbuf), "(Tx=%lx Rx=%lx State=%02x)",
+ ip->txq, ip->rxq, ip->state);
+ pl = strlen(pbuf);
+ if (!(cp = (char *)malloc(pl + 1))) {
+ (void) fprintf(stderr,
+ "%s: can't allocate %d bytes for IPX sock state, PID: %d\n",
+ Pn, (int)(pl + 1), Lp->pid);
+ Exit(1);
+ }
+ (void) snpf(cp, pl + 1, "%s", pbuf);
+ Lf->nma = cp;
+}
+
+
+/*
+ * print_tcptpi() - print TCP/TPI state
+ */
+
+void
+print_tcptpi(nl)
+ int nl; /* 1 == '\n' required */
+{
+ char buf[128];
+ char *cp = (char *)NULL;
+ int ps = 0;
+ int s;
+
+ if ((Ftcptpi & TCPTPI_STATE) && Lf->lts.type == 0) {
+ if (!TcpSt)
+ (void) build_IPstates();
+ if ((s = Lf->lts.state.i + TcpStOff) < 0 || s >= TcpNstates) {
+ (void) snpf(buf, sizeof(buf), "UNKNOWN_TCP_STATE_%d",
+ Lf->lts.state.i);
+ cp = buf;
+ } else
+ cp = TcpSt[s];
+ if (cp) {
+ if (Ffield)
+ (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
+ else {
+ putchar('(');
+ (void) fputs(cp, stdout);
+ }
+ ps++;
+ }
+ }
+
+# if defined(HASTCPTPIQ)
+ if (Ftcptpi & TCPTPI_QUEUES) {
+ if (Lf->lts.rqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QR=%lu", Lf->lts.rq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.sqs) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("QS=%lu", Lf->lts.sq);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+# endif /* defined(HASTCPTPIQ) */
+
+# if defined(HASTCPTPIW)
+ if (Ftcptpi & TCPTPI_WINDOWS) {
+ if (Lf->lts.rws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WR=%lu", Lf->lts.rw);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ if (Lf->lts.wws) {
+ if (Ffield)
+ putchar(LSOF_FID_TCPTPI);
+ else {
+ if (ps)
+ putchar(' ');
+ else
+ putchar('(');
+ }
+ (void) printf("WW=%lu", Lf->lts.ww);
+ if (Ffield)
+ putchar(Terminator);
+ ps++;
+ }
+ }
+# endif /* defined(HASTCPTPIW) */
+
+ if (!Ffield && ps)
+ putchar(')');
+ if (nl)
+ putchar('\n');
+}
+
+
+/*
+ * process_proc_sock() - process /proc-based socket
+ */
+
+void
+process_proc_sock(p, pbr, s, ss, l, lss)
+ char *p; /* node's readlink() path */
+ char *pbr; /* node's path before readlink() */
+ struct stat *s; /* stat() result for path */
+ int ss; /* *s status -- i.e, SB_* values */
+ struct stat *l; /* lstat() result for FD (NULL for
+ * others) */
+ int lss; /* *l status -- i.e, SB_* values */
+{
+ struct ax25sin *ap;
+ char *cp, *path, tbuf[64];
+ unsigned char *fa, *la;
+ struct in_addr fs, ls;
+ struct icmpin *icmpp;
+ struct ipxsin *ip;
+ int i, len, nl;
+ struct nlksin *np;
+ struct packin *pp;
+ char *pr;
+ static char *prp = (char *)NULL;
+ struct rawsin *rp;
+ struct sctpsin *sp;
+ static ssize_t sz;
+ struct tcp_udp *tp;
+ struct uxsin *up;
+
+#if defined(HASIPv6)
+ int af;
+ struct tcp_udp6 *tp6;
+#endif /* defined(HASIPv6) */
+
+/*
+ * Enter offset, if possible.
+ */
+ if (Foffset || !Fsize) {
+ if (l && (lss & SB_SIZE) && OffType) {
+ Lf->off = (SZOFFTYPE)l->st_size;
+ Lf->off_def = 1;
+ }
+ }
+/*
+ * Check for socket's inode presence in the protocol info caches.
+ */
+ if (AX25path) {
+ (void) get_ax25(AX25path);
+ (void) free((FREE_P *)AX25path);
+ AX25path = (char *)NULL;
+ }
+ if ((ss & SB_INO)
+ && (ap = check_ax25((INODETYPE)s->st_ino))
+ ) {
+
+ /*
+ * The inode is connected to an AX25 /proc record.
+ *
+ * Set the type to "ax25"; save the device name; save the inode number;
+ * save the destination and source addresses; save the send and receive
+ * queue sizes; and save the connection state.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "ax25");
+ if (ap->dev_ch)
+ (void) enter_dev_ch(ap->dev_ch);
+ Lf->inode = ap->inode;
+ Lf->inp_ty = 1;
+ print_ax25info(ap);
+ return;
+ }
+ if (Ipxpath) {
+ (void) get_ipx(Ipxpath);
+ (void) free((FREE_P *)Ipxpath);
+ Ipxpath = (char *)NULL;
+ }
+ if ((ss & SB_INO)
+ && (ip = check_ipx((INODETYPE)s->st_ino))
+ ) {
+
+ /*
+ * The inode is connected to an IPX /proc record.
+ *
+ * Set the type to "ipx"; enter the inode and device numbers; store
+ * the addresses, queue sizes, and state in the NAME column.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "ipx");
+ if (ss & SB_INO) {
+ Lf->inode = (INODETYPE)s->st_ino;
+ Lf->inp_ty = 1;
+ }
+ if (ss & SB_DEV) {
+ Lf->dev = s->st_dev;
+ Lf->dev_def = 1;
+ }
+ cp = Namech;
+ nl = Namechl;
+ *cp = '\0';
+ if (ip->la && nl) {
+
+ /*
+ * Store the local IPX address.
+ */
+ len = strlen(ip->la);
+ if (len > nl)
+ len = nl;
+ (void) strncpy(cp, ip->la, len);
+ cp += len;
+ *cp = '\0';
+ nl -= len;
+ }
+ if (ip->ra && nl) {
+
+ /*
+ * Store the remote IPX address, prefixed with "->".
+ */
+ if (nl > 2) {
+ (void) snpf(cp, nl, "->");
+ cp += 2;
+ nl -= 2;
+ }
+ if (nl) {
+ (void) snpf(cp, nl, "%s", ip->ra);
+ cp += len;
+ nl -= len;
+ }
+ }
+ (void) print_ipxinfo(ip);
+ if (Namech[0])
+ enter_nm(Namech);
+ return;
+ }
+ if (Rawpath) {
+ (void) get_raw(Rawpath);
+ (void) free((FREE_P *)Rawpath);
+ Rawpath = (char *)NULL;
+ }
+ if ((ss & SB_INO)
+ && (rp = check_raw((INODETYPE)s->st_ino))
+ ) {
+
+ /*
+ * The inode is connected to a raw /proc record.
+ *
+ * Set the type to "raw"; enter the inode number; store the local
+ * address, remote address, and state in the NAME column.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "raw");
+ if (ss & SB_INO) {
+ Lf->inode = (INODETYPE)s->st_ino;
+ Lf->inp_ty = 1;
+ }
+ cp = Namech;
+ nl = Namechl - 2;
+ *cp = '\0';
+ if (rp->la && rp->lal) {
+
+ /*
+ * Store the local raw address.
+ */
+ if (nl > rp->lal) {
+ (void) snpf(cp, nl, "%s", rp->la);
+ cp += rp->lal;
+ *cp = '\0';
+ nl -= rp->lal;
+ }
+ }
+ if (rp->ra && rp->ral) {
+
+ /*
+ * Store the remote raw address, prefixed with "->".
+ */
+ if (nl > (rp->ral + 2)) {
+ (void) snpf(cp, nl, "->%s", rp->ra);
+ cp += (rp->ral + 2);
+ *cp = '\0';
+ nl -= (rp->ral + 2);
+ }
+ }
+ if (rp->sp && rp->spl) {
+
+ /*
+ * Store the state, optionally prefixed by a space, in the
+ * form "st=x...x".
+ */
+
+ if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
+ (void) snpf(cp, nl, "%sst=%s",
+ (cp == Namech) ? "" : " ", rp->sp);
+ cp += len;
+ *cp = '\0';
+ nl -= len;
+ }
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+ return;
+ }
+ if (Nlkpath) {
+ (void) get_netlink(Nlkpath);
+ (void) free((FREE_P *) Nlkpath);
+ Nlkpath = (char *)NULL;
+ }
+ if ((ss & SB_INO)
+ && (np = check_netlink((INODETYPE)s->st_ino))
+ ) {
+ /*
+ * The inode is connected to a Netlink /proc record.
+ *
+ * Set the type to "netlink" and store the protocol in the NAME
+ * column. Save the inode number.
+ */
+
+ (void) snpf(Lf->type, sizeof(Lf->type), "netlink");
+ switch (np->pr) {
+
+#if defined(NETLINK_ROUTE)
+ case NETLINK_ROUTE:
+ cp = "ROUTE";
+ break;
+#endif /* defined(NETLINK_ROUTE) */
+
+#if defined(NETLINK_UNUSED)
+ case NETLINK_UNUSED:
+ cp = "UNUSED";
+ break;
+#endif /* defined(NETLINK_UNUSED) */
+
+#if defined(NETLINK_USERSOCK)
+ case NETLINK_USERSOCK:
+ cp = "USERSOCK";
+ break;
+#endif /* defined(NETLINK_USERSOCK) */
+
+#if defined(NETLINK_FIREWALL)
+ case NETLINK_FIREWALL:
+ cp = "FIREWALL";
+ break;
+#endif /* defined(NETLINK_FIREWALL) */
+
+#if defined(NETLINK_INET_DIAG)
+ case NETLINK_INET_DIAG:
+ cp = "INET_DIAG";
+ break;
+#endif /* defined(NETLINK_INET_DIAG) */
+
+#if defined(NETLINK_NFLOG)
+ case NETLINK_NFLOG:
+ cp = "NFLOG";
+ break;
+#endif /* defined(NETLINK_NFLOG) */
+
+#if defined(NETLINK_XFRM)
+ case NETLINK_XFRM:
+ cp = "XFRM";
+ break;
+#endif /* defined(NETLINK_XFRM) */
+
+#if defined(NETLINK_SELINUX)
+ case NETLINK_SELINUX:
+ cp = "SELINUX";
+ break;
+#endif /* defined(NETLINK_SELINUX) */
+
+#if defined(NETLINK_ISCSI)
+ case NETLINK_ISCSI:
+ cp = "ISCSI";
+ break;
+#endif /* defined(NETLINK_ISCSI) */
+
+#if defined(NETLINK_AUDIT)
+ case NETLINK_AUDIT:
+ cp = "AUDIT";
+ break;
+#endif /* defined(NETLINK_AUDIT) */
+
+#if defined(NETLINK_FIB_LOOKUP)
+ case NETLINK_FIB_LOOKUP:
+ cp = "FIB_LOOKUP";
+ break;
+#endif /* defined(NETLINK_FIB_LOOKUP) */
+
+#if defined(NETLINK_CONNECTOR)
+ case NETLINK_CONNECTOR:
+ cp = "CONNECTOR";
+ break;
+#endif /* defined(NETLINK_CONNECTOR) */
+
+#if defined(NETLINK_NETFILTER)
+ case NETLINK_NETFILTER:
+ cp = "NETFILTER";
+ break;
+#endif /* defined(NETLINK_NETFILTER) */
+
+#if defined(NETLINK_IP6_FW)
+ case NETLINK_IP6_FW:
+ cp = "IP6_FW";
+ break;
+#endif /* defined(NETLINK_IP6_FW) */
+
+#if defined(NETLINK_DNRTMSG)
+ case NETLINK_DNRTMSG:
+ cp = "DNRTMSG";
+ break;
+#endif /* defined(NETLINK_DNRTMSG) */
+
+#if defined(NETLINK_KOBJECT_UEVENT)
+ case NETLINK_KOBJECT_UEVENT:
+ cp = "KOBJECT_UEVENT";
+ break;
+#endif /* defined(NETLINK_KOBJECT_UEVENT) */
+
+#if defined(NETLINK_GENERIC)
+ case NETLINK_GENERIC:
+ cp = "GENERIC";
+ break;
+#endif /* defined(NETLINK_GENERIC) */
+
+#if defined(NETLINK_SCSITRANSPORT)
+ case NETLINK_SCSITRANSPORT:
+ cp = "SCSITRANSPORT";
+ break;
+#endif /* defined(NETLINK_SCSITRANSPORT) */
+
+#if defined(NETLINK_ECRYPTFS)
+ case NETLINK_ECRYPTFS:
+ cp = "ECRYPTFS";
+ break;
+#endif /* defined(NETLINK_ECRYPTFS) */
+
+ default:
+ (void) snpf(Namech, Namechl, "unknown protocol: %d", np->pr);
+ cp = (char *)NULL;
+ }
+ if (cp)
+ (void) snpf(Namech, Namechl, "%s", cp);
+ Lf->inode = (INODETYPE)s->st_ino;
+ Lf->inp_ty = 1;
+ if (Namech[0])
+ enter_nm(Namech);
+ return;
+ }
+ if (Packpath) {
+ (void) get_pack(Packpath);
+ (void) free((FREE_P *)Packpath);
+ Packpath = (char *)NULL;
+ }
+ if ((ss & SB_INO)
+ && (pp = check_pack((INODETYPE)s->st_ino))
+ ) {
+
+ /*
+ * The inode is connected to a packet /proc record.
+ *
+ * Set the type to "pack" and store the socket type in the NAME
+ * column. Put the protocol name in the NODE column and the inode
+ * number in the DEVICE column.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "pack");
+ switch(pp->ty) {
+
+#if defined(SOCK_STREAM)
+ case SOCK_STREAM:
+ cp = "STREAM";
+ break;
+#endif /* defined(SOCK_STREAM) */
+
+#if defined(SOCK_DGRAM)
+ case SOCK_DGRAM:
+ cp = "DGRAM";
+ break;
+#endif /* defined(SOCK_DGRAM) */
+
+#if defined(SOCK_RAW)
+ case SOCK_RAW:
+ cp = "RAW";
+ break;
+#endif /* defined(SOCK_RAW) */
+
+#if defined(SOCK_RDM)
+ case SOCK_RDM:
+ cp = "RDM";
+ break;
+#endif /* defined(SOCK_RDM) */
+
+#if defined(SOCK_SEQPACKET)
+ case SOCK_SEQPACKET:
+ cp = "SEQPACKET";
+ break;
+#endif /* defined(SOCK_SEQPACKET) */
+
+#if defined(SOCK_PACKET)
+ case SOCK_PACKET:
+ cp = "PACKET";
+ break;
+#endif /* defined(SOCK_PACKET) */
+
+ default:
+ (void) snpf(Namech, Namechl, "unknown type: %d", pp->ty);
+ cp = (char *)NULL;
+ }
+ if (cp)
+ (void) snpf(Namech, Namechl, "type=SOCK_%s", cp);
+ switch (pp->pr) {
+
+#if defined(ETH_P_LOOP)
+ case ETH_P_LOOP:
+ cp = "LOOP";
+ break;
+#endif /* defined(ETH_P_LOOP) */
+
+#if defined(ETH_P_PUP)
+ case ETH_P_PUP:
+ cp = "PUP";
+ break;
+#endif /* defined(ETH_P_PUP) */
+
+#if defined(ETH_P_PUPAT)
+ case ETH_P_PUPAT:
+ cp = "PUPAT";
+ break;
+#endif /* defined(ETH_P_PUPAT) */
+
+#if defined(ETH_P_IP)
+ case ETH_P_IP:
+ cp = "IP";
+ break;
+#endif /* defined(ETH_P_IP) */
+
+#if defined(ETH_P_X25)
+ case ETH_P_X25:
+ cp = "X25";
+ break;
+#endif /* defined(ETH_P_X25) */
+
+#if defined(ETH_P_ARP)
+ case ETH_P_ARP:
+ cp = "ARP";
+ break;
+#endif /* defined(ETH_P_ARP) */
+
+#if defined(ETH_P_BPQ)
+ case ETH_P_BPQ:
+ cp = "BPQ";
+ break;
+#endif /* defined(ETH_P_BPQ) */
+
+#if defined(ETH_P_IEEEPUP)
+ case ETH_P_IEEEPUP:
+ cp = "I3EPUP";
+ break;
+#endif /* defined(ETH_P_IEEEPUP) */
+
+#if defined(ETH_P_IEEEPUPAT)
+ case ETH_P_IEEEPUPAT:
+ cp = "I3EPUPA";
+ break;
+#endif /* defined(ETH_P_IEEEPUPAT) */
+
+#if defined(ETH_P_DEC)
+ case ETH_P_DEC:
+ cp = "DEC";
+ break;
+#endif /* defined(ETH_P_DEC) */
+
+#if defined(ETH_P_DNA_DL)
+ case ETH_P_DNA_DL:
+ cp = "DNA_DL";
+ break;
+#endif /* defined(ETH_P_DNA_DL) */
+
+#if defined(ETH_P_DNA_RC)
+ case ETH_P_DNA_RC:
+ cp = "DNA_RC";
+ break;
+#endif /* defined(ETH_P_DNA_RC) */
+
+#if defined(ETH_P_DNA_RT)
+ case ETH_P_DNA_RT:
+ cp = "DNA_RT";
+ break;
+#endif /* defined(ETH_P_DNA_RT) */
+
+#if defined(ETH_P_LAT)
+ case ETH_P_LAT:
+ cp = "LAT";
+ break;
+#endif /* defined(ETH_P_LAT) */
+
+#if defined(ETH_P_DIAG)
+ case ETH_P_DIAG:
+ cp = "DIAG";
+ break;
+#endif /* defined(ETH_P_DIAG) */
+
+#if defined(ETH_P_CUST)
+ case ETH_P_CUST:
+ cp = "CUST";
+ break;
+#endif /* defined(ETH_P_CUST) */
+
+#if defined(ETH_P_SCA)
+ case ETH_P_SCA:
+ cp = "SCA";
+ break;
+#endif /* defined(ETH_P_SCA) */
+
+#if defined(ETH_P_RARP)
+ case ETH_P_RARP:
+ cp = "RARP";
+ break;
+#endif /* defined(ETH_P_RARP) */
+
+#if defined(ETH_P_ATALK)
+ case ETH_P_ATALK:
+ cp = "ATALK";
+ break;
+#endif /* defined(ETH_P_ATALK) */
+
+#if defined(ETH_P_AARP)
+ case ETH_P_AARP:
+ cp = "AARP";
+ break;
+#endif /* defined(ETH_P_AARP) */
+
+#if defined(ETH_P_8021Q)
+ case ETH_P_8021Q:
+ cp = "8021Q";
+ break;
+#endif /* defined(ETH_P_8021Q) */
+
+#if defined(ETH_P_IPX)
+ case ETH_P_IPX:
+ cp = "IPX";
+ break;
+#endif /* defined(ETH_P_IPX) */
+
+#if defined(ETH_P_IPV6)
+ case ETH_P_IPV6:
+ cp = "IPV6";
+ break;
+#endif /* defined(ETH_P_IPV6) */
+
+#if defined(ETH_P_SLOW)
+ case ETH_P_SLOW:
+ cp = "SLOW";
+ break;
+#endif /* defined(ETH_P_SLOW) */
+
+#if defined(ETH_P_WCCP)
+ case ETH_P_WCCP:
+ cp = "WCCP";
+ break;
+#endif /* defined(ETH_P_WCCP) */
+
+#if defined(ETH_P_PPP_DISC)
+ case ETH_P_PPP_DISC:
+ cp = "PPP_DIS";
+ break;
+#endif /* defined(ETH_P_PPP_DISC) */
+
+#if defined(ETH_P_PPP_SES)
+ case ETH_P_PPP_SES:
+ cp = "PPP_SES";
+ break;
+#endif /* defined(ETH_P_PPP_SES) */
+
+#if defined(ETH_P_MPLS_UC)
+ case ETH_P_MPLS_UC:
+ cp = "MPLS_UC";
+ break;
+#endif /* defined(ETH_P_MPLS_UC) */
+
+#if defined(ETH_P_ATMMPOA)
+ case ETH_P_ATMMPOA:
+ cp = "ATMMPOA";
+ break;
+#endif /* defined(ETH_P_ATMMPOA) */
+
+#if defined(ETH_P_MPLS_MC)
+ case ETH_P_MPLS_MC:
+ cp = "MPLS_MC";
+ break;
+#endif /* defined(ETH_P_MPLS_MC) */
+
+#if defined(ETH_P_ATMFATE)
+ case ETH_P_ATMFATE:
+ cp = "ATMFATE";
+ break;
+#endif /* defined(ETH_P_ATMFATE) */
+
+#if defined(ETH_P_AOE)
+ case ETH_P_AOE:
+ cp = "AOE";
+ break;
+#endif /* defined(ETH_P_AOE) */
+
+#if defined(ETH_P_TIPC)
+ case ETH_P_TIPC:
+ cp = "TIPC";
+ break;
+#endif /* defined(ETH_P_TIPC) */
+
+#if defined(ETH_P_802_3)
+ case ETH_P_802_3:
+ cp = "802.3";
+ break;
+#endif /* defined(ETH_P_802_3) */
+
+#if defined(ETH_P_AX25)
+ case ETH_P_AX25:
+ cp = "AX25";
+ break;
+#endif /* defined(ETH_P_AX25) */
+
+#if defined(ETH_P_ALL)
+ case ETH_P_ALL:
+ cp = "ALL";
+ break;
+#endif /* defined(ETH_P_ALL) */
+
+#if defined(ETH_P_802_2)
+ case ETH_P_802_2:
+ cp = "802.2";
+ break;
+#endif /* defined(ETH_P_802_2) */
+
+#if defined(ETH_P_SNAP)
+ case ETH_P_SNAP:
+ cp = "SNAP";
+ break;
+#endif /* defined(ETH_P_SNAP) */
+
+#if defined(ETH_P_DDCMP)
+ case ETH_P_DDCMP:
+ cp = "DDCMP";
+ break;
+#endif /* defined(ETH_P_DDCMP) */
+
+#if defined(ETH_P_WAN_PPP)
+ case ETH_P_WAN_PPP:
+ cp = "WAN_PPP";
+ break;
+#endif /* defined(ETH_P_WAN_PPP) */
+
+#if defined(ETH_P_PPP_MP)
+ case ETH_P_PPP_MP:
+ cp = "PPP MP";
+ break;
+#endif /* defined(ETH_P_PPP_MP) */
+
+#if defined(ETH_P_LOCALTALK)
+ case ETH_P_LOCALTALK:
+ cp = "LCLTALK";
+ break;
+#endif /* defined(ETH_P_LOCALTALK) */
+
+#if defined(ETH_P_PPPTALK)
+ case ETH_P_PPPTALK:
+ cp = "PPPTALK";
+ break;
+#endif /* defined(ETH_P_PPPTALK) */
+
+#if defined(ETH_P_TR_802_2)
+ case ETH_P_TR_802_2:
+ cp = "802.2";
+ break;
+#endif /* defined(ETH_P_TR_802_2) */
+
+#if defined(ETH_P_MOBITEX)
+ case ETH_P_MOBITEX:
+ cp = "MOBITEX";
+ break;
+#endif /* defined(ETH_P_MOBITEX) */
+
+#if defined(ETH_P_CONTROL)
+ case ETH_P_CONTROL:
+ cp = "CONTROL";
+ break;
+#endif /* defined(ETH_P_CONTROL) */
+
+#if defined(ETH_P_IRDA)
+ case ETH_P_IRDA:
+ cp = "IRDA";
+ break;
+#endif /* defined(ETH_P_IRDA) */
+
+#if defined(ETH_P_ECONET)
+ case ETH_P_ECONET:
+ cp = "ECONET";
+ break;
+#endif /* defined(ETH_P_ECONET) */
+
+#if defined(ETH_P_HDLC)
+ case ETH_P_HDLC:
+ cp = "HDLC";
+ break;
+#endif /* defined(ETH_P_HDLC) */
+
+#if defined(ETH_P_ARCNET)
+ case ETH_P_ARCNET:
+ cp = "ARCNET";
+ break;
+#endif /* defined(ETH_P_ARCNET) */
+
+ default:
+ (void) snpf(tbuf, sizeof(tbuf) - 1, "%d", pp->pr);
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ cp = tbuf;
+ }
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, cp);
+ Lf->inp_ty = 2;
+ if (ss & SB_INO) {
+ (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
+ (INODETYPE)s->st_ino);
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ enter_dev_ch(tbuf);
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+ return;
+ }
+ if (UNIXpath) {
+ (void) get_unix(UNIXpath);
+ (void) free((FREE_P *)UNIXpath);
+ UNIXpath = (char *)NULL;
+ }
+ if ((ss & SB_INO)
+ && (up = check_unix((INODETYPE)s->st_ino))
+ ) {
+
+ /*
+ * The inode is connected to a UNIX /proc record.
+ *
+ * Set the type to "unix"; enter the PCB address in the DEVICE column;
+ * enter the inode number; and save the optional path.
+ */
+ if (Funix)
+ Lf->sf |= SELUNX;
+ (void) snpf(Lf->type, sizeof(Lf->type), "unix");
+ if (up->pcb)
+ enter_dev_ch(up->pcb);
+ if (ss & SB_INO) {
+ Lf->inode = (INODETYPE)s->st_ino;
+ Lf->inp_ty = 1;
+ }
+ path = up->path ? up->path : p;
+ (void) enter_nm(path);
+ if (Sfile) {
+
+ /*
+ * See if this UNIX domain socket was specified as a search
+ * argument.
+ *
+ * Search first by device and node numbers, if that is possible;
+ * then search by name.
+ */
+ unsigned char f = 0; /* file-found flag */
+
+ if (up->sb_def) {
+
+ /*
+ * If the UNIX socket information includes stat(2) results, do
+ * a device and node number search.
+ *
+ * Note: that requires the saving, temporary modification and
+ * restoration of some *Lf values.
+ */
+ unsigned char sv_dev_def; /* saved dev_def */
+ unsigned char sv_inp_ty; /* saved inp_ty */
+ unsigned char sv_rdev_def; /* saved rdev_def */
+ dev_t sv_dev; /* saved dev */
+ INODETYPE sv_inode; /* saved inode */
+ dev_t sv_rdev; /* saved rdev */
+
+ sv_dev_def = Lf->dev_def;
+ sv_dev = Lf->dev;
+ sv_inode = Lf->inode;
+ sv_inp_ty = Lf->inp_ty;
+ sv_rdev_def = Lf->rdev_def;
+ sv_rdev = Lf->rdev;
+ Lf->dev_def = Lf->inp_ty = Lf->rdev_def = 1;
+ Lf->dev = up->sb_dev;
+ Lf->inode = up->sb_ino;
+ Lf->rdev = up->sb_rdev;
+ if (is_file_named(0, path, (struct mounts *)NULL, 0)) {
+ f = 1;
+ Lf->sf |= SELNM;
+ }
+ Lf->dev_def = sv_dev_def;
+ Lf->dev = sv_dev;
+ Lf->inode = sv_inode;
+ Lf->inp_ty = sv_inp_ty;
+ Lf->rdev_def = sv_rdev_def;
+ Lf->rdev = sv_rdev;
+ }
+ if (!f && (ss & SB_MODE)) {
+
+ /*
+ * If the file has not yet been found and the stat buffer has
+ * st_mode, search for the file by full path.
+ */
+ if (is_file_named(2, path, (struct mounts *)NULL,
+ ((s->st_mode & S_IFMT) == S_IFCHR)) ? 1 : 0)
+ {
+ Lf->sf |= SELNM;
+ }
+ }
+ }
+ return;
+ }
+
+#if defined(HASIPv6)
+ if (Raw6path) {
+ if (!Fxopt)
+ (void) get_raw6(Raw6path);
+ (void) free((FREE_P *)Raw6path);
+ Raw6path = (char *)NULL;
+ }
+ if (!Fxopt && (ss & SB_INO)
+ && (rp = check_raw6((INODETYPE)s->st_ino))
+ ) {
+
+ /*
+ * The inode is connected to a raw IPv6 /proc record.
+ *
+ * Set the type to "raw6"; enter the inode number; store the local
+ * address, remote address, and state in the NAME column.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "raw6");
+ if (ss & SB_INO) {
+ Lf->inode = (INODETYPE)s->st_ino;
+ Lf->inp_ty = 1;
+ }
+ cp = Namech;
+ nl = MAXPATHLEN - 2;
+ if (rp->la && rp->lal) {
+
+ /*
+ * Store the local raw IPv6 address.
+ */
+ if (nl > rp->lal) {
+ (void) snpf(cp, nl, "%s", rp->la);
+ cp += rp->lal;
+ *cp = '\0';
+ nl -= rp->lal;
+ }
+ }
+ if (rp->ra && rp->ral) {
+
+ /*
+ * Store the remote raw address, prefixed with "->".
+ */
+ if (nl > (rp->ral + 2)) {
+ (void) snpf(cp, nl, "->%s", rp->ra);
+ cp += (rp->ral + 2);
+ nl -= (rp->ral + 2);
+ }
+ }
+ if (rp->sp && rp->spl) {
+
+ /*
+ * Store the state, optionally prefixed by a space, in the
+ * form "st=x...x".
+ */
+
+ if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
+ (void) snpf(cp, nl, "%sst=%s",
+ (cp == Namech) ? "" : " ", rp->sp);
+ cp += len;
+ *cp = '\0';
+ nl -= len;
+ }
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+ return;
+ }
+ if (TCP6path) {
+ if (!Fxopt)
+ (void) get_tcpudp6(TCP6path, 0, 1);
+ (void) free((FREE_P *)TCP6path);
+ TCP6path = (char *)NULL;
+ }
+ if (UDP6path) {
+ if (!Fxopt)
+ (void) get_tcpudp6(UDP6path, 1, 0);
+ (void) free((FREE_P *)UDP6path);
+ UDP6path = (char *)NULL;
+ }
+ if (UDPLITE6path) {
+ if (!Fxopt)
+ (void) get_tcpudp6(UDPLITE6path, 2, 0);
+ (void) free((FREE_P *)UDPLITE6path);
+ UDPLITE6path = (char *)NULL;
+ }
+ if (!Fxopt && (ss & SB_INO)
+ && (tp6 = check_tcpudp6((INODETYPE)s->st_ino, &pr))
+ ) {
+
+ /*
+ * The inode is connected to an IPv6 TCP or UDP /proc record.
+ *
+ * Set the type to "IPv6"; enter the protocol; put the inode number
+ * in the DEVICE column in lieu of the PCB address; save the local
+ * and foreign IPv6 addresses; save the type and protocol; and
+ * (optionally) save the queue sizes.
+ */
+ i = tp6->state + TcpStOff;
+ if (TcpStXn) {
+
+ /*
+ * Check for state exclusion.
+ */
+ if (i >= 0 && i < TcpNstates) {
+ if (TcpStX[i]) {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ if (TcpStIn) {
+
+ /*
+ * Check for state inclusion.
+ */
+ if (i >= 0 && i < TcpNstates) {
+ if (TcpStI[i])
+ TcpStI[i] = 2;
+ else {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ if (Fnet && (FnetTy != 4))
+ Lf->sf |= SELNET;
+ (void) snpf(Lf->type, sizeof(Lf->type), "IPv6");
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
+ Lf->inp_ty = 2;
+ if (ss & SB_INO) {
+ (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
+ (INODETYPE)s->st_ino);
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ enter_dev_ch(tbuf);
+ }
+ af = AF_INET6;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->faddr) || tp6->fport)
+ fa = (unsigned char *)&tp6->faddr;
+ else
+ fa = (unsigned char *)NULL;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->laddr) || tp6->lport)
+ la = (unsigned char *)&tp6->laddr;
+ else
+ la = (unsigned char *)NULL;
+ if ((fa && IN6_IS_ADDR_V4MAPPED(&tp6->faddr))
+ || (la && IN6_IS_ADDR_V4MAPPED(&tp6->laddr))) {
+ af = AF_INET;
+ if (fa)
+ fa += 12;
+ if (la)
+ la += 12;
+ }
+ ent_inaddr(la, tp6->lport, fa, tp6->fport, af);
+ Lf->lts.type = tp6->proto;
+ Lf->lts.state.i = tp6->state;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = tp6->rxq;
+ Lf->lts.sq = tp6->txq;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+ return;
+ }
+#endif /* defined(HASIPv6) */
+
+ if (TCPpath) {
+ if (!Fxopt)
+ (void) get_tcpudp(TCPpath, 0, 1);
+ (void) free((FREE_P *)TCPpath);
+ TCPpath = (char *)NULL;
+ }
+ if (UDPpath) {
+ if (!Fxopt)
+ (void) get_tcpudp(UDPpath, 1, 0);
+ (void) free((FREE_P *)UDPpath);
+ UDPpath = (char *)NULL;
+ }
+ if (UDPLITEpath) {
+ if (!Fxopt)
+ (void) get_tcpudp(UDPLITEpath, 2, 0);
+ (void) free((FREE_P *)UDPLITEpath);
+ UDPLITEpath = (char *)NULL;
+ }
+ if (!Fxopt && (ss & SB_INO)
+ && (tp = check_tcpudp((INODETYPE)s->st_ino, &pr))
+ ) {
+
+ /*
+ * The inode is connected to an IPv4 TCP or UDP /proc record.
+ *
+ * Set the type to "inet" or "IPv4"; enter the protocol; put the
+ * inode number in the DEVICE column in lieu of the PCB address;
+ * save the local and foreign IPv4 addresses; save the type and
+ * protocol; and (optionally) save the queue sizes.
+ */
+ i = tp->state + TcpStOff;
+ if (TcpStXn) {
+
+ /*
+ * Check for state exclusion.
+ */
+ if (i >= 0 && i < TcpNstates) {
+ if (TcpStX[i]) {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ if (TcpStIn) {
+
+ /*
+ * Check for state inclusion.
+ */
+ if (i >= 0 && i < TcpNstates) {
+ if (TcpStI[i])
+ TcpStI[i] = 2;
+ else {
+ Lf->sf |= SELEXCLF;
+ return;
+ }
+ }
+ }
+ if (Fnet && (FnetTy != 6))
+ Lf->sf |= SELNET;
+
+#if defined(HASIPv6)
+ (void) snpf(Lf->type, sizeof(Lf->type), "IPv4");
+#else /* !defined(HASIPv6) */
+ (void) snpf(Lf->type, sizeof(Lf->type), "inet");
+#endif /* defined(HASIPv6) */
+
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
+ Lf->inp_ty = 2;
+ if (ss & SB_INO) {
+ (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
+ (INODETYPE)s->st_ino);
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ enter_dev_ch(tbuf);
+ }
+ if (tp->faddr || tp->fport) {
+ fs.s_addr = tp->faddr;
+ fa = (unsigned char *)&fs;
+ } else
+ fa = (unsigned char *)NULL;
+ if (tp->laddr || tp->lport) {
+ ls.s_addr = tp->laddr;
+ la = (unsigned char *)&ls;
+ } else
+ la = (unsigned char *)NULL;
+ ent_inaddr(la, tp->lport, fa, tp->fport, AF_INET);
+ Lf->lts.type = tp->proto;
+ Lf->lts.state.i = tp->state;
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rq = tp->rxq;
+ Lf->lts.sq = tp->txq;
+ Lf->lts.rqs = Lf->lts.sqs = 1;
+#endif /* defined(HASTCPTPIQ) */
+
+ return;
+ }
+ if (SCTPPath[0]) {
+ (void) get_sctp();
+ for (i = 0; i < NSCTPPATHS; i++) {
+ (void) free((FREE_P *)SCTPPath[i]);
+ SCTPPath[i] = (char *)NULL;
+ }
+ }
+ if ((ss & SB_INO) && (sp = check_sctp((INODETYPE)s->st_ino))
+ ) {
+
+ /*
+ * The inode is connected to an SCTP /proc record.
+ *
+ * Set the type to "sock"; enter the inode number in the DEVICE
+ * column; set the protocol to SCTP; and fill in the NAME column
+ * with ASSOC, ASSOC-ID, ENDPT, LADDRS, LPORT, RADDRS and RPORT.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1,
+ "SCTP");
+ Lf->inp_ty = 2;
+ (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d, (INODETYPE)s->st_ino);
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ enter_dev_ch(tbuf);
+ Namech[0] = '\0';
+ if (sp->type == 1) {
+
+ /*
+ * This is an ENDPT SCTP file.
+ */
+ (void) snpf(Namech, Namechl,
+ "ENDPT: %s%s%s%s%s%s",
+ sp->addr ? sp->addr : "",
+ (sp->laddrs || sp->lport) ? " " : "",
+ sp->laddrs ? sp->laddrs : "",
+ sp->lport ? "[" : "",
+ sp->lport ? sp->lport : "",
+ sp->lport ? "]" : ""
+ );
+ } else {
+
+ /*
+ * This is an ASSOC, or ASSOC and ENDPT socket file.
+ */
+ (void) snpf(Namech, Namechl,
+ "%s: %s%s%s %s%s%s%s%s%s%s%s%s",
+ sp->type ? "ASSOC+ENDPT" : "ASSOC",
+ sp->addr ? sp->addr : "",
+ (sp->addr && sp->assocID) ? "," : "",
+ sp->assocID ? sp->assocID : "",
+ sp->laddrs ? sp->laddrs : "",
+ sp->lport ? "[" : "",
+ sp->lport ? sp->lport : "",
+ sp->lport ? "]" : "",
+ ((sp->laddrs || sp->lport) && (sp->raddrs || sp->rport))
+ ? "<->" : "",
+ sp->raddrs ? sp->raddrs : "",
+ sp->rport ? "[" : "",
+ sp->rport ? sp->rport : "",
+ sp->rport ? "]" : ""
+ );
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+ return;
+ }
+ if (ICMPpath) {
+ (void) get_icmp(ICMPpath);
+ (void) free((FREE_P *)ICMPpath);
+ ICMPpath = (char *)NULL;
+ }
+ if ((ss & SB_INO)
+ && (icmpp = check_icmp((INODETYPE)s->st_ino))
+ ) {
+
+ /*
+ * The inode is connected to an ICMP /proc record.
+ *
+ * Set the type to "icmp" and store the type in the NAME
+ * column. Save the inode number.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "icmp");
+ Lf->inode = (INODETYPE)s->st_ino;
+ Lf->inp_ty = 1;
+ cp = Namech;
+ nl = Namechl- 2;
+ *cp = '\0';
+ if (icmpp->la && icmpp->lal) {
+
+ /*
+ * Store the local raw address.
+ */
+ if (nl > icmpp->lal) {
+ (void) snpf(cp, nl, "%s", icmpp->la);
+ cp += icmpp->lal;
+ *cp = '\0';
+ nl -= icmpp->lal;
+ }
+ }
+ if (icmpp->ra && icmpp->ral) {
+
+ /*
+ * Store the remote raw address, prefixed with "->".
+ */
+ if (nl > (icmpp->ral + 2)) {
+ (void) snpf(cp, nl, "->%s", icmpp->ra);
+ cp += (icmpp->ral + 2);
+ *cp = '\0';
+ nl -= (icmpp->ral + 2);
+ }
+ }
+ if (Namech[0])
+ enter_nm(Namech);
+ return;
+ }
+/*
+ * The socket's protocol can't be identified.
+ */
+ (void) snpf(Lf->type, sizeof(Lf->type), "sock");
+ if (ss & SB_INO) {
+ Lf->inode = (INODETYPE)s->st_ino;
+ Lf->inp_ty = 1;
+ }
+ if (ss & SB_DEV) {
+ Lf->dev = s->st_dev;
+ Lf->dev_def = 1;
+ }
+ if (Fxopt)
+ enter_nm("can't identify protocol (-X specified)");
+ else {
+ (void) snpf(Namech, Namechl, "protocol: ");
+ if (!prp) {
+ i = (int)strlen(Namech);
+ prp = &Namech[i];
+ sz = (ssize_t)(Namechl - i - 1);
+ }
+ if ((getxattr(pbr, "system.sockprotoname", prp, sz)) < 0)
+ enter_nm("can't identify protocol");
+ else
+ enter_nm(Namech);
+ }
+}
+
+
+/*
+ * set_net_paths() - set /proc/net paths
+ */
+
+void
+set_net_paths(p, pl)
+ char *p; /* path to /proc/net/ */
+ int pl; /* strlen(p) */
+{
+ int i;
+ int pathl;
+
+ pathl = 0;
+ (void) make_proc_path(p, pl, &AX25path, &pathl, "ax25");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &ICMPpath, &pathl, "icmp");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &Ipxpath, &pathl, "ipx");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &Nlkpath, &pathl, "netlink");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &Packpath, &pathl, "packet");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &Rawpath, &pathl, "raw");
+ for (i = 0; i < NSCTPPATHS; i++) {
+ pathl = 0;
+ (void) make_proc_path(p, pl, &SCTPPath[i], &pathl, SCTPSfx[i]);
+ }
+ pathl = 0;
+ (void) make_proc_path(p, pl, &SockStatPath, &pathl, "sockstat");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &TCPpath, &pathl, "tcp");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &UDPpath, &pathl, "udp");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &UDPLITEpath, &pathl, "udplite");
+
+#if defined(HASIPv6)
+ pathl = 0;
+ (void) make_proc_path(p, pl, &Raw6path, &pathl, "raw6");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &SockStatPath6, &pathl, "sockstat6");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &TCP6path, &pathl, "tcp6");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &UDP6path, &pathl, "udp6");
+ pathl = 0;
+ (void) make_proc_path(p, pl, &UDPLITE6path, &pathl, "udplite6");
+#endif /* defined(HASIPv6) */
+
+ pathl = 0;
+ (void) make_proc_path(p, pl, &UNIXpath, &pathl, "unix");
+}