Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Jun 2025 23:48:04 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 5fea0d9e9dbf - main - sysctl net.inet.tcp.ktlslist
Message-ID:  <202506092348.559Nm4O4088827@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=5fea0d9e9dbfe741ab614d05d916ab91472144bf

commit 5fea0d9e9dbfe741ab614d05d916ab91472144bf
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-05-20 08:07:49 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-06-09 23:47:13 +0000

    sysctl net.inet.tcp.ktlslist
    
    Reviewed by:    jhb (previous version), markj
    Sponsored by:   NVidia networking
    Differential revision:  https://reviews.freebsd.org/D50653
---
 sys/netinet/tcp_subr.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/netinet/tcp_var.h  |   3 +
 2 files changed, 215 insertions(+)

diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index f3f28f54c459..f766bf25ad66 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2664,6 +2664,218 @@ SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist,
     NULL, 0, tcp_pcblist, "S,xtcpcb",
     "List of active TCP connections");
 
+#define SND_TAG_STATUS_MAXLEN	128
+
+#ifdef KERN_TLS
+static int
+tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys)
+{
+	struct xinpgen xig;
+	struct inpcb *inp;
+	struct socket *so;
+	struct ktls_session *ksr, *kss;
+	char *buf;
+	struct xktls_session *xktls;
+	uint64_t ipi_gencnt;
+	size_t buflen, len, sz;
+	u_int cnt;
+	int error;
+	bool ek, p;
+
+	if (req->newptr != NULL)
+		return (EPERM);
+
+	len = 0;
+	cnt = 0;
+	ipi_gencnt = V_tcbinfo.ipi_gencnt;
+	bzero(&xig, sizeof(xig));
+	xig.xig_len = sizeof(xig);
+	xig.xig_gen = atomic_load_acq_64(&ktls_glob_gen);
+	xig.xig_sogen = so_gencnt;
+
+	struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_tcbinfo,
+	    INPLOOKUP_RLOCKPCB);
+	while ((inp = inp_next(&inpi)) != NULL) {
+		if (inp->inp_gencnt > ipi_gencnt ||
+		    cr_canseeinpcb(req->td->td_ucred, inp) != 0)
+			continue;
+
+		so = inp->inp_socket;
+		if (so != NULL && so->so_gencnt <= xig.xig_sogen) {
+			p = false;
+			ek = export_keys && cr_canexport_ktlskeys(
+			    req->td, inp);
+			ksr = so->so_rcv.sb_tls_info;
+			if (ktls_session_genvis(ksr, xig.xig_gen)) {
+				p = true;
+				if (ek) {
+					sz = SIZE_T_MAX;
+					ktls_session_copy_keys(ksr,
+					    NULL, &sz);
+					len += sz;
+				}
+				if (ksr->snd_tag != NULL &&
+				    ksr->snd_tag->sw->snd_tag_status_str !=
+				    NULL) {
+					sz = SND_TAG_STATUS_MAXLEN;
+					ksr->snd_tag->sw->snd_tag_status_str(
+					    ksr->snd_tag, NULL, &sz);
+					len += sz;
+				}
+			}
+			kss = so->so_snd.sb_tls_info;
+			if (ktls_session_genvis(kss, xig.xig_gen)) {
+				p = true;
+				if (ek) {
+					sz = SIZE_T_MAX;
+					ktls_session_copy_keys(kss,
+					    NULL, &sz);
+					len += sz;
+				}
+				if (kss->snd_tag != NULL &&
+				    kss->snd_tag->sw->snd_tag_status_str !=
+				    NULL) {
+					sz = SND_TAG_STATUS_MAXLEN;
+					kss->snd_tag->sw->snd_tag_status_str(
+					    kss->snd_tag, NULL, &sz);
+					len += sz;
+				}
+			}
+			if (p) {
+				len += sizeof(*xktls);
+				len = roundup2(len, __alignof(struct
+				    xktls_session));
+			}
+		}
+	}
+	if (req->oldptr == NULL) {
+		len += 2 * sizeof(xig);
+		len += 3 * len / 4;
+		req->oldidx = len;
+		return (0);
+	}
+
+	if ((error = sysctl_wire_old_buffer(req, 0)) != 0)
+		return (error);
+
+	error = SYSCTL_OUT(req, &xig, sizeof xig);
+	if (error != 0)
+		return (error);
+
+	buflen = roundup2(sizeof(*xktls) + 2 * TLS_MAX_PARAM_SIZE +
+	    2 * SND_TAG_STATUS_MAXLEN, __alignof(struct xktls_session));
+	buf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO);
+	struct inpcb_iterator inpi1 = INP_ALL_ITERATOR(&V_tcbinfo,
+	    INPLOOKUP_RLOCKPCB);
+	while ((inp = inp_next(&inpi1)) != NULL) {
+		if (inp->inp_gencnt > ipi_gencnt ||
+		    cr_canseeinpcb(req->td->td_ucred, inp) != 0)
+			continue;
+
+		so = inp->inp_socket;
+		if (so == NULL)
+			continue;
+
+		p = false;
+		ek = export_keys && cr_canexport_ktlskeys(req->td, inp);
+		ksr = so->so_rcv.sb_tls_info;
+		kss = so->so_snd.sb_tls_info;
+		xktls = (struct xktls_session *)buf;
+		if (ktls_session_genvis(ksr, xig.xig_gen)) {
+			p = true;
+			ktls_session_to_xktls_onedir(ksr, ek, &xktls->rcv);
+		}
+		if (ktls_session_genvis(kss, xig.xig_gen)) {
+			p = true;
+			ktls_session_to_xktls_onedir(kss, ek, &xktls->snd);
+		}
+		if (!p)
+			continue;
+
+		xktls->inp_gencnt = inp->inp_gencnt;
+		xktls->so_pcb = (kvaddr_t)inp;
+		memcpy(&xktls->coninf, &inp->inp_inc, sizeof(xktls->coninf));
+		len = sizeof(*xktls);
+		if (ktls_session_genvis(ksr, xig.xig_gen)) {
+			if (ek) {
+				sz = buflen - len;
+				ktls_session_copy_keys(ksr, buf + len, &sz);
+				len += sz;
+			} else {
+				xktls->rcv.cipher_key_len = 0;
+				xktls->rcv.auth_key_len = 0;
+			}
+			if (ksr->snd_tag != NULL &&
+			    ksr->snd_tag->sw->snd_tag_status_str != NULL) {
+				sz = SND_TAG_STATUS_MAXLEN;
+				ksr->snd_tag->sw->snd_tag_status_str(
+				    ksr->snd_tag, buf + len, &sz);
+				len += sz;
+			}
+		}
+		if (ktls_session_genvis(kss, xig.xig_gen)) {
+			if (ek) {
+				sz = buflen - len;
+				ktls_session_copy_keys(kss, buf + len, &sz);
+				len += sz;
+			} else {
+				xktls->snd.cipher_key_len = 0;
+				xktls->snd.auth_key_len = 0;
+			}
+			if (kss->snd_tag != NULL &&
+			    kss->snd_tag->sw->snd_tag_status_str != NULL) {
+				sz = SND_TAG_STATUS_MAXLEN;
+				kss->snd_tag->sw->snd_tag_status_str(
+				    kss->snd_tag, buf + len, &sz);
+				len += sz;
+			}
+		}
+		len = roundup2(len, __alignof(*xktls));
+		xktls->tsz = len;
+		xktls->fsz = sizeof(*xktls);
+
+		error = SYSCTL_OUT(req, xktls, len);
+		if (error != 0) {
+			INP_RUNLOCK(inp);
+			break;
+		}
+		cnt++;
+	}
+
+	if (error == 0) {
+		atomic_thread_fence_rel();
+		xig.xig_gen = atomic_load_64(&ktls_glob_gen);
+		xig.xig_sogen = so_gencnt;
+		xig.xig_count = cnt;
+		error = SYSCTL_OUT(req, &xig, sizeof(xig));
+	}
+
+	zfree(buf, M_TEMP);
+	return (error);
+}
+
+static int
+tcp_ktlslist_nokeys(SYSCTL_HANDLER_ARGS)
+{
+	return (tcp_ktlslist(oidp, arg1, arg2, req, false));
+}
+
+static int
+tcp_ktlslist_wkeys(SYSCTL_HANDLER_ARGS)
+{
+	return (tcp_ktlslist(oidp, arg1, arg2, req, true));
+}
+
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_KTLSLIST, ktlslist,
+    CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
+    NULL, 0, tcp_ktlslist_nokeys, "S,xktls_session",
+    "List of active kTLS sessions for TCP connections");
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_KTLSLIST_WKEYS, ktlslist_wkeys,
+    CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
+    NULL, 0, tcp_ktlslist_wkeys, "S,xktls_session",
+    "List of active kTLS sessions for TCP connections with keys");
+#endif /* KERN_TLS */
+
 #ifdef INET
 static int
 tcp_getcred(SYSCTL_HANDLER_ARGS)
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index ddc701581f90..4d49f5d2a954 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1234,6 +1234,9 @@ struct tcp_function_info {
 #define	TCPCTL_SACK		14	/* Selective Acknowledgement,rfc 2018 */
 #define	TCPCTL_DROP		15	/* drop tcp connection */
 #define	TCPCTL_STATES		16	/* connection counts by TCP state */
+#define	TCPCTL_KTLSLIST		17	/* connections with active ktls
+					   session */
+#define	TCPCTL_KTLSLIST_WKEYS	18	/* KTLSLIST with key data exported */
 
 #ifdef _KERNEL
 #ifdef SYSCTL_DECL



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506092348.559Nm4O4088827>