1139823Simp/*-
21541Srgrimes * Copyright (c) 1982, 1986, 1993
3169272Srwatson *	The Regents of the University of California.
4169272Srwatson * All rights reserved.
51541Srgrimes *
61541Srgrimes * Redistribution and use in source and binary forms, with or without
71541Srgrimes * modification, are permitted provided that the following conditions
81541Srgrimes * are met:
91541Srgrimes * 1. Redistributions of source code must retain the above copyright
101541Srgrimes *    notice, this list of conditions and the following disclaimer.
111541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer in the
131541Srgrimes *    documentation and/or other materials provided with the distribution.
141541Srgrimes * 4. Neither the name of the University nor the names of its contributors
151541Srgrimes *    may be used to endorse or promote products derived from this software
161541Srgrimes *    without specific prior written permission.
171541Srgrimes *
181541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
191541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
201541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
221541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
231541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
251541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281541Srgrimes * SUCH DAMAGE.
291541Srgrimes *
301541Srgrimes *	@(#)tcp_debug.c	8.1 (Berkeley) 6/10/93
311541Srgrimes */
321541Srgrimes
33172467Ssilby#include <sys/cdefs.h>
34172467Ssilby__FBSDID("$FreeBSD$");
35172467Ssilby
3632350Seivind#include "opt_inet.h"
3755679Sshin#include "opt_inet6.h"
3829514Sjoerg#include "opt_tcpdebug.h"
3929514Sjoerg
401541Srgrimes#ifdef TCPDEBUG
411541Srgrimes/* load symbolic names */
421541Srgrimes#define PRUREQUESTS
431541Srgrimes#define TCPSTATES
441541Srgrimes#define	TCPTIMERS
451541Srgrimes#define	TANAMES
461541Srgrimes#endif
471541Srgrimes
481541Srgrimes#include <sys/param.h>
491541Srgrimes#include <sys/systm.h>
50169272Srwatson#include <sys/kernel.h>
51169272Srwatson#include <sys/lock.h>
52126239Smlaier#include <sys/mbuf.h>
53169272Srwatson#include <sys/mutex.h>
541541Srgrimes#include <sys/protosw.h>
5556801Sshin#include <sys/socket.h>
561541Srgrimes
571541Srgrimes#include <netinet/in.h>
581541Srgrimes#include <netinet/in_systm.h>
5955679Sshin#include <netinet/ip.h>
6055679Sshin#ifdef INET6
6162587Sitojun#include <netinet/ip6.h>
6255679Sshin#endif
631541Srgrimes#include <netinet/ip_var.h>
641541Srgrimes#include <netinet/tcp.h>
651541Srgrimes#include <netinet/tcp_fsm.h>
661541Srgrimes#include <netinet/tcp_timer.h>
671541Srgrimes#include <netinet/tcp_var.h>
681541Srgrimes#include <netinet/tcpip.h>
691541Srgrimes#include <netinet/tcp_debug.h>
701541Srgrimes
711541Srgrimes#ifdef TCPDEBUG
72169272Srwatsonstatic int		tcpconsdebug = 0;
731541Srgrimes#endif
7415238Sbde
75169272Srwatson/*
76169272Srwatson * Global ring buffer of TCP debugging state.  Each entry captures a snapshot
77169272Srwatson * of TCP connection state at any given moment.  tcp_debx addresses at the
78169272Srwatson * next available slot.  There is no explicit export of this data structure;
79169272Srwatson * it will be read via /dev/kmem by debugging tools.
80169272Srwatson */
81169272Srwatsonstatic struct tcp_debug	tcp_debug[TCP_NDEBUG];
82169272Srwatsonstatic int		tcp_debx;
8315238Sbde
841541Srgrimes/*
85169272Srwatson * All global state is protected by tcp_debug_mtx; tcp_trace() is split into
86169272Srwatson * two parts, one of which saves connection and other state into the global
87169272Srwatson * array (locked by tcp_debug_mtx).
881541Srgrimes */
89169272Srwatsonstruct mtx		tcp_debug_mtx;
90169272SrwatsonMTX_SYSINIT(tcp_debug_mtx, &tcp_debug_mtx, "tcp_debug_mtx", MTX_DEF);
91169272Srwatson
92169272Srwatson/*
93169272Srwatson * Save TCP state at a given moment; optionally, both tcpcb and TCP packet
94169272Srwatson * header state will be saved.
95169272Srwatson */
961541Srgrimesvoid
97169272Srwatsontcp_trace(short act, short ostate, struct tcpcb *tp, void *ipgen,
98169272Srwatson    struct tcphdr *th, int req)
991541Srgrimes{
10055679Sshin#ifdef INET6
10155679Sshin	int isipv6;
10255679Sshin#endif /* INET6 */
1031541Srgrimes	tcp_seq seq, ack;
1041541Srgrimes	int len, flags;
105169272Srwatson	struct tcp_debug *td;
1061541Srgrimes
107169272Srwatson	mtx_lock(&tcp_debug_mtx);
108169272Srwatson	td = &tcp_debug[tcp_debx++];
109169350Srwatson	if (tcp_debx == TCP_NDEBUG)
110169350Srwatson		tcp_debx = 0;
111169350Srwatson	bzero(td, sizeof(*td));
11255679Sshin#ifdef INET6
11355679Sshin	isipv6 = (ipgen != NULL && ((struct ip *)ipgen)->ip_v == 6) ? 1 : 0;
11455679Sshin#endif /* INET6 */
11556801Sshin	td->td_family =
11656801Sshin#ifdef INET6
117169350Srwatson	    (isipv6 != 0) ? AF_INET6 :
11856801Sshin#endif
119169350Srwatson	    AF_INET;
120193895Sbz#ifdef INET
1211541Srgrimes	td->td_time = iptime();
122193895Sbz#endif
1231541Srgrimes	td->td_act = act;
1241541Srgrimes	td->td_ostate = ostate;
1251541Srgrimes	td->td_tcb = (caddr_t)tp;
126169350Srwatson	if (tp != NULL)
1271541Srgrimes		td->td_cb = *tp;
128169350Srwatson	if (ipgen != NULL) {
12956801Sshin		switch (td->td_family) {
130193895Sbz#ifdef INET
13156801Sshin		case AF_INET:
132169350Srwatson			bcopy(ipgen, &td->td_ti.ti_i, sizeof(td->td_ti.ti_i));
13356801Sshin			break;
134193895Sbz#endif
13555679Sshin#ifdef INET6
13656801Sshin		case AF_INET6:
137169350Srwatson			bcopy(ipgen, td->td_ip6buf, sizeof(td->td_ip6buf));
13856801Sshin			break;
13955679Sshin#endif
14056801Sshin		}
14156801Sshin	}
142169350Srwatson	if (th != NULL) {
14356801Sshin		switch (td->td_family) {
144193895Sbz#ifdef INET
14556801Sshin		case AF_INET:
14656801Sshin			td->td_ti.ti_t = *th;
14756801Sshin			break;
148193895Sbz#endif
14956801Sshin#ifdef INET6
15056801Sshin		case AF_INET6:
15156801Sshin			td->td_ti6.th = *th;
15256801Sshin			break;
15356801Sshin#endif
15456801Sshin		}
15556801Sshin	}
1561541Srgrimes	td->td_req = req;
157169272Srwatson	mtx_unlock(&tcp_debug_mtx);
1581541Srgrimes#ifdef TCPDEBUG
1591541Srgrimes	if (tcpconsdebug == 0)
1601541Srgrimes		return;
161169350Srwatson	if (tp != NULL)
1626283Swollman		printf("%p %s:", tp, tcpstates[ostate]);
1631541Srgrimes	else
1641541Srgrimes		printf("???????? ");
1651541Srgrimes	printf("%s ", tanames[act]);
1661541Srgrimes	switch (act) {
1671541Srgrimes	case TA_INPUT:
1681541Srgrimes	case TA_OUTPUT:
1691541Srgrimes	case TA_DROP:
17055679Sshin		if (ipgen == NULL || th == NULL)
1711541Srgrimes			break;
17255679Sshin		seq = th->th_seq;
17355679Sshin		ack = th->th_ack;
17455679Sshin		len =
17555679Sshin#ifdef INET6
176182855Sbz		    isipv6 ? ntohs(((struct ip6_hdr *)ipgen)->ip6_plen) :
17755679Sshin#endif
178241913Sglebius		    ntohs(((struct ip *)ipgen)->ip_len);
1791541Srgrimes		if (act == TA_OUTPUT) {
1801541Srgrimes			seq = ntohl(seq);
1811541Srgrimes			ack = ntohl(ack);
1821541Srgrimes		}
1831541Srgrimes		if (act == TA_OUTPUT)
1841541Srgrimes			len -= sizeof (struct tcphdr);
1851541Srgrimes		if (len)
1861541Srgrimes			printf("[%x..%x)", seq, seq+len);
1871541Srgrimes		else
1881541Srgrimes			printf("%x", seq);
18955679Sshin		printf("@%x, urp=%x", ack, th->th_urp);
19055679Sshin		flags = th->th_flags;
1911541Srgrimes		if (flags) {
1921541Srgrimes			char *cp = "<";
1936283Swollman#define pf(f) {					\
19455679Sshin	if (th->th_flags & TH_##f) {		\
1956283Swollman		printf("%s%s", cp, #f);		\
1966283Swollman		cp = ",";			\
1976283Swollman	}					\
1986283Swollman}
1991541Srgrimes			pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG);
2001541Srgrimes			printf(">");
2011541Srgrimes		}
2021541Srgrimes		break;
2031541Srgrimes
2041541Srgrimes	case TA_USER:
2051541Srgrimes		printf("%s", prurequests[req&0xff]);
2061541Srgrimes		if ((req & 0xff) == PRU_SLOWTIMO)
2071541Srgrimes			printf("<%s>", tcptimers[req>>8]);
2081541Srgrimes		break;
2091541Srgrimes	}
210169350Srwatson	if (tp != NULL)
2111541Srgrimes		printf(" -> %s", tcpstates[tp->t_state]);
2121541Srgrimes	/* print out internal state of tp !?! */
2131541Srgrimes	printf("\n");
214169350Srwatson	if (tp == NULL)
2151541Srgrimes		return;
21638373Sbde	printf(
21738373Sbde	"\trcv_(nxt,wnd,up) (%lx,%lx,%lx) snd_(una,nxt,max) (%lx,%lx,%lx)\n",
21838373Sbde	    (u_long)tp->rcv_nxt, tp->rcv_wnd, (u_long)tp->rcv_up,
21938373Sbde	    (u_long)tp->snd_una, (u_long)tp->snd_nxt, (u_long)tp->snd_max);
22038373Sbde	printf("\tsnd_(wl1,wl2,wnd) (%lx,%lx,%lx)\n",
22138373Sbde	    (u_long)tp->snd_wl1, (u_long)tp->snd_wl2, tp->snd_wnd);
2221541Srgrimes#endif /* TCPDEBUG */
2231541Srgrimes}
224