1 /* tcp_usrreq.c 1.40 81/12/12 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/mbuf.h" 6 #include "../h/socket.h" 7 #include "../h/socketvar.h" 8 #include "../h/protosw.h" 9 #include "../net/in.h" 10 #include "../net/in_pcb.h" 11 #include "../net/in_systm.h" 12 #include "../net/if.h" 13 #include "../net/ip.h" 14 #include "../net/ip_var.h" 15 #include "../net/tcp.h" 16 #include "../net/tcp_fsm.h" 17 #include "../net/tcp_seq.h" 18 #include "../net/tcp_timer.h" 19 #include "../net/tcp_var.h" 20 #include "../net/tcpip.h" 21 #include "../errno.h" 22 23 extern char *tcpstates[]; 24 struct tcpcb *tcp_newtcpcb(); 25 /* 26 * Process a TCP user request for tcp tb. If this is a send request 27 * then m is the mbuf chain of send data. If this is a timer expiration 28 * (called from the software clock routine), then timertype tells which timer. 29 */ 30 tcp_usrreq(so, req, m, addr) 31 struct socket *so; 32 int req; 33 struct mbuf *m; 34 caddr_t addr; 35 { 36 register struct inpcb *inp = sotoinpcb(so); 37 register struct tcpcb *tp; 38 int s = splnet(); 39 int error = 0; 40 COUNT(TCP_USRREQ); 41 42 /* 43 * Make sure attached. If not, 44 * only PRU_ATTACH is valid. 45 */ 46 printf("tcp_usrreq %d so %x inp %x\n", req, so, inp); 47 if (inp == 0 && req != PRU_ATTACH) { 48 splx(s); 49 return (EINVAL); 50 } 51 if (inp) { 52 tp = intotcpcb(inp); 53 #ifdef KPROF 54 tcp_acounts[tp->t_state][req]++; 55 #endif 56 } 57 switch (req) { 58 59 case PRU_ATTACH: 60 if (inp) { 61 error = EISCONN; 62 break; 63 } 64 error = in_pcbattach(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr); 65 if (error) 66 break; 67 inp = (struct inpcb *)so->so_pcb; 68 tp = tcp_newtcpcb(inp); 69 if (so->so_options & SO_ACCEPTCONN) { 70 if (tp == 0) { 71 in_pcbdetach(inp); 72 error = ENOBUFS; 73 break; 74 } 75 tp->t_state = TCPS_LISTEN; 76 } else 77 tp->t_state = TCPS_CLOSED; 78 break; 79 80 case PRU_DETACH: 81 in_pcbdetach(inp); 82 break; 83 84 case PRU_CONNECT: 85 error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 86 if (error) 87 break; 88 tp = tcp_newtcpcb(inp); 89 if (tp == 0) 90 goto badcon; 91 tp->t_template = tcp_template(tp); 92 if (tp->t_template == 0) 93 goto badcon2; 94 tp->t_inpcb = inp; 95 inp->inp_ppcb = (caddr_t)tp; 96 soisconnecting(so); 97 tp->t_state = TCPS_SYN_SENT; 98 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; 99 tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; 100 tcp_sendseqinit(tp); 101 (void) tcp_output(tp); 102 break; 103 104 badcon2: 105 (void) m_free(dtom(tp)); 106 badcon: 107 in_pcbdisconnect(inp); 108 error = ENOBUFS; 109 break; 110 111 case PRU_ACCEPT: 112 soisconnected(so); 113 break; 114 115 case PRU_DISCONNECT: 116 if (tp->t_state < TCPS_ESTABLISHED) 117 tcp_close(tp); 118 else { 119 soisdisconnecting(so); 120 tcp_usrclosed(tp); 121 (void) tcp_output(tp); 122 } 123 break; 124 125 case PRU_SHUTDOWN: 126 socantsendmore(so); 127 tcp_usrclosed(tp); 128 (void) tcp_output(tp); 129 break; 130 131 case PRU_RCVD: 132 (void) tcp_output(tp); 133 break; 134 135 case PRU_SEND: 136 sbappend(&so->so_snd, m); 137 /* 138 if (tp->t_flags & TF_PUSH) 139 tp->snd_end = tp->snd_una + so->so_snd.sb_cc; 140 */ 141 if (tp->t_flags & TF_URG) 142 tp->snd_up = tp->snd_una + so->so_snd.sb_cc + 1; 143 (void) tcp_output(tp); 144 break; 145 146 case PRU_ABORT: 147 tcp_drop(tp, ECONNABORTED); 148 break; 149 150 case PRU_CONTROL: 151 error = EOPNOTSUPP; 152 break; 153 154 case PRU_SENSE: 155 error = EOPNOTSUPP; 156 break; 157 158 case PRU_RCVOOB: 159 error = EOPNOTSUPP; 160 break; 161 162 case PRU_SENDOOB: 163 error = EOPNOTSUPP; 164 break; 165 166 case PRU_SLOWTIMO: 167 tcp_timers(tp, (int)addr); 168 break; 169 170 default: 171 panic("tcp_usrreq"); 172 } 173 splx(s); 174 return (error); 175 } 176 177 pseqno(tp) 178 struct tcpcb *tp; 179 { 180 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 printf("snd_una %x snd_nxt %x snd_wnd %d snd_wl1 %x snd_wl2 %x iss %x\n", 182 tp->snd_una, tp->snd_nxt, tp->snd_wnd, tp->snd_wl1, tp->snd_wl2, tp->iss); 183 } 184 185 tcp_usrclosed(tp) 186 struct tcpcb *tp; 187 { 188 189 printf("usrclosed in %s\n", tcpstates[tp->t_state]); 190 switch (tp->t_state) { 191 192 case TCPS_LISTEN: 193 case TCPS_SYN_SENT: 194 tp->t_state = TCPS_CLOSED; 195 tcp_close(tp); 196 break; 197 198 case TCPS_SYN_RECEIVED: 199 case TCPS_ESTABLISHED: 200 tp->t_state = TCPS_FIN_WAIT_1; 201 break; 202 203 case TCPS_CLOSE_WAIT: 204 tp->t_state = TCPS_LAST_ACK; 205 break; 206 } 207 printf("after usrclosed state %s\n", tcpstates[tp->t_state]); 208 } 209