[Midnightbsd-cvs] src [11421] trunk/usr.bin/sockstat/sockstat.c: sync sockstat with freebsd

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Jul 6 22:39:35 EDT 2018


Revision: 11421
          http://svnweb.midnightbsd.org/src/?rev=11421
Author:   laffer1
Date:     2018-07-06 22:39:35 -0400 (Fri, 06 Jul 2018)
Log Message:
-----------
sync sockstat with freebsd

Modified Paths:
--------------
    trunk/usr.bin/sockstat/Makefile
    trunk/usr.bin/sockstat/sockstat.1
    trunk/usr.bin/sockstat/sockstat.c

Property Changed:
----------------
    trunk/usr.bin/sockstat/sockstat.1

Modified: trunk/usr.bin/sockstat/Makefile
===================================================================
--- trunk/usr.bin/sockstat/Makefile	2018-07-07 02:39:00 UTC (rev 11420)
+++ trunk/usr.bin/sockstat/Makefile	2018-07-07 02:39:35 UTC (rev 11421)
@@ -1,4 +1,5 @@
 # $MidnightBSD$
+# $FreeBSD: stable/10/usr.bin/sockstat/Makefile 201386 2010-01-02 10:27:05Z ed $
 
 PROG=		sockstat
 

Modified: trunk/usr.bin/sockstat/sockstat.1
===================================================================
--- trunk/usr.bin/sockstat/sockstat.1	2018-07-07 02:39:00 UTC (rev 11420)
+++ trunk/usr.bin/sockstat/sockstat.1	2018-07-07 02:39:35 UTC (rev 11421)
@@ -1,5 +1,6 @@
+.\" $MidnightBSD$
 .\"-
-.\" Copyright (c) 1999 Dag-Erling Co\xEFdan Sm\xF8rgrav
+.\" Copyright (c) 1999 Dag-Erling Coïdan Smørgrav
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -25,9 +26,9 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $MidnightBSD$
+.\" $FreeBSD: stable/10/usr.bin/sockstat/sockstat.1 294231 2016-01-17 18:37:36Z tuexen $
 .\"
-.Dd May 16, 2012
+.Dd August 27, 2015
 .Dt SOCKSTAT 1
 .Os
 .Sh NAME
@@ -35,7 +36,7 @@
 .Nd list open sockets
 .Sh SYNOPSIS
 .Nm
-.Op Fl 46cLlu
+.Op Fl 46cLlsu
 .Op Fl j Ar jid
 .Op Fl p Ar ports
 .Op Fl P Ar protocols
@@ -61,7 +62,7 @@
 .It Fl j Ar jid
 Show only sockets belonging to the specified jail ID.
 .It Fl L
-Only show Internet sockets if the local or foreign addresses are not
+Only show Internet sockets if the local and foreign addresses are not
 in the loopback network prefix
 .Li 127.0.0.0/8 ,
 or do not contain the IPv6 loopback address
@@ -69,7 +70,7 @@
 .It Fl l
 Show listening sockets.
 .It Fl p Ar ports
-Only show Internet sockets if either the local or foreign port number
+Only show Internet sockets if the local or foreign port number
 is on the specified list.
 The
 .Ar ports
@@ -83,6 +84,9 @@
 argument is a comma-separated list of protocol names,
 as they are defined in
 .Xr protocols 5 .
+.It Fl s
+Display the protocol state, if applicable.
+This is currently only implemented for SCTP and TCP.
 .It Fl u
 Show
 .Dv AF_LOCAL
@@ -119,7 +123,9 @@
 The file descriptor number of the socket.
 .It Li PROTO
 The transport protocol associated with the socket for Internet
-sockets, or the type of socket (stream or datagram) for
+sockets, or the type of socket
+.Pq stream, datagram, or seqpacket
+for
 .Ux
 sockets.
 .It Li LOCAL ADDRESS


Property changes on: trunk/usr.bin/sockstat/sockstat.1
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/usr.bin/sockstat/sockstat.c
===================================================================
--- trunk/usr.bin/sockstat/sockstat.c	2018-07-07 02:39:00 UTC (rev 11420)
+++ trunk/usr.bin/sockstat/sockstat.c	2018-07-07 02:39:35 UTC (rev 11421)
@@ -1,5 +1,6 @@
+/* $MidnightBSD$ */
 /*-
- * Copyright (c) 2002 Dag-Erling Co\xEFdan Sm\xF8rgrav
+ * Copyright (c) 2002 Dag-Erling Coïdan Smørgrav
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/usr.bin/sockstat/sockstat.c 294232 2016-01-17 18:39:01Z tuexen $");
 
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -43,7 +44,10 @@
 
 #include <netinet/in.h>
 #include <netinet/in_pcb.h>
+#include <netinet/sctp.h>
 #include <netinet/tcp.h>
+#define TCPSTATES /* load state names */
+#include <netinet/tcp_fsm.h>
 #include <netinet/tcp_seq.h>
 #include <netinet/tcp_var.h>
 #include <arpa/inet.h>
