#ifdef __APPLE__
#include <TargetConditionals.h>
#endif
#include <stdio.h>
#include <err.h>
#include <stdlib.h>
#include <strings.h>
#include <inttypes.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/mptcp_var.h>
#include <arpa/inet.h>
#include "netstat.h"
static const char *tcpstates[] = {
"CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD",
"ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
"LAST_ACK", "FIN_WAIT_2", "TIME_WAIT"
};
static const char *mptcpstates[] = {
"CLOSED", "LISTEN", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1",
"CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", "TERMINATE"
};
int mptcp_done = 0;
extern void inetprint (struct in_addr *, int, char *, int);
extern void inet6print (struct in6_addr *, int, char *, int);
static void
printmptcp(int id, conninfo_mptcp_t *mptcp)
{
int i;
conninfo_tcp_t *tcpci;
struct sockaddr_storage *src, *dst;
mptcp_flow_t *flow;
int af;
printf("mptcp/%-2.2d %-8.8x/%-8.8x %50s \n"
" [tok(%#"PRIx32") snd(%#"PRIx64") rcv(%#"PRIx64") "
"aid(%d)]\n", id,
mptcp->mptcpci_mpte_flags, mptcp->mptcpci_flags,
mptcpstates[mptcp->mptcpci_state], mptcp->mptcpci_rtoken,
mptcp->mptcpci_sndnxt, mptcp->mptcpci_rcvnxt,
mptcp->mptcpci_mpte_addrid);
flow = (mptcp_flow_t*)((caddr_t)mptcp + mptcp->mptcpci_flow_offset);
for (i = 0; i < mptcp->mptcpci_nflows; i++) {
src = &flow->flow_src;
dst = &flow->flow_dst;
af = src->ss_family;
printf(" tcp%d/%-2.2d ", af == AF_INET ? 4 : 6,
flow->flow_cid);
printf("%-8.8x ", flow->flow_flags);
#define SIN(x) ((struct sockaddr_in *)(x))
#define SIN6(x) ((struct sockaddr_in6 *)(x))
switch (af) {
case AF_INET:
inetprint(&SIN(src)->sin_addr, SIN(src)->sin_port,
"tcp", nflag);
inetprint(&SIN(dst)->sin_addr, SIN(dst)->sin_port,
"tcp", nflag);
break;
#ifdef INET6
case AF_INET6:
inet6print(&SIN6(src)->sin6_addr, SIN6(src)->sin6_port,
"tcp", nflag);
inet6print(&SIN6(dst)->sin6_addr, SIN6(dst)->sin6_port,
"tcp", nflag);
break;
}
#endif
#undef SIN
#undef SIN6
tcpci = (conninfo_tcp_t*)((caddr_t)flow +
flow->flow_tcpci_offset);
printf("%s \n"
" [relseq(%-4.4d), err(%d)]\n",
tcpstates[tcpci->tcpci_tcp_info.tcpi_state],
flow->flow_relseq,
flow->flow_soerror);
flow = (mptcp_flow_t*)((caddr_t)flow + flow->flow_len);
}
}
void
mptcppr(uint32_t off, char *name, int af)
{
#pragma unused(off, name, af)
const char *mibvar = "net.inet.mptcp.pcblist";
size_t len = 0;
conninfo_mptcp_t *mptcp;
char *buf, *bufp;
int id = 0;
if (Lflag || Aflag || mptcp_done)
return;
mptcp_done = 1;
if (sysctlbyname(mibvar, 0, &len, NULL, 0) < 0) {
if (errno != ENOENT)
warn("sysctl: %s", mibvar);
return;
}
if ((buf = malloc(len)) == NULL) {
warn("malloc");
return;
}
if (sysctlbyname(mibvar, buf, &len, NULL, 0) < 0) {
warn("sysctl: %s", mibvar);
free(buf);
return;
}
printf("Active Multipath Internet connections\n");
printf("%-8.8s %-9.9s %-22.22s %-22.22s %-11.11s\n",
"Proto/ID", "Flags",
"Local Address", "Foreign Address",
"(state)");
bufp = buf;
while (bufp < buf + len) {
if (buf + len - bufp < sizeof(conninfo_mptcp_t))
break;
mptcp = (conninfo_mptcp_t *)bufp;
printmptcp(id++, mptcp);
bufp += mptcp->mptcpci_len;
}
free(buf);
}