summaryrefslogtreecommitdiffstats
path: root/usr.bin/sockstat/sockstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/sockstat/sockstat.c')
-rw-r--r--usr.bin/sockstat/sockstat.c88
1 files changed, 82 insertions, 6 deletions
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;
OpenPOWER on IntegriCloud