1*4731Swnj /* tcp_usrreq.c 1.23 81/11/03 */ 24567Swnj 34497Swnj #include "../h/param.h" 44567Swnj #include "../h/systm.h" 54664Swnj #include "../h/mbuf.h" 64664Swnj #include "../h/socket.h" 74664Swnj #include "../inet/inet.h" 84664Swnj #include "../inet/inet_systm.h" 94664Swnj #include "../inet/imp.h" 104664Swnj #include "../inet/ip.h" 114664Swnj #include "../inet/tcp.h" 124567Swnj #define TCPFSTAB 134584Swnj #ifdef TCPDEBUG 144584Swnj #define TCPSTATES 154584Swnj #endif 164664Swnj #include "../inet/tcp_fsm.h" 174497Swnj 184567Swnj tcp_timeo() 194497Swnj { 204567Swnj register struct tcb *tp; 214567Swnj int s = splnet(); 22*4731Swnj register u_char *tmp; 23*4731Swnj register int i; 244567Swnj COUNT(TCP_TIMEO); 254497Swnj 264567Swnj /* 274567Swnj * Search through tcb's and update active timers. 284567Swnj */ 294682Swnj for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->tcb_next) { 30*4731Swnj tmp = &tp->t_init; 31*4731Swnj for (i = 0; i < TNTIMERS; i++) 32*4731Swnj if (*tmp && --*tmp == 0) 33*4731Swnj tcp_usrreq(ISTIMER, i, tp, 0); 344567Swnj tp->t_xmt++; 354567Swnj } 364664Swnj tcp_iss += ISSINCR; /* increment iss */ 374567Swnj timeout(tcp_timeo, 0, hz); /* reschedule every second */ 384567Swnj splx(s); 394497Swnj } 404497Swnj 41*4731Swnj /* 42*4731Swnj * Process a TCP user request for tcp tb. If this is a send request 43*4731Swnj * then m is the mbuf chain of send data. If this is a timer expiration 44*4731Swnj * (called from the software clock routine), then timertype tells which timer. 45*4731Swnj */ 46*4731Swnj tcp_usrreq(input, timertype, tp, m) 474584Swnj int input, timertype; 484567Swnj register struct tcb *tp; 49*4731Swnj struct mbuf *m; 504497Swnj { 514567Swnj int s = splnet(); 524567Swnj register int nstate; 534584Swnj #ifdef TCPDEBUG 544584Swnj struct tcp_debug tdb; 554584Swnj #endif 564567Swnj COUNT(TCP_USRREQ); 574497Swnj 584567Swnj nstate = tp->t_state; 594576Swnj tp->tc_flags &= ~TC_NET_KEEP; 60*4731Swnj #ifdef KPROF 614567Swnj acounts[nstate][input]++; 62*4731Swnj #endif 634584Swnj #ifdef TCPDEBUG 644584Swnj if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 654605Swnj tdb_setup(tp, (struct th *)0, input, &tdb); 664584Swnj tdb.td_tim = timertype; 674584Swnj } else 684584Swnj tdb.td_tod = 0; 694584Swnj #endif 70*4731Swnj switch (input) { 714497Swnj 72*4731Swnj /* 73*4731Swnj * Passive open. Create a tcp control block 74*4731Swnj * and enter listen state. 75*4731Swnj */ 76*4731Swnj case IUOPENA: /* 2 */ 77*4731Swnj if (nstate != 0 && nstate != CLOSED) 78*4731Swnj goto bad; 794676Swnj tcp_open(tp, PASSIVE); 804567Swnj nstate = LISTEN; 814567Swnj break; 824497Swnj 83*4731Swnj /* 84*4731Swnj * Active open. Create a tcp control block, 85*4731Swnj * send a SYN and enter SYN_SENT state. 86*4731Swnj */ 87*4731Swnj case IUOPENR: /* 1 */ 88*4731Swnj if (nstate != 0 && nstate != CLOSED) 89*4731Swnj goto bad; 904676Swnj tcp_open(tp, ACTIVE); 914676Swnj tcp_sndctl(tp); 924567Swnj nstate = SYN_SENT; 934567Swnj break; 944497Swnj 95*4731Swnj /* 96*4731Swnj * Tcp close call. Can be generated by a user ioctl (half-close), 97*4731Swnj * or when higher level close occurs, if a close hasn't happened 98*4731Swnj * already. 99*4731Swnj */ 100*4731Swnj case IUCLOSE: 101*4731Swnj switch (nstate) { 1024497Swnj 103*4731Swnj /* 104*4731Swnj * If we are aborting out of a listener or a active 105*4731Swnj * connection which has not yet completed we can just 106*4731Swnj * delete the tcb. 107*4731Swnj */ 108*4731Swnj case LISTEN: 109*4731Swnj case SYN_SENT: /* 10 */ 110*4731Swnj tcp_close(tp, UCLOSED); 111*4731Swnj nstate = CLOSED; 112*4731Swnj break; 113*4731Swnj 114*4731Swnj /* 115*4731Swnj * If we have gotten as far as receiving a syn from 116*4731Swnj * our foreign peer, we must be sure to send a FIN. 117*4731Swnj * If we have gotten a FIN from the foreign peer already 118*4731Swnj * (CLOSE_WAIT state), then all that remains is to wait 119*4731Swnj * for his ack of the FIN (LAST_ACK state). If we have 120*4731Swnj * not gotten a FIN from the foreign peer then we need 121*4731Swnj * to either: 122*4731Swnj * 1. rcv ack of our FIN (to FIN_W2) and then 123*4731Swnj * send an ACK (to TIME_WAIT) and timeout at 2*MSL. 124*4731Swnj * or 2. receive hist FIN (to CLOSING), send an ACK 125*4731Swnj * (to TIME_WAIT), and then timeout. 126*4731Swnj * In any case this starts with a transition to FIN_W1 here. 127*4731Swnj */ 128*4731Swnj case SYN_RCVD: /* 24,25 */ 129*4731Swnj case L_SYN_RCVD: 130*4731Swnj case ESTAB: 131*4731Swnj case CLOSE_WAIT: /* 10 */ 132*4731Swnj tp->tc_flags |= TC_SND_FIN; 133*4731Swnj tcp_sndctl(tp); 134*4731Swnj tp->tc_flags |= TC_USR_CLOSED; 135*4731Swnj nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK; 136*4731Swnj break; 137*4731Swnj 138*4731Swnj /* 139*4731Swnj * In these states the user has already closed; 140*4731Swnj * trying to close again is an error. 141*4731Swnj */ 142*4731Swnj case FIN_W1: 143*4731Swnj case FIN_W2: 144*4731Swnj case TIME_WAIT: 145*4731Swnj case CLOSING: 146*4731Swnj case LAST_ACK: 147*4731Swnj case RCV_WAIT: 148*4731Swnj to_user(tp->t_ucb, UCLSERR); 149*4731Swnj break; 150*4731Swnj 151*4731Swnj default: 152*4731Swnj goto bad; 153*4731Swnj } 1544567Swnj break; 1554497Swnj 156*4731Swnj /* 157*4731Swnj * TCP Timer processing. 158*4731Swnj * Timers should expire only on open connections 159*4731Swnj * not in LISTEN state. 160*4731Swnj */ 161*4731Swnj case ISTIMER: /* 14,17,34,35,36,37,38 */ 162*4731Swnj switch (nstate) { 163*4731Swnj 164*4731Swnj case 0: 165*4731Swnj case CLOSED: 166*4731Swnj case LISTEN: 167*4731Swnj goto bad; 168*4731Swnj 169*4731Swnj default: 170*4731Swnj nstate = tcp_timers(tp, timertype); 171*4731Swnj } 1724567Swnj break; 1734497Swnj 174*4731Swnj /* 175*4731Swnj * User notification of more window availability after 176*4731Swnj * reading out data. This should not happen before a connection 177*4731Swnj * is established or after it is closed. 178*4731Swnj * If the foreign peer has closed and the local entity 179*4731Swnj * has not, inform him of the FIN (give end of file). 180*4731Swnj * If the local entity is in RCV_WAIT state (draining data 181*4731Swnj * out of the TCP buffers after foreign close) and there 182*4731Swnj * is no more data, institute a close. 183*4731Swnj */ 184*4731Swnj case IURECV: /* 42 */ 185*4731Swnj if (nstate < ESTAB || nstate == CLOSED) 186*4731Swnj goto bad; 187*4731Swnj tcp_sndwin(tp); /* send new window */ 1884691Swnj if ((tp->tc_flags&TC_FIN_RCVD) && 1894691Swnj (tp->tc_flags&TC_USR_CLOSED) == 0 && 1904691Swnj rcv_empty(tp)) 1914691Swnj to_user(tp, UCLOSED); 192*4731Swnj if (nstate == RCV_WAIT && rcv_empty(tp)) { 1934676Swnj tcp_close(tp, UCLOSED); 1944567Swnj nstate = CLOSED; 195*4731Swnj } 1964567Swnj break; 1974497Swnj 198*4731Swnj /* 199*4731Swnj * Send request on open connection. 200*4731Swnj * Should not happen if the connection is not yet established. 201*4731Swnj * Allowed only on ESTAB connection and after FIN from 202*4731Swnj * foreign peer. 203*4731Swnj */ 204*4731Swnj case IUSEND: /* 40,41 */ 205*4731Swnj switch (nstate) { 2064567Swnj 207*4731Swnj case ESTAB: 208*4731Swnj case CLOSE_WAIT: 209*4731Swnj nstate = tcp_usrsend(tp, m); 210*4731Swnj break; 211*4731Swnj 212*4731Swnj default: 213*4731Swnj if (nstate < ESTAB) 214*4731Swnj goto bad; 215*4731Swnj to_user(tp, UCLSERR); 216*4731Swnj break; 217*4731Swnj } 2184567Swnj break; 2194567Swnj 220*4731Swnj /* 221*4731Swnj * User abort of connection. 222*4731Swnj * If a SYN has been received, but we have not exchanged FINs 223*4731Swnj * then we need to send an RST. In any case we then 224*4731Swnj * enter closed state. 225*4731Swnj */ 226*4731Swnj case IUABORT: /* 44,45 */ 227*4731Swnj if (nstate == 0 || nstate == CLOSED) 228*4731Swnj break; 229*4731Swnj switch (nstate) { 2304567Swnj 231*4731Swnj case 0: 232*4731Swnj case CLOSED: 233*4731Swnj break; 2344567Swnj 235*4731Swnj case SYN_RCVD: 236*4731Swnj case ESTAB: 237*4731Swnj case FIN_W1: 238*4731Swnj case FIN_W2: 239*4731Swnj case CLOSE_WAIT: 240*4731Swnj tp->tc_flags |= TC_SND_RST; 241*4731Swnj tcp_sndnull(tp); 242*4731Swnj /* fall into ... */ 243*4731Swnj 244*4731Swnj default: 245*4731Swnj tcp_close(tp, UABORT); 246*4731Swnj nstate = CLOSED; 247*4731Swnj } 2484567Swnj break; 2494567Swnj 250*4731Swnj /* 251*4731Swnj * Network down entry. Discard the tcb and force 252*4731Swnj * the state to be closed, ungracefully. 253*4731Swnj */ 254*4731Swnj case INCLEAR: /* 47 */ 255*4731Swnj if (nstate == 0 || nstate == CLOSED) 256*4731Swnj break; 2574676Swnj tcp_close(tp, UNETDWN); 2584567Swnj nstate = CLOSED; 2594567Swnj break; 2604567Swnj 261*4731Swnj default: 262*4731Swnj panic("tcp_usrreq"); 263*4731Swnj bad: 264*4731Swnj printf("tcp: bad state: tcb=%x state=%d input=%d\n", 265*4731Swnj tp, tp->t_state, input); 266*4731Swnj nstate = EFAILEC; 2674567Swnj break; 2684567Swnj } 2694567Swnj #ifdef TCPDEBUG 2704605Swnj if (tdb.td_tod) 2714605Swnj tdb_stuff(&tdb, nstate); 2724567Swnj #endif 2734567Swnj /* YECH */ 2744567Swnj switch (nstate) { 2754567Swnj 2764584Swnj case CLOSED: 2774567Swnj case SAME: 2784567Swnj break; 2794567Swnj 2804567Swnj case EFAILEC: 281*4731Swnj if (m) 282*4731Swnj m_freem(dtom(m)); 2834567Swnj break; 2844567Swnj 2854567Swnj default: 2864567Swnj tp->t_state = nstate; 2874567Swnj break; 2884567Swnj } 2894567Swnj splx(s); 2904497Swnj } 2914497Swnj 2924682Swnj /* 2934682Swnj * Open routine, called to initialize newly created tcb fields. 2944682Swnj */ 2954682Swnj tcp_open(tp, mode) 2964567Swnj register struct tcb *tp; 2974567Swnj int mode; 2984497Swnj { 2994682Swnj register struct ucb *up = tp->t_ucb; 3004682Swnj COUNT(TCP_OPEN); 3014497Swnj 3024682Swnj /* 3034682Swnj * Link in tcb queue and make 3044682Swnj * initialize empty reassembly queue. 3054682Swnj */ 3064682Swnj tp->tcb_next = tcb.tcb_next; 3074682Swnj tcb.tcb_next->tcb_prev = tp; 3084682Swnj tp->tcb_prev = (struct tcb *)&tcb; 3094682Swnj tcb.tcb_next = tp; 3104682Swnj tp->t_rcv_next = tp->t_rcv_prev = (struct th *)tp; 3114497Swnj 3124682Swnj /* 3134682Swnj * Initialize sequence numbers and 3144682Swnj * round trip retransmit timer. 3154682Swnj * (Other fields were init'd to zero when tcb allocated.) 3164682Swnj */ 3174567Swnj tp->t_xmtime = T_REXMT; 3184682Swnj tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una = 3194682Swnj tp->iss = tcp_iss; 3204567Swnj tp->snd_off = tp->iss + 1; 3214664Swnj tcp_iss += (ISSINCR >> 1) + 1; 3224567Swnj 3234682Swnj /* 3244682Swnj * Set timeout for open. 3254682Swnj * SHOULD THIS BE A HIGHER LEVEL FUNCTION!?! THINK SO. 3264682Swnj */ 3274682Swnj if (up->uc_timeo) 3284682Swnj tp->t_init = up->uc_timeo; 3294682Swnj else if (mode == ACTIVE) 3304682Swnj tp->t_init = T_INIT; 3314682Swnj /* else 3324682Swnj tp->t_init = 0; */ 3334682Swnj up->uc_timeo = 0; /* ### */ 3344497Swnj } 3354497Swnj 3364682Swnj /* 3374682Swnj * Internal close of a connection, shutting down the tcb. 3384682Swnj */ 3394676Swnj tcp_close(tp, state) 3404567Swnj register struct tcb *tp; 3414567Swnj short state; 3424497Swnj { 3434682Swnj register struct ucb *up = tp->t_ucb; 3444567Swnj register struct th *t; 3454567Swnj register struct mbuf *m; 3464682Swnj COUNT(TCP_CLOSE); 3474497Swnj 3484682Swnj /* 3494682Swnj * Cancel all timers. 3504682Swnj * SHOULD LOOP HERE !?! 3514682Swnj */ 3524567Swnj tp->t_init = tp->t_rexmt = tp->t_rexmttl = tp->t_persist = 3534567Swnj tp->t_finack = 0; 3544497Swnj 3554682Swnj /* 3564682Swnj * Remque the tcb 3574682Swnj */ 3584682Swnj tp->tcb_prev->tcb_next = tp->tcb_next; 3594682Swnj tp->tcb_next->tcb_prev = tp->tcb_prev; 3604567Swnj 3614682Swnj /* 3624682Swnj * Discard all buffers... 3634682Swnj * 3644682Swnj * SHOULD COUNT EACH RESOURCE TO 0 AND PANIC IF CONFUSED 3654682Swnj */ 3664567Swnj for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next) 3674567Swnj m_freem(dtom(t)); 3684567Swnj if (up->uc_rbuf != NULL) { 3694567Swnj m_freem(up->uc_rbuf); 3704567Swnj up->uc_rbuf = NULL; 3714567Swnj } 3724657Swnj up->uc_rcc = 0; 3734567Swnj if (up->uc_sbuf != NULL) { 3744567Swnj m_freem(up->uc_sbuf); 3754567Swnj up->uc_sbuf = NULL; 3764567Swnj } 3774592Swnj up->uc_ssize = 0; 3784567Swnj for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) { 3794567Swnj m_freem(m); 3804567Swnj tp->t_rcv_unack = NULL; 3814567Swnj } 3824682Swnj 3834682Swnj /* 3844682Swnj * Free tcp send template. 3854682Swnj */ 3864664Swnj if (up->uc_template) { 3874664Swnj m_free(dtom(up->uc_template)); 3884664Swnj up->uc_template = 0; 3894664Swnj } 3904682Swnj 3914682Swnj /* 3924682Swnj * Free the tcb 3934682Swnj * WOULD THIS BETTER BE DONE AT USER CLOSE? 3944682Swnj */ 3954670Swnj wmemfree((caddr_t)tp, 1024); 3964567Swnj up->uc_tcb = NULL; 3974567Swnj 3984682Swnj /* 3994682Swnj * Lower buffer allocation. 4004682Swnj * SHOULD BE A M_ROUTINE CALL. 4014682Swnj */ 4024664Swnj mbstat.m_lowat -= up->uc_snd + (up->uc_rhiwat/MSIZE) + 2; 4034664Swnj mbstat.m_hiwat = 2 * mbstat.m_lowat; 4044682Swnj 4054682Swnj /* 4064682Swnj * Free routing table entry. 4074682Swnj */ 4084567Swnj if (up->uc_host != NULL) { 4094567Swnj h_free(up->uc_host); 4104567Swnj up->uc_host = NULL; 4114567Swnj } 4124567Swnj 4134682Swnj /* 4144682Swnj * If user has initiated close (via close call), delete ucb 4154682Swnj * entry, otherwise just wakeup so user can issue close call 4164682Swnj */ 4174576Swnj if (tp->tc_flags&TC_USR_ABORT) 4184567Swnj up->uc_proc = NULL; 4194567Swnj else 4204682Swnj to_user(up, state); /* ### */ 4214497Swnj } 4224497Swnj 4234682Swnj /* 4244682Swnj * User routine to send data queue headed by m0 into the protocol. 4254682Swnj */ 4264678Swnj tcp_usrsend(tp, m0) 4274584Swnj register struct tcb *tp; 4284584Swnj struct mbuf *m0; 4294497Swnj { 4304497Swnj register struct mbuf *m, *n; 4314584Swnj register struct ucb *up = tp->t_ucb; 4324497Swnj register off; 4334574Swnj seq_t last; 4344682Swnj COUNT(TCP_USRSEND); 4354497Swnj 4364497Swnj last = tp->snd_off; 4374584Swnj for (m = n = m0; m != NULL; m = m->m_next) { 4384497Swnj up->uc_ssize++; 4394591Swnj if (m->m_off > MMAXOFF) 4404588Swnj up->uc_ssize += NMBPG; 4414497Swnj last += m->m_len; 4424497Swnj } 4434588Swnj if ((m = up->uc_sbuf) == NULL) 4444588Swnj up->uc_sbuf = n; 4454588Swnj else { 4464588Swnj while (m->m_next != NULL) { 4474497Swnj m = m->m_next; 4484497Swnj last += m->m_len; 4494497Swnj } 4504591Swnj if (m->m_off <= MMAXOFF) { 4514588Swnj last += m->m_len; 4524588Swnj off = m->m_off + m->m_len; 4534591Swnj while (n && n->m_off <= MMAXOFF && 4544591Swnj (MMAXOFF - off) >= n->m_len) { 4554588Swnj bcopy((caddr_t)((int)n + n->m_off), 4564588Swnj (caddr_t)((int)m + off), n->m_len); 4574588Swnj m->m_len += n->m_len; 4584588Swnj off += n->m_len; 4594588Swnj up->uc_ssize--; 4604588Swnj n = m_free(n); 4614588Swnj } 4624497Swnj } 4634497Swnj m->m_next = n; 4644588Swnj } 4654588Swnj if (up->uc_flags & UEOL) 4664497Swnj tp->snd_end = last; 4674588Swnj if (up->uc_flags & UURG) { 4684497Swnj tp->snd_urp = last+1; 4694576Swnj tp->tc_flags |= TC_SND_URG; 4704567Swnj } 4714678Swnj tcp_send(tp); 4724567Swnj return (SAME); 4734497Swnj } 4744497Swnj 4754682Swnj /* 4764682Swnj * TCP timer went off processing. 4774682Swnj */ 4784584Swnj tcp_timers(tp, timertype) 4794584Swnj register struct tcb *tp; 4804584Swnj int timertype; 4814497Swnj { 4824497Swnj 4834567Swnj COUNT(TCP_TIMERS); 4844584Swnj switch (timertype) { 4854497Swnj 4864567Swnj case TINIT: /* initialization timer */ 4874576Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */ 4884676Swnj tcp_close(tp, UINTIMO); 4894567Swnj return (CLOSED); 4904567Swnj } 4914567Swnj return (SAME); 4924497Swnj 4934567Swnj case TFINACK: /* fin-ack timer */ 4944567Swnj switch (tp->t_state) { 4954497Swnj 4964567Swnj case TIME_WAIT: 4974567Swnj /* 4984567Swnj * We can be sure our ACK of foreign FIN was rcvd, 4994567Swnj * and can close if no data left for user. 5004567Swnj */ 5014567Swnj if (rcv_empty(tp)) { 5024676Swnj tcp_close(tp, UCLOSED); /* 14 */ 5034567Swnj return (CLOSED); 5044567Swnj } 5054567Swnj return (RCV_WAIT); /* 17 */ 5064497Swnj 507*4731Swnj case CLOSING: 5084576Swnj tp->tc_flags |= TC_WAITED_2_ML; 5094567Swnj return (SAME); 5104497Swnj 5114567Swnj default: 5124567Swnj return (SAME); 5134567Swnj } 5144497Swnj 5154567Swnj case TREXMT: /* retransmission timer */ 5164567Swnj if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 5174567Swnj /* 5184567Swnj * Set up for a retransmission, increase rexmt time 5194567Swnj * in case of multiple retransmissions. 5204567Swnj */ 5214567Swnj tp->snd_nxt = tp->snd_una; 5224576Swnj tp->tc_flags |= TC_REXMT; 5234567Swnj tp->t_xmtime = tp->t_xmtime << 1; 5244567Swnj if (tp->t_xmtime > T_REMAX) 5254567Swnj tp->t_xmtime = T_REMAX; 5264678Swnj tcp_send(tp); 5274567Swnj } 5284567Swnj return (SAME); 5294497Swnj 5304567Swnj case TREXMTTL: /* retransmit too long */ 5314567Swnj if (tp->t_rtl_val > tp->snd_una) /* 36 */ 5324567Swnj to_user(tp->t_ucb, URXTIMO); 5334567Swnj /* 5344567Swnj * If user has already closed, abort the connection. 5354567Swnj */ 5364576Swnj if (tp->tc_flags & TC_USR_CLOSED) { 5374676Swnj tcp_close(tp, URXTIMO); 5384567Swnj return (CLOSED); 5394567Swnj } 5404567Swnj return (SAME); 5414497Swnj 5424567Swnj case TPERSIST: /* persist timer */ 5434567Swnj /* 5444567Swnj * Force a byte send through closed window. 5454567Swnj */ 5464576Swnj tp->tc_flags |= TC_FORCE_ONE; 5474678Swnj tcp_send(tp); 5484567Swnj return (SAME); 5494567Swnj } 5504567Swnj panic("tcp_timers"); 5514497Swnj } 5524497Swnj 5534567Swnj /* THIS ROUTINE IS A CROCK */ 5544567Swnj to_user(up, state) 5554567Swnj register struct ucb *up; 5564567Swnj register short state; 5574497Swnj { 5584567Swnj COUNT(TO_USER); 5594497Swnj 5604567Swnj up->uc_state |= state; 5614567Swnj netwakeup(up); 5624567Swnj if (state == UURGENT) 5634567Swnj psignal(up->uc_proc, SIGURG); 5644497Swnj } 5654584Swnj 5664584Swnj #ifdef TCPDEBUG 5674682Swnj /* 5684682Swnj * TCP debugging utility subroutines. 5694682Swnj * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID. 5704682Swnj */ 5714670Swnj tdb_setup(tp, n, input, tdp) 5724670Swnj struct tcb *tp; 5734670Swnj register struct th *n; 5744670Swnj int input; 5754670Swnj register struct tcp_debug *tdp; 5764670Swnj { 5774670Swnj 5784682Swnj COUNT(TDB_SETUP); 5794670Swnj tdp->td_tod = time; 5804670Swnj tdp->td_tcb = tp; 5814670Swnj tdp->td_old = tp->t_state; 5824670Swnj tdp->td_inp = input; 5834670Swnj tdp->td_tim = 0; 5844670Swnj tdp->td_new = -1; 5854670Swnj if (n) { 5864670Swnj tdp->td_sno = n->t_seq; 5874670Swnj tdp->td_ano = n->t_ackno; 5884670Swnj tdp->td_wno = n->t_win; 5894670Swnj tdp->td_lno = n->t_len; 5904670Swnj tdp->td_flg = n->th_flags; 5914670Swnj } else 5924670Swnj tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno = 5934670Swnj tdp->td_flg = 0; 5944670Swnj } 5954670Swnj 5964670Swnj tdb_stuff(tdp, nstate) 5974670Swnj struct tcp_debug *tdp; 5984670Swnj int nstate; 5994670Swnj { 6004682Swnj COUNT(TDB_STUFF); 6014670Swnj 6024670Swnj tdp->td_new = nstate; 6034670Swnj tcp_debug[tdbx++ % TDBSIZE] = *tdp; 6044670Swnj if (tcpconsdebug & 2) 6054670Swnj tcp_prt(tdp); 6064670Swnj } 6074682Swnj 6084682Swnj tcp_prt(tdp) 6094682Swnj register struct tcp_debug *tdp; 6104682Swnj { 6114682Swnj COUNT(TCP_PRT); 6124682Swnj 6134698Swnj printf("%x ", ((int)tdp->td_tcb)&0xffffff); 6144698Swnj if (tdp->td_inp == INSEND) { 6154698Swnj printf("SEND #%x", tdp->td_sno); 6164698Swnj tdp->td_lno = ntohs(tdp->td_lno); 6174698Swnj tdp->td_wno = ntohs(tdp->td_wno); 6184698Swnj } else { 6194698Swnj if (tdp->td_inp == INRECV) 6204698Swnj printf("RCV #%x ", tdp->td_sno); 6214698Swnj printf("%s.%s", 6224698Swnj tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]); 6234698Swnj if (tdp->td_inp == ISTIMER) 6244698Swnj printf("(%s)", tcptimers[tdp->td_tim]); 6254698Swnj printf(" -> %s", 6264698Swnj tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]); 6274698Swnj if (tdp->td_new == -1) 6284698Swnj printf(" (FAILED)"); 6294698Swnj } 6304682Swnj /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */ 6314698Swnj if (tdp->td_lno) 6324698Swnj printf(" len=%d", tdp->td_lno); 6334698Swnj if (tdp->td_wno) 6344698Swnj printf(" win=%d", tdp->td_wno); 6354698Swnj if (tdp->td_flg & TH_FIN) printf(" FIN"); 6364698Swnj if (tdp->td_flg & TH_SYN) printf(" SYN"); 6374698Swnj if (tdp->td_flg & TH_RST) printf(" RST"); 6384698Swnj if (tdp->td_flg & TH_EOL) printf(" EOL"); 6394698Swnj if (tdp->td_flg & TH_ACK) printf(" ACK %x", tdp->td_ano); 6404698Swnj if (tdp->td_flg & TH_URG) printf(" URG"); 6414682Swnj printf("\n"); 6424682Swnj } 6434670Swnj #endif 644