git: d7339c42673a - stable/13 - trpt: fix several bugs and add deprecation notice

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Thu, 20 Apr 2023 22:15:36 UTC
The branch stable/13 has been updated by tuexen:

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

commit d7339c42673a84e222f630e80b5606776b755229
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2023-04-20 22:09:40 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2023-04-20 22:09:40 +0000

    trpt: fix several bugs and add deprecation notice
    
    This patch fixes several bugs releated to trpt including
    * the computation of the TCP payload bytes, in particular when
      TCP options are present or IPv4 is used.
    * the logging of incoming and outgoing packets.
    * the logging of timers, in particular add support for logging of
      the delayed ack timer.
    Also add a deprecation note, since support for this utility has been
    removed from the main branch. Therefore, this is a direct commit to
    stable/13.
    
    Reviewed by:            cc, glebius, rrs
    Sponsored by:           Netflix, Inc.
    Differential Revision:  https://reviews.freebsd.org/D39436
---
 sys/netinet/tcp_debug.c  |  9 +++++----
 sys/netinet/tcp_input.c  | 13 ++++++++++++-
 sys/netinet/tcp_output.c | 28 ++++++++--------------------
 sys/netinet/tcp_timer.c  | 20 +++++++++++++++-----
 sys/netinet/tcp_timer.h  |  6 ++++++
 usr.sbin/trpt/trpt.8     | 31 ++++++++++++++++++++++---------
 usr.sbin/trpt/trpt.c     | 10 ++++------
 7 files changed, 72 insertions(+), 45 deletions(-)

diff --git a/sys/netinet/tcp_debug.c b/sys/netinet/tcp_debug.c
index aedaa131095f..640940b1ce8c 100644
--- a/sys/netinet/tcp_debug.c
+++ b/sys/netinet/tcp_debug.c
@@ -177,13 +177,13 @@ tcp_trace(short act, short ostate, struct tcpcb *tp, void *ipgen,
 #ifdef INET6
 		    isipv6 ? ntohs(((struct ip6_hdr *)ipgen)->ip6_plen) :
 #endif
-		    ntohs(((struct ip *)ipgen)->ip_len);
+		    ntohs(((struct ip *)ipgen)->ip_len) -
+		        (((struct ip *)ipgen)->ip_hl << 2);
 		if (act == TA_OUTPUT) {
 			seq = ntohl(seq);
 			ack = ntohl(ack);
 		}
-		if (act == TA_OUTPUT)
-			len -= sizeof (struct tcphdr);
+		len -= th->th_off << 2;
 		if (len)
 			printf("[%x..%x)", seq, seq+len);
 		else
@@ -205,7 +205,8 @@ tcp_trace(short act, short ostate, struct tcpcb *tp, void *ipgen,
 
 	case TA_USER:
 		printf("%s", prurequests[req&0xff]);
-		if ((req & 0xff) == PRU_SLOWTIMO)
+		if ((req & 0xff) == PRU_SLOWTIMO ||
+		    (req & 0xff) == PRU_FASTTIMO)
 			printf("<%s>", tcptimers[req>>8]);
 		break;
 	}
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 9bc9923530e0..bb2a0e497dcf 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1561,7 +1561,18 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
 	 */
 	u_char tcp_saveipgen[IP6_HDR_LEN];
 	struct tcphdr tcp_savetcp;
-	short ostate = 0;
+	short ostate;
+
+	if (so->so_options & SO_DEBUG) {
+		ostate = tp->t_state;
+#ifdef INET6
+		if (mtod(m, struct ip *)->ip_v == 6)
+			bcopy(mtod(m, char *), (char *)tcp_saveipgen, sizeof(struct ip6_hdr));
+		else
+#endif
+			bcopy(mtod(m, char *), (char *)tcp_saveipgen, sizeof(struct ip));
+		tcp_savetcp = *th;
+	}
 #endif
 	thflags = th->th_flags;
 	inc = &tp->t_inpcb->inp_inc;
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index fea54cdcc5cb..f979649ca608 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1430,26 +1430,6 @@ send:
 	hhook_run_tcp_est_out(tp, th, &to, len, tso);
 #endif
 
-#ifdef TCPDEBUG
-	/*
-	 * Trace.
-	 */
-	if (so->so_options & SO_DEBUG) {
-		u_short save = 0;
-#ifdef INET6
-		if (!isipv6)
-#endif
-		{
-			save = ipov->ih_len;
-			ipov->ih_len = htons(m->m_pkthdr.len /* - hdrlen + (th->th_off << 2) */);
-		}
-		tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, void *), th, 0);
-#ifdef INET6
-		if (!isipv6)
-#endif
-		ipov->ih_len = save;
-	}
-#endif /* TCPDEBUG */
 	TCP_PROBE3(debug__output, tp, th, m);
 
 	/* We're getting ready to send; log now. */
