1*4809Swnj /* tcp_usrreq.c 1.26 81/11/08 */ 24567Swnj 34497Swnj #include "../h/param.h" 44567Swnj #include "../h/systm.h" 54664Swnj #include "../h/mbuf.h" 64664Swnj #include "../h/socket.h" 7*4809Swnj #include "../h/socketvar.h" 8*4809Swnj #include "../h/protosw.h" 9*4809Swnj #include "../net/inet.h" 10*4809Swnj #include "../net/inet_systm.h" 11*4809Swnj #include "../net/imp.h" 12*4809Swnj #include "../net/ip.h" 13*4809Swnj #include "../net/tcp.h" 144567Swnj #define TCPFSTAB 154584Swnj #ifdef TCPDEBUG 164584Swnj #define TCPSTATES 174584Swnj #endif 18*4809Swnj #include "../net/tcp_fsm.h" 19*4809Swnj #include "../net/tcp_var.h" 20*4809Swnj #include "/usr/include/errno.h" 214497Swnj 22*4809Swnj struct tcb *tcp_attach(); 23*4809Swnj 244734Swnj /* 25*4809Swnj * Tcp initialization 26*4809Swnj */ 27*4809Swnj tcp_init() 28*4809Swnj { 29*4809Swnj 30*4809Swnj tcp_iss = 1; /* wrong */ 31*4809Swnj tcb.tcb_next = tcb.tcb_prev = (struct tcb *)&tcb; 32*4809Swnj } 33*4809Swnj 34*4809Swnj /* 354734Swnj * Tcp finite state machine entries for timer and user generated 364734Swnj * requests. These routines raise the ipl to that of the network 374734Swnj * to prevent reentry. In particluar, this requires that the software 384734Swnj * clock interrupt have lower priority than the network so that 394734Swnj * we can enter the network from timeout routines without improperly 404734Swnj * nesting the interrupt stack. 414734Swnj */ 424734Swnj 434734Swnj /* 44*4809Swnj * Tcp protocol timeout routine called every 500 ms. 454734Swnj * Updates the timers in all active tcb's and 464734Swnj * causes finite state machine actions if timers expire. 474734Swnj */ 48*4809Swnj tcp_slowtimo() 494497Swnj { 504567Swnj register struct tcb *tp; 514567Swnj int s = splnet(); 52*4809Swnj register short *tmp; 534731Swnj register int i; 544567Swnj COUNT(TCP_TIMEO); 554497Swnj 564567Swnj /* 574567Swnj * Search through tcb's and update active timers. 584567Swnj */ 59*4809Swnj tp = tcb.tcb_next; 60*4809Swnj for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next) { 614731Swnj tmp = &tp->t_init; 624735Swnj for (i = 0; i < TNTIMERS; i++) { 634731Swnj if (*tmp && --*tmp == 0) 64*4809Swnj tcp_usrreq(tp->t_socket, PRU_SLOWTIMO, 0, i); 654735Swnj tmp++; 664735Swnj } 674567Swnj tp->t_xmt++; 684567Swnj } 69*4809Swnj tcp_iss += ISSINCR/2; /* increment iss */ 704567Swnj splx(s); 714497Swnj } 724497Swnj 734731Swnj /* 744734Swnj * Cancel all timers for tcp tp. 754734Swnj */ 764734Swnj tcp_tcancel(tp) 774734Swnj struct tcb *tp; 784734Swnj { 79*4809Swnj register short *tmp = &tp->t_init; 804734Swnj register int i; 814734Swnj 824734Swnj for (i = 0; i < TNTIMERS; i++) 834734Swnj *tmp++ = 0; 844734Swnj } 854734Swnj 864734Swnj /* 874731Swnj * Process a TCP user request for tcp tb. If this is a send request 884731Swnj * then m is the mbuf chain of send data. If this is a timer expiration 894731Swnj * (called from the software clock routine), then timertype tells which timer. 904731Swnj */ 91*4809Swnj tcp_usrreq(so, req, m, addr) 92*4809Swnj struct socket *so; 93*4809Swnj int req; 944731Swnj struct mbuf *m; 95*4809Swnj caddr_t addr; 964497Swnj { 97*4809Swnj register struct tcb *tp = (struct tcb *)so->so_pcb; 984567Swnj int s = splnet(); 994567Swnj register int nstate; 1004584Swnj #ifdef TCPDEBUG 1014584Swnj struct tcp_debug tdb; 1024584Swnj #endif 103*4809Swnj int error = 0; 1044567Swnj COUNT(TCP_USRREQ); 1054497Swnj 106*4809Swnj if (tp) { 107*4809Swnj nstate = tp->t_state; 108*4809Swnj tp->tc_flags &= ~TC_NET_KEEP; 109*4809Swnj } else 110*4809Swnj if (req != PRU_ATTACH) 111*4809Swnj return (ENOTCONN); 1124731Swnj #ifdef KPROF 113*4809Swnj acounts[nstate][req]++; 1144731Swnj #endif 1154584Swnj #ifdef TCPDEBUG 116*4809Swnj if (tp && ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug)) { 117*4809Swnj tdb_setup(tp, (struct th *)0, req, &tdb); 1184584Swnj tdb.td_tim = timertype; 1194584Swnj } else 1204584Swnj tdb.td_tod = 0; 1214584Swnj #endif 122*4809Swnj switch (req) { 1234497Swnj 1244731Swnj /* 125*4809Swnj * Attach a tcp control block to this socket. 126*4809Swnj * TCP is not multicast, so this is possible 127*4809Swnj * only if no connection currently exists. 1284731Swnj */ 129*4809Swnj case PRU_ATTACH: 130*4809Swnj if (tp) 131*4809Swnj error = EISCONN; 132*4809Swnj else 133*4809Swnj tp = tcp_attach(so, &error); 134*4809Swnj nstate = CLOSED; 1354567Swnj break; 1364497Swnj 1374731Swnj /* 138*4809Swnj * Detach the TCP from this socket. This 139*4809Swnj * is possible only if a connection currently exists. 1404731Swnj */ 141*4809Swnj case PRU_DETACH: 142*4809Swnj so->so_pcb = 0; 143*4809Swnj break; 144*4809Swnj 145*4809Swnj /* 146*4809Swnj * Form connection: send a SYN. 147*4809Swnj */ 148*4809Swnj case PRU_CONNECT: 1494731Swnj if (nstate != 0 && nstate != CLOSED) 1504731Swnj goto bad; 1514676Swnj tcp_sndctl(tp); 1524567Swnj nstate = SYN_SENT; 1534567Swnj break; 1544497Swnj 155*4809Swnj case PRU_DISCONNECT: 156*4809Swnj so->so_pcb = 0; 157*4809Swnj tcp_destroy(tp); 158*4809Swnj break; 159*4809Swnj 1604731Swnj /* 161*4809Swnj * Declare no further transmissions. 162*4809Swnj * Can be generated by a user ioctl (half-close), 1634731Swnj * or when higher level close occurs, if a close hasn't happened 1644731Swnj * already. 1654731Swnj */ 166*4809Swnj case PRU_SHUTDOWN: 1674731Swnj switch (nstate) { 1684497Swnj 1694731Swnj /* 1704731Swnj * If we are aborting out of a listener or a active 1714731Swnj * connection which has not yet completed we can just 1724731Swnj * delete the tcb. 1734731Swnj */ 1744731Swnj case LISTEN: 1754734Swnj case SYN_SENT: 1764731Swnj nstate = CLOSED; 1774731Swnj break; 1784731Swnj 1794731Swnj /* 1804731Swnj * If we have gotten as far as receiving a syn from 1814731Swnj * our foreign peer, we must be sure to send a FIN. 1824731Swnj * If we have gotten a FIN from the foreign peer already 1834731Swnj * (CLOSE_WAIT state), then all that remains is to wait 1844731Swnj * for his ack of the FIN (LAST_ACK state). If we have 1854731Swnj * not gotten a FIN from the foreign peer then we need 1864731Swnj * to either: 1874731Swnj * 1. rcv ack of our FIN (to FIN_W2) and then 1884731Swnj * send an ACK (to TIME_WAIT) and timeout at 2*MSL. 1894731Swnj * or 2. receive hist FIN (to CLOSING), send an ACK 1904731Swnj * (to TIME_WAIT), and then timeout. 1914731Swnj * In any case this starts with a transition to FIN_W1 here. 1924731Swnj */ 1934734Swnj case SYN_RCVD: 1944731Swnj case L_SYN_RCVD: 1954731Swnj case ESTAB: 1964734Swnj case CLOSE_WAIT: 1974731Swnj tp->tc_flags |= TC_SND_FIN; 1984731Swnj tcp_sndctl(tp); 1994731Swnj tp->tc_flags |= TC_USR_CLOSED; 2004731Swnj nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK; 2014731Swnj break; 2024731Swnj 2034731Swnj /* 2044731Swnj * In these states the user has already closed; 2054731Swnj * trying to close again is an error. 2064731Swnj */ 2074731Swnj case FIN_W1: 2084731Swnj case FIN_W2: 2094731Swnj case TIME_WAIT: 2104731Swnj case CLOSING: 2114731Swnj case LAST_ACK: 2124731Swnj case RCV_WAIT: 2134731Swnj break; 2144731Swnj 2154731Swnj default: 2164731Swnj goto bad; 2174731Swnj } 2184567Swnj break; 2194497Swnj 2204731Swnj /* 2214731Swnj * User notification of more window availability after 2224731Swnj * reading out data. This should not happen before a connection 2234731Swnj * is established or after it is closed. 2244731Swnj * If the foreign peer has closed and the local entity 2254731Swnj * has not, inform him of the FIN (give end of file). 2264731Swnj * If the local entity is in RCV_WAIT state (draining data 2274731Swnj * out of the TCP buffers after foreign close) and there 2284731Swnj * is no more data, institute a close. 2294731Swnj */ 230*4809Swnj case PRU_RCVD: 2314731Swnj if (nstate < ESTAB || nstate == CLOSED) 2324731Swnj goto bad; 2334734Swnj tcp_sndwin(tp); 2344691Swnj if ((tp->tc_flags&TC_FIN_RCVD) && 2354691Swnj (tp->tc_flags&TC_USR_CLOSED) == 0 && 2364691Swnj rcv_empty(tp)) 237*4809Swnj tcp_error(tp, ESHUTDOWN); 238*4809Swnj if (nstate == RCV_WAIT && rcv_empty(tp)) 2394567Swnj nstate = CLOSED; 2404567Swnj break; 2414497Swnj 2424731Swnj /* 2434731Swnj * Send request on open connection. 2444731Swnj * Should not happen if the connection is not yet established. 2454731Swnj * Allowed only on ESTAB connection and after FIN from 2464731Swnj * foreign peer. 2474731Swnj */ 248*4809Swnj case PRU_SEND: 2494731Swnj switch (nstate) { 2504567Swnj 2514731Swnj case ESTAB: 2524731Swnj case CLOSE_WAIT: 2534731Swnj nstate = tcp_usrsend(tp, m); 2544731Swnj break; 2554731Swnj 2564731Swnj default: 2574731Swnj if (nstate < ESTAB) 2584731Swnj goto bad; 259*4809Swnj m_freem(m); 260*4809Swnj /* tcp_user(tp, UCLSERR); */ 2614731Swnj break; 2624731Swnj } 2634567Swnj break; 2644567Swnj 2654731Swnj /* 2664731Swnj * User abort of connection. 2674731Swnj * If a SYN has been received, but we have not exchanged FINs 2684731Swnj * then we need to send an RST. In any case we then 2694731Swnj * enter closed state. 2704731Swnj */ 271*4809Swnj case PRU_ABORT: 2724731Swnj if (nstate == 0 || nstate == CLOSED) 2734731Swnj break; 2744731Swnj switch (nstate) { 2754567Swnj 2764731Swnj case 0: 2774731Swnj case CLOSED: 2784731Swnj break; 2794567Swnj 2804731Swnj case SYN_RCVD: 2814731Swnj case ESTAB: 2824731Swnj case FIN_W1: 2834731Swnj case FIN_W2: 2844731Swnj case CLOSE_WAIT: 2854731Swnj tp->tc_flags |= TC_SND_RST; 2864731Swnj tcp_sndnull(tp); 2874731Swnj /* fall into ... */ 2884731Swnj 2894731Swnj default: 2904731Swnj nstate = CLOSED; 2914731Swnj } 2924567Swnj break; 2934567Swnj 2944731Swnj /* 2954731Swnj * Network down entry. Discard the tcb and force 2964731Swnj * the state to be closed, ungracefully. 2974731Swnj */ 298*4809Swnj case PRU_CLEAR: 2994731Swnj if (nstate == 0 || nstate == CLOSED) 3004731Swnj break; 3014567Swnj nstate = CLOSED; 3024567Swnj break; 3034567Swnj 304*4809Swnj /* 305*4809Swnj * Ioctl on protocols. 306*4809Swnj */ 307*4809Swnj case PRU_CONTROL: 308*4809Swnj break; 309*4809Swnj 310*4809Swnj /* 311*4809Swnj * TCP Timer processing. 312*4809Swnj * Timers should expire only on open connections 313*4809Swnj * not in LISTEN state. 314*4809Swnj */ 315*4809Swnj case PRU_SLOWTIMO: 316*4809Swnj switch (nstate) { 317*4809Swnj 318*4809Swnj case 0: 319*4809Swnj case CLOSED: 320*4809Swnj case LISTEN: 321*4809Swnj goto bad; 322*4809Swnj 323*4809Swnj default: 324*4809Swnj nstate = tcp_timers(tp, (int)addr); 325*4809Swnj } 326*4809Swnj break; 327*4809Swnj 3284731Swnj default: 3294731Swnj panic("tcp_usrreq"); 3304731Swnj bad: 3314731Swnj printf("tcp: bad state: tcb=%x state=%d input=%d\n", 332*4809Swnj tp, tp->t_state, req); 3334731Swnj nstate = EFAILEC; 3344567Swnj break; 3354567Swnj } 3364567Swnj #ifdef TCPDEBUG 3374605Swnj if (tdb.td_tod) 3384605Swnj tdb_stuff(&tdb, nstate); 3394567Swnj #endif 3404567Swnj /* YECH */ 3414567Swnj switch (nstate) { 3424567Swnj 3434584Swnj case CLOSED: 3444567Swnj case SAME: 3454567Swnj break; 3464567Swnj 3474567Swnj case EFAILEC: 3484731Swnj if (m) 3494731Swnj m_freem(dtom(m)); 3504567Swnj break; 3514567Swnj 3524567Swnj default: 3534567Swnj tp->t_state = nstate; 3544567Swnj break; 3554567Swnj } 3564567Swnj splx(s); 3574497Swnj } 3584497Swnj 359*4809Swnj tcp_sense() 360*4809Swnj { 361*4809Swnj 362*4809Swnj } 363*4809Swnj 3644682Swnj /* 3654682Swnj * Open routine, called to initialize newly created tcb fields. 3664682Swnj */ 367*4809Swnj struct tcb * 368*4809Swnj tcp_attach(so) 369*4809Swnj register struct socket *so; 370*4809Swnj { 3714567Swnj register struct tcb *tp; 372*4809Swnj COUNT(TCP_ATTACH); 3734497Swnj 3744682Swnj /* 3754682Swnj * Link in tcb queue and make 3764682Swnj * initialize empty reassembly queue. 3774682Swnj */ 378*4809Swnj tp->tcb_hd.tcb_next = tcb.tcb_next; 379*4809Swnj tcb.tcb_next->tcb_hd.tcb_prev = tp; 380*4809Swnj tp->tcb_hd.tcb_prev = (struct tcb *)&tcb; 3814682Swnj tcb.tcb_next = tp; 382*4809Swnj tp->tcb_hd.seg_next = tp->tcb_hd.seg_prev = (struct th *)tp; 3834497Swnj 3844682Swnj /* 3854682Swnj * Initialize sequence numbers and 3864682Swnj * round trip retransmit timer. 3874682Swnj * (Other fields were init'd to zero when tcb allocated.) 3884682Swnj */ 3894567Swnj tp->t_xmtime = T_REXMT; 3904682Swnj tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una = 3914682Swnj tp->iss = tcp_iss; 3924567Swnj tp->snd_off = tp->iss + 1; 3934664Swnj tcp_iss += (ISSINCR >> 1) + 1; 3944497Swnj } 3954497Swnj 3964682Swnj /* 397*4809Swnj * Destroy a tcb. 3984682Swnj */ 399*4809Swnj tcp_detach(tp) 4004567Swnj register struct tcb *tp; 4014497Swnj { 402*4809Swnj register struct socket *so = tp->t_socket; 4034567Swnj register struct th *t; 4044567Swnj register struct mbuf *m; 405*4809Swnj COUNT(TCP_DETACH); 4064497Swnj 4074682Swnj /* 4084734Swnj * Remove from tcb queue and cancel timers. 4094682Swnj */ 410*4809Swnj tp->tcb_hd.tcb_prev->tcb_hd.tcb_next = tp->tcb_hd.tcb_next; 411*4809Swnj tp->tcb_hd.tcb_next->tcb_hd.tcb_prev = tp->tcb_hd.tcb_prev; 4124734Swnj tcp_tcancel(tp); 4134567Swnj 4144682Swnj /* 4154734Swnj * Discard all buffers. 4164682Swnj */ 417*4809Swnj for (t = tp->tcb_hd.seg_next; t != (struct th *)tp; t = t->t_next) 4184567Swnj m_freem(dtom(t)); 419*4809Swnj if (so->so_rcv.sb_mb) 420*4809Swnj { m_freem(so->so_rcv.sb_mb); so->so_rcv.sb_mb = 0; } 421*4809Swnj so->so_rcv.sb_cc = 0; so->so_rcv.sb_mbcnt = 0; 422*4809Swnj if (so->so_snd.sb_mb) 423*4809Swnj { m_freem(so->so_snd.sb_mb); so->so_rcv.sb_mb = 0; } 424*4809Swnj so->so_snd.sb_cc = 0; so->so_snd.sb_mbcnt = 0; 425*4809Swnj 426*4809Swnj for (m = tp->seg_unack; m; m = m->m_act) 4274567Swnj m_freem(m); 428*4809Swnj tp->seg_unack = 0; 429*4809Swnj 430*4809Swnj /* 431*4809Swnj * Free routing table entry. 432*4809Swnj */ 433*4809Swnj if (tp->t_host) { 434*4809Swnj h_free(tp->t_host); 435*4809Swnj tp->t_host = 0; 4364567Swnj } 4374682Swnj 4384682Swnj /* 4394734Swnj * Free tcp send template, the tcb itself, 440*4809Swnj * and the space we had reserved in the meory pool. 4414682Swnj */ 4424734Swnj if (tp->t_template) { 4434734Swnj m_free(dtom(tp->t_template)); 4444734Swnj tp->t_template = 0; 4454664Swnj } 4464670Swnj wmemfree((caddr_t)tp, 1024); 447*4809Swnj m_release(so->so_rcv.sb_hiwat + so->so_snd.sb_hiwat + 2 * MSIZE); 4484497Swnj } 4494497Swnj 4504682Swnj /* 4514734Swnj * Send data queue headed by m0 into the protocol. 4524682Swnj */ 4534678Swnj tcp_usrsend(tp, m0) 4544584Swnj register struct tcb *tp; 4554584Swnj struct mbuf *m0; 4564497Swnj { 4574497Swnj register struct mbuf *m, *n; 458*4809Swnj register struct socket *so = tp->t_socket; 4594497Swnj register off; 4604574Swnj seq_t last; 4614682Swnj COUNT(TCP_USRSEND); 4624497Swnj 4634497Swnj last = tp->snd_off; 4644584Swnj for (m = n = m0; m != NULL; m = m->m_next) { 465*4809Swnj so->so_snd.sb_mbcnt++; 4664591Swnj if (m->m_off > MMAXOFF) 467*4809Swnj so->so_snd.sb_mbcnt += NMBPG; 4684497Swnj last += m->m_len; 4694497Swnj } 470*4809Swnj if ((m = so->so_snd.sb_mb) == NULL) 471*4809Swnj so->so_snd.sb_mb = n; 4724588Swnj else { 4734588Swnj while (m->m_next != NULL) { 4744497Swnj m = m->m_next; 4754497Swnj last += m->m_len; 4764497Swnj } 4774591Swnj if (m->m_off <= MMAXOFF) { 4784588Swnj last += m->m_len; 4794588Swnj off = m->m_off + m->m_len; 4804591Swnj while (n && n->m_off <= MMAXOFF && 4814591Swnj (MMAXOFF - off) >= n->m_len) { 4824588Swnj bcopy((caddr_t)((int)n + n->m_off), 4834588Swnj (caddr_t)((int)m + off), n->m_len); 4844588Swnj m->m_len += n->m_len; 4854588Swnj off += n->m_len; 486*4809Swnj so->so_snd.sb_mbcnt--; 4874588Swnj n = m_free(n); 4884588Swnj } 4894497Swnj } 4904497Swnj m->m_next = n; 4914588Swnj } 492*4809Swnj if (tp->t_options & TO_EOL) 4934497Swnj tp->snd_end = last; 494*4809Swnj if (tp->t_options & TO_URG) { 4954497Swnj tp->snd_urp = last+1; 4964576Swnj tp->tc_flags |= TC_SND_URG; 4974567Swnj } 4984678Swnj tcp_send(tp); 4994567Swnj return (SAME); 5004497Swnj } 5014497Swnj 5024682Swnj /* 5034682Swnj * TCP timer went off processing. 5044682Swnj */ 5054584Swnj tcp_timers(tp, timertype) 5064584Swnj register struct tcb *tp; 5074584Swnj int timertype; 5084497Swnj { 5094497Swnj 5104567Swnj COUNT(TCP_TIMERS); 5114584Swnj switch (timertype) { 5124497Swnj 5134567Swnj case TINIT: /* initialization timer */ 5144576Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */ 515*4809Swnj /* XXX */ /* tcp_close(tp, UINTIMO); */ 5164567Swnj return (CLOSED); 5174567Swnj } 5184567Swnj return (SAME); 5194497Swnj 5204567Swnj case TFINACK: /* fin-ack timer */ 5214567Swnj switch (tp->t_state) { 5224497Swnj 5234567Swnj case TIME_WAIT: 5244567Swnj /* 5254567Swnj * We can be sure our ACK of foreign FIN was rcvd, 5264567Swnj * and can close if no data left for user. 5274567Swnj */ 5284567Swnj if (rcv_empty(tp)) { 529*4809Swnj /* XXX */ /* tcp_close(tp, UCLOSED); */ /* 14 */ 5304567Swnj return (CLOSED); 5314567Swnj } 5324567Swnj return (RCV_WAIT); /* 17 */ 5334497Swnj 5344731Swnj case CLOSING: 5354576Swnj tp->tc_flags |= TC_WAITED_2_ML; 5364567Swnj return (SAME); 5374497Swnj 5384567Swnj default: 5394567Swnj return (SAME); 5404567Swnj } 5414497Swnj 5424567Swnj case TREXMT: /* retransmission timer */ 5434567Swnj if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 5444567Swnj /* 545*4809Swnj * Set so for a retransmission, increase rexmt time 5464567Swnj * in case of multiple retransmissions. 5474567Swnj */ 5484567Swnj tp->snd_nxt = tp->snd_una; 5494576Swnj tp->tc_flags |= TC_REXMT; 5504567Swnj tp->t_xmtime = tp->t_xmtime << 1; 5514567Swnj if (tp->t_xmtime > T_REMAX) 5524567Swnj tp->t_xmtime = T_REMAX; 5534678Swnj tcp_send(tp); 5544567Swnj } 5554567Swnj return (SAME); 5564497Swnj 5574567Swnj case TREXMTTL: /* retransmit too long */ 5584567Swnj if (tp->t_rtl_val > tp->snd_una) /* 36 */ 559*4809Swnj /* XXX */ /* to_user(tp->t_socket, URXTIMO); */; 5604567Swnj /* 5614567Swnj * If user has already closed, abort the connection. 5624567Swnj */ 5634576Swnj if (tp->tc_flags & TC_USR_CLOSED) { 564*4809Swnj /* XXX */ /* tcp_close(tp, URXTIMO); */ 5654567Swnj return (CLOSED); 5664567Swnj } 5674567Swnj return (SAME); 5684497Swnj 5694567Swnj case TPERSIST: /* persist timer */ 5704567Swnj /* 5714567Swnj * Force a byte send through closed window. 5724567Swnj */ 5734576Swnj tp->tc_flags |= TC_FORCE_ONE; 5744678Swnj tcp_send(tp); 5754567Swnj return (SAME); 5764567Swnj } 5774567Swnj panic("tcp_timers"); 5784497Swnj } 5794497Swnj 580*4809Swnj tcp_error(so, errno) 581*4809Swnj struct socket *so; 582*4809Swnj int errno; 5834497Swnj { 5844567Swnj COUNT(TO_USER); 5854497Swnj 586*4809Swnj so->so_error = errno; 587*4809Swnj sowakeup(so); 5884497Swnj } 5894584Swnj 5904584Swnj #ifdef TCPDEBUG 5914682Swnj /* 5924682Swnj * TCP debugging utility subroutines. 5934682Swnj * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID. 5944682Swnj */ 5954670Swnj tdb_setup(tp, n, input, tdp) 5964670Swnj struct tcb *tp; 5974670Swnj register struct th *n; 5984670Swnj int input; 5994670Swnj register struct tcp_debug *tdp; 6004670Swnj { 6014670Swnj 6024682Swnj COUNT(TDB_SETUP); 6034670Swnj tdp->td_tod = time; 6044670Swnj tdp->td_tcb = tp; 6054670Swnj tdp->td_old = tp->t_state; 6064670Swnj tdp->td_inp = input; 6074670Swnj tdp->td_tim = 0; 6084670Swnj tdp->td_new = -1; 6094670Swnj if (n) { 6104670Swnj tdp->td_sno = n->t_seq; 6114670Swnj tdp->td_ano = n->t_ackno; 6124670Swnj tdp->td_wno = n->t_win; 6134670Swnj tdp->td_lno = n->t_len; 6144670Swnj tdp->td_flg = n->th_flags; 6154670Swnj } else 6164670Swnj tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno = 6174670Swnj tdp->td_flg = 0; 6184670Swnj } 6194670Swnj 6204670Swnj tdb_stuff(tdp, nstate) 6214670Swnj struct tcp_debug *tdp; 6224670Swnj int nstate; 6234670Swnj { 6244682Swnj COUNT(TDB_STUFF); 6254670Swnj 6264670Swnj tdp->td_new = nstate; 6274670Swnj tcp_debug[tdbx++ % TDBSIZE] = *tdp; 6284670Swnj if (tcpconsdebug & 2) 6294670Swnj tcp_prt(tdp); 6304670Swnj } 6314682Swnj 6324682Swnj tcp_prt(tdp) 6334682Swnj register struct tcp_debug *tdp; 6344682Swnj { 6354682Swnj COUNT(TCP_PRT); 6364682Swnj 6374698Swnj printf("%x ", ((int)tdp->td_tcb)&0xffffff); 6384698Swnj if (tdp->td_inp == INSEND) { 6394698Swnj printf("SEND #%x", tdp->td_sno); 6404698Swnj tdp->td_lno = ntohs(tdp->td_lno); 6414698Swnj tdp->td_wno = ntohs(tdp->td_wno); 6424698Swnj } else { 6434698Swnj if (tdp->td_inp == INRECV) 6444698Swnj printf("RCV #%x ", tdp->td_sno); 6454698Swnj printf("%s.%s", 6464698Swnj tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]); 6474698Swnj if (tdp->td_inp == ISTIMER) 6484698Swnj printf("(%s)", tcptimers[tdp->td_tim]); 6494698Swnj printf(" -> %s", 6504698Swnj tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]); 6514698Swnj if (tdp->td_new == -1) 6524698Swnj printf(" (FAILED)"); 6534698Swnj } 6544682Swnj /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */ 6554698Swnj if (tdp->td_lno) 6564698Swnj printf(" len=%d", tdp->td_lno); 6574698Swnj if (tdp->td_wno) 6584698Swnj printf(" win=%d", tdp->td_wno); 6594698Swnj if (tdp->td_flg & TH_FIN) printf(" FIN"); 6604698Swnj if (tdp->td_flg & TH_SYN) printf(" SYN"); 6614698Swnj if (tdp->td_flg & TH_RST) printf(" RST"); 6624698Swnj if (tdp->td_flg & TH_EOL) printf(" EOL"); 6634698Swnj if (tdp->td_flg & TH_ACK) printf(" ACK %x", tdp->td_ano); 6644698Swnj if (tdp->td_flg & TH_URG) printf(" URG"); 6654682Swnj printf("\n"); 6664682Swnj } 6674670Swnj #endif 668