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