@@ -1502,6 +1482,10 @@ send:
 		/* Save packet, if requested. */
 		tcp_pcap_add(th, m, &(tp->t_outpkts));
 #endif
+#ifdef TCPDEBUG
+		if (so->so_options & SO_DEBUG)
+			tcp_trace(TA_OUTPUT, tp->t_state, tp, (void *)ip6, th, 0);
+#endif /* TCPDEBUG */
 
 		/* TODO: IPv6 IP6TOS_ECT bit on */
 		error = ip6_output(m, tp->t_inpcb->in6p_outputopts,
@@ -1549,6 +1533,10 @@ send:
 	/* Save packet, if requested. */
 	tcp_pcap_add(th, m, &(tp->t_outpkts));
 #endif
+#ifdef TCPDEBUG
+	if (so->so_options & SO_DEBUG)
+		tcp_trace(TA_OUTPUT, tp->t_state, tp, (void *)ip, th, 0);
+#endif /* TCPDEBUG */
 
 	error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
 	    ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0,
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 4b00b686be32..21e6b66ff81c 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -266,8 +266,12 @@ tcp_timer_delack(void *xtp)
 	struct epoch_tracker et;
 	struct tcpcb *tp = xtp;
 	struct inpcb *inp;
-	CURVNET_SET(tp->t_vnet);
+#ifdef TCPDEBUG
+	int ostate;
 
+	ostate = tp->t_state;
+#endif
+	CURVNET_SET(tp->t_vnet);
 	inp = tp->t_inpcb;
 	KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
 	INP_WLOCK(inp);
@@ -287,6 +291,11 @@ tcp_timer_delack(void *xtp)
 	TCPSTAT_INC(tcps_delack);
 	NET_EPOCH_ENTER(et);
 	(void) tp->t_fb->tfb_tcp_output(tp);
+#ifdef TCPDEBUG
+	if (inp->inp_socket->so_options & SO_DEBUG)
+		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
+			  (TCPT_DELACK << 8) | PRU_FASTTIMO);
+#endif
 	INP_WUNLOCK(inp);
 	NET_EPOCH_EXIT(et);
 	CURVNET_RESTORE();
@@ -380,7 +389,7 @@ tcp_timer_2msl(void *xtp)
 #ifdef TCPDEBUG
 	if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
 		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
-			  PRU_SLOWTIMO);
+			  (TCPT_2MSL << 8) | PRU_SLOWTIMO);
 #endif
 	TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
 
@@ -502,7 +511,7 @@ dropit:
 #ifdef TCPDEBUG
 	if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
 		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
-			  PRU_SLOWTIMO);
+			  (TCPT_KEEP << 8) | PRU_SLOWTIMO);
 #endif
 	TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
 	NET_EPOCH_EXIT(et);
@@ -592,7 +601,8 @@ tcp_timer_persist(void *xtp)
 
 #ifdef TCPDEBUG
 	if (tp != NULL && tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
-		tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO);
+		tcp_trace(TA_USER, ostate, tp, NULL, NULL,
+			  (TCPT_PERSIST << 8) | PRU_SLOWTIMO);
 #endif
 	TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
 	INP_WUNLOCK(inp);
@@ -875,7 +885,7 @@ tcp_timer_rexmt(void * xtp)
 #ifdef TCPDEBUG
 	if (tp != NULL && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
 		tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
-			  PRU_SLOWTIMO);
+			  (TCPT_REXMT << 8) | PRU_SLOWTIMO);
 #endif
 	TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
 	INP_WUNLOCK(inp);
diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h
index 316b76e50f7e..d0bc74669123 100644
--- a/sys/netinet/tcp_timer.h
+++ b/sys/netinet/tcp_timer.h
@@ -35,6 +35,12 @@
 #ifndef _NETINET_TCP_TIMER_H_
 #define _NETINET_TCP_TIMER_H_
 
+#define	TCPT_REXMT	0		/* retransmit */
+#define	TCPT_PERSIST	1		/* retransmit persistance */
+#define	TCPT_KEEP	2		/* keep alive */
+#define	TCPT_2MSL	3		/* 2*msl quiet time timer */
+#define	TCPT_DELACK	4		/* delay ack */
+
 /*
  * The TCPT_REXMT timer is used to force retransmissions.
  * The TCP has the TCPT_REXMT timer set whenever segments
diff --git a/usr.sbin/trpt/trpt.8 b/usr.sbin/trpt/trpt.8
index 3c66f5afe761..8d674f76298b 100644
--- a/usr.sbin/trpt/trpt.8
+++ b/usr.sbin/trpt/trpt.8
@@ -28,13 +28,19 @@
 .\"     @(#)trpt.8	8.2 (Berkeley) 12/11/93
 .\" $FreeBSD$
 .\"
-.Dd February 15, 2018
+.Dd April 21, 2023
 .Dt TRPT 8
 .Os
 .Sh NAME
 .Nm trpt
 .Nd transliterate protocol trace
 .Sh SYNOPSIS
+To add support for this utility to the kernel, add the following line to the
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "options TCPDEBUG"
+.Ed
+.Pp
 .Nm
 .Op Fl a
 .Op Fl f
@@ -44,12 +50,15 @@
 .Oo
 .Ar system Op Ar core
 .Oc
+.Sh DEPRECATION NOTICE
+.Nm
+is deprecated and will not be available in
+.Fx 14.0
+and later.
 .Sh DESCRIPTION
 The
 .Nm
-utility interrogates the buffer of
-.Tn TCP
-trace records created
+utility interrogates the buffer of TCP trace records created
 when a socket is marked for
 .Dq debugging
 (see
@@ -58,11 +67,8 @@ and prints a readable description of these records.
 When no options are supplied,
 .Nm
 prints all the trace records found in the system
-grouped according to
-.Tn TCP
-connection protocol control
-block
-.Pq Tn PCB .
+grouped according to TCP connection protocol control block
+.Pq PCB .
 .Pp
 The following options may be used to
 alter this behavior:
@@ -142,3 +148,10 @@ but this is not saved in the trace record.
 .Pp
 The output format is inscrutable and should be described
 here.
+.Pp
+It is not possible to use the
+.Nm
+utility if the following line is in the kernel config file:
+.Bd -ragged -offset indent
+.Cd "options TCPPCAP"
+.Ed
diff --git a/usr.sbin/trpt/trpt.c b/usr.sbin/trpt/trpt.c
index e8198f7d080e..b89a82c191d8 100644
--- a/usr.sbin/trpt/trpt.c
+++ b/usr.sbin/trpt/trpt.c
@@ -124,7 +124,7 @@ main(int argc, char **argv)
 		case 'p':
 			if (npcbs >= TCP_NDEBUG)
 				errx(1, "too many pcb's specified");
-			(void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]);
+			(void)sscanf(optarg, "%lx", (long *)&tcp_pcbs[npcbs++]);
 			break;
 		case 's':
 			++sflag;
@@ -369,18 +369,16 @@ tcp_trace(short act, short ostate, struct tcpcb *tp, int family __unused,
 
 		len =
 #ifdef INET6
-		    isipv6 ? ip6->ip6_plen :
+		    isipv6 ? ntohs(ip6->ip6_plen) :
 #endif
-		    ip4->ip_len;
+		    ntohs(ip4->ip_len) - (ip4->ip_hl << 2);
 		win = th->th_win;
 		if (act == TA_OUTPUT) {
 			seq = ntohl(seq);
 			ack = ntohl(ack);
-			len = ntohs(len);
 			win = ntohs(win);
 		}
-		if (act == TA_OUTPUT)
-			len -= sizeof(struct tcphdr);
+		len -= th->th_off << 2;
 		if (len)
 			printf("[%lx..%lx)", (u_long)seq, (u_long)(seq + len));
 		else