1*5270Sroot /* tcp_usrreq.c 1.43 81/12/20 */ 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" 95089Swnj #include "../net/in.h" 105089Swnj #include "../net/in_pcb.h" 115089Swnj #include "../net/in_systm.h" 124954Swnj #include "../net/if.h" 134809Swnj #include "../net/ip.h" 144900Swnj #include "../net/ip_var.h" 154809Swnj #include "../net/tcp.h" 164809Swnj #include "../net/tcp_fsm.h" 175089Swnj #include "../net/tcp_seq.h" 185089Swnj #include "../net/tcp_timer.h" 194809Swnj #include "../net/tcp_var.h" 205089Swnj #include "../net/tcpip.h" 21*5270Sroot #include "../net/tcp_debug.h" 225113Swnj #include "../errno.h" 234497Swnj 245245Sroot extern char *tcpstates[]; 254954Swnj struct tcpcb *tcp_newtcpcb(); 264734Swnj /* 274731Swnj * Process a TCP user request for tcp tb. If this is a send request 284731Swnj * then m is the mbuf chain of send data. If this is a timer expiration 294731Swnj * (called from the software clock routine), then timertype tells which timer. 304731Swnj */ 314809Swnj tcp_usrreq(so, req, m, addr) 324809Swnj struct socket *so; 334809Swnj int req; 344731Swnj struct mbuf *m; 354809Swnj caddr_t addr; 364497Swnj { 374886Swnj register struct inpcb *inp = sotoinpcb(so); 384911Swnj register struct tcpcb *tp; 394567Swnj int s = splnet(); 404809Swnj int error = 0; 41*5270Sroot int ostate; 424567Swnj COUNT(TCP_USRREQ); 434497Swnj 444886Swnj /* 454886Swnj * Make sure attached. If not, 464886Swnj * only PRU_ATTACH is valid. 474886Swnj */ 485089Swnj if (inp == 0 && req != PRU_ATTACH) { 495075Swnj splx(s); 505075Swnj return (EINVAL); 515075Swnj } 525075Swnj if (inp) { 534911Swnj tp = intotcpcb(inp); 544731Swnj #ifdef KPROF 555075Swnj tcp_acounts[tp->t_state][req]++; 564731Swnj #endif 57*5270Sroot ostate = tp->t_state; 584911Swnj } 594809Swnj switch (req) { 604497Swnj 614809Swnj case PRU_ATTACH: 624954Swnj if (inp) { 634809Swnj error = EISCONN; 644911Swnj break; 654886Swnj } 665165Swnj error = in_pcbattach(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr); 675075Swnj if (error) 684954Swnj break; 694954Swnj inp = (struct inpcb *)so->so_pcb; 705245Sroot tp = tcp_newtcpcb(inp); 715062Swnj if (so->so_options & SO_ACCEPTCONN) { 725062Swnj if (tp == 0) { 735165Swnj in_pcbdetach(inp); 745062Swnj error = ENOBUFS; 755062Swnj break; 765062Swnj } 775075Swnj tp->t_state = TCPS_LISTEN; 785062Swnj } else 795075Swnj tp->t_state = TCPS_CLOSED; 804567Swnj break; 814497Swnj 824809Swnj case PRU_DETACH: 83*5270Sroot if (tp) 84*5270Sroot goto disconn; 855165Swnj in_pcbdetach(inp); 864809Swnj break; 874809Swnj 884809Swnj case PRU_CONNECT: 895165Swnj error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 904954Swnj if (error) 914886Swnj break; 925174Swnj tp->t_template = tcp_template(tp); 935245Sroot if (tp->t_template == 0) 945245Sroot goto badcon2; 955062Swnj tp->t_inpcb = inp; 965062Swnj inp->inp_ppcb = (caddr_t)tp; 974886Swnj soisconnecting(so); 985075Swnj tp->t_state = TCPS_SYN_SENT; 995245Sroot tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 1005245Sroot tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; 1015245Sroot tcp_sendseqinit(tp); 1025113Swnj (void) tcp_output(tp); 1034567Swnj break; 1044497Swnj 1055245Sroot badcon2: 1065245Sroot (void) m_free(dtom(tp)); 1075245Sroot badcon: 1085245Sroot in_pcbdisconnect(inp); 1095245Sroot error = ENOBUFS; 1105245Sroot break; 1115245Sroot 1124925Swnj case PRU_ACCEPT: 113*5270Sroot *(struct sockaddr *)addr = so->so_addr; 1144954Swnj break; 1154925Swnj 1164809Swnj case PRU_DISCONNECT: 117*5270Sroot disconn: 1185075Swnj if (tp->t_state < TCPS_ESTABLISHED) 1195075Swnj tcp_close(tp); 1204886Swnj else { 1214886Swnj soisdisconnecting(so); 1225245Sroot tcp_usrclosed(tp); 1235113Swnj (void) tcp_output(tp); 1244886Swnj } 1254809Swnj break; 1264809Swnj 1274809Swnj case PRU_SHUTDOWN: 1285089Swnj socantsendmore(so); 1295245Sroot tcp_usrclosed(tp); 1305245Sroot (void) tcp_output(tp); 1314567Swnj break; 1324497Swnj 1334809Swnj case PRU_RCVD: 1345113Swnj (void) tcp_output(tp); 1354567Swnj break; 1364497Swnj 1374809Swnj case PRU_SEND: 1385075Swnj sbappend(&so->so_snd, m); 1395089Swnj /* 1405089Swnj if (tp->t_flags & TF_PUSH) 1415075Swnj tp->snd_end = tp->snd_una + so->so_snd.sb_cc; 1425089Swnj */ 1435089Swnj if (tp->t_flags & TF_URG) 1445089Swnj tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1; 1455113Swnj (void) tcp_output(tp); 1464567Swnj break; 1474567Swnj 1484809Swnj case PRU_ABORT: 1495075Swnj tcp_drop(tp, ECONNABORTED); 1504567Swnj break; 1514567Swnj 1524809Swnj case PRU_CONTROL: 1534886Swnj error = EOPNOTSUPP; 1544809Swnj break; 1554809Swnj 1565113Swnj case PRU_SENSE: 1575113Swnj error = EOPNOTSUPP; 1585113Swnj break; 1595113Swnj 1605113Swnj case PRU_RCVOOB: 1615113Swnj error = EOPNOTSUPP; 1625113Swnj break; 1635113Swnj 1645113Swnj case PRU_SENDOOB: 1655113Swnj error = EOPNOTSUPP; 1665113Swnj break; 1675113Swnj 1684809Swnj case PRU_SLOWTIMO: 1695075Swnj tcp_timers(tp, (int)addr); 170*5270Sroot req |= (int)addr << 8; /* for debug's sake */ 1714809Swnj break; 1724809Swnj 1734731Swnj default: 1744731Swnj panic("tcp_usrreq"); 1754567Swnj } 176*5270Sroot if (tp && (so->so_options & SO_DEBUG)) 177*5270Sroot tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req); 1784567Swnj splx(s); 1794886Swnj return (error); 1804497Swnj } 1815245Sroot 1825245Sroot tcp_usrclosed(tp) 1835245Sroot struct tcpcb *tp; 1845245Sroot { 1855245Sroot 1865245Sroot switch (tp->t_state) { 1875245Sroot 1885245Sroot case TCPS_LISTEN: 1895245Sroot case TCPS_SYN_SENT: 1905245Sroot tp->t_state = TCPS_CLOSED; 1915245Sroot tcp_close(tp); 1925245Sroot break; 1935245Sroot 1945245Sroot case TCPS_SYN_RECEIVED: 1955245Sroot case TCPS_ESTABLISHED: 1965245Sroot tp->t_state = TCPS_FIN_WAIT_1; 1975245Sroot break; 1985245Sroot 1995245Sroot case TCPS_CLOSE_WAIT: 2005245Sroot tp->t_state = TCPS_LAST_ACK; 2015245Sroot break; 2025245Sroot } 2035245Sroot } 204