1*5113Swnj /* tcp_usrreq.c 1.37 81/11/29 */ 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*5113Swnj #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 } 624954Swnj error = in_pcballoc(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) { 695075Swnj in_pcbfree(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: 794809Swnj break; 804809Swnj 814809Swnj case PRU_CONNECT: 824954Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 834954Swnj if (error) 844886Swnj break; 855062Swnj tp = tcp_newtcpcb(inp); 865062Swnj if (tp == 0) { 875062Swnj inp->inp_faddr.s_addr = 0; 885062Swnj error = ENOBUFS; 895062Swnj break; 905062Swnj } 915062Swnj tp->t_inpcb = inp; 925062Swnj inp->inp_ppcb = (caddr_t)tp; 934886Swnj soisconnecting(so); 945075Swnj tp->t_state = TCPS_SYN_SENT; 95*5113Swnj (void) tcp_output(tp); 964567Swnj break; 974497Swnj 984925Swnj case PRU_ACCEPT: 994954Swnj soisconnected(so); 1004954Swnj break; 1014925Swnj 1024809Swnj case PRU_DISCONNECT: 1035075Swnj if (tp->t_state < TCPS_ESTABLISHED) 1045075Swnj tcp_close(tp); 1054886Swnj else { 1064886Swnj soisdisconnecting(so); 107*5113Swnj (void) tcp_output(tp); 1084886Swnj } 1094809Swnj break; 1104809Swnj 1114809Swnj case PRU_SHUTDOWN: 1125089Swnj socantsendmore(so); 1135075Swnj switch (tp->t_state) { 1144497Swnj 1155066Swnj case TCPS_LISTEN: 1165066Swnj case TCPS_SYN_SENT: 1175075Swnj tp->t_state = TCPS_CLOSED; 1184731Swnj break; 1194731Swnj 1205089Swnj case TCPS_SYN_RECEIVED: 1215089Swnj case TCPS_ESTABLISHED: 1225075Swnj tp->t_state = TCPS_FIN_WAIT_1; 123*5113Swnj (void) tcp_output(tp); 1245075Swnj break; 1255075Swnj 1265066Swnj case TCPS_CLOSE_WAIT: 1275075Swnj tp->t_state = TCPS_LAST_ACK; 128*5113Swnj (void) tcp_output(tp); 1294731Swnj break; 1304731Swnj } 1314567Swnj break; 1324497Swnj 1334809Swnj case PRU_RCVD: 134*5113Swnj (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; 145*5113Swnj (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 156*5113Swnj case PRU_SENSE: 157*5113Swnj error = EOPNOTSUPP; 158*5113Swnj break; 159*5113Swnj 160*5113Swnj case PRU_RCVOOB: 161*5113Swnj error = EOPNOTSUPP; 162*5113Swnj break; 163*5113Swnj 164*5113Swnj case PRU_SENDOOB: 165*5113Swnj error = EOPNOTSUPP; 166*5113Swnj break; 167*5113Swnj 1684809Swnj case PRU_SLOWTIMO: 1695075Swnj tcp_timers(tp, (int)addr); 1704809Swnj break; 1714809Swnj 1724731Swnj default: 1734731Swnj panic("tcp_usrreq"); 1744567Swnj } 1754567Swnj splx(s); 1764886Swnj return (error); 1774497Swnj } 178