summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/elfdump/elfdump.c2
-rw-r--r--usr.bin/fetch/fetch.17
-rw-r--r--usr.bin/fetch/fetch.c25
-rw-r--r--usr.bin/iscsictl/iscsictl.817
-rw-r--r--usr.bin/iscsictl/iscsictl.c79
-rw-r--r--usr.bin/kdump/Makefile13
-rw-r--r--usr.bin/kdump/kdump.c46
-rw-r--r--usr.bin/kdump/linux32_syscalls.conf11
-rw-r--r--usr.bin/less/defines.h5
-rw-r--r--usr.bin/netstat/sctp.c23
-rw-r--r--usr.bin/sockstat/sockstat.17
-rw-r--r--usr.bin/sockstat/sockstat.c88
-rw-r--r--usr.bin/systat/Makefile2
-rw-r--r--usr.bin/systat/cmdtab.c3
-rw-r--r--usr.bin/systat/extern.h11
-rw-r--r--usr.bin/systat/sctp.c362
-rw-r--r--usr.bin/systat/systat.19
17 files changed, 646 insertions, 64 deletions
diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c
index fe330f8..929125b 100644
--- a/usr.bin/elfdump/elfdump.c
+++ b/usr.bin/elfdump/elfdump.c
@@ -379,7 +379,9 @@ sh_types(uint64_t machine, uint64_t sht) {
break;
case EM_MIPS:
switch (sht) {
+ case SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO";
case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS";
+ case SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS";
}
break;
}
diff --git a/usr.bin/fetch/fetch.1 b/usr.bin/fetch/fetch.1
index b9d4785..615a1ad 100644
--- a/usr.bin/fetch/fetch.1
+++ b/usr.bin/fetch/fetch.1
@@ -30,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 28, 2014
+.Dd March 25, 2015
.Dt FETCH 1
.Os
.Sh NAME
@@ -39,7 +39,6 @@
.Sh SYNOPSIS
.Nm
.Op Fl 146AadFlMmnPpqRrsUv
-.Op Fl -allow-sslv2
.Op Fl B Ar bytes
.Op Fl -bind-address= Ns Ar host
.Op Fl -ca-cert= Ns Ar file
@@ -113,9 +112,6 @@ Some broken Web sites will return a redirect instead of a not-found
error when the requested object does not exist.
.It Fl a , -retry
Automatically retry the transfer upon soft failures.
-.It Fl -allow-sslv2
-[SSL]
-Allow SSL version 2 when negotiating the connection.
.It Fl B Ar bytes , Fl -buffer-size= Ns Ar bytes
Specify the read buffer size in bytes.
The default is 16,384 bytes.
@@ -350,7 +346,6 @@ for a description of additional environment variables, including
.Ev NETRC ,
.Ev NO_PROXY ,
.Ev no_proxy ,
-.Ev SSL_ALLOW_SSL2 ,
.Ev SSL_CA_CERT_FILE ,
.Ev SSL_CA_CERT_PATH ,
.Ev SSL_CLIENT_CERT_FILE ,
diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c
index 3f64151..3fbf343 100644
--- a/usr.bin/fetch/fetch.c
+++ b/usr.bin/fetch/fetch.c
@@ -102,7 +102,6 @@ enum options
OPTION_HTTP_REFERER,
OPTION_HTTP_USER_AGENT,
OPTION_NO_PROXY,
- OPTION_SSL_ALLOW_SSL2,
OPTION_SSL_CA_CERT_FILE,
OPTION_SSL_CA_CERT_PATH,
OPTION_SSL_CLIENT_CERT_FILE,
@@ -154,7 +153,6 @@ static struct option longopts[] =
{ "referer", required_argument, NULL, OPTION_HTTP_REFERER },
{ "user-agent", required_argument, NULL, OPTION_HTTP_USER_AGENT },
{ "no-proxy", required_argument, NULL, OPTION_NO_PROXY },
- { "allow-sslv2", no_argument, NULL, OPTION_SSL_ALLOW_SSL2 },
{ "ca-cert", required_argument, NULL, OPTION_SSL_CA_CERT_FILE },
{ "ca-path", required_argument, NULL, OPTION_SSL_CA_CERT_PATH },
{ "cert", required_argument, NULL, OPTION_SSL_CLIENT_CERT_FILE },
@@ -845,17 +843,17 @@ static void
usage(void)
{
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
-"usage: fetch [-146AadFlMmnPpqRrsUv] [--allow-sslv2] [-B bytes]",
-" [--bind-address=host] [--ca-cert=file] [--ca-path=dir] [--cert=file]",
-" [--crl=file] [-i file] [--key=file] [-N file] [--no-passive]",
-" [--no-proxy=list] [--no-sslv3] [--no-tlsv1] [--no-verify-hostname]",
-" [--no-verify-peer] [-o file] [--referer=URL] [-S bytes] [-T seconds]",
+"usage: fetch [-146AadFlMmnPpqRrsUv] [-B bytes] [--bind-address=host]",
+" [--ca-cert=file] [--ca-path=dir] [--cert=file] [--crl=file]",
+" [-i file] [--key=file] [-N file] [--no-passive] [--no-proxy=list]",
+" [--no-sslv3] [--no-tlsv1] [--no-verify-hostname] [--no-verify-peer]",
+" [-o file] [--referer=URL] [-S bytes] [-T seconds]",
" [--user-agent=agent-string] [-w seconds] URL ...",
-" fetch [-146AadFlMmnPpqRrsUv] [--allow-sslv2] [-B bytes]",
-" [--bind-address=host] [--ca-cert=file] [--ca-path=dir] [--cert=file]",
-" [--crl=file] [-i file] [--key=file] [-N file] [--no-passive]",
-" [--no-proxy=list] [--no-sslv3] [--no-tlsv1] [--no-verify-hostname]",
-" [--no-verify-peer] [-o file] [--referer=URL] [-S bytes] [-T seconds]",
+" fetch [-146AadFlMmnPpqRrsUv] [-B bytes] [--bind-address=host]",
+" [--ca-cert=file] [--ca-path=dir] [--cert=file] [--crl=file]",
+" [-i file] [--key=file] [-N file] [--no-passive] [--no-proxy=list]",
+" [--no-sslv3] [--no-tlsv1] [--no-verify-hostname] [--no-verify-peer]",
+" [-o file] [--referer=URL] [-S bytes] [-T seconds]",
" [--user-agent=agent-string] [-w seconds] -h host -f file [-c dir]");
}
@@ -1004,9 +1002,6 @@ main(int argc, char *argv[])
case OPTION_NO_PROXY:
setenv("NO_PROXY", optarg, 1);
break;
- case OPTION_SSL_ALLOW_SSL2:
- setenv("SSL_ALLOW_SSL2", "", 1);
- break;
case OPTION_SSL_CA_CERT_FILE:
setenv("SSL_CA_CERT_FILE", optarg, 1);
break;
diff --git a/usr.bin/iscsictl/iscsictl.8 b/usr.bin/iscsictl/iscsictl.8
index b9231ac..811f808 100644
--- a/usr.bin/iscsictl/iscsictl.8
+++ b/usr.bin/iscsictl/iscsictl.8
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 12, 2014
+.Dd October 17, 2015
.Dt ISCSICTL 8
.Os
.Sh NAME
@@ -36,7 +36,9 @@
.Sh SYNOPSIS
.Nm
.Fl A
-.Fl p Ar portal Fl t Ar target Op Fl u Ar user Fl s Ar secret
+.Fl p Ar portal Fl t Ar target
+.Op Fl u Ar user Fl s Ar secret
+.Op Fl w Ar timeout
.Nm
.Fl A
.Fl d Ar discovery-host Op Fl u Ar user Fl s Ar secret
@@ -70,6 +72,7 @@
.Nm
.Fl L
.Op Fl v
+.Op Fl w Ar timeout
.Sh DESCRIPTION
The
.Nm
@@ -113,6 +116,10 @@ Target name.
CHAP login.
.It Fl v
Verbose mode.
+.It Fl w
+Instead of returning immediately, wait up to
+.Ar timeout
+seconds until all configured sessions are successfully established.
.El
.Pp
Certain parameters are necessary when adding a session.
@@ -132,9 +139,11 @@ via configuration file.
.Pp
Since connecting to the target is performed in background, non-zero
exit status does not mean that the session was successfully established.
-Use
+Use either
.Nm Fl L
-to check the connection status.
+to check the connection status, or the
+.Fl w
+flag to wait for session establishment.
.Pp
Note that in order for the iSCSI initiator to be able to connect to a target,
the
diff --git a/usr.bin/iscsictl/iscsictl.c b/usr.bin/iscsictl/iscsictl.c
index a27e32b..8e7faac 100644
--- a/usr.bin/iscsictl/iscsictl.c
+++ b/usr.bin/iscsictl/iscsictl.c
@@ -550,12 +550,70 @@ kernel_list(int iscsi_fd, const struct target *targ __unused,
return (0);
}
+static int
+kernel_wait(int iscsi_fd, int timeout)
+{
+ struct iscsi_session_state *states = NULL;
+ const struct iscsi_session_state *state;
+ const struct iscsi_session_conf *conf;
+ struct iscsi_session_list isl;
+ unsigned int i, nentries = 1;
+ bool all_connected;
+ int error;
+
+ for (;;) {
+ for (;;) {
+ states = realloc(states,
+ nentries * sizeof(struct iscsi_session_state));
+ if (states == NULL)
+ err(1, "realloc");
+
+ memset(&isl, 0, sizeof(isl));
+ isl.isl_nentries = nentries;
+ isl.isl_pstates = states;
+
+ error = ioctl(iscsi_fd, ISCSISLIST, &isl);
+ if (error != 0 && errno == EMSGSIZE) {
+ nentries *= 4;
+ continue;
+ }
+ break;
+ }
+ if (error != 0) {
+ warn("ISCSISLIST");
+ return (error);
+ }
+
+ all_connected = true;
+ for (i = 0; i < isl.isl_nentries; i++) {
+ state = &states[i];
+ conf = &state->iss_conf;
+
+ if (!state->iss_connected) {
+ all_connected = false;
+ break;
+ }
+ }
+
+ if (all_connected)
+ return (0);
+
+ sleep(1);
+
+ if (timeout > 0) {
+ timeout--;
+ if (timeout == 0)
+ return (1);
+ }
+ }
+}
+
static void
usage(void)
{
fprintf(stderr, "usage: iscsictl -A -p portal -t target "
- "[-u user -s secret]\n");
+ "[-u user -s secret] [-w timeout]\n");
fprintf(stderr, " iscsictl -A -d discovery-host "
"[-u user -s secret]\n");
fprintf(stderr, " iscsictl -A -a [-c path]\n");
@@ -567,7 +625,7 @@ usage(void)
fprintf(stderr, " iscsictl -R [-p portal] [-t target]\n");
fprintf(stderr, " iscsictl -R -a\n");
fprintf(stderr, " iscsictl -R -n nickname [-c path]\n");
- fprintf(stderr, " iscsictl -L [-v]\n");
+ fprintf(stderr, " iscsictl -L [-v] [-w timeout]\n");
exit(1);
}
@@ -589,6 +647,7 @@ main(int argc, char **argv)
const char *conf_path = DEFAULT_CONFIG_PATH;
char *nickname = NULL, *discovery_host = NULL, *portal = NULL,
*target = NULL, *user = NULL, *secret = NULL;
+ int timeout = -1;
long long session_id = -1;
char *end;
int ch, error, iscsi_fd, retval, saved_errno;
@@ -596,7 +655,7 @@ main(int argc, char **argv)
struct conf *conf;
struct target *targ;
- while ((ch = getopt(argc, argv, "AMRLac:d:i:n:p:t:u:s:v")) != -1) {
+ while ((ch = getopt(argc, argv, "AMRLac:d:i:n:p:t:u:s:vw:")) != -1) {
switch (ch) {
case 'A':
Aflag = 1;
@@ -647,6 +706,13 @@ main(int argc, char **argv)
case 'v':
vflag = 1;
break;
+ case 'w':
+ timeout = strtol(optarg, &end, 10);
+ if ((size_t)(end - optarg) != strlen(optarg))
+ errx(1, "trailing characters after timeout");
+ if (timeout < 0)
+ errx(1, "timeout cannot be negative");
+ break;
case '?':
default:
usage();
@@ -737,6 +803,8 @@ main(int argc, char **argv)
if (vflag != 0)
errx(1, "-v cannot be used with -M");
+ if (timeout != -1)
+ errx(1, "-w cannot be used with -M");
} else if (Rflag != 0) {
if (user != NULL)
@@ -766,6 +834,8 @@ main(int argc, char **argv)
errx(1, "-i cannot be used with -R");
if (vflag != 0)
errx(1, "-v cannot be used with -R");
+ if (timeout != -1)
+ errx(1, "-w cannot be used with -R");
} else {
assert(Lflag != 0);
@@ -851,6 +921,9 @@ main(int argc, char **argv)
failed += kernel_list(iscsi_fd, targ, vflag);
}
+ if (timeout != -1)
+ failed += kernel_wait(iscsi_fd, timeout);
+
error = close(iscsi_fd);
if (error != 0)
err(1, "close");
diff --git a/usr.bin/kdump/Makefile b/usr.bin/kdump/Makefile
index d450da5..378c416 100644
--- a/usr.bin/kdump/Makefile
+++ b/usr.bin/kdump/Makefile
@@ -3,10 +3,6 @@
.include <bsd.own.mk>
-.if (${MACHINE_ARCH} == "amd64")
-SFX= 32
-.endif
-
.PATH: ${.CURDIR}/../ktrace
PROG= kdump
@@ -24,6 +20,9 @@ CLEANFILES= ioctl.c kdump_subr.c kdump_subr.h
.if (${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386")
CLEANFILES+= linux_syscalls.c
.endif
+.if (${MACHINE_ARCH} == "amd64")
+CLEANFILES+= linux32_syscalls.c
+.endif
ioctl.c: mkioctls
env MACHINE=${MACHINE} CPP="${CPP}" \
@@ -37,7 +36,11 @@ kdump_subr.c: mksubr kdump_subr.h
sh ${.CURDIR}/mksubr ${DESTDIR}/usr/include >${.TARGET}
.if (${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386")
sh ${.CURDIR}/../../sys/kern/makesyscalls.sh \
- ${.CURDIR}/../../sys/${MACHINE_ARCH}/linux${SFX}/syscalls.master ${.CURDIR}/linux_syscalls.conf
+ ${.CURDIR}/../../sys/${MACHINE_ARCH}/linux/syscalls.master ${.CURDIR}/linux_syscalls.conf
+.endif
+.if (${MACHINE_ARCH} == "amd64")
+ sh ${.CURDIR}/../../sys/kern/makesyscalls.sh \
+ ${.CURDIR}/../../sys/${MACHINE_ARCH}/linux32/syscalls.master ${.CURDIR}/linux32_syscalls.conf
.endif
.include <bsd.prog.mk>
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
index bd0e000..f028e51 100644
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -139,13 +139,11 @@ static struct ktr_header ktr_header;
#if defined(__amd64__) || defined(__i386__)
-void linux_ktrsyscall(struct ktr_syscall *);
-void linux_ktrsysret(struct ktr_sysret *);
+void linux_ktrsyscall(struct ktr_syscall *, u_int);
+void linux_ktrsysret(struct ktr_sysret *, u_int);
extern const char *linux_syscallnames[];
#include <linux_syscalls.c>
-static int nlinux_syscalls = sizeof(linux_syscallnames) / \
- sizeof(linux_syscallnames[0]);
/*
* from linux.h
@@ -165,6 +163,12 @@ static int bsd_to_linux_errno[ELAST + 1] = {
};
#endif
+#if defined(__amd64__)
+extern const char *linux32_syscallnames[];
+
+#include <linux32_syscalls.c>
+#endif
+
struct proc_info
{
TAILQ_ENTRY(proc_info) info;
@@ -331,7 +335,8 @@ main(int argc, char *argv[])
case KTR_SYSCALL:
#if defined(__amd64__) || defined(__i386__)
if ((sv_flags & SV_ABI_MASK) == SV_ABI_LINUX)
- linux_ktrsyscall((struct ktr_syscall *)m);
+ linux_ktrsyscall((struct ktr_syscall *)m,
+ sv_flags);
else
#endif
ktrsyscall((struct ktr_syscall *)m, sv_flags);
@@ -339,7 +344,8 @@ main(int argc, char *argv[])
case KTR_SYSRET:
#if defined(__amd64__) || defined(__i386__)
if ((sv_flags & SV_ABI_MASK) == SV_ABI_LINUX)
- linux_ktrsysret((struct ktr_sysret *)m);
+ linux_ktrsysret((struct ktr_sysret *)m,
+ sv_flags);
else
#endif
ktrsysret((struct ktr_sysret *)m, sv_flags);
@@ -1891,16 +1897,28 @@ ktrfaultend(struct ktr_faultend *ktr)
}
#if defined(__amd64__) || defined(__i386__)
+
+#if defined(__amd64__)
+#define NLINUX_SYSCALLS(v) ((v) & SV_ILP32 ? \
+ nitems(linux32_syscallnames) : nitems(linux_syscallnames))
+#define LINUX_SYSCALLNAMES(v, i) ((v) & SV_ILP32 ? \
+ linux32_syscallnames[i] : linux_syscallnames[i])
+#else
+#define NLINUX_SYSCALLS(v) (nitems(linux_syscallnames))
+#define LINUX_SYSCALLNAMES(v, i) (linux_syscallnames[i])
+#endif
+
void
-linux_ktrsyscall(struct ktr_syscall *ktr)
+linux_ktrsyscall(struct ktr_syscall *ktr, u_int sv_flags)
{
int narg = ktr->ktr_narg;
+ unsigned code = ktr->ktr_code;
register_t *ip;
- if (ktr->ktr_code >= nlinux_syscalls || ktr->ktr_code < 0)
+ if (ktr->ktr_code < 0 || code >= NLINUX_SYSCALLS(sv_flags))
printf("[%d]", ktr->ktr_code);
else {
- printf("%s", linux_syscallnames[ktr->ktr_code]);
+ printf("%s", LINUX_SYSCALLNAMES(sv_flags, ktr->ktr_code));
if (syscallno)
printf("[%d]", ktr->ktr_code);
}
@@ -1915,16 +1933,16 @@ linux_ktrsyscall(struct ktr_syscall *ktr)
}
void
-linux_ktrsysret(struct ktr_sysret *ktr)
+linux_ktrsysret(struct ktr_sysret *ktr, u_int sv_flags)
{
register_t ret = ktr->ktr_retval;
+ unsigned code = ktr->ktr_code;
int error = ktr->ktr_error;
- int code = ktr->ktr_code;
- if (code >= nlinux_syscalls || code < 0)
- printf("[%d] ", code);
+ if (ktr->ktr_code < 0 || code >= NLINUX_SYSCALLS(sv_flags))
+ printf("[%d] ", ktr->ktr_code);
else {
- printf("%s", linux_syscallnames[code]);
+ printf("%s ", LINUX_SYSCALLNAMES(sv_flags, code));
if (syscallno)
printf("[%d]", code);
printf(" ");
diff --git a/usr.bin/kdump/linux32_syscalls.conf b/usr.bin/kdump/linux32_syscalls.conf
new file mode 100644
index 0000000..66a67fd
--- /dev/null
+++ b/usr.bin/kdump/linux32_syscalls.conf
@@ -0,0 +1,11 @@
+# $FreeBSD$
+sysnames="linux32_syscalls.c"
+sysproto="/dev/null"
+sysproto_h=_LINUX32_SYSPROTO_H_
+syshdr="/dev/null"
+syssw="/dev/null"
+sysmk="/dev/null"
+syscallprefix="LINUX32_SYS_"
+switchname="/dev/null"
+namesname="linux32_syscallnames"
+systrace="/dev/null"
diff --git a/usr.bin/less/defines.h b/usr.bin/less/defines.h
index 27b73ce..9b0f5c9 100644
--- a/usr.bin/less/defines.h
+++ b/usr.bin/less/defines.h
@@ -418,6 +418,11 @@
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
diff --git a/usr.bin/netstat/sctp.c b/usr.bin/netstat/sctp.c
index 687d039..347aa57 100644
--- a/usr.bin/netstat/sctp.c
+++ b/usr.bin/netstat/sctp.c
@@ -572,25 +572,34 @@ sctp_statesprint(uint32_t state)
int idx;
switch (state) {
- case SCTP_STATE_COOKIE_WAIT:
+ case SCTP_CLOSED:
+ idx = NETSTAT_SCTP_STATES_CLOSED;
+ break;
+ case SCTP_BOUND:
+ idx = NETSTAT_SCTP_STATES_BOUND;
+ break;
+ case SCTP_LISTEN:
+ idx = NETSTAT_SCTP_STATES_LISTEN;
+ break;
+ case SCTP_COOKIE_WAIT:
idx = NETSTAT_SCTP_STATES_COOKIE_WAIT;
break;
- case SCTP_STATE_COOKIE_ECHOED:
+ case SCTP_COOKIE_ECHOED:
idx = NETSTAT_SCTP_STATES_COOKIE_ECHOED;
break;
- case SCTP_STATE_OPEN:
+ case SCTP_ESTABLISHED:
idx = NETSTAT_SCTP_STATES_ESTABLISHED;
break;
- case SCTP_STATE_SHUTDOWN_SENT:
+ case SCTP_SHUTDOWN_SENT:
idx = NETSTAT_SCTP_STATES_SHUTDOWN_SENT;
break;
- case SCTP_STATE_SHUTDOWN_RECEIVED:
+ case SCTP_SHUTDOWN_RECEIVED:
idx = NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED;
break;
- case SCTP_STATE_SHUTDOWN_ACK_SENT:
+ case SCTP_SHUTDOWN_ACK_SENT:
idx = NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT;
break;
- case SCTP_STATE_SHUTDOWN_PENDING:
+ case SCTP_SHUTDOWN_PENDING:
idx = NETSTAT_SCTP_STATES_SHUTDOWN_PENDING;
break;
default:
diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1
index 040213d..4200594 100644
--- a/usr.bin/sockstat/sockstat.1
+++ b/usr.bin/sockstat/sockstat.1
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 20, 2015
+.Dd August 27, 2015
.Dt SOCKSTAT 1
.Os
.Sh NAME
@@ -35,7 +35,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
@@ -83,6 +83,9 @@ The
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
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c
index 8a8afc0..98d86b5 100644
--- a/usr.bin/sockstat/sockstat.c
+++ b/usr.bin/sockstat/sockstat.c
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
#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>
@@ -71,6 +73,7 @@ static int opt_c; /* Show connected sockets */
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 */
@@ -101,6 +104,7 @@ struct sock {
int vflag;
int family;
int proto;
+ int state;
const char *protoname;
struct addr *laddr;
struct addr *faddr;
@@ -328,6 +332,10 @@ gather_sctp(void)
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;
@@ -417,6 +425,7 @@ gather_sctp(void)
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;
@@ -594,9 +603,10 @@ gather_inet(int proto)
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)) {
warnx("struct xtcpcb size mismatch");
goto out;
@@ -607,7 +617,6 @@ gather_inet(int proto)
break;
case IPPROTO_UDP:
case IPPROTO_DIVERT:
- xip = (struct xinpcb *)xig;
if (xip->xi_len != sizeof(*xip)) {
warnx("struct xinpcb size mismatch");
goto out;
@@ -670,6 +679,8 @@ gather_inet(int proto)
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];
@@ -900,11 +911,51 @@ check_ports(struct sock *s)
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;
@@ -917,6 +968,7 @@ displaysock(struct sock *s, int pos)
pos += xprintf("6 ");
laddr = s->laddr;
faddr = s->faddr;
+ first = 1;
while (laddr != NULL || faddr != NULL) {
while (pos < 36)
pos += xprintf(" ");
@@ -968,6 +1020,23 @@ displaysock(struct sock *s, int pos)
default:
abort();
}
+ 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 (laddr != NULL)
laddr = laddr->next;
if (faddr != NULL)
@@ -976,6 +1045,7 @@ displaysock(struct sock *s, int pos)
xprintf("\n");
pos = 0;
}
+ first = 0;
}
xprintf("\n");
}
@@ -988,9 +1058,12 @@ display(void)
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)
@@ -1061,7 +1134,7 @@ static void
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);
}
@@ -1072,7 +1145,7 @@ main(int argc, char *argv[])
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;
@@ -1098,6 +1171,9 @@ main(int argc, char *argv[])
case 'P':
protos_defined = parse_protos(optarg);
break;
+ case 's':
+ opt_s = 1;
+ break;
case 'u':
opt_u = 1;
break;
diff --git a/usr.bin/systat/Makefile b/usr.bin/systat/Makefile
index 5773c36..817a0bc 100644
--- a/usr.bin/systat/Makefile
+++ b/usr.bin/systat/Makefile
@@ -6,7 +6,7 @@
PROG= systat
SRCS= cmds.c cmdtab.c devs.c fetch.c iostat.c keyboard.c main.c \
netcmds.c netstat.c pigs.c swap.c icmp.c \
- mode.c ip.c tcp.c \
+ mode.c ip.c sctp.c tcp.c \
vmstat.c convtbl.c ifcmds.c ifstat.c
.if ${MK_INET6_SUPPORT} != "no"
diff --git a/usr.bin/systat/cmdtab.c b/usr.bin/systat/cmdtab.c
index c9c9e7d..63a69f6 100644
--- a/usr.bin/systat/cmdtab.c
+++ b/usr.bin/systat/cmdtab.c
@@ -69,6 +69,9 @@ struct cmdtab cmdtab[] = {
initip6, openip6, closeip6, cmdmode,
resetip6, CF_LOADAV },
#endif
+ { "sctp", showsctp, fetchsctp, labelsctp,
+ initsctp, opensctp, closesctp, cmdmode,
+ resetsctp, CF_LOADAV },
{ "tcp", showtcp, fetchtcp, labeltcp,
inittcp, opentcp, closetcp, cmdmode,
resettcp, CF_LOADAV },
diff --git a/usr.bin/systat/extern.h b/usr.bin/systat/extern.h
index 17fffc1..461ef8d 100644
--- a/usr.bin/systat/extern.h
+++ b/usr.bin/systat/extern.h
@@ -163,3 +163,14 @@ void showtcp(void);
void status(void);
void suspend(int);
char *sysctl_dynread(const char *, size_t *);
+
+#define SYSTAT_CMD(name) \
+ void close ## name(WINDOW *); \
+ void fetch ## name(void); \
+ int init ## name(void); \
+ void label ## name(void); \
+ WINDOW *open ## name(void); \
+ void reset ## name(void); \
+ void show ## name(void)
+
+SYSTAT_CMD ( sctp );
diff --git a/usr.bin/systat/sctp.c b/usr.bin/systat/sctp.c
new file mode 100644
index 0000000..ea0edd8
--- /dev/null
+++ b/usr.bin/systat/sctp.c
@@ -0,0 +1,362 @@
+/*-
+ * Copyright (c) 2015
+ * The Regents of the University of California. All rights reserved.
+ * Michael Tuexen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <netinet/sctp.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+static struct sctpstat curstat, initstat, oldstat;
+
+/*-
+--0 1 2 3 4 5 6 7
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+00 SCTP Associations SCTP Packets
+01999999999999 associations initiated 999999999999 packets sent
+02999999999999 associations accepted 999999999999 packets received
+03999999999999 associations established 999999999999 - out of the blue
+04999999999999 associations restarted 999999999999 - bad vtag
+05999999999999 associations terminated 999999999999 - bad crc32c
+06999999999999 associations aborted
+07
+08 SCTP Timers SCTP Chunks
+09999999999999 init timeouts 999999999999 control chunks sent
+10999999999999 cookie timeouts 999999999999 data chunks sent
+11999999999999 data timeouts 999999999999 - ordered
+12999999999999 delayed sack timeouts 999999999999 - unordered
+13999999999999 shutdown timeouts 999999999999 control chunks received
+14999999999999 shutdown-ack timeouts 999999999999 data chunks received
+15999999999999 shutdown guard timeouts 999999999999 - ordered
+16999999999999 heartbeat timeouts 999999999999 - unordered
+17999999999999 path MTU timeouts
+18999999999999 autoclose timeouts SCTP user messages
+19999999999999 asconf timeouts 999999999999 fragmented
+20999999999999 stream reset timeouts 999999999999 reassembled
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+--0 1 2 3 4 5 6 7
+*/
+
+WINDOW *
+opensctp(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closesctp(WINDOW *w)
+{
+ if (w != NULL) {
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+ }
+}
+
+void
+labelsctp(void)
+{
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+#define L(row, str) mvwprintw(wnd, row, 13, str)
+#define R(row, str) mvwprintw(wnd, row, 51, str);
+ L(0, "SCTP Associations"); R(0, "SCTP Packets");
+ L(1, "associations initiated"); R(1, "packets sent");
+ L(2, "associations accepted"); R(2, "packets received");
+ L(3, "associations established"); R(3, "- out of the blue");
+ L(4, "associations restarted"); R(4, "- bad vtag");
+ L(5, "associations terminated"); R(5, "- bad crc32c");
+ L(6, "associations aborted");
+
+ L(8, "SCTP Timers"); R(8, "SCTP Chunks");
+ L(9, "init timeouts"); R(9, "control chunks sent");
+ L(10, "cookie timeouts"); R(10, "data chunks sent");
+ L(11, "data timeouts"); R(11, "- ordered");
+ L(12, "delayed sack timeouts"); R(12, "- unordered");
+ L(13, "shutdown timeouts"); R(13, "control chunks received");
+ L(14, "shutdown-ack timeouts"); R(14, "data chunks received");
+ L(15, "shutdown guard timeouts"); R(15, "- ordered");
+ L(16, "heartbeat timeouts"); R(16, "- unordered");
+ L(17, "path MTU timeouts");
+ L(18, "autoclose timeouts"); R(18, "SCTP User Messages");
+ L(19, "asconf timeouts"); R(19, "fragmented");
+ L(20, "stream reset timeouts"); R(20, "reassembled");
+#undef L
+#undef R
+}
+
+static void
+domode(struct sctpstat *ret)
+{
+ const struct sctpstat *sub;
+ int divisor = 1;
+
+ switch(currentmode) {
+ case display_RATE:
+ sub = &oldstat;
+ divisor = (delay > 1000000) ? delay / 1000000 : 1;
+ break;
+ case display_DELTA:
+ sub = &oldstat;
+ break;
+ case display_SINCE:
+ sub = &initstat;
+ break;
+ default:
+ *ret = curstat;
+ return;
+ }
+#define DO(stat) ret->stat = (curstat.stat - sub->stat) / divisor
+ DO(sctps_currestab);
+ DO(sctps_activeestab);
+ DO(sctps_restartestab);
+ DO(sctps_collisionestab);
+ DO(sctps_passiveestab);
+ DO(sctps_aborted);
+ DO(sctps_shutdown);
+ DO(sctps_outoftheblue);
+ DO(sctps_checksumerrors);
+ DO(sctps_outcontrolchunks);
+ DO(sctps_outorderchunks);
+ DO(sctps_outunorderchunks);
+ DO(sctps_incontrolchunks);
+ DO(sctps_inorderchunks);
+ DO(sctps_inunorderchunks);
+ DO(sctps_fragusrmsgs);
+ DO(sctps_reasmusrmsgs);
+ DO(sctps_outpackets);
+ DO(sctps_inpackets);
+
+ DO(sctps_recvpackets);
+ DO(sctps_recvdatagrams);
+ DO(sctps_recvpktwithdata);
+ DO(sctps_recvsacks);
+ DO(sctps_recvdata);
+ DO(sctps_recvdupdata);
+ DO(sctps_recvheartbeat);
+ DO(sctps_recvheartbeatack);
+ DO(sctps_recvecne);
+ DO(sctps_recvauth);
+ DO(sctps_recvauthmissing);
+ DO(sctps_recvivalhmacid);
+ DO(sctps_recvivalkeyid);
+ DO(sctps_recvauthfailed);
+ DO(sctps_recvexpress);
+ DO(sctps_recvexpressm);
+ DO(sctps_recvnocrc);
+ DO(sctps_recvswcrc);
+ DO(sctps_recvhwcrc);
+
+ DO(sctps_sendpackets);
+ DO(sctps_sendsacks);
+ DO(sctps_senddata);
+ DO(sctps_sendretransdata);
+ DO(sctps_sendfastretrans);
+ DO(sctps_sendmultfastretrans);
+ DO(sctps_sendheartbeat);
+ DO(sctps_sendecne);
+ DO(sctps_sendauth);
+ DO(sctps_senderrors);
+ DO(sctps_sendnocrc);
+ DO(sctps_sendswcrc);
+ DO(sctps_sendhwcrc);
+
+ DO(sctps_pdrpfmbox);
+ DO(sctps_pdrpfehos);
+ DO(sctps_pdrpmbda);
+ DO(sctps_pdrpmbct);
+ DO(sctps_pdrpbwrpt);
+ DO(sctps_pdrpcrupt);
+ DO(sctps_pdrpnedat);
+ DO(sctps_pdrppdbrk);
+ DO(sctps_pdrptsnnf);
+ DO(sctps_pdrpdnfnd);
+ DO(sctps_pdrpdiwnp);
+ DO(sctps_pdrpdizrw);
+ DO(sctps_pdrpbadd);
+ DO(sctps_pdrpmark);
+
+ DO(sctps_timoiterator);
+ DO(sctps_timodata);
+ DO(sctps_timowindowprobe);
+ DO(sctps_timoinit);
+ DO(sctps_timosack);
+ DO(sctps_timoshutdown);
+ DO(sctps_timoheartbeat);
+ DO(sctps_timocookie);
+ DO(sctps_timosecret);
+ DO(sctps_timopathmtu);
+ DO(sctps_timoshutdownack);
+ DO(sctps_timoshutdownguard);
+ DO(sctps_timostrmrst);
+ DO(sctps_timoearlyfr);
+ DO(sctps_timoasconf);
+ DO(sctps_timodelprim);
+ DO(sctps_timoautoclose);
+ DO(sctps_timoassockill);
+ DO(sctps_timoinpkill);
+
+ DO(sctps_hdrops);
+ DO(sctps_badsum);
+ DO(sctps_noport);
+ DO(sctps_badvtag);
+ DO(sctps_badsid);
+ DO(sctps_nomem);
+ DO(sctps_fastretransinrtt);
+ DO(sctps_markedretrans);
+ DO(sctps_naglesent);
+ DO(sctps_naglequeued);
+ DO(sctps_maxburstqueued);
+ DO(sctps_ifnomemqueued);
+ DO(sctps_windowprobed);
+ DO(sctps_lowlevelerr);
+ DO(sctps_lowlevelerrusr);
+ DO(sctps_datadropchklmt);
+ DO(sctps_datadroprwnd);
+ DO(sctps_ecnereducedcwnd);
+ DO(sctps_vtagexpress);
+ DO(sctps_vtagbogus);
+ DO(sctps_primary_randry);
+ DO(sctps_cmt_randry);
+ DO(sctps_slowpath_sack);
+ DO(sctps_wu_sacks_sent);
+ DO(sctps_sends_with_flags);
+ DO(sctps_sends_with_unord);
+ DO(sctps_sends_with_eof);
+ DO(sctps_sends_with_abort);
+ DO(sctps_protocol_drain_calls);
+ DO(sctps_protocol_drains_done);
+ DO(sctps_read_peeks);
+ DO(sctps_cached_chk);
+ DO(sctps_cached_strmoq);
+ DO(sctps_left_abandon);
+ DO(sctps_send_burst_avoid);
+ DO(sctps_send_cwnd_avoid);
+ DO(sctps_fwdtsn_map_over);
+ DO(sctps_queue_upd_ecne);
+#undef DO
+}
+
+void
+showsctp(void)
+{
+ struct sctpstat stats;
+
+ memset(&stats, 0, sizeof stats);
+ domode(&stats);
+
+#define DO(stat, row, col) \
+ mvwprintw(wnd, row, col, "%12lu", stats.stat)
+#define L(row, stat) DO(stat, row, 0)
+#define R(row, stat) DO(stat, row, 38)
+ L(1, sctps_activeestab); R(1, sctps_outpackets);
+ L(2, sctps_passiveestab); R(2, sctps_inpackets);
+ L(3, sctps_currestab); R(3, sctps_outoftheblue);
+ L(4, sctps_restartestab); R(4, sctps_badvtag);
+ L(5, sctps_shutdown); R(5, sctps_checksumerrors);
+ L(6, sctps_aborted);
+
+
+ L(9, sctps_timoinit); R(9, sctps_outcontrolchunks);
+ L(10, sctps_timocookie); R(10, sctps_senddata);
+ L(11, sctps_timodata); R(11, sctps_outorderchunks);
+ L(12, sctps_timosack); R(12, sctps_outunorderchunks);
+ L(13, sctps_timoshutdown); R(13, sctps_incontrolchunks);
+ L(14, sctps_timoshutdownack); R(14, sctps_recvdata);
+ L(15, sctps_timoshutdownguard); R(15, sctps_inorderchunks);
+ L(16, sctps_timoheartbeat); R(16, sctps_inunorderchunks);
+ L(17, sctps_timopathmtu);
+ L(18, sctps_timoautoclose);
+ L(19, sctps_timoasconf); R(19, sctps_fragusrmsgs);
+ L(20, sctps_timostrmrst); R(20, sctps_reasmusrmsgs);
+#undef DO
+#undef L
+#undef R
+}
+
+int
+initsctp(void)
+{
+ size_t len;
+ const char *name = "net.inet.sctp.stats";
+
+ len = 0;
+ if (sysctlbyname(name, NULL, &len, NULL, 0) < 0) {
+ error("sysctl getting sctpstat size failed");
+ return 0;
+ }
+ if (len > sizeof curstat) {
+ error("sctpstat structure has grown--recompile systat!");
+ return 0;
+ }
+ if (sysctlbyname(name, &initstat, &len, NULL, 0) < 0) {
+ error("sysctl getting sctpstat failed");
+ return 0;
+ }
+ oldstat = initstat;
+ return 1;
+}
+
+void
+resetsctp(void)
+{
+ size_t len;
+ const char *name = "net.inet.sctp.stats";
+
+ len = sizeof initstat;
+ if (sysctlbyname(name, &initstat, &len, NULL, 0) < 0) {
+ error("sysctl getting sctpstat failed");
+ }
+ oldstat = initstat;
+}
+
+void
+fetchsctp(void)
+{
+ size_t len;
+ const char *name = "net.inet.sctp.stats";
+
+ oldstat = curstat;
+ len = sizeof curstat;
+ if (sysctlbyname(name, &curstat, &len, NULL, 0) < 0) {
+ error("sysctl getting sctpstat failed");
+ }
+ return;
+}
diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1
index 9c144e7..46c2cb9 100644
--- a/usr.bin/systat/systat.1
+++ b/usr.bin/systat/systat.1
@@ -28,7 +28,7 @@
.\" @(#)systat.1 8.2 (Berkeley) 12/30/93
.\" $FreeBSD$
.\"
-.Dd July 15, 2013
+.Dd October 24, 2015
.Dt SYSTAT 1
.Os
.Sh NAME
@@ -95,6 +95,7 @@ to be one of:
.Ic ip6 ,
.Ic netstat ,
.Ic pigs ,
+.Ic sctp ,
.Ic swap ,
.Ic tcp ,
or
@@ -223,6 +224,12 @@ except that it displays
statistics.
It does not display
.Tn UDP statistics.
+.It Ic sctp
+Like
+.Ic icmp ,
+but with
+.Tn SCTP
+statistics.
.It Ic tcp
Like
.Ic icmp ,
OpenPOWER on IntegriCloud