1*5066Swnj /* tcp_usrreq.c 1.34 81/11/24 */ 24567Swnj 34497Swnj #include "../h/param.h" 44567Swnj #include "../h/systm.h" 54664Swnj #include "../h/mbuf.h" 64664Swnj #include "../h/socket.h" 74809Swnj #include "../h/socketvar.h" 84809Swnj #include "../h/protosw.h" 94809Swnj #include "../net/inet.h" 104886Swnj #include "../net/inet_pcb.h" 114809Swnj #include "../net/inet_systm.h" 124954Swnj #include "../net/if.h" 134809Swnj #include "../net/imp.h" 144809Swnj #include "../net/ip.h" 154900Swnj #include "../net/ip_var.h" 164809Swnj #include "../net/tcp.h" 174809Swnj #include "../net/tcp_fsm.h" 184809Swnj #include "../net/tcp_var.h" 194809Swnj #include "/usr/include/errno.h" 204497Swnj 214954Swnj struct tcpcb *tcp_newtcpcb(); 224734Swnj /* 234731Swnj * Process a TCP user request for tcp tb. If this is a send request 244731Swnj * then m is the mbuf chain of send data. If this is a timer expiration 254731Swnj * (called from the software clock routine), then timertype tells which timer. 264731Swnj */ 274809Swnj tcp_usrreq(so, req, m, addr) 284809Swnj struct socket *so; 294809Swnj int req; 304731Swnj struct mbuf *m; 314809Swnj caddr_t addr; 324497Swnj { 334886Swnj register struct inpcb *inp = sotoinpcb(so); 344911Swnj register struct tcpcb *tp; 354567Swnj int s = splnet(); 364567Swnj register int nstate; 374809Swnj int error = 0; 384567Swnj COUNT(TCP_USRREQ); 394497Swnj 404886Swnj /* 414886Swnj * Make sure attached. If not, 424886Swnj * only PRU_ATTACH is valid. 434886Swnj */ 444911Swnj if (inp == 0) { 454886Swnj if (req != PRU_ATTACH) { 464886Swnj splx(s); 474886Swnj return (EINVAL); 484886Swnj } 494911Swnj } else { 504911Swnj tp = intotcpcb(inp); 514911Swnj nstate = tp->t_state; 524731Swnj #ifdef KPROF 534911Swnj tcp_acounts[nstate][req]++; 544731Swnj #endif 554911Swnj } 564911Swnj 574809Swnj switch (req) { 584497Swnj 594809Swnj case PRU_ATTACH: 604954Swnj if (inp) { 614809Swnj error = EISCONN; 624911Swnj break; 634886Swnj } 644954Swnj error = in_pcballoc(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr); 654954Swnj if (error) { 664967Swnj (void) m_free(dtom(tp)); 674954Swnj break; 684954Swnj } 694954Swnj inp = (struct inpcb *)so->so_pcb; 705062Swnj if (so->so_options & SO_ACCEPTCONN) { 715062Swnj tp = tcp_newtcpcb(inp); 725062Swnj if (tp == 0) { 735062Swnj error = ENOBUFS; 745062Swnj break; 755062Swnj } 764886Swnj nstate = LISTEN; 775062Swnj } else 784886Swnj nstate = CLOSED; 794567Swnj break; 804497Swnj 814809Swnj case PRU_DETACH: 824809Swnj break; 834809Swnj 844809Swnj case PRU_CONNECT: 854954Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 864954Swnj if (error) 874886Swnj break; 885062Swnj tp = tcp_newtcpcb(inp); 895062Swnj if (tp == 0) { 905062Swnj inp->inp_faddr.s_addr = 0; 915062Swnj error = ENOBUFS; 925062Swnj break; 935062Swnj } 945062Swnj tp->t_inpcb = inp; 955062Swnj inp->inp_ppcb = (caddr_t)tp; 964911Swnj (void) tcp_sndctl(tp); 974567Swnj nstate = SYN_SENT; 984886Swnj soisconnecting(so); 994567Swnj break; 1004497Swnj 1014925Swnj case PRU_ACCEPT: 1024954Swnj soisconnected(so); 1034954Swnj break; 1044925Swnj 1054809Swnj case PRU_DISCONNECT: 1064886Swnj if (nstate < ESTAB) 1074911Swnj tcp_disconnect(tp); 1084886Swnj else { 1094886Swnj tp->tc_flags |= TC_SND_FIN; 1104911Swnj (void) tcp_sndctl(tp); 1114886Swnj soisdisconnecting(so); 1124886Swnj } 1134809Swnj break; 1144809Swnj 1154809Swnj case PRU_SHUTDOWN: 1164731Swnj switch (nstate) { 1174497Swnj 118*5066Swnj case TCPS_LISTEN: 119*5066Swnj case TCPS_SYN_SENT: 120*5066Swnj nstate = TCPS_CLOSED; 1214731Swnj break; 1224731Swnj 123*5066Swnj case TCPS_SYN_RCVD: 124*5066Swnj case TCPS_ESTABLISHED: 125*5066Swnj case TCPS_CLOSE_WAIT: 1264731Swnj tp->tc_flags |= TC_SND_FIN; 1274911Swnj (void) tcp_sndctl(tp); 1284731Swnj nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK; 1294731Swnj break; 1304731Swnj 131*5066Swnj case TCPS_FIN_W1: 132*5066Swnj case TCPS_FIN_W2: 133*5066Swnj case TCPS_TIME_WAIT: 134*5066Swnj case TCPS_CLOSING: 135*5066Swnj case TCPS_LAST_ACK: 136*5066Swnj case TCPS_RCV_WAIT: 1374731Swnj break; 1384731Swnj 1394731Swnj default: 1404731Swnj goto bad; 1414731Swnj } 1424567Swnj break; 1434497Swnj 1444809Swnj case PRU_RCVD: 145*5066Swnj if (nstate < TCPS_ESTAB) 1464731Swnj goto bad; 1474734Swnj tcp_sndwin(tp); 148*5066Swnj if (nstate == TCPS_RCV_WAIT && rcv_empty(tp)) 149*5066Swnj nstate = TCPS_CLOSED; 1504567Swnj break; 1514497Swnj 1524809Swnj case PRU_SEND: 1534731Swnj switch (nstate) { 1544567Swnj 1554731Swnj case ESTAB: 1564731Swnj case CLOSE_WAIT: 1574886Swnj tcp_usrsend(tp, m); 1584731Swnj break; 1594731Swnj 1604731Swnj default: 1614731Swnj if (nstate < ESTAB) 1624731Swnj goto bad; 1634809Swnj m_freem(m); 1644886Swnj error = ENOTCONN; 1654731Swnj break; 1664731Swnj } 1674567Swnj break; 1684567Swnj 1694809Swnj case PRU_ABORT: 1704886Swnj tcp_abort(tp); 1714567Swnj nstate = CLOSED; 1724567Swnj break; 1734567Swnj 1744809Swnj case PRU_CONTROL: 1754886Swnj error = EOPNOTSUPP; 1764809Swnj break; 1774809Swnj 1784809Swnj case PRU_SLOWTIMO: 1794809Swnj switch (nstate) { 1804809Swnj 1814809Swnj case 0: 1824809Swnj case CLOSED: 1834809Swnj case LISTEN: 1844809Swnj goto bad; 1854809Swnj 1864809Swnj default: 1874809Swnj nstate = tcp_timers(tp, (int)addr); 1884809Swnj } 1894809Swnj break; 1904809Swnj 1914731Swnj default: 1924731Swnj panic("tcp_usrreq"); 1934731Swnj bad: 1944731Swnj printf("tcp: bad state: tcb=%x state=%d input=%d\n", 1954809Swnj tp, tp->t_state, req); 1964731Swnj nstate = EFAILEC; 1974567Swnj break; 1984567Swnj } 1994567Swnj switch (nstate) { 2004567Swnj 2014584Swnj case CLOSED: 2024567Swnj case SAME: 2034567Swnj break; 2044567Swnj 2054567Swnj case EFAILEC: 2064731Swnj if (m) 2074731Swnj m_freem(dtom(m)); 2084567Swnj break; 2094567Swnj 2104567Swnj default: 2114567Swnj tp->t_state = nstate; 2124567Swnj break; 2134567Swnj } 2144567Swnj splx(s); 2154886Swnj return (error); 2164497Swnj } 2174497Swnj 2184954Swnj struct tcpcb * 2195062Swnj tcp_newtcpcb(inp) 2205062Swnj struct inpcb *inp; 2214809Swnj { 2224954Swnj struct mbuf *m = m_getclr(0); 2234954Swnj register struct tcpcb *tp; 2244954Swnj COUNT(TCP_NEWTCPCB); 2254497Swnj 2264954Swnj if (m == 0) 2274954Swnj return (0); 2284954Swnj tp = mtod(m, struct tcpcb *); 2294954Swnj 2304682Swnj /* 2314886Swnj * Make empty reassembly queue. 2324682Swnj */ 2334886Swnj tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; 2344497Swnj 2354682Swnj /* 2364886Swnj * Initialize sequence numbers and round trip retransmit timer. 2374682Swnj */ 2384567Swnj tp->t_xmtime = T_REXMT; 2394682Swnj tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una = 2404682Swnj tp->iss = tcp_iss; 2414567Swnj tp->snd_off = tp->iss + 1; 2424664Swnj tcp_iss += (ISSINCR >> 1) + 1; 2435062Swnj 2445062Swnj /* 2455062Swnj * Hook to inpcb. 2465062Swnj */ 2475062Swnj tp->t_inpcb = inp; 2485062Swnj inp->inp_ppcb = (caddr_t)tp; 2494954Swnj return (tp); 2504497Swnj } 2514497Swnj 2524886Swnj tcp_disconnect(tp) 2534886Swnj register struct tcpcb *tp; 2544886Swnj { 2554886Swnj register struct tcpiphdr *t; 2564886Swnj 2574954Swnj COUNT(TCP_DISCONNECT); 2584734Swnj tcp_tcancel(tp); 2594886Swnj t = tp->seg_next; 2604900Swnj for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next) 2614567Swnj m_freem(dtom(t)); 2624886Swnj tcp_drainunack(tp); 2634734Swnj if (tp->t_template) { 2644911Swnj (void) m_free(dtom(tp->t_template)); 2654734Swnj tp->t_template = 0; 2664664Swnj } 2674886Swnj in_pcbfree(tp->t_inpcb); 2685062Swnj (void) m_free(dtom(tp)); 2694497Swnj } 2704497Swnj 2714911Swnj tcp_abort(tp) 2724911Swnj register struct tcpcb *tp; 2734886Swnj { 2744886Swnj 2754954Swnj COUNT(TCP_ABORT); 2764886Swnj switch (tp->t_state) { 2774886Swnj 2784886Swnj case SYN_RCVD: 2794886Swnj case ESTAB: 2804886Swnj case FIN_W1: 2814886Swnj case FIN_W2: 2824886Swnj case CLOSE_WAIT: 2834886Swnj tp->tc_flags |= TC_SND_RST; 2844886Swnj tcp_sndnull(tp); 2854886Swnj } 2864911Swnj soisdisconnected(tp->t_inpcb->inp_socket); 2875062Swnj tcp_disconnect(tp); 2884886Swnj } 2894886Swnj 2904682Swnj /* 2914734Swnj * Send data queue headed by m0 into the protocol. 2924682Swnj */ 2934678Swnj tcp_usrsend(tp, m0) 2944886Swnj register struct tcpcb *tp; 2954584Swnj struct mbuf *m0; 2964497Swnj { 2974886Swnj register struct socket *so = tp->t_inpcb->inp_socket; 2984682Swnj COUNT(TCP_USRSEND); 2994497Swnj 3004886Swnj sbappend(&so->so_snd, m0); 3014809Swnj if (tp->t_options & TO_EOL) 3024886Swnj tp->snd_end = tp->snd_off + so->so_snd.sb_cc; 3034809Swnj if (tp->t_options & TO_URG) { 3044886Swnj tp->snd_urp = tp->snd_off + so->so_snd.sb_cc + 1; 3054576Swnj tp->tc_flags |= TC_SND_URG; 3064567Swnj } 3074911Swnj (void) tcp_send(tp); 3084497Swnj } 3094497Swnj 3104911Swnj /*ARGSUSED*/ 3114886Swnj tcp_sense(m) 3124886Swnj struct mbuf *m; 3134886Swnj { 3144886Swnj 3154954Swnj COUNT(TCP_SENSE); 3164886Swnj return (EOPNOTSUPP); 3174886Swnj } 3184886Swnj 3195062Swnj tcp_drop(tp, errno) 3204911Swnj struct tcpcb *tp; 3214809Swnj int errno; 3224497Swnj { 3234911Swnj struct socket *so = tp->t_inpcb->inp_socket; 3244954Swnj 3254911Swnj COUNT(TCP_ERROR); 3264809Swnj so->so_error = errno; 3274886Swnj sorwakeup(so); 3284886Swnj sowwakeup(so); 3295062Swnj tcp_disconnect(tp); 3304497Swnj } 3314584Swnj 332*5066Swnj tcp_drain() 3334670Swnj { 334*5066Swnj register struct inpcb *ip; 3354670Swnj 336*5066Swnj COUNT(TCP_DRAIN); 337*5066Swnj for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) 338*5066Swnj tcp_drainunack(intotcpcb(ip)); 3394670Swnj } 3404670Swnj 341*5066Swnj tcp_drainunack(tp) 342*5066Swnj register struct tcpcb *tp; 3434670Swnj { 344*5066Swnj register struct mbuf *m; 3454670Swnj 346*5066Swnj COUNT(TCP_DRAINUNACK); 347*5066Swnj for (m = tp->seg_unack; m; m = m->m_act) 348*5066Swnj m_freem(m); 349*5066Swnj tp->seg_unack = 0; 3504670Swnj } 351*5066Swnj 352*5066Swnj tcp_ctlinput(m) 353*5066Swnj struct mbuf *m; 3544682Swnj { 3554682Swnj 356*5066Swnj COUNT(TCP_CTLINPUT); 357*5066Swnj m_freem(m); 3584682Swnj } 359