@@ -59,6 +63,11 @@
 #include <string.h>
 #include <unistd.h>
 
+#define	sstosin(ss)	((struct sockaddr_in *)(ss))
+#define	sstosin6(ss)	((struct sockaddr_in6 *)(ss))
+#define	sstosun(ss)	((struct sockaddr_un *)(ss))
+#define	sstosa(ss)	((struct sockaddr *)(ss))
+
 static int	 opt_4;		/* Show IPv4 sockets */
 static int	 opt_6;		/* Show IPv6 sockets */
 static int	 opt_c;		/* Show connected sockets */
@@ -65,6 +74,7 @@
 static int	 opt_j;		/* Show specified jail */
 static int	 opt_L;		/* Don't show IPv4 or IPv6 loopback sockets */
 static int	 opt_l;		/* Show listening sockets */
+static int	 opt_s;		/* Show protocol state if applicable */
 static int	 opt_u;		/* Show Unix domain sockets */
 static int	 opt_v;		/* Verbose mode */
 
@@ -71,9 +81,8 @@
 /*
  * Default protocols to use if no -P was defined.
  */
-static const char *default_protos[] = {"tcp", "udp", "divert" };
-static size_t	   default_numprotos =
-    sizeof(default_protos) / sizeof(default_protos[0]);
+static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" };
+static size_t	   default_numprotos = nitems(default_protos);
 
 static int	*protos;	/* protocols to use */
 static size_t	 numprotos;	/* allocated size of protos[] */
@@ -84,6 +93,11 @@
 #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0)
 #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT)))
 
+struct addr {
+	struct sockaddr_storage address;
+	struct addr *next;
+};
+
 struct sock {
 	void *socket;
 	void *pcb;
@@ -91,9 +105,10 @@
 	int vflag;
 	int family;
 	int proto;
+	int state;
 	const char *protoname;
-	struct sockaddr_storage laddr;
-	struct sockaddr_storage faddr;
+	struct addr *laddr;
+	struct addr *faddr;
 	struct sock *next;
 };
 
@@ -134,7 +149,8 @@
 }
 
 
