1*5174Swnj /* tcp_usrreq.c 1.39 81/12/03 */ 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 234954Swnj struct tcpcb *tcp_newtcpcb(); 244734Swnj /* 254731Swnj * Process a TCP user request for tcp tb. If this is a send request 264731Swnj * then m is the mbuf chain of send data. If this is a timer expiration 274731Swnj * (called from the software clock routine), then timertype tells which timer. 284731Swnj */ 294809Swnj tcp_usrreq(so, req, m, addr) 304809Swnj struct socket *so; 314809Swnj int req; 324731Swnj struct mbuf *m; 334809Swnj caddr_t addr; 344497Swnj { 354886Swnj register struct inpcb *inp = sotoinpcb(so); 364911Swnj register struct tcpcb *tp; 374567Swnj int s = splnet(); 384809Swnj int error = 0; 394567Swnj COUNT(TCP_USRREQ); 404497Swnj 414886Swnj /* 424886Swnj * Make sure attached. If not, 434886Swnj * only PRU_ATTACH is valid. 444886Swnj */ 455089Swnj if (inp == 0 && req != PRU_ATTACH) { 465075Swnj splx(s); 475075Swnj return (EINVAL); 485075Swnj } 495075Swnj if (inp) { 504911Swnj tp = intotcpcb(inp); 514731Swnj #ifdef KPROF 525075Swnj tcp_acounts[tp->t_state][req]++; 534731Swnj #endif 544911Swnj } 554809Swnj switch (req) { 564497Swnj 574809Swnj case PRU_ATTACH: 584954Swnj if (inp) { 594809Swnj error = EISCONN; 604911Swnj break; 614886Swnj } 625165Swnj error = in_pcbattach(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr); 635075Swnj if (error) 644954Swnj break; 654954Swnj inp = (struct inpcb *)so->so_pcb; 665062Swnj if (so->so_options & SO_ACCEPTCONN) { 675062Swnj tp = tcp_newtcpcb(inp); 685062Swnj if (tp == 0) { 695165Swnj in_pcbdetach(inp); 705062Swnj error = ENOBUFS; 715062Swnj break; 725062Swnj } 735075Swnj tp->t_state = TCPS_LISTEN; 745062Swnj } else 755075Swnj tp->t_state = TCPS_CLOSED; 764567Swnj break; 774497Swnj 784809Swnj case PRU_DETACH: 795165Swnj in_pcbdetach(inp); 804809Swnj break; 814809Swnj 824809Swnj case PRU_CONNECT: 835165Swnj error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 844954Swnj if (error) 854886Swnj break; 865062Swnj tp = tcp_newtcpcb(inp); 875062Swnj if (tp == 0) { 885165Swnj in_pcbdisconnect(inp); 895062Swnj error = ENOBUFS; 905062Swnj break; 915062Swnj } 92*5174Swnj tp->t_template = tcp_template(tp); 935062Swnj tp->t_inpcb = inp; 945062Swnj inp->inp_ppcb = (caddr_t)tp; 954886Swnj soisconnecting(so); 965075Swnj tp->t_state = TCPS_SYN_SENT; 975113Swnj (void) tcp_output(tp); 984567Swnj break; 994497Swnj 1004925Swnj case PRU_ACCEPT: 1014954Swnj soisconnected(so); 1024954Swnj break; 1034925Swnj 1044809Swnj case PRU_DISCONNECT: 1055075Swnj if (tp->t_state < TCPS_ESTABLISHED) 1065075Swnj tcp_close(tp); 1074886Swnj else { 1084886Swnj soisdisconnecting(so); 1095113Swnj (void) tcp_output(tp); 1104886Swnj } 1114809Swnj break; 1124809Swnj 1134809Swnj case PRU_SHUTDOWN: 1145089Swnj socantsendmore(so); 1155075Swnj switch (tp->t_state) { 1164497Swnj 1175066Swnj case TCPS_LISTEN: 1185066Swnj case TCPS_SYN_SENT: 1195075Swnj tp->t_state = TCPS_CLOSED; 1204731Swnj break; 1214731Swnj 1225089Swnj case TCPS_SYN_RECEIVED: 1235089Swnj case TCPS_ESTABLISHED: 1245075Swnj tp->t_state = TCPS_FIN_WAIT_1; 1255113Swnj (void) tcp_output(tp); 1265075Swnj break; 1275075Swnj 1285066Swnj case TCPS_CLOSE_WAIT: 1295075Swnj tp->t_state = TCPS_LAST_ACK; 1305113Swnj (void) tcp_output(tp); 1314731Swnj break; 1324731Swnj } 1334567Swnj break; 1344497Swnj 1354809Swnj case PRU_RCVD: 1365113Swnj (void) tcp_output(tp); 1374567Swnj break; 1384497Swnj 1394809Swnj case PRU_SEND: 1405075Swnj sbappend(&so->so_snd, m); 1415089Swnj /* 1425089Swnj if (tp->t_flags & TF_PUSH) 1435075Swnj tp->snd_end = tp->snd_una + so->so_snd.sb_cc; 1445089Swnj */ 1455089Swnj if (tp->t_flags & TF_URG) 1465089Swnj tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1; 1475113Swnj (void) tcp_output(tp); 1484567Swnj break; 1494567Swnj 1504809Swnj case PRU_ABORT: 1515075Swnj tcp_drop(tp, ECONNABORTED); 1524567Swnj break; 1534567Swnj 1544809Swnj case PRU_CONTROL: 1554886Swnj error = EOPNOTSUPP; 1564809Swnj break; 1574809Swnj 1585113Swnj case PRU_SENSE: 1595113Swnj error = EOPNOTSUPP; 1605113Swnj break; 1615113Swnj 1625113Swnj case PRU_RCVOOB: 1635113Swnj error = EOPNOTSUPP; 1645113Swnj break; 1655113Swnj 1665113Swnj case PRU_SENDOOB: 1675113Swnj error = EOPNOTSUPP; 1685113Swnj break; 1695113Swnj 1704809Swnj case PRU_SLOWTIMO: 1715075Swnj tcp_timers(tp, (int)addr); 1724809Swnj break; 1734809Swnj 1744731Swnj default: 1754731Swnj panic("tcp_usrreq"); 1764567Swnj } 1774567Swnj splx(s); 1784886Swnj return (error); 1794497Swnj } 180