Index: sys/netinet/tcp_fastopen.c =================================================================== --- sys/netinet/tcp_fastopen.c +++ sys/netinet/tcp_fastopen.c @@ -137,6 +137,9 @@ * Install a new pre-shared key by writing net.inet.tcp.fastopen.keylen * bytes to this sysctl. * + * net.inet.tcp.fastopen.ccache_list (RO) + * Print the connection cache. + * * In order for TFO connections to be created via a listen socket, that * socket must have the TCP_FASTOPEN socket option set on it. This option * can be set on the socket either before or after the listen() is invoked. @@ -166,11 +169,14 @@ #include "opt_inet.h" #include +#include #include #include #include #include +#include #include +#include #include #include #include @@ -343,6 +349,12 @@ &sysctl_net_inet_tcp_fastopen_setpsk, "", "Install a new pre-shared key"); +static int sysctl_net_inet_tcp_fastopen_ccache_list(SYSCTL_HANDLER_ARGS); +SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, ccache_list, + CTLFLAG_VNET | CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP, NULL, 0, + sysctl_net_inet_tcp_fastopen_ccache_list, "A", + "List of all connection cache entries"); + static VNET_DEFINE(struct rmlock, tcp_fastopen_keylock); #define V_tcp_fastopen_keylock VNET(tcp_fastopen_keylock) @@ -1123,5 +1135,73 @@ TAILQ_REMOVE(&ccb->ccb_entries, cce, cce_link); ccb->ccb_num_entries--; uma_zfree(V_tcp_fastopen_ccache.zone, cce); +} + +static int +sysctl_net_inet_tcp_fastopen_ccache_list(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sb; + struct tcp_fastopen_ccache_bucket *ccb; + struct tcp_fastopen_ccache_entry *cce; + const int linesize = 128; + int i, error, num_entries; + unsigned int j; +#ifdef INET6 + char clt_buf[INET6_ADDRSTRLEN], srv_buf[INET6_ADDRSTRLEN]; +#else + char clt_buf[INET_ADDRSTRLEN], srv_buf[INET_ADDRSTRLEN]; +#endif + + if (jailed_without_vnet(curthread->td_ucred) != 0) + return (EPERM); + + num_entries = 0; + for (i = 0; i < V_tcp_fastopen_ccache.buckets; i++) { + ccb = &V_tcp_fastopen_ccache.base[i]; + CCB_LOCK(ccb); + if (ccb->ccb_num_entries > 0) + num_entries += ccb->ccb_num_entries; + CCB_UNLOCK(ccb); + } + sbuf_new(&sb, NULL, linesize * (num_entries + 1), SBUF_INCLUDENUL); + + sbuf_printf(&sb, + "\nLocal IP address Remote IP address Port MSS" + " Status Cookie\n"); + + for (i = 0; i < V_tcp_fastopen_ccache.buckets; i++) { + ccb = &V_tcp_fastopen_ccache.base[i]; + CCB_LOCK(ccb); + TAILQ_FOREACH(cce, &ccb->ccb_entries, cce_link) { + sbuf_printf(&sb, + "%-20s %-20s %5u %5u %8s ", + cce->af == AF_INET ? + inet_ntoa_r(cce->cce_client_ip.v4, clt_buf) : +#ifdef INET6 + ip6_sprintf(clt_buf, &cce->cce_client_ip.v6), +#else + "IPv6?", +#endif + cce->af == AF_INET ? + inet_ntoa_r(cce->cce_server_ip.v4, srv_buf) : +#ifdef INET6 + ip6_sprintf(srv_buf, &cce->cce_server_ip.v6), +#else + "IPv6?", +#endif + ntohs(cce->server_port), + cce->server_mss, + cce->disable_time != 0 ? "disabled" : "enabled"); + for (j = 0; j < cce->cookie_len; j++) + sbuf_printf(&sb, "%02x", cce->cookie[j]); + sbuf_putc(&sb, '\n'); + } + CCB_UNLOCK(ccb); + } + error = sbuf_finish(&sb); + if (error == 0) + error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb)); + sbuf_delete(&sb); + return (error); }