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