1*5075Swnj /* tcp_usrreq.c 1.35 81/11/25 */ 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(); 364809Swnj int error = 0; 37*5075Swnj struct tcpiphdr ti; 384567Swnj COUNT(TCP_USRREQ); 394497Swnj 404886Swnj /* 414886Swnj * Make sure attached. If not, 424886Swnj * only PRU_ATTACH is valid. 434886Swnj */ 44*5075Swnj if (inp == 0 && req != PRU_ATTACH) 45*5075Swnj splx(s); 46*5075Swnj return (EINVAL); 47*5075Swnj } 48*5075Swnj if (inp) { 494911Swnj tp = intotcpcb(inp); 504731Swnj #ifdef KPROF 51*5075Swnj tcp_acounts[tp->t_state][req]++; 524731Swnj #endif 534911Swnj } 544809Swnj switch (req) { 554497Swnj 564809Swnj case PRU_ATTACH: 574954Swnj if (inp) { 584809Swnj error = EISCONN; 594911Swnj break; 604886Swnj } 614954Swnj error = in_pcballoc(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr); 62*5075Swnj if (error) 634954Swnj break; 644954Swnj inp = (struct inpcb *)so->so_pcb; 655062Swnj if (so->so_options & SO_ACCEPTCONN) { 665062Swnj tp = tcp_newtcpcb(inp); 675062Swnj if (tp == 0) { 68*5075Swnj in_pcbfree(inp); 695062Swnj error = ENOBUFS; 705062Swnj break; 715062Swnj } 72*5075Swnj tp->t_state = TCPS_LISTEN; 735062Swnj } else 74*5075Swnj tp->t_state = TCPS_CLOSED; 754567Swnj break; 764497Swnj 774809Swnj case PRU_DETACH: 784809Swnj break; 794809Swnj 804809Swnj case PRU_CONNECT: 814954Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 824954Swnj if (error) 834886Swnj break; 845062Swnj tp = tcp_newtcpcb(inp); 855062Swnj if (tp == 0) { 865062Swnj inp->inp_faddr.s_addr = 0; 875062Swnj error = ENOBUFS; 885062Swnj break; 895062Swnj } 905062Swnj tp->t_inpcb = inp; 915062Swnj inp->inp_ppcb = (caddr_t)tp; 924886Swnj soisconnecting(so); 93*5075Swnj tp->t_state = TCPS_SYN_SENT; 94*5075Swnj tcp_output(tp); 954567Swnj break; 964497Swnj 974925Swnj case PRU_ACCEPT: 984954Swnj soisconnected(so); 994954Swnj break; 1004925Swnj 1014809Swnj case PRU_DISCONNECT: 102*5075Swnj if (tp->t_state < TCPS_ESTABLISHED) 103*5075Swnj tcp_close(tp); 1044886Swnj else { 1054886Swnj soisdisconnecting(so); 106*5075Swnj tcp_output(tp); 1074886Swnj } 1084809Swnj break; 1094809Swnj 1104809Swnj case PRU_SHUTDOWN: 111*5075Swnj socantsndmore(so); 112*5075Swnj switch (tp->t_state) { 1134497Swnj 1145066Swnj case TCPS_LISTEN: 1155066Swnj case TCPS_SYN_SENT: 116*5075Swnj tp->t_state = TCPS_CLOSED; 1174731Swnj break; 1184731Swnj 1195066Swnj case TCPS_SYN_RCVD: 120*5075Swnj case TCPS_ESTAB: 121*5075Swnj tp->t_state = TCPS_FIN_WAIT_1; 122*5075Swnj tcp_output(tp); 123*5075Swnj break; 124*5075Swnj 1255066Swnj case TCPS_CLOSE_WAIT: 126*5075Swnj tp->t_state = TCPS_LAST_ACK; 127*5075Swnj tcp_output(tp); 1284731Swnj break; 1294731Swnj } 1304567Swnj break; 1314497Swnj 1324809Swnj case PRU_RCVD: 133*5075Swnj if (tp->t_state < TCPS_ESTABLISHED) { 134*5075Swnj error = ENOTCONN; 135*5075Swnj break; 136*5075Swnj } 137*5075Swnj tcp_output(tp); 1384567Swnj break; 1394497Swnj 1404809Swnj case PRU_SEND: 141*5075Swnj if (tp->t_state < TCPS_ESTABLISHED) { 142*5075Swnj error = ENOTCONN; 1434731Swnj break; 144*5075Swnj } 145*5075Swnj if (tp->t_state > TCPS_CLOSE_WAIT) { 146*5075Swnj error = EISDISCONN; 1474809Swnj m_freem(m); 1484731Swnj break; 1494731Swnj } 150*5075Swnj sbappend(&so->so_snd, m); 151*5075Swnj if (tp->t_options & TO_EOL) 152*5075Swnj tp->snd_end = tp->snd_una + so->so_snd.sb_cc; 153*5075Swnj if (tp->t_options & TO_URG) 154*5075Swnj tp->snd_urp = tp->snd_una + so->so_snd.sb_cc + 1; 155*5075Swnj tcp_output(tp); 1564567Swnj break; 1574567Swnj 1584809Swnj case PRU_ABORT: 159*5075Swnj tcp_drop(tp, ECONNABORTED); 1604567Swnj break; 1614567Swnj 1624809Swnj case PRU_CONTROL: 1634886Swnj error = EOPNOTSUPP; 1644809Swnj break; 1654809Swnj 1664809Swnj case PRU_SLOWTIMO: 167*5075Swnj tcp_timers(tp, (int)addr); 1684809Swnj break; 1694809Swnj 1704731Swnj default: 1714731Swnj panic("tcp_usrreq"); 1724567Swnj } 1734567Swnj splx(s); 1744886Swnj return (error); 1754497Swnj } 176