1*5165Swnj /* tcp_usrreq.c 1.38 81/12/02 */ 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 } 62*5165Swnj 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) { 69*5165Swnj 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: 79*5165Swnj in_pcbdetach(inp); 804809Swnj break; 814809Swnj 824809Swnj case PRU_CONNECT: 83*5165Swnj error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 844954Swnj if (error) 854886Swnj break; 865062Swnj tp = tcp_newtcpcb(inp); 875062Swnj if (tp == 0) { 88*5165Swnj in_pcbdisconnect(inp); 895062Swnj error = ENOBUFS; 905062Swnj break; 915062Swnj } 925062Swnj tp->t_inpcb = inp; 935062Swnj inp->inp_ppcb = (caddr_t)tp; 944886Swnj soisconnecting(so); 955075Swnj tp->t_state = TCPS_SYN_SENT; 965113Swnj (void) tcp_output(tp); 974567Swnj break; 984497Swnj 994925Swnj case PRU_ACCEPT: 1004954Swnj soisconnected(so); 1014954Swnj break; 1024925Swnj 1034809Swnj case PRU_DISCONNECT: 1045075Swnj if (tp->t_state < TCPS_ESTABLISHED) 1055075Swnj tcp_close(tp); 1064886Swnj else { 1074886Swnj soisdisconnecting(so); 1085113Swnj (void) tcp_output(tp); 1094886Swnj } 1104809Swnj break; 1114809Swnj 1124809Swnj case PRU_SHUTDOWN: 1135089Swnj socantsendmore(so); 1145075Swnj switch (tp->t_state) { 1154497Swnj 1165066Swnj case TCPS_LISTEN: 1175066Swnj case TCPS_SYN_SENT: 1185075Swnj tp->t_state = TCPS_CLOSED; 1194731Swnj break; 1204731Swnj 1215089Swnj case TCPS_SYN_RECEIVED: 1225089Swnj case TCPS_ESTABLISHED: 1235075Swnj tp->t_state = TCPS_FIN_WAIT_1; 1245113Swnj (void) tcp_output(tp); 1255075Swnj break; 1265075Swnj 1275066Swnj case TCPS_CLOSE_WAIT: 1285075Swnj tp->t_state = TCPS_LAST_ACK; 1295113Swnj (void) tcp_output(tp); 1304731Swnj break; 1314731Swnj } 1324567Swnj break; 1334497Swnj 1344809Swnj case PRU_RCVD: 1355113Swnj (void) tcp_output(tp); 1364567Swnj break; 1374497Swnj 1384809Swnj case PRU_SEND: 1395075Swnj sbappend(&so->so_snd, m); 1405089Swnj /* 1415089Swnj if (tp->t_flags & TF_PUSH) 1425075Swnj tp->snd_end = tp->snd_una + so->so_snd.sb_cc; 1435089Swnj */ 1445089Swnj if (tp->t_flags & TF_URG) 1455089Swnj tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1; 1465113Swnj (void) tcp_output(tp); 1474567Swnj break; 1484567Swnj 1494809Swnj case PRU_ABORT: 1505075Swnj tcp_drop(tp, ECONNABORTED); 1514567Swnj break; 1524567Swnj 1534809Swnj case PRU_CONTROL: 1544886Swnj error = EOPNOTSUPP; 1554809Swnj break; 1564809Swnj 1575113Swnj case PRU_SENSE: 1585113Swnj error = EOPNOTSUPP; 1595113Swnj break; 1605113Swnj 1615113Swnj case PRU_RCVOOB: 1625113Swnj error = EOPNOTSUPP; 1635113Swnj break; 1645113Swnj 1655113Swnj case PRU_SENDOOB: 1665113Swnj error = EOPNOTSUPP; 1675113Swnj break; 1685113Swnj 1694809Swnj case PRU_SLOWTIMO: 1705075Swnj tcp_timers(tp, (int)addr); 1714809Swnj break; 1724809Swnj 1734731Swnj default: 1744731Swnj panic("tcp_usrreq"); 1754567Swnj } 1764567Swnj splx(s); 1774886Swnj return (error); 1784497Swnj } 179