1a9643ea8Slogwang /*-
2*22ce4affSfengbojiang * SPDX-License-Identifier: BSD-3-Clause
3*22ce4affSfengbojiang *
4a9643ea8Slogwang * Copyright (c) 1982, 1986, 1993
5a9643ea8Slogwang * The Regents of the University of California.
6a9643ea8Slogwang * All rights reserved.
7a9643ea8Slogwang *
8a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without
9a9643ea8Slogwang * modification, are permitted provided that the following conditions
10a9643ea8Slogwang * are met:
11a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright
12a9643ea8Slogwang * notice, this list of conditions and the following disclaimer.
13a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright
14a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the
15a9643ea8Slogwang * documentation and/or other materials provided with the distribution.
16*22ce4affSfengbojiang * 3. Neither the name of the University nor the names of its contributors
17a9643ea8Slogwang * may be used to endorse or promote products derived from this software
18a9643ea8Slogwang * without specific prior written permission.
19a9643ea8Slogwang *
20a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21a9643ea8Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22a9643ea8Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23a9643ea8Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24a9643ea8Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25a9643ea8Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26a9643ea8Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27a9643ea8Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29a9643ea8Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30a9643ea8Slogwang * SUCH DAMAGE.
31a9643ea8Slogwang *
32a9643ea8Slogwang * @(#)tcp_debug.c 8.1 (Berkeley) 6/10/93
33a9643ea8Slogwang */
34a9643ea8Slogwang
35a9643ea8Slogwang #include <sys/cdefs.h>
36a9643ea8Slogwang __FBSDID("$FreeBSD$");
37a9643ea8Slogwang
38a9643ea8Slogwang #include "opt_inet.h"
39a9643ea8Slogwang #include "opt_inet6.h"
40a9643ea8Slogwang #include "opt_tcpdebug.h"
41a9643ea8Slogwang
42a9643ea8Slogwang #ifdef TCPDEBUG
43a9643ea8Slogwang /* load symbolic names */
44a9643ea8Slogwang #define PRUREQUESTS
45a9643ea8Slogwang #define TCPSTATES
46a9643ea8Slogwang #define TCPTIMERS
47a9643ea8Slogwang #define TANAMES
48a9643ea8Slogwang #endif
49a9643ea8Slogwang
50a9643ea8Slogwang #include <sys/param.h>
51a9643ea8Slogwang #include <sys/systm.h>
52a9643ea8Slogwang #include <sys/kernel.h>
53a9643ea8Slogwang #include <sys/lock.h>
54a9643ea8Slogwang #include <sys/mbuf.h>
55a9643ea8Slogwang #include <sys/mutex.h>
56a9643ea8Slogwang #include <sys/protosw.h>
57a9643ea8Slogwang #include <sys/socket.h>
58a9643ea8Slogwang
59a9643ea8Slogwang #include <netinet/in.h>
60a9643ea8Slogwang #include <netinet/in_systm.h>
61a9643ea8Slogwang #include <netinet/ip.h>
62a9643ea8Slogwang #ifdef INET6
63a9643ea8Slogwang #include <netinet/ip6.h>
64a9643ea8Slogwang #endif
65a9643ea8Slogwang #include <netinet/ip_var.h>
66a9643ea8Slogwang #include <netinet/tcp.h>
67a9643ea8Slogwang #include <netinet/tcp_fsm.h>
68a9643ea8Slogwang #include <netinet/tcp_timer.h>
69a9643ea8Slogwang #include <netinet/tcp_var.h>
70a9643ea8Slogwang #include <netinet/tcpip.h>
71a9643ea8Slogwang #include <netinet/tcp_debug.h>
72a9643ea8Slogwang
73a9643ea8Slogwang #ifdef TCPDEBUG
74a9643ea8Slogwang static int tcpconsdebug = 0;
75a9643ea8Slogwang #endif
76a9643ea8Slogwang
77a9643ea8Slogwang /*
78a9643ea8Slogwang * Global ring buffer of TCP debugging state. Each entry captures a snapshot
79a9643ea8Slogwang * of TCP connection state at any given moment. tcp_debx addresses at the
80a9643ea8Slogwang * next available slot. There is no explicit export of this data structure;
81a9643ea8Slogwang * it will be read via /dev/kmem by debugging tools.
82a9643ea8Slogwang */
83a9643ea8Slogwang static struct tcp_debug tcp_debug[TCP_NDEBUG];
84a9643ea8Slogwang static int tcp_debx;
85a9643ea8Slogwang
86a9643ea8Slogwang /*
87a9643ea8Slogwang * All global state is protected by tcp_debug_mtx; tcp_trace() is split into
88a9643ea8Slogwang * two parts, one of which saves connection and other state into the global
89a9643ea8Slogwang * array (locked by tcp_debug_mtx).
90a9643ea8Slogwang */
91a9643ea8Slogwang struct mtx tcp_debug_mtx;
92a9643ea8Slogwang MTX_SYSINIT(tcp_debug_mtx, &tcp_debug_mtx, "tcp_debug_mtx", MTX_DEF);
93a9643ea8Slogwang
94a9643ea8Slogwang /*
95a9643ea8Slogwang * Save TCP state at a given moment; optionally, both tcpcb and TCP packet
96a9643ea8Slogwang * header state will be saved.
97a9643ea8Slogwang */
98a9643ea8Slogwang void
tcp_trace(short act,short ostate,struct tcpcb * tp,void * ipgen,struct tcphdr * th,int req)99a9643ea8Slogwang tcp_trace(short act, short ostate, struct tcpcb *tp, void *ipgen,
100a9643ea8Slogwang struct tcphdr *th, int req)
101a9643ea8Slogwang {
102a9643ea8Slogwang #ifdef INET6
103a9643ea8Slogwang int isipv6;
104a9643ea8Slogwang #endif /* INET6 */
105a9643ea8Slogwang tcp_seq seq, ack;
106a9643ea8Slogwang int len, flags;
107a9643ea8Slogwang struct tcp_debug *td;
108a9643ea8Slogwang
109a9643ea8Slogwang mtx_lock(&tcp_debug_mtx);
110a9643ea8Slogwang td = &tcp_debug[tcp_debx++];
111a9643ea8Slogwang if (tcp_debx == TCP_NDEBUG)
112a9643ea8Slogwang tcp_debx = 0;
113a9643ea8Slogwang bzero(td, sizeof(*td));
114a9643ea8Slogwang #ifdef INET6
115a9643ea8Slogwang isipv6 = (ipgen != NULL && ((struct ip *)ipgen)->ip_v == 6) ? 1 : 0;
116a9643ea8Slogwang #endif /* INET6 */
117a9643ea8Slogwang td->td_family =
118a9643ea8Slogwang #ifdef INET6
119a9643ea8Slogwang (isipv6 != 0) ? AF_INET6 :
120a9643ea8Slogwang #endif
121a9643ea8Slogwang AF_INET;
122a9643ea8Slogwang #ifdef INET
123a9643ea8Slogwang td->td_time = iptime();
124a9643ea8Slogwang #endif
125a9643ea8Slogwang td->td_act = act;
126a9643ea8Slogwang td->td_ostate = ostate;
127a9643ea8Slogwang td->td_tcb = (caddr_t)tp;
128a9643ea8Slogwang if (tp != NULL)
129a9643ea8Slogwang td->td_cb = *tp;
130a9643ea8Slogwang if (ipgen != NULL) {
131a9643ea8Slogwang switch (td->td_family) {
132a9643ea8Slogwang #ifdef INET
133a9643ea8Slogwang case AF_INET:
134a9643ea8Slogwang bcopy(ipgen, &td->td_ti.ti_i, sizeof(td->td_ti.ti_i));
135a9643ea8Slogwang break;
136a9643ea8Slogwang #endif
137a9643ea8Slogwang #ifdef INET6
138a9643ea8Slogwang case AF_INET6:
139a9643ea8Slogwang bcopy(ipgen, td->td_ip6buf, sizeof(td->td_ip6buf));
140a9643ea8Slogwang break;
141a9643ea8Slogwang #endif
142a9643ea8Slogwang }
143a9643ea8Slogwang }
144a9643ea8Slogwang if (th != NULL) {
145a9643ea8Slogwang switch (td->td_family) {
146a9643ea8Slogwang #ifdef INET
147a9643ea8Slogwang case AF_INET:
148a9643ea8Slogwang td->td_ti.ti_t = *th;
149a9643ea8Slogwang break;
150a9643ea8Slogwang #endif
151a9643ea8Slogwang #ifdef INET6
152a9643ea8Slogwang case AF_INET6:
153a9643ea8Slogwang td->td_ti6.th = *th;
154a9643ea8Slogwang break;
155a9643ea8Slogwang #endif
156a9643ea8Slogwang }
157a9643ea8Slogwang }
158a9643ea8Slogwang td->td_req = req;
159a9643ea8Slogwang mtx_unlock(&tcp_debug_mtx);
160a9643ea8Slogwang #ifdef TCPDEBUG
161a9643ea8Slogwang if (tcpconsdebug == 0)
162a9643ea8Slogwang return;
163a9643ea8Slogwang if (tp != NULL)
164a9643ea8Slogwang printf("%p %s:", tp, tcpstates[ostate]);
165a9643ea8Slogwang else
166a9643ea8Slogwang printf("???????? ");
167a9643ea8Slogwang printf("%s ", tanames[act]);
168a9643ea8Slogwang switch (act) {
169a9643ea8Slogwang case TA_INPUT:
170a9643ea8Slogwang case TA_OUTPUT:
171a9643ea8Slogwang case TA_DROP:
172a9643ea8Slogwang if (ipgen == NULL || th == NULL)
173a9643ea8Slogwang break;
174a9643ea8Slogwang seq = th->th_seq;
175a9643ea8Slogwang ack = th->th_ack;
176a9643ea8Slogwang len =
177a9643ea8Slogwang #ifdef INET6
178a9643ea8Slogwang isipv6 ? ntohs(((struct ip6_hdr *)ipgen)->ip6_plen) :
179a9643ea8Slogwang #endif
180a9643ea8Slogwang ntohs(((struct ip *)ipgen)->ip_len);
181a9643ea8Slogwang if (act == TA_OUTPUT) {
182a9643ea8Slogwang seq = ntohl(seq);
183a9643ea8Slogwang ack = ntohl(ack);
184a9643ea8Slogwang }
185a9643ea8Slogwang if (act == TA_OUTPUT)
186a9643ea8Slogwang len -= sizeof (struct tcphdr);
187a9643ea8Slogwang if (len)
188a9643ea8Slogwang printf("[%x..%x)", seq, seq+len);
189a9643ea8Slogwang else
190a9643ea8Slogwang printf("%x", seq);
191a9643ea8Slogwang printf("@%x, urp=%x", ack, th->th_urp);
192a9643ea8Slogwang flags = th->th_flags;
193a9643ea8Slogwang if (flags) {
194a9643ea8Slogwang char *cp = "<";
195a9643ea8Slogwang #define pf(f) { \
196a9643ea8Slogwang if (th->th_flags & TH_##f) { \
197a9643ea8Slogwang printf("%s%s", cp, #f); \
198a9643ea8Slogwang cp = ","; \
199a9643ea8Slogwang } \
200a9643ea8Slogwang }
201a9643ea8Slogwang pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG);
202a9643ea8Slogwang printf(">");
203a9643ea8Slogwang }
204a9643ea8Slogwang break;
205a9643ea8Slogwang
206a9643ea8Slogwang case TA_USER:
207a9643ea8Slogwang printf("%s", prurequests[req&0xff]);
208a9643ea8Slogwang if ((req & 0xff) == PRU_SLOWTIMO)
209a9643ea8Slogwang printf("<%s>", tcptimers[req>>8]);
210a9643ea8Slogwang break;
211a9643ea8Slogwang }
212a9643ea8Slogwang if (tp != NULL)
213a9643ea8Slogwang printf(" -> %s", tcpstates[tp->t_state]);
214a9643ea8Slogwang /* print out internal state of tp !?! */
215a9643ea8Slogwang printf("\n");
216a9643ea8Slogwang if (tp == NULL)
217a9643ea8Slogwang return;
218a9643ea8Slogwang printf(
219a9643ea8Slogwang "\trcv_(nxt,wnd,up) (%lx,%lx,%lx) snd_(una,nxt,max) (%lx,%lx,%lx)\n",
220*22ce4affSfengbojiang (u_long)tp->rcv_nxt, (u_long)tp->rcv_wnd, (u_long)tp->rcv_up,
221a9643ea8Slogwang (u_long)tp->snd_una, (u_long)tp->snd_nxt, (u_long)tp->snd_max);
222a9643ea8Slogwang printf("\tsnd_(wl1,wl2,wnd) (%lx,%lx,%lx)\n",
223*22ce4affSfengbojiang (u_long)tp->snd_wl1, (u_long)tp->snd_wl2, (u_long)tp->snd_wnd);
224a9643ea8Slogwang #endif /* TCPDEBUG */
225a9643ea8Slogwang }
226