-static void init_protos(int num)
+static void
+init_protos(int num)
 {
 	int proto_count = 0;
 
@@ -157,7 +173,6 @@
 parse_protos(char *protospec)
 {
 	char *prot;
-	char *tmp = protospec;
 	int proto_type, proto_index;
 
 	if (protospec == NULL)
@@ -165,7 +180,7 @@
 
 	init_protos(0);
 	proto_index = 0;
-	while ((prot = strsep(&tmp, ",")) != NULL) {
+	while ((prot = strsep(&protospec, ",")) != NULL) {
 		if (strlen(prot) == 0)
 			continue;
 		proto_type = get_proto_type(prot);
@@ -222,26 +237,32 @@
 }
 
 static void
-sockaddr(struct sockaddr_storage *sa, int af, void *addr, int port)
+sockaddr(struct sockaddr_storage *ss, int af, void *addr, int port)
 {
 	struct sockaddr_in *sin4;
 	struct sockaddr_in6 *sin6;
 
-	bzero(sa, sizeof *sa);
+	bzero(ss, sizeof(*ss));
 	switch (af) {
 	case AF_INET:
-		sin4 = (struct sockaddr_in *)sa;
-		sin4->sin_len = sizeof *sin4;
+		sin4 = sstosin(ss);
+		sin4->sin_len = sizeof(*sin4);
 		sin4->sin_family = af;
 		sin4->sin_port = port;
 		sin4->sin_addr = *(struct in_addr *)addr;
 		break;
 	case AF_INET6:
-		sin6 = (struct sockaddr_in6 *)sa;
-		sin6->sin6_len = sizeof *sin6;
+		sin6 = sstosin6(ss);
+		sin6->sin6_len = sizeof(*sin6);
 		sin6->sin6_family = af;
 		sin6->sin6_port = port;
 		sin6->sin6_addr = *(struct in6_addr *)addr;
+#define	s6_addr16	__u6_addr.__u6_addr16
+		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+			sin6->sin6_scope_id =
+			    ntohs(sin6->sin6_addr.s6_addr16[1]);
+			sin6->sin6_addr.s6_addr16[1] = 0;
+		}
 		break;
 	default:
 		abort();
@@ -249,6 +270,272 @@
 }
 
 static void
+free_socket(struct sock *sock)
+{
+	struct addr *cur, *next;
+
+	cur = sock->laddr;
+	while (cur != NULL) {
+		next = cur->next;
+		free(cur);
+		cur = next;
+	}
+	cur = sock->faddr;
+	while (cur != NULL) {
+		next = cur->next;
+		free(cur);
+		cur = next;
+	}
+	free(sock);
+}
+
+static void
+gather_sctp(void)
+{
+	struct sock *sock;
+	struct addr *laddr, *prev_laddr, *faddr, *prev_faddr;
+	struct xsctp_inpcb *xinpcb;
+	struct xsctp_tcb *xstcb;
+	struct xsctp_raddr *xraddr;
+	struct xsctp_laddr *xladdr;
+	const char *varname;
+	size_t len, offset;
+	char *buf;
+	int hash, vflag;
+	int no_stcb, local_all_loopback, foreign_all_loopback;
+
+	vflag = 0;
+	if (opt_4)
+		vflag |= INP_IPV4;
+	if (opt_6)
+		vflag |= INP_IPV6;
+
+	varname = "net.inet.sctp.assoclist";
+	if (sysctlbyname(varname, 0, &len, 0, 0) < 0) {
+		if (errno != ENOENT)
+			err(1, "sysctlbyname()");
+		return;
+	}
+	if ((buf = (char *)malloc(len)) == NULL) {
+		err(1, "malloc()");
+		return;
+	}
+	if (sysctlbyname(varname, buf, &len, 0, 0) < 0) {
+		err(1, "sysctlbyname()");
+		free(buf);
+		return;
+	}
+	xinpcb = (struct xsctp_inpcb *)(void *)buf;
+	offset = sizeof(struct xsctp_inpcb);
+	while ((offset < len) && (xinpcb->last == 0)) {
+		if ((sock = calloc(1, sizeof *sock)) == NULL)
+			err(1, "malloc()");
+		sock->socket = xinpcb->socket;
+		sock->proto = IPPROTO_SCTP;
+		sock->protoname = "sctp";
+		if (xinpcb->maxqlen == 0)
+			sock->state = SCTP_CLOSED;
+		else
+			sock->state = SCTP_LISTEN;
+		if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
+			sock->family = AF_INET6;
+			sock->vflag = INP_IPV6;
+		} else {
+			sock->family = AF_INET;
+			sock->vflag = INP_IPV4;
+		}
+		prev_laddr = NULL;
+		local_all_loopback = 1;
+		while (offset < len) {
+			xladdr = (struct xsctp_laddr *)(void *)(buf + offset);
+			offset += sizeof(struct xsctp_laddr);
+			if (xladdr->last == 1)
+				break;
+			if ((laddr = calloc(1, sizeof(struct addr))) == NULL)
+				err(1, "malloc()");
+			switch (xladdr->address.sa.sa_family) {
+			case AF_INET:
+#define __IN_IS_ADDR_LOOPBACK(pina) \
+	((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+				if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr))
+					local_all_loopback = 0;
+#undef __IN_IS_ADDR_LOOPBACK
+				sockaddr(&laddr->address,
+				         AF_INET,
+				         &xladdr->address.sin.sin_addr,
+				         htons(xinpcb->local_port));
+				break;
+			case AF_INET6:
+				if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr))
+					local_all_loopback = 0;
+				sockaddr(&laddr->address,
+				         AF_INET6,
+				         &xladdr->address.sin6.sin6_addr,
+				         htons(xinpcb->local_port));
+				break;
+			default:
+				errx(1, "address family %d not supported",
+				     xladdr->address.sa.sa_family);
+			}
+			laddr->next = NULL;
+			if (prev_laddr == NULL)
+				sock->laddr = laddr;
+			else
+				prev_laddr->next = laddr;
+			prev_laddr = laddr;
+		}
+		if (sock->laddr == NULL) {
+			if ((sock->laddr = calloc(1, sizeof(struct addr))) == NULL)
+				err(1, "malloc()");
+			sock->laddr->address.ss_family = sock->family;
+			if (sock->family == AF_INET)
+				sock->laddr->address.ss_len = sizeof(struct sockaddr_in);
+			else
+				sock->laddr->address.ss_len = sizeof(struct sockaddr_in);
+			local_all_loopback = 0;
+		}
+		if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL)
+			err(1, "malloc()");
+		sock->faddr->address.ss_family = sock->family;
+		if (sock->family == AF_INET)
+			sock->faddr->address.ss_len = sizeof(struct sockaddr_in);
+		else
+			sock->faddr->address.ss_len = sizeof(struct sockaddr_in);
+		no_stcb = 1;
+		while (offset < len) {
+			xstcb = (struct xsctp_tcb *)(void *)(buf + offset);
+			offset += sizeof(struct xsctp_tcb);
+			if (no_stcb) {
+				if (opt_l &&
+				    (!opt_L || !local_all_loopback) &&
+				    ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) ||
+				     (xstcb->last == 1))) {
+					hash = (int)((uintptr_t)sock->socket % HASHSIZE);
+					sock->next = sockhash[hash];
+					sockhash[hash] = sock;
+				} else {
+					free_socket(sock);
+				}
+			}
+			if (xstcb->last == 1)
+				break;
+			no_stcb = 0;
+			if (opt_c) {
+				if ((sock = calloc(1, sizeof *sock)) == NULL)
+					err(1, "malloc()");
+				sock->socket = xinpcb->socket;
+				sock->proto = IPPROTO_SCTP;
+				sock->protoname = "sctp";
+				sock->state = (int)xstcb->state;
+				if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
+					sock->family = AF_INET6;
+					sock->vflag = INP_IPV6;
+				} else {
+					sock->family = AF_INET;
+					sock->vflag = INP_IPV4;
+				}
+			}
+			prev_laddr = NULL;
+			local_all_loopback = 1;
+			while (offset < len) {
+				xladdr = (struct xsctp_laddr *)(void *)(buf + offset);
+				offset += sizeof(struct xsctp_laddr);
+				if (xladdr->last == 1)
+					break;
+				if (!opt_c)
+					continue;
+				if ((laddr = calloc(1, sizeof(struct addr))) == NULL)
+					err(1, "malloc()");
+				switch (xladdr->address.sa.sa_family) {
+				case AF_INET:
+#define __IN_IS_ADDR_LOOPBACK(pina) \
+	((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+					if (!__IN_IS_ADDR_LOOPBACK(&xladdr->address.sin.sin_addr))
+						local_all_loopback = 0;
+#undef __IN_IS_ADDR_LOOPBACK
+					sockaddr(&laddr->address,
+						 AF_INET,
+						 &xladdr->address.sin.sin_addr,
+						 htons(xstcb->local_port));
+					break;
+				case AF_INET6:
+					if (!IN6_IS_ADDR_LOOPBACK(&xladdr->address.sin6.sin6_addr))
+						local_all_loopback = 0;
+					sockaddr(&laddr->address,
+						 AF_INET6,
+						 &xladdr->address.sin6.sin6_addr,
+						 htons(xstcb->local_port));
+					break;
+				default:
+					errx(1, "address family %d not supported",
+					     xladdr->address.sa.sa_family);
+				}
+				laddr->next = NULL;
+				if (prev_laddr == NULL)
+					sock->laddr = laddr;
+				else
+					prev_laddr->next = laddr;
+				prev_laddr = laddr;
+			}
+			prev_faddr = NULL;
+			foreign_all_loopback = 1;
+			while (offset < len) {
+				xraddr = (struct xsctp_raddr *)(void *)(buf + offset);
+				offset += sizeof(struct xsctp_raddr);
+				if (xraddr->last == 1)
+					break;
+				if (!opt_c)
+					continue;
+				if ((faddr = calloc(1, sizeof(struct addr))) == NULL)
+					err(1, "malloc()");
+				switch (xraddr->address.sa.sa_family) {
+				case AF_INET:
+#define __IN_IS_ADDR_LOOPBACK(pina) \
+	((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+					if (!__IN_IS_ADDR_LOOPBACK(&xraddr->address.sin.sin_addr))
+						foreign_all_loopback = 0;
+#undef __IN_IS_ADDR_LOOPBACK
+					sockaddr(&faddr->address,
+						 AF_INET,
+						 &xraddr->address.sin.sin_addr,
+						 htons(xstcb->remote_port));
+					break;
+				case AF_INET6:
+					if (!IN6_IS_ADDR_LOOPBACK(&xraddr->address.sin6.sin6_addr))
+						foreign_all_loopback = 0;
+					sockaddr(&faddr->address,
+						 AF_INET6,
+						 &xraddr->address.sin6.sin6_addr,
+						 htons(xstcb->remote_port));
+					break;
+				default:
+					errx(1, "address family %d not supported",
+					     xraddr->address.sa.sa_family);
+				}
+				faddr->next = NULL;
+				if (prev_faddr == NULL)
+					sock->faddr = faddr;
+				else
+					prev_faddr->next = faddr;
+				prev_faddr = faddr;
+			}
+			if (opt_c) {
+				if (!opt_L || !(local_all_loopback || foreign_all_loopback)) {
+					hash = (int)((uintptr_t)sock->socket % HASHSIZE);
+					sock->next = sockhash[hash];
+					sockhash[hash] = sock;
+				} else {
+					free_socket(sock);
+				}
+			}
+		}
+		xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset);
+		offset += sizeof(struct xsctp_inpcb);
+	}
+	free(buf);
+}
+
+static void
 gather_inet(int proto)
 {
 	struct xinpgen *xig, *exig;
@@ -257,6 +544,7 @@
 	struct inpcb *inp;
 	struct xsocket *so;
 	struct sock *sock;
+	struct addr *laddr, *faddr;
 	const char *varname, *protoname;
 	size_t len, bufsize;
 	void *buf;
@@ -316,10 +604,11 @@
 		xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
 		if (xig >= exig)
 			break;
+		xip = (struct xinpcb *)xig;
+		xtp = (struct xtcpcb *)xig;
 		switch (proto) {
 		case IPPROTO_TCP:
-			xtp = (struct xtcpcb *)xig;
-			if (xtp->xt_len != sizeof *xtp) {
+			if (xtp->xt_len != sizeof(*xtp)) {
 				warnx("struct xtcpcb size mismatch");
 				goto out;
 			}
@@ -329,8 +618,7 @@
 			break;
 		case IPPROTO_UDP:
 		case IPPROTO_DIVERT:
-			xip = (struct xinpcb *)xig;
-			if (xip->xi_len != sizeof *xip) {
+			if (xip->xi_len != sizeof(*xip)) {
 				warnx("struct xinpcb size mismatch");
 				goto out;
 			}
@@ -366,24 +654,34 @@
 				warnx("invalid vflag 0x%x", inp->inp_vflag);
 			continue;
 		}
-		if ((sock = calloc(1, sizeof *sock)) == NULL)
+		if ((sock = calloc(1, sizeof(*sock))) == NULL)
 			err(1, "malloc()");
+		if ((laddr = calloc(1, sizeof *laddr)) == NULL)
+			err(1, "malloc()");
+		if ((faddr = calloc(1, sizeof *faddr)) == NULL)
+			err(1, "malloc()");
 		sock->socket = so->xso_so;
 		sock->proto = proto;
 		if (inp->inp_vflag & INP_IPV4) {
 			sock->family = AF_INET;
-			sockaddr(&sock->laddr, sock->family,
+			sockaddr(&laddr->address, sock->family,
 			    &inp->inp_laddr, inp->inp_lport);
-			sockaddr(&sock->faddr, sock->family,
+			sockaddr(&faddr->address, sock->family,
 			    &inp->inp_faddr, inp->inp_fport);
 		} else if (inp->inp_vflag & INP_IPV6) {
 			sock->family = AF_INET6;
-			sockaddr(&sock->laddr, sock->family,
+			sockaddr(&laddr->address, sock->family,
 			    &inp->in6p_laddr, inp->inp_lport);
-			sockaddr(&sock->faddr, sock->family,
+			sockaddr(&faddr->address, sock->family,
 			    &inp->in6p_faddr, inp->inp_fport);
 		}
+		laddr->next = NULL;
+		faddr->next = NULL;
+		sock->laddr = laddr;
+		sock->faddr = faddr;
 		sock->vflag = inp->inp_vflag;
+		if (proto == IPPROTO_TCP)
+			sock->state = xtp->xt_tp.t_state;
 		sock->protoname = protoname;
 		hash = (int)((uintptr_t)sock->socket % HASHSIZE);
 		sock->next = sockhash[hash];
@@ -399,6 +697,7 @@
 	struct xunpgen *xug, *exug;
 	struct xunpcb *xup;
 	struct sock *sock;
+	struct addr *laddr, *faddr;
 	const char *varname, *protoname;
 	size_t len, bufsize;
 	void *buf;
@@ -413,6 +712,10 @@
 		varname = "net.local.dgram.pcblist";
 		protoname = "dgram";
 		break;
+	case SOCK_SEQPACKET:
+		varname = "net.local.seqpacket.pcblist";
+		protoname = "seqpac";
+		break;
 	default:
 		abort();
 	}
@@ -432,9 +735,9 @@
 		}
 		xug = (struct xunpgen *)buf;
 		exug = (struct xunpgen *)(void *)
-		    ((char *)buf + len - sizeof *exug);
-		if (xug->xug_len != sizeof *xug ||
-		    exug->xug_len != sizeof *exug) {
+		    ((char *)buf + len - sizeof(*exug));
+		if (xug->xug_len != sizeof(*xug) ||
+		    exug->xug_len != sizeof(*exug)) {
 			warnx("struct xinpgen size mismatch");
 			goto out;
 		}
@@ -448,7 +751,7 @@
 		if (xug >= exug)
 			break;
 		xup = (struct xunpcb *)xug;
-		if (xup->xu_len != sizeof *xup) {
+		if (xup->xu_len != sizeof(*xup)) {
 			warnx("struct xunpcb size mismatch");
 			goto out;
 		}
@@ -455,8 +758,12 @@
 		if ((xup->xu_unp.unp_conn == NULL && !opt_l) ||
 		    (xup->xu_unp.unp_conn != NULL && !opt_c))
 			continue;
-		if ((sock = calloc(1, sizeof *sock)) == NULL)
+		if ((sock = calloc(1, sizeof(*sock))) == NULL)
 			err(1, "malloc()");
+		if ((laddr = calloc(1, sizeof *laddr)) == NULL)
+			err(1, "malloc()");
+		if ((faddr = calloc(1, sizeof *faddr)) == NULL)
+			err(1, "malloc()");
 		sock->socket = xup->xu_socket.xso_so;
 		sock->pcb = xup->xu_unpp;
 		sock->proto = proto;
@@ -463,10 +770,14 @@
 		sock->family = AF_UNIX;
 		sock->protoname = protoname;
 		if (xup->xu_unp.unp_addr != NULL)
-			sock->laddr =
+			laddr->address =
 			    *(struct sockaddr_storage *)(void *)&xup->xu_addr;
 		else if (xup->xu_unp.unp_conn != NULL)
-			*(void **)&sock->faddr = xup->xu_unp.unp_conn;
+			*(void **)&(faddr->address) = xup->xu_unp.unp_conn;
+		laddr->next = NULL;
+		faddr->next = NULL;
+		sock->laddr = laddr;
+		sock->faddr = faddr;
 		hash = (int)((uintptr_t)sock->socket % HASHSIZE);
 		sock->next = sockhash[hash];
 		sockhash[hash] = sock;
@@ -480,7 +791,7 @@
 {
 	size_t len, olen;
 
-	olen = len = sizeof *xfiles;
+	olen = len = sizeof(*xfiles);
 	if ((xfiles = malloc(len)) == NULL)
 		err(1, "malloc()");
 	while (sysctlbyname("kern.file", xfiles, &len, 0, 0) == -1) {
@@ -490,39 +801,40 @@
 		if ((xfiles = realloc(xfiles, len)) == NULL)
 			err(1, "realloc()");
 	}
-	if (len > 0 && xfiles->xf_size != sizeof *xfiles)
+	if (len > 0 && xfiles->xf_size != sizeof(*xfiles))
 		errx(1, "struct xfile size mismatch");
-	nxfiles = len / sizeof *xfiles;
+	nxfiles = len / sizeof(*xfiles);
 }
 
 static int
-printaddr(int af, struct sockaddr_storage *ss)
+printaddr(struct sockaddr_storage *ss)
 {
-	char addrstr[INET6_ADDRSTRLEN] = { '\0', '\0' };
 	struct sockaddr_un *sun;
-	void *addr = NULL; /* Keep compiler happy. */
-	int off, port = 0;
+	char addrstr[NI_MAXHOST] = { '\0', '\0' };
+	int error, off, port = 0;
 
-	switch (af) {
+	switch (ss->ss_family) {
 	case AF_INET:
-		addr = &((struct sockaddr_in *)ss)->sin_addr;
-		if (inet_lnaof(*(struct in_addr *)addr) == INADDR_ANY)
+		if (inet_lnaof(sstosin(ss)->sin_addr) == INADDR_ANY)
 			addrstr[0] = '*';
-		port = ntohs(((struct sockaddr_in *)ss)->sin_port);
+		port = ntohs(sstosin(ss)->sin_port);
 		break;
 	case AF_INET6:
-		addr = &((struct sockaddr_in6 *)ss)->sin6_addr;
-		if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)addr))
+		if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr))
 			addrstr[0] = '*';
-		port = ntohs(((struct sockaddr_in6 *)ss)->sin6_port);
+		port = ntohs(sstosin6(ss)->sin6_port);
 		break;
 	case AF_UNIX:
-		sun = (struct sockaddr_un *)ss;
+		sun = sstosun(ss);
 		off = (int)((char *)&sun->sun_path - (char *)sun);
 		return (xprintf("%.*s", sun->sun_len - off, sun->sun_path));
 	}
-	if (addrstr[0] == '\0')
-		inet_ntop(af, addr, addrstr, sizeof addrstr);
+	if (addrstr[0] == '\0') {
+		error = getnameinfo(sstosa(ss), ss->ss_len, addrstr,
+		    sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
+		if (error)
+			errx(1, "getnameinfo()");
+	}
 	if (port == 0)
 		return xprintf("%s:*", addrstr);
 	else
@@ -540,8 +852,8 @@
 	mib[1] = KERN_PROC;
 	mib[2] = KERN_PROC_PID;
 	mib[3] = (int)pid;
-	len = sizeof proc;
-	if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) {
+	len = sizeof(proc);
+	if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) {
 		/* Do not warn if the process exits before we get its name. */
 		if (errno != ESRCH)
 			warn("sysctl()");
@@ -561,8 +873,8 @@
 	mib[1] = KERN_PROC;
 	mib[2] = KERN_PROC_PID;
 	mib[3] = (int)pid;
-	len = sizeof proc;
-	if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) {
+	len = sizeof(proc);
+	if (sysctl(mib, nitems(mib), &proc, &len, NULL, 0) == -1) {
 		/* Do not warn if the process exits before we get its jid. */
 		if (errno != ESRCH)
 			warn("sysctl()");
@@ -575,31 +887,78 @@
 check_ports(struct sock *s)
 {
 	int port;
+	struct addr *addr;
 
 	if (ports == NULL)
 		return (1);
 	if ((s->family != AF_INET) && (s->family != AF_INET6))
 		return (1);
-	if (s->family == AF_INET)
-		port = ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port);
-	else
-		port = ntohs(((struct sockaddr_in6 *)(&s->laddr))->sin6_port);
-	if (CHK_PORT(port))
-		return (1);
-	if (s->family == AF_INET)
-		port = ntohs(((struct sockaddr_in *)(&s->faddr))->sin_port);
-	else
-		port = ntohs(((struct sockaddr_in6 *)(&s->faddr))->sin6_port);
-	if (CHK_PORT(port))
-		return (1);
+	for (addr = s->laddr; addr != NULL; addr = addr->next) {
+		if (s->family == AF_INET)
+			port = ntohs(sstosin(&addr->address)->sin_port);
+		else
+			port = ntohs(sstosin6(&addr->address)->sin6_port);
+		if (CHK_PORT(port))
+			return (1);
+	}
+	for (addr = s->faddr; addr != NULL; addr = addr->next) {
+		if (s->family == AF_INET)
+			port = ntohs(sstosin(&addr->address)->sin_port);
+		else
+			port = ntohs(sstosin6(&addr->address)->sin6_port);
+		if (CHK_PORT(port))
+			return (1);
+	}
 	return (0);
 }
 
+static const char *
+sctp_state(int state)
+{
+	switch (state) {
+	case SCTP_CLOSED:
+		return "CLOSED";
+		break;
+	case SCTP_BOUND:
+		return "BOUND";
+		break;
+	case SCTP_LISTEN:
+		return "LISTEN";
+		break;
+	case SCTP_COOKIE_WAIT:
+		return "COOKIE_WAIT";
+		break;
+	case SCTP_COOKIE_ECHOED:
+		return "COOKIE_ECHOED";
+		break;
+	case SCTP_ESTABLISHED:
+		return "ESTABLISHED";
+		break;
+	case SCTP_SHUTDOWN_SENT:
+		return "SHUTDOWN_SENT";
+		break;
+	case SCTP_SHUTDOWN_RECEIVED:
+		return "SHUTDOWN_RECEIVED";
+		break;
+	case SCTP_SHUTDOWN_ACK_SENT:
+		return "SHUTDOWN_ACK_SENT";
+		break;
+	case SCTP_SHUTDOWN_PENDING:
+		return "SHUTDOWN_PENDING";
+		break;
+	default:
+		return "UNKNOWN";
+		break;
+	}
+}
+
 static void
 displaysock(struct sock *s, int pos)
 {
 	void *p;
-	int hash;
+	int hash, first;
+	struct addr *laddr, *faddr;
+	struct sock *s_tmp;
 
 	while (pos < 29)
 		pos += xprintf(" ");
@@ -608,45 +967,86 @@
 		pos += xprintf("4 ");
 	if (s->vflag & INP_IPV6)
 		pos += xprintf("6 ");
-	while (pos < 36)
-		pos += xprintf(" ");
-	switch (s->family) {
-	case AF_INET:
-	case AF_INET6:
-		pos += printaddr(s->family, &s->laddr);
-		if (s->family == AF_INET6 && pos >= 58)
+	laddr = s->laddr;
+	faddr = s->faddr;
+	first = 1;
+	while (laddr != NULL || faddr != NULL) {
+		while (pos < 36)
 			pos += xprintf(" ");
-		while (pos < 58)
-			pos += xprintf(" ");
-		pos += printaddr(s->family, &s->faddr);
-		break;
-	case AF_UNIX:
-		/* server */
-		if (s->laddr.ss_len > 0) {
-			pos += printaddr(s->family, &s->laddr);
+		switch (s->family) {
+		case AF_INET:
+		case AF_INET6:
+			if (laddr != NULL) {
+				pos += printaddr(&laddr->address);
+				if (s->family == AF_INET6 && pos >= 58)
+					pos += xprintf(" ");
+			}
+			while (pos < 58)
+				pos += xprintf(" ");
+			if (faddr != NULL)
+				pos += printaddr(&faddr->address);
 			break;
-		}
-		/* client */
-		p = *(void **)&s->faddr;
-		if (p == NULL) {
-			pos += xprintf("(not connected)");
+		case AF_UNIX:
+			if ((laddr == NULL) || (faddr == NULL))
+				errx(1, "laddr = %p or faddr = %p is NULL",
+				     (void *)laddr, (void *)faddr);
+			/* server */
+			if (laddr->address.ss_len > 0) {
+				pos += printaddr(&laddr->address);
+				break;
+			}
+			/* client */
+			p = *(void **)&(faddr->address);
+			if (p == NULL) {
+				pos += xprintf("(not connected)");
+				break;
+			}
+			pos += xprintf("-> ");
+			for (hash = 0; hash < HASHSIZE; ++hash) {
+				for (s_tmp = sockhash[hash];
+				     s_tmp != NULL;
+				     s_tmp = s_tmp->next)
+					if (s_tmp->pcb == p)
+						break;
+				if (s_tmp != NULL)
+					break;
+			}
+			if (s_tmp == NULL ||
+			    s_tmp->laddr == NULL ||
+			    s_tmp->laddr->address.ss_len == 0)
+				pos += xprintf("??");
+			else
+				pos += printaddr(&s_tmp->laddr->address);
 			break;
+		default:
+			abort();
 		}
-		pos += xprintf("-> ");
-		for (hash = 0; hash < HASHSIZE; ++hash) {
-			for (s = sockhash[hash]; s != NULL; s = s->next)
-				if (s->pcb == p)
-					break;
-			if (s != NULL)
+		if (first && opt_s &&
+		    (s->proto == IPPROTO_SCTP || s->proto == IPPROTO_TCP)) {
+			while (pos < 80)
+				pos += xprintf(" ");
+			switch (s->proto) {
+			case IPPROTO_SCTP:
+				pos += xprintf("%s", sctp_state(s->state));
 				break;
+			case IPPROTO_TCP:
+				if (s->state >= 0 && s->state < TCP_NSTATES)
+					pos +=
+					    xprintf("%s", tcpstates[s->state]);
+				else
+					pos += xprintf("?");
+				break;
+			}
 		}
-		if (s == NULL || s->laddr.ss_len == 0)
-			pos += xprintf("??");
-		else
-			pos += printaddr(s->family, &s->laddr);
-		break;
-	default:
-		abort();
+		if (laddr != NULL)
+			laddr = laddr->next;
+		if (faddr != NULL)
+			faddr = faddr->next;
+		if ((laddr != NULL) || (faddr != NULL)) {
+			xprintf("\n");
+			pos = 0;
+		}
+		first = 0;
 	}
 	xprintf("\n");
 }
@@ -659,9 +1059,12 @@
 	struct sock *s;
 	int hash, n, pos;
 
-	printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s\n",
+	printf("%-8s %-10s %-5s %-2s %-6s %-21s %-21s",
 	    "USER", "COMMAND", "PID", "FD", "PROTO",
 	    "LOCAL ADDRESS", "FOREIGN ADDRESS");
+	if (opt_s)
+		printf(" %-12s", "STATE");
+	printf("\n");
 	setpassent(1);
 	for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) {
 		if (xf->xf_data == NULL)
@@ -669,29 +1072,28 @@
 		if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid))
 			continue;
 		hash = (int)((uintptr_t)xf->xf_data % HASHSIZE);
-		for (s = sockhash[hash]; s != NULL; s = s->next)
-			if ((void *)s->socket == xf->xf_data)
-				break;
-		if (s == NULL)
-			continue;
-		if (!check_ports(s))
-			continue;
-		s->shown = 1;
-		pos = 0;
-		if ((pwd = getpwuid(xf->xf_uid)) == NULL)
-			pos += xprintf("%lu ", (u_long)xf->xf_uid);
-		else
-			pos += xprintf("%s ", pwd->pw_name);
-		while (pos < 9)
-			pos += xprintf(" ");
-		pos += xprintf("%.10s", getprocname(xf->xf_pid));
-		while (pos < 20)
-			pos += xprintf(" ");
-		pos += xprintf("%lu ", (u_long)xf->xf_pid);
-		while (pos < 26)
-			pos += xprintf(" ");
-		pos += xprintf("%d ", xf->xf_fd);
-		displaysock(s, pos);
+		for (s = sockhash[hash]; s != NULL; s = s->next) {
+			if ((void *)s->socket != xf->xf_data)
+				continue;
+			if (!check_ports(s))
+				continue;
+			s->shown = 1;
+			pos = 0;
+			if ((pwd = getpwuid(xf->xf_uid)) == NULL)
+				pos += xprintf("%lu ", (u_long)xf->xf_uid);
+			else
+				pos += xprintf("%s ", pwd->pw_name);
+			while (pos < 9)
+				pos += xprintf(" ");
+			pos += xprintf("%.10s", getprocname(xf->xf_pid));
+			while (pos < 20)
+				pos += xprintf(" ");
+			pos += xprintf("%lu ", (u_long)xf->xf_pid);
+			while (pos < 26)
+				pos += xprintf(" ");
+			pos += xprintf("%d ", xf->xf_fd);
+			displaysock(s, pos);
+		}
 	}
 	if (opt_j >= 0)
 		return;
@@ -733,7 +1135,7 @@
 usage(void)
 {
 	fprintf(stderr,
-	    "Usage: sockstat [-46cLlu] [-j jid] [-p ports] [-P protocols]\n");
+	    "usage: sockstat [-46cLlsu] [-j jid] [-p ports] [-P protocols]\n");
 	exit(1);
 }
 
@@ -744,7 +1146,7 @@
 	int o, i;
 
 	opt_j = -1;
-	while ((o = getopt(argc, argv, "46cj:Llp:P:uv")) != -1)
+	while ((o = getopt(argc, argv, "46cj:Llp:P:suv")) != -1)
 		switch (o) {
 		case '4':
 			opt_4 = 1;
@@ -770,6 +1172,9 @@
 		case 'P':
 			protos_defined = parse_protos(optarg);
 			break;
+		case 's':
+			opt_s = 1;
+			break;
 		case 'u':
 			opt_u = 1;
 			break;
@@ -797,12 +1202,16 @@
 
 	if (opt_4 || opt_6) {
 		for (i = 0; i < protos_defined; i++)
-			gather_inet(protos[i]);
+			if (protos[i] == IPPROTO_SCTP)
+				gather_sctp();
+			else
+				gather_inet(protos[i]);
 	}
 
 	if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) {
 		gather_unix(SOCK_STREAM);
 		gather_unix(SOCK_DGRAM);
+		gather_unix(SOCK_SEQPACKET);
 	}
 	getfiles();
 	display();



More information about the Midnightbsd-cvs mailing list