1*5245Sroot /* tcp_usrreq.c 1.40 81/12/12 */ 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" 215113Swnj #include "../errno.h" 224497Swnj 23*5245Sroot extern char *tcpstates[]; 244954Swnj struct tcpcb *tcp_newtcpcb(); 254734Swnj /* 264731Swnj * Process a TCP user request for tcp tb. If this is a send request 274731Swnj * then m is the mbuf chain of send data. If this is a timer expiration 284731Swnj * (called from the software clock routine), then timertype tells which timer. 294731Swnj */ 304809Swnj tcp_usrreq(so, req, m, addr) 314809Swnj struct socket *so; 324809Swnj int req; 334731Swnj struct mbuf *m; 344809Swnj caddr_t addr; 354497Swnj { 364886Swnj register struct inpcb *inp = sotoinpcb(so); 374911Swnj register struct tcpcb *tp; 384567Swnj int s = splnet(); 394809Swnj int error = 0; 404567Swnj COUNT(TCP_USRREQ); 414497Swnj 424886Swnj /* 434886Swnj * Make sure attached. If not, 444886Swnj * only PRU_ATTACH is valid. 454886Swnj */ 46*5245Sroot printf("tcp_usrreq %d so %x inp %x\n", req, so, inp); 475089Swnj if (inp == 0 && req != PRU_ATTACH) { 485075Swnj splx(s); 495075Swnj return (EINVAL); 505075Swnj } 515075Swnj if (inp) { 524911Swnj tp = intotcpcb(inp); 534731Swnj #ifdef KPROF 545075Swnj tcp_acounts[tp->t_state][req]++; 554731Swnj #endif 564911Swnj } 574809Swnj switch (req) { 584497Swnj 594809Swnj case PRU_ATTACH: 604954Swnj if (inp) { 614809Swnj error = EISCONN; 624911Swnj break; 634886Swnj } 645165Swnj error = in_pcbattach(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr); 655075Swnj if (error) 664954Swnj break; 674954Swnj inp = (struct inpcb *)so->so_pcb; 68*5245Sroot tp = tcp_newtcpcb(inp); 695062Swnj if (so->so_options & SO_ACCEPTCONN) { 705062Swnj if (tp == 0) { 715165Swnj in_pcbdetach(inp); 725062Swnj error = ENOBUFS; 735062Swnj break; 745062Swnj } 755075Swnj tp->t_state = TCPS_LISTEN; 765062Swnj } else 775075Swnj tp->t_state = TCPS_CLOSED; 784567Swnj break; 794497Swnj 804809Swnj case PRU_DETACH: 815165Swnj in_pcbdetach(inp); 824809Swnj break; 834809Swnj 844809Swnj case PRU_CONNECT: 855165Swnj error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 864954Swnj if (error) 874886Swnj break; 885062Swnj tp = tcp_newtcpcb(inp); 89*5245Sroot if (tp == 0) 90*5245Sroot goto badcon; 915174Swnj tp->t_template = tcp_template(tp); 92*5245Sroot if (tp->t_template == 0) 93*5245Sroot goto badcon2; 945062Swnj tp->t_inpcb = inp; 955062Swnj inp->inp_ppcb = (caddr_t)tp; 964886Swnj soisconnecting(so); 975075Swnj tp->t_state = TCPS_SYN_SENT; 98*5245Sroot tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 99*5245Sroot tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; 100*5245Sroot tcp_sendseqinit(tp); 1015113Swnj (void) tcp_output(tp); 1024567Swnj break; 1034497Swnj 104*5245Sroot badcon2: 105*5245Sroot (void) m_free(dtom(tp)); 106*5245Sroot badcon: 107*5245Sroot in_pcbdisconnect(inp); 108*5245Sroot error = ENOBUFS; 109*5245Sroot break; 110*5245Sroot 1114925Swnj case PRU_ACCEPT: 1124954Swnj soisconnected(so); 1134954Swnj break; 1144925Swnj 1154809Swnj case PRU_DISCONNECT: 1165075Swnj if (tp->t_state < TCPS_ESTABLISHED) 1175075Swnj tcp_close(tp); 1184886Swnj else { 1194886Swnj soisdisconnecting(so); 120*5245Sroot tcp_usrclosed(tp); 1215113Swnj (void) tcp_output(tp); 1224886Swnj } 1234809Swnj break; 1244809Swnj 1254809Swnj case PRU_SHUTDOWN: 1265089Swnj socantsendmore(so); 127*5245Sroot tcp_usrclosed(tp); 128*5245Sroot (void) tcp_output(tp); 1294567Swnj break; 1304497Swnj 1314809Swnj case PRU_RCVD: 1325113Swnj (void) tcp_output(tp); 1334567Swnj break; 1344497Swnj 1354809Swnj case PRU_SEND: 1365075Swnj sbappend(&so->so_snd, m); 1375089Swnj /* 1385089Swnj if (tp->t_flags & TF_PUSH) 1395075Swnj tp->snd_end = tp->snd_una + so->so_snd.sb_cc; 1405089Swnj */ 1415089Swnj if (tp->t_flags & TF_URG) 1425089Swnj tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1; 1435113Swnj (void) tcp_output(tp); 1444567Swnj break; 1454567Swnj 1464809Swnj case PRU_ABORT: 1475075Swnj tcp_drop(tp, ECONNABORTED); 1484567Swnj break; 1494567Swnj 1504809Swnj case PRU_CONTROL: 1514886Swnj error = EOPNOTSUPP; 1524809Swnj break; 1534809Swnj 1545113Swnj case PRU_SENSE: 1555113Swnj error = EOPNOTSUPP; 1565113Swnj break; 1575113Swnj 1585113Swnj case PRU_RCVOOB: 1595113Swnj error = EOPNOTSUPP; 1605113Swnj break; 1615113Swnj 1625113Swnj case PRU_SENDOOB: 1635113Swnj error = EOPNOTSUPP; 1645113Swnj break; 1655113Swnj 1664809Swnj case PRU_SLOWTIMO: 1675075Swnj tcp_timers(tp, (int)addr); 1684809Swnj break; 1694809Swnj 1704731Swnj default: 1714731Swnj panic("tcp_usrreq"); 1724567Swnj } 1734567Swnj splx(s); 1744886Swnj return (error); 1754497Swnj } 176*5245Sroot 177*5245Sroot pseqno(tp) 178*5245Sroot struct tcpcb *tp; 179*5245Sroot { 180*5245Sroot printf("tp %x state %s rcv_nxt %x rcv_wnd %d irs %x\n", tp, tcpstates[tp->t_state],tp->rcv_nxt, tp->rcv_wnd, tp->irs); 181*5245Sroot printf("snd_una %x snd_nxt %x snd_wnd %d snd_wl1 %x snd_wl2 %x iss %x\n", 182*5245Sroot tp->snd_una, tp->snd_nxt, tp->snd_wnd, tp->snd_wl1, tp->snd_wl2, tp->iss); 183*5245Sroot } 184*5245Sroot 185*5245Sroot tcp_usrclosed(tp) 186*5245Sroot struct tcpcb *tp; 187*5245Sroot { 188*5245Sroot 189*5245Sroot printf("usrclosed in %s\n", tcpstates[tp->t_state]); 190*5245Sroot switch (tp->t_state) { 191*5245Sroot 192*5245Sroot case TCPS_LISTEN: 193*5245Sroot case TCPS_SYN_SENT: 194*5245Sroot tp->t_state = TCPS_CLOSED; 195*5245Sroot tcp_close(tp); 196*5245Sroot break; 197*5245Sroot 198*5245Sroot case TCPS_SYN_RECEIVED: 199*5245Sroot case TCPS_ESTABLISHED: 200*5245Sroot tp->t_state = TCPS_FIN_WAIT_1; 201*5245Sroot break; 202*5245Sroot 203*5245Sroot case TCPS_CLOSE_WAIT: 204*5245Sroot tp->t_state = TCPS_LAST_ACK; 205*5245Sroot break; 206*5245Sroot } 207*5245Sroot printf("after usrclosed state %s\n", tcpstates[tp->t_state]); 208*5245Sroot } 209