1/* 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
| 1/* 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
|
34 * $Id: tcp_usrreq.c,v 1.31 1997/04/27 20:01:14 wollman Exp $
| 34 * $Id: tcp_usrreq.c,v 1.32 1997/08/02 14:32:58 bde Exp $
|
35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> 40#include <sys/sysctl.h> 41#include <sys/mbuf.h> 42#include <sys/socket.h> 43#include <sys/socketvar.h> 44#include <sys/protosw.h> 45 46#include <net/if.h> 47#include <net/route.h> 48 49#include <netinet/in.h> 50#include <netinet/in_systm.h> 51#include <netinet/in_pcb.h> 52#include <netinet/in_var.h> 53#include <netinet/ip_var.h> 54#include <netinet/tcp.h> 55#include <netinet/tcp_fsm.h> 56#include <netinet/tcp_seq.h> 57#include <netinet/tcp_timer.h> 58#include <netinet/tcp_var.h> 59#include <netinet/tcpip.h> 60#ifdef TCPDEBUG 61#include <netinet/tcp_debug.h> 62#endif 63 64/* 65 * TCP protocol interface to socket abstraction. 66 */ 67extern char *tcpstates[]; /* XXX ??? */ 68 69static int tcp_attach __P((struct socket *, struct proc *));
| 35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> 40#include <sys/sysctl.h> 41#include <sys/mbuf.h> 42#include <sys/socket.h> 43#include <sys/socketvar.h> 44#include <sys/protosw.h> 45 46#include <net/if.h> 47#include <net/route.h> 48 49#include <netinet/in.h> 50#include <netinet/in_systm.h> 51#include <netinet/in_pcb.h> 52#include <netinet/in_var.h> 53#include <netinet/ip_var.h> 54#include <netinet/tcp.h> 55#include <netinet/tcp_fsm.h> 56#include <netinet/tcp_seq.h> 57#include <netinet/tcp_timer.h> 58#include <netinet/tcp_var.h> 59#include <netinet/tcpip.h> 60#ifdef TCPDEBUG 61#include <netinet/tcp_debug.h> 62#endif 63 64/* 65 * TCP protocol interface to socket abstraction. 66 */ 67extern char *tcpstates[]; /* XXX ??? */ 68 69static int tcp_attach __P((struct socket *, struct proc *));
|
70static int tcp_connect __P((struct tcpcb *, struct mbuf *,
| 70static int tcp_connect __P((struct tcpcb *, struct sockaddr *,
|
71 struct proc *)); 72static struct tcpcb * 73 tcp_disconnect __P((struct tcpcb *)); 74static struct tcpcb * 75 tcp_usrclosed __P((struct tcpcb *)); 76 77#ifdef TCPDEBUG 78#define TCPDEBUG0 int ostate 79#define TCPDEBUG1() ostate = tp ? tp->t_state : 0 80#define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \ 81 tcp_trace(TA_USER, ostate, tp, 0, req) 82#else 83#define TCPDEBUG0 84#define TCPDEBUG1() 85#define TCPDEBUG2(req) 86#endif 87 88/* 89 * TCP attaches to socket via pru_attach(), reserving space, 90 * and an internet control block. 91 */ 92static int 93tcp_usr_attach(struct socket *so, int proto, struct proc *p) 94{ 95 int s = splnet(); 96 int error; 97 struct inpcb *inp = sotoinpcb(so); 98 struct tcpcb *tp = 0; 99 TCPDEBUG0; 100 101 TCPDEBUG1(); 102 if (inp) { 103 error = EISCONN; 104 goto out; 105 } 106 107 error = tcp_attach(so, p); 108 if (error) 109 goto out; 110 111 if ((so->so_options & SO_LINGER) && so->so_linger == 0) 112 so->so_linger = TCP_LINGERTIME * hz; 113 tp = sototcpcb(so); 114out: 115 TCPDEBUG2(PRU_ATTACH); 116 splx(s); 117 return error; 118} 119 120/* 121 * pru_detach() detaches the TCP protocol from the socket. 122 * If the protocol state is non-embryonic, then can't 123 * do this directly: have to initiate a pru_disconnect(), 124 * which may finish later; embryonic TCB's can just 125 * be discarded here. 126 */ 127static int 128tcp_usr_detach(struct socket *so) 129{ 130 int s = splnet(); 131 int error = 0; 132 struct inpcb *inp = sotoinpcb(so); 133 struct tcpcb *tp; 134 TCPDEBUG0; 135 136 if (inp == 0) { 137 splx(s); 138 return EINVAL; /* XXX */ 139 } 140 tp = intotcpcb(inp); 141 TCPDEBUG1();
| 71 struct proc *)); 72static struct tcpcb * 73 tcp_disconnect __P((struct tcpcb *)); 74static struct tcpcb * 75 tcp_usrclosed __P((struct tcpcb *)); 76 77#ifdef TCPDEBUG 78#define TCPDEBUG0 int ostate 79#define TCPDEBUG1() ostate = tp ? tp->t_state : 0 80#define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \ 81 tcp_trace(TA_USER, ostate, tp, 0, req) 82#else 83#define TCPDEBUG0 84#define TCPDEBUG1() 85#define TCPDEBUG2(req) 86#endif 87 88/* 89 * TCP attaches to socket via pru_attach(), reserving space, 90 * and an internet control block. 91 */ 92static int 93tcp_usr_attach(struct socket *so, int proto, struct proc *p) 94{ 95 int s = splnet(); 96 int error; 97 struct inpcb *inp = sotoinpcb(so); 98 struct tcpcb *tp = 0; 99 TCPDEBUG0; 100 101 TCPDEBUG1(); 102 if (inp) { 103 error = EISCONN; 104 goto out; 105 } 106 107 error = tcp_attach(so, p); 108 if (error) 109 goto out; 110 111 if ((so->so_options & SO_LINGER) && so->so_linger == 0) 112 so->so_linger = TCP_LINGERTIME * hz; 113 tp = sototcpcb(so); 114out: 115 TCPDEBUG2(PRU_ATTACH); 116 splx(s); 117 return error; 118} 119 120/* 121 * pru_detach() detaches the TCP protocol from the socket. 122 * If the protocol state is non-embryonic, then can't 123 * do this directly: have to initiate a pru_disconnect(), 124 * which may finish later; embryonic TCB's can just 125 * be discarded here. 126 */ 127static int 128tcp_usr_detach(struct socket *so) 129{ 130 int s = splnet(); 131 int error = 0; 132 struct inpcb *inp = sotoinpcb(so); 133 struct tcpcb *tp; 134 TCPDEBUG0; 135 136 if (inp == 0) { 137 splx(s); 138 return EINVAL; /* XXX */ 139 } 140 tp = intotcpcb(inp); 141 TCPDEBUG1();
|
142 if (tp->t_state > TCPS_LISTEN) 143 tp = tcp_disconnect(tp); 144 else 145 tp = tcp_close(tp);
| 142 tp = tcp_disconnect(tp);
|
146 147 TCPDEBUG2(PRU_DETACH); 148 splx(s); 149 return error; 150} 151 152#define COMMON_START() TCPDEBUG0; \ 153 do { \ 154 if (inp == 0) { \ 155 splx(s); \ 156 return EINVAL; \ 157 } \ 158 tp = intotcpcb(inp); \ 159 TCPDEBUG1(); \ 160 } while(0) 161 162#define COMMON_END(req) out: TCPDEBUG2(req); splx(s); return error; goto out 163 164 165/* 166 * Give the socket an address. 167 */ 168static int
| 143 144 TCPDEBUG2(PRU_DETACH); 145 splx(s); 146 return error; 147} 148 149#define COMMON_START() TCPDEBUG0; \ 150 do { \ 151 if (inp == 0) { \ 152 splx(s); \ 153 return EINVAL; \ 154 } \ 155 tp = intotcpcb(inp); \ 156 TCPDEBUG1(); \ 157 } while(0) 158 159#define COMMON_END(req) out: TCPDEBUG2(req); splx(s); return error; goto out 160 161 162/* 163 * Give the socket an address. 164 */ 165static int
|
169tcp_usr_bind(struct socket *so, struct mbuf *nam, struct proc *p)
| 166tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
|
170{ 171 int s = splnet(); 172 int error = 0; 173 struct inpcb *inp = sotoinpcb(so); 174 struct tcpcb *tp; 175 struct sockaddr_in *sinp; 176 177 COMMON_START(); 178 179 /* 180 * Must check for multicast addresses and disallow binding 181 * to them. 182 */
| 167{ 168 int s = splnet(); 169 int error = 0; 170 struct inpcb *inp = sotoinpcb(so); 171 struct tcpcb *tp; 172 struct sockaddr_in *sinp; 173 174 COMMON_START(); 175 176 /* 177 * Must check for multicast addresses and disallow binding 178 * to them. 179 */
|
183 sinp = mtod(nam, struct sockaddr_in *);
| 180 sinp = (struct sockaddr_in *)nam;
|
184 if (sinp->sin_family == AF_INET && 185 IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 186 error = EAFNOSUPPORT; 187 goto out; 188 } 189 error = in_pcbbind(inp, nam, p); 190 if (error) 191 goto out; 192 COMMON_END(PRU_BIND); 193 194} 195 196/* 197 * Prepare to accept connections. 198 */ 199static int 200tcp_usr_listen(struct socket *so, struct proc *p) 201{ 202 int s = splnet(); 203 int error = 0; 204 struct inpcb *inp = sotoinpcb(so); 205 struct tcpcb *tp; 206 207 COMMON_START(); 208 if (inp->inp_lport == 0)
| 181 if (sinp->sin_family == AF_INET && 182 IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 183 error = EAFNOSUPPORT; 184 goto out; 185 } 186 error = in_pcbbind(inp, nam, p); 187 if (error) 188 goto out; 189 COMMON_END(PRU_BIND); 190 191} 192 193/* 194 * Prepare to accept connections. 195 */ 196static int 197tcp_usr_listen(struct socket *so, struct proc *p) 198{ 199 int s = splnet(); 200 int error = 0; 201 struct inpcb *inp = sotoinpcb(so); 202 struct tcpcb *tp; 203 204 COMMON_START(); 205 if (inp->inp_lport == 0)
|
209 error = in_pcbbind(inp, (struct mbuf *)0, p);
| 206 error = in_pcbbind(inp, (struct sockaddr *)0, p);
|
210 if (error == 0) 211 tp->t_state = TCPS_LISTEN; 212 COMMON_END(PRU_LISTEN); 213} 214 215/* 216 * Initiate connection to peer. 217 * Create a template for use in transmissions on this connection. 218 * Enter SYN_SENT state, and mark socket as connecting. 219 * Start keep-alive timer, and seed output sequence space. 220 * Send initial segment on connection. 221 */ 222static int
| 207 if (error == 0) 208 tp->t_state = TCPS_LISTEN; 209 COMMON_END(PRU_LISTEN); 210} 211 212/* 213 * Initiate connection to peer. 214 * Create a template for use in transmissions on this connection. 215 * Enter SYN_SENT state, and mark socket as connecting. 216 * Start keep-alive timer, and seed output sequence space. 217 * Send initial segment on connection. 218 */ 219static int
|
223tcp_usr_connect(struct socket *so, struct mbuf *nam, struct proc *p)
| 220tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
|
224{ 225 int s = splnet(); 226 int error = 0; 227 struct inpcb *inp = sotoinpcb(so); 228 struct tcpcb *tp; 229 struct sockaddr_in *sinp; 230 231 COMMON_START(); 232 233 /* 234 * Must disallow TCP ``connections'' to multicast addresses. 235 */
| 221{ 222 int s = splnet(); 223 int error = 0; 224 struct inpcb *inp = sotoinpcb(so); 225 struct tcpcb *tp; 226 struct sockaddr_in *sinp; 227 228 COMMON_START(); 229 230 /* 231 * Must disallow TCP ``connections'' to multicast addresses. 232 */
|
236 sinp = mtod(nam, struct sockaddr_in *);
| 233 sinp = (struct sockaddr_in *)nam;
|
237 if (sinp->sin_family == AF_INET 238 && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 239 error = EAFNOSUPPORT; 240 goto out; 241 } 242 243 if ((error = tcp_connect(tp, nam, p)) != 0) 244 goto out; 245 error = tcp_output(tp); 246 COMMON_END(PRU_CONNECT); 247} 248 249/* 250 * Initiate disconnect from peer. 251 * If connection never passed embryonic stage, just drop; 252 * else if don't need to let data drain, then can just drop anyways, 253 * else have to begin TCP shutdown process: mark socket disconnecting, 254 * drain unread data, state switch to reflect user close, and 255 * send segment (e.g. FIN) to peer. Socket will be really disconnected 256 * when peer sends FIN and acks ours. 257 * 258 * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. 259 */ 260static int 261tcp_usr_disconnect(struct socket *so) 262{ 263 int s = splnet(); 264 int error = 0; 265 struct inpcb *inp = sotoinpcb(so); 266 struct tcpcb *tp; 267 268 COMMON_START(); 269 tp = tcp_disconnect(tp); 270 COMMON_END(PRU_DISCONNECT); 271} 272 273/* 274 * Accept a connection. Essentially all the work is 275 * done at higher levels; just return the address 276 * of the peer, storing through addr. 277 */ 278static int
| 234 if (sinp->sin_family == AF_INET 235 && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 236 error = EAFNOSUPPORT; 237 goto out; 238 } 239 240 if ((error = tcp_connect(tp, nam, p)) != 0) 241 goto out; 242 error = tcp_output(tp); 243 COMMON_END(PRU_CONNECT); 244} 245 246/* 247 * Initiate disconnect from peer. 248 * If connection never passed embryonic stage, just drop; 249 * else if don't need to let data drain, then can just drop anyways, 250 * else have to begin TCP shutdown process: mark socket disconnecting, 251 * drain unread data, state switch to reflect user close, and 252 * send segment (e.g. FIN) to peer. Socket will be really disconnected 253 * when peer sends FIN and acks ours. 254 * 255 * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. 256 */ 257static int 258tcp_usr_disconnect(struct socket *so) 259{ 260 int s = splnet(); 261 int error = 0; 262 struct inpcb *inp = sotoinpcb(so); 263 struct tcpcb *tp; 264 265 COMMON_START(); 266 tp = tcp_disconnect(tp); 267 COMMON_END(PRU_DISCONNECT); 268} 269 270/* 271 * Accept a connection. Essentially all the work is 272 * done at higher levels; just return the address 273 * of the peer, storing through addr. 274 */ 275static int
|
279tcp_usr_accept(struct socket *so, struct mbuf *nam)
| 276tcp_usr_accept(struct socket *so, struct sockaddr **nam)
|
280{ 281 int s = splnet(); 282 int error = 0; 283 struct inpcb *inp = sotoinpcb(so); 284 struct tcpcb *tp; 285 286 COMMON_START(); 287 in_setpeeraddr(so, nam); 288 COMMON_END(PRU_ACCEPT); 289} 290 291/* 292 * Mark the connection as being incapable of further output. 293 */ 294static int 295tcp_usr_shutdown(struct socket *so) 296{ 297 int s = splnet(); 298 int error = 0; 299 struct inpcb *inp = sotoinpcb(so); 300 struct tcpcb *tp; 301 302 COMMON_START(); 303 socantsendmore(so); 304 tp = tcp_usrclosed(tp); 305 if (tp) 306 error = tcp_output(tp); 307 COMMON_END(PRU_SHUTDOWN); 308} 309 310/* 311 * After a receive, possibly send window update to peer. 312 */ 313static int 314tcp_usr_rcvd(struct socket *so, int flags) 315{ 316 int s = splnet(); 317 int error = 0; 318 struct inpcb *inp = sotoinpcb(so); 319 struct tcpcb *tp; 320 321 COMMON_START(); 322 tcp_output(tp); 323 COMMON_END(PRU_RCVD); 324} 325 326/* 327 * Do a send by putting data in output queue and updating urgent 328 * marker if URG set. Possibly send more data. 329 */ 330static int
| 277{ 278 int s = splnet(); 279 int error = 0; 280 struct inpcb *inp = sotoinpcb(so); 281 struct tcpcb *tp; 282 283 COMMON_START(); 284 in_setpeeraddr(so, nam); 285 COMMON_END(PRU_ACCEPT); 286} 287 288/* 289 * Mark the connection as being incapable of further output. 290 */ 291static int 292tcp_usr_shutdown(struct socket *so) 293{ 294 int s = splnet(); 295 int error = 0; 296 struct inpcb *inp = sotoinpcb(so); 297 struct tcpcb *tp; 298 299 COMMON_START(); 300 socantsendmore(so); 301 tp = tcp_usrclosed(tp); 302 if (tp) 303 error = tcp_output(tp); 304 COMMON_END(PRU_SHUTDOWN); 305} 306 307/* 308 * After a receive, possibly send window update to peer. 309 */ 310static int 311tcp_usr_rcvd(struct socket *so, int flags) 312{ 313 int s = splnet(); 314 int error = 0; 315 struct inpcb *inp = sotoinpcb(so); 316 struct tcpcb *tp; 317 318 COMMON_START(); 319 tcp_output(tp); 320 COMMON_END(PRU_RCVD); 321} 322 323/* 324 * Do a send by putting data in output queue and updating urgent 325 * marker if URG set. Possibly send more data. 326 */ 327static int
|
331tcp_usr_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam, 332 struct mbuf *control, struct proc *p)
| 328tcp_usr_send(struct socket *so, int flags, struct mbuf *m, 329 struct sockaddr *nam, struct mbuf *control, struct proc *p)
|
333{ 334 int s = splnet(); 335 int error = 0; 336 struct inpcb *inp = sotoinpcb(so); 337 struct tcpcb *tp; 338 339 COMMON_START(); 340 if (control && control->m_len) { 341 m_freem(control); /* XXX shouldn't caller do this??? */ 342 if (m) 343 m_freem(m); 344 return EINVAL; 345 } 346 347 if(!(flags & PRUS_OOB)) { 348 sbappend(&so->so_snd, m); 349 if (nam && tp->t_state < TCPS_SYN_SENT) { 350 /* 351 * Do implied connect if not yet connected, 352 * initialize window to default value, and 353 * initialize maxseg/maxopd using peer's cached 354 * MSS. 355 */ 356 error = tcp_connect(tp, nam, p); 357 if (error) 358 goto out; 359 tp->snd_wnd = TTCP_CLIENT_SND_WND; 360 tcp_mss(tp, -1); 361 } 362 363 if (flags & PRUS_EOF) { 364 /* 365 * Close the send side of the connection after 366 * the data is sent. 367 */ 368 socantsendmore(so); 369 tp = tcp_usrclosed(tp); 370 } 371 if (tp != NULL) 372 error = tcp_output(tp); 373 } else { 374 if (sbspace(&so->so_snd) < -512) { 375 m_freem(m); 376 error = ENOBUFS; 377 goto out; 378 } 379 /* 380 * According to RFC961 (Assigned Protocols), 381 * the urgent pointer points to the last octet 382 * of urgent data. We continue, however, 383 * to consider it to indicate the first octet 384 * of data past the urgent section. 385 * Otherwise, snd_up should be one lower. 386 */ 387 sbappend(&so->so_snd, m); 388 if (nam && tp->t_state < TCPS_SYN_SENT) { 389 /* 390 * Do implied connect if not yet connected, 391 * initialize window to default value, and 392 * initialize maxseg/maxopd using peer's cached 393 * MSS. 394 */ 395 error = tcp_connect(tp, nam, p); 396 if (error) 397 goto out; 398 tp->snd_wnd = TTCP_CLIENT_SND_WND; 399 tcp_mss(tp, -1); 400 } 401 tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 402 tp->t_force = 1; 403 error = tcp_output(tp); 404 tp->t_force = 0; 405 } 406 COMMON_END((flags & PRUS_OOB) ? PRU_SENDOOB : 407 ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND)); 408} 409 410/* 411 * Abort the TCP. 412 */ 413static int 414tcp_usr_abort(struct socket *so) 415{ 416 int s = splnet(); 417 int error = 0; 418 struct inpcb *inp = sotoinpcb(so); 419 struct tcpcb *tp; 420 421 COMMON_START(); 422 tp = tcp_drop(tp, ECONNABORTED); 423 COMMON_END(PRU_ABORT); 424} 425 426/* 427 * Receive out-of-band data. 428 */ 429static int 430tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags) 431{ 432 int s = splnet(); 433 int error = 0; 434 struct inpcb *inp = sotoinpcb(so); 435 struct tcpcb *tp; 436 437 COMMON_START(); 438 if ((so->so_oobmark == 0 && 439 (so->so_state & SS_RCVATMARK) == 0) || 440 so->so_options & SO_OOBINLINE || 441 tp->t_oobflags & TCPOOB_HADDATA) { 442 error = EINVAL; 443 goto out; 444 } 445 if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { 446 error = EWOULDBLOCK; 447 goto out; 448 } 449 m->m_len = 1; 450 *mtod(m, caddr_t) = tp->t_iobc; 451 if ((flags & MSG_PEEK) == 0) 452 tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); 453 COMMON_END(PRU_RCVOOB); 454} 455 456/* xxx - should be const */ 457struct pr_usrreqs tcp_usrreqs = { 458 tcp_usr_abort, tcp_usr_accept, tcp_usr_attach, tcp_usr_bind, 459 tcp_usr_connect, pru_connect2_notsupp, in_control, tcp_usr_detach, 460 tcp_usr_disconnect, tcp_usr_listen, in_setpeeraddr, tcp_usr_rcvd, 461 tcp_usr_rcvoob, tcp_usr_send, pru_sense_null, tcp_usr_shutdown, 462 in_setsockaddr, sosend, soreceive, soselect 463}; 464 465/* 466 * Common subroutine to open a TCP connection to remote host specified 467 * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local 468 * port number if needed. Call in_pcbladdr to do the routing and to choose 469 * a local host address (interface). If there is an existing incarnation 470 * of the same connection in TIME-WAIT state and if the remote host was 471 * sending CC options and if the connection duration was < MSL, then 472 * truncate the previous TIME-WAIT state and proceed. 473 * Initialize connection parameters and enter SYN-SENT state. 474 */ 475static int 476tcp_connect(tp, nam, p) 477 register struct tcpcb *tp;
| 330{ 331 int s = splnet(); 332 int error = 0; 333 struct inpcb *inp = sotoinpcb(so); 334 struct tcpcb *tp; 335 336 COMMON_START(); 337 if (control && control->m_len) { 338 m_freem(control); /* XXX shouldn't caller do this??? */ 339 if (m) 340 m_freem(m); 341 return EINVAL; 342 } 343 344 if(!(flags & PRUS_OOB)) { 345 sbappend(&so->so_snd, m); 346 if (nam && tp->t_state < TCPS_SYN_SENT) { 347 /* 348 * Do implied connect if not yet connected, 349 * initialize window to default value, and 350 * initialize maxseg/maxopd using peer's cached 351 * MSS. 352 */ 353 error = tcp_connect(tp, nam, p); 354 if (error) 355 goto out; 356 tp->snd_wnd = TTCP_CLIENT_SND_WND; 357 tcp_mss(tp, -1); 358 } 359 360 if (flags & PRUS_EOF) { 361 /* 362 * Close the send side of the connection after 363 * the data is sent. 364 */ 365 socantsendmore(so); 366 tp = tcp_usrclosed(tp); 367 } 368 if (tp != NULL) 369 error = tcp_output(tp); 370 } else { 371 if (sbspace(&so->so_snd) < -512) { 372 m_freem(m); 373 error = ENOBUFS; 374 goto out; 375 } 376 /* 377 * According to RFC961 (Assigned Protocols), 378 * the urgent pointer points to the last octet 379 * of urgent data. We continue, however, 380 * to consider it to indicate the first octet 381 * of data past the urgent section. 382 * Otherwise, snd_up should be one lower. 383 */ 384 sbappend(&so->so_snd, m); 385 if (nam && tp->t_state < TCPS_SYN_SENT) { 386 /* 387 * Do implied connect if not yet connected, 388 * initialize window to default value, and 389 * initialize maxseg/maxopd using peer's cached 390 * MSS. 391 */ 392 error = tcp_connect(tp, nam, p); 393 if (error) 394 goto out; 395 tp->snd_wnd = TTCP_CLIENT_SND_WND; 396 tcp_mss(tp, -1); 397 } 398 tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 399 tp->t_force = 1; 400 error = tcp_output(tp); 401 tp->t_force = 0; 402 } 403 COMMON_END((flags & PRUS_OOB) ? PRU_SENDOOB : 404 ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND)); 405} 406 407/* 408 * Abort the TCP. 409 */ 410static int 411tcp_usr_abort(struct socket *so) 412{ 413 int s = splnet(); 414 int error = 0; 415 struct inpcb *inp = sotoinpcb(so); 416 struct tcpcb *tp; 417 418 COMMON_START(); 419 tp = tcp_drop(tp, ECONNABORTED); 420 COMMON_END(PRU_ABORT); 421} 422 423/* 424 * Receive out-of-band data. 425 */ 426static int 427tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags) 428{ 429 int s = splnet(); 430 int error = 0; 431 struct inpcb *inp = sotoinpcb(so); 432 struct tcpcb *tp; 433 434 COMMON_START(); 435 if ((so->so_oobmark == 0 && 436 (so->so_state & SS_RCVATMARK) == 0) || 437 so->so_options & SO_OOBINLINE || 438 tp->t_oobflags & TCPOOB_HADDATA) { 439 error = EINVAL; 440 goto out; 441 } 442 if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { 443 error = EWOULDBLOCK; 444 goto out; 445 } 446 m->m_len = 1; 447 *mtod(m, caddr_t) = tp->t_iobc; 448 if ((flags & MSG_PEEK) == 0) 449 tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); 450 COMMON_END(PRU_RCVOOB); 451} 452 453/* xxx - should be const */ 454struct pr_usrreqs tcp_usrreqs = { 455 tcp_usr_abort, tcp_usr_accept, tcp_usr_attach, tcp_usr_bind, 456 tcp_usr_connect, pru_connect2_notsupp, in_control, tcp_usr_detach, 457 tcp_usr_disconnect, tcp_usr_listen, in_setpeeraddr, tcp_usr_rcvd, 458 tcp_usr_rcvoob, tcp_usr_send, pru_sense_null, tcp_usr_shutdown, 459 in_setsockaddr, sosend, soreceive, soselect 460}; 461 462/* 463 * Common subroutine to open a TCP connection to remote host specified 464 * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local 465 * port number if needed. Call in_pcbladdr to do the routing and to choose 466 * a local host address (interface). If there is an existing incarnation 467 * of the same connection in TIME-WAIT state and if the remote host was 468 * sending CC options and if the connection duration was < MSL, then 469 * truncate the previous TIME-WAIT state and proceed. 470 * Initialize connection parameters and enter SYN-SENT state. 471 */ 472static int 473tcp_connect(tp, nam, p) 474 register struct tcpcb *tp;
|
478 struct mbuf *nam;
| 475 struct sockaddr *nam;
|
479 struct proc *p; 480{ 481 struct inpcb *inp = tp->t_inpcb, *oinp; 482 struct socket *so = inp->inp_socket; 483 struct tcpcb *otp;
| 476 struct proc *p; 477{ 478 struct inpcb *inp = tp->t_inpcb, *oinp; 479 struct socket *so = inp->inp_socket; 480 struct tcpcb *otp;
|
484 struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
| 481 struct sockaddr_in *sin = (struct sockaddr_in *)nam;
|
485 struct sockaddr_in *ifaddr; 486 int error; 487 struct rmxp_tao *taop; 488 struct rmxp_tao tao_noncached; 489 490 if (inp->inp_lport == 0) {
| 482 struct sockaddr_in *ifaddr; 483 int error; 484 struct rmxp_tao *taop; 485 struct rmxp_tao tao_noncached; 486 487 if (inp->inp_lport == 0) {
|
491 error = in_pcbbind(inp, (struct mbuf *)0, p);
| 488 error = in_pcbbind(inp, (struct sockaddr *)0, p);
|
492 if (error) 493 return error; 494 } 495 496 /* 497 * Cannot simply call in_pcbconnect, because there might be an 498 * earlier incarnation of this same connection still in 499 * TIME_WAIT state, creating an ADDRINUSE error. 500 */ 501 error = in_pcbladdr(inp, nam, &ifaddr); 502 if (error) 503 return error; 504 oinp = in_pcblookuphash(inp->inp_pcbinfo, 505 sin->sin_addr, sin->sin_port, 506 inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr 507 : ifaddr->sin_addr, 508 inp->inp_lport, 0); 509 if (oinp) { 510 if (oinp != inp && (otp = intotcpcb(oinp)) != NULL && 511 otp->t_state == TCPS_TIME_WAIT && 512 otp->t_duration < TCPTV_MSL && 513 (otp->t_flags & TF_RCVD_CC)) 514 otp = tcp_close(otp); 515 else 516 return EADDRINUSE; 517 } 518 if (inp->inp_laddr.s_addr == INADDR_ANY) 519 inp->inp_laddr = ifaddr->sin_addr; 520 inp->inp_faddr = sin->sin_addr; 521 inp->inp_fport = sin->sin_port; 522 in_pcbrehash(inp); 523 524 tp->t_template = tcp_template(tp); 525 if (tp->t_template == 0) { 526 in_pcbdisconnect(inp); 527 return ENOBUFS; 528 } 529 530 /* Compute window scaling to request. */ 531 while (tp->request_r_scale < TCP_MAX_WINSHIFT && 532 (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) 533 tp->request_r_scale++; 534 535 soisconnecting(so); 536 tcpstat.tcps_connattempt++; 537 tp->t_state = TCPS_SYN_SENT; 538 tp->t_timer[TCPT_KEEP] = tcp_keepinit; 539 tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; 540 tcp_sendseqinit(tp); 541 542 /* 543 * Generate a CC value for this connection and 544 * check whether CC or CCnew should be used. 545 */ 546 if ((taop = tcp_gettaocache(tp->t_inpcb)) == NULL) { 547 taop = &tao_noncached; 548 bzero(taop, sizeof(*taop)); 549 } 550 551 tp->cc_send = CC_INC(tcp_ccgen); 552 if (taop->tao_ccsent != 0 && 553 CC_GEQ(tp->cc_send, taop->tao_ccsent)) { 554 taop->tao_ccsent = tp->cc_send; 555 } else { 556 taop->tao_ccsent = 0; 557 tp->t_flags |= TF_SENDCCNEW; 558 } 559 560 return 0; 561} 562 563int 564tcp_ctloutput(op, so, level, optname, mp, p) 565 int op; 566 struct socket *so; 567 int level, optname; 568 struct mbuf **mp; 569 struct proc *p; 570{ 571 int error = 0, s; 572 struct inpcb *inp; 573 register struct tcpcb *tp; 574 register struct mbuf *m; 575 register int i; 576 577 s = splnet(); 578 inp = sotoinpcb(so); 579 if (inp == NULL) { 580 splx(s); 581 if (op == PRCO_SETOPT && *mp) 582 (void) m_free(*mp); 583 return (ECONNRESET); 584 } 585 if (level != IPPROTO_TCP) { 586 error = ip_ctloutput(op, so, level, optname, mp, p); 587 splx(s); 588 return (error); 589 } 590 tp = intotcpcb(inp); 591 592 switch (op) { 593 594 case PRCO_SETOPT: 595 m = *mp; 596 switch (optname) { 597 598 case TCP_NODELAY: 599 if (m == NULL || m->m_len < sizeof (int)) 600 error = EINVAL; 601 else if (*mtod(m, int *)) 602 tp->t_flags |= TF_NODELAY; 603 else 604 tp->t_flags &= ~TF_NODELAY; 605 break; 606 607 case TCP_MAXSEG: 608 if (m && (i = *mtod(m, int *)) > 0 && i <= tp->t_maxseg) 609 tp->t_maxseg = i; 610 else 611 error = EINVAL; 612 break; 613 614 case TCP_NOOPT: 615 if (m == NULL || m->m_len < sizeof (int)) 616 error = EINVAL; 617 else if (*mtod(m, int *)) 618 tp->t_flags |= TF_NOOPT; 619 else 620 tp->t_flags &= ~TF_NOOPT; 621 break; 622 623 case TCP_NOPUSH: 624 if (m == NULL || m->m_len < sizeof (int)) 625 error = EINVAL; 626 else if (*mtod(m, int *)) 627 tp->t_flags |= TF_NOPUSH; 628 else 629 tp->t_flags &= ~TF_NOPUSH; 630 break; 631 632 default: 633 error = ENOPROTOOPT; 634 break; 635 } 636 if (m) 637 (void) m_free(m); 638 break; 639 640 case PRCO_GETOPT: 641 *mp = m = m_get(M_WAIT, MT_SOOPTS); 642 m->m_len = sizeof(int); 643 644 switch (optname) { 645 case TCP_NODELAY: 646 *mtod(m, int *) = tp->t_flags & TF_NODELAY; 647 break; 648 case TCP_MAXSEG: 649 *mtod(m, int *) = tp->t_maxseg; 650 break; 651 case TCP_NOOPT: 652 *mtod(m, int *) = tp->t_flags & TF_NOOPT; 653 break; 654 case TCP_NOPUSH: 655 *mtod(m, int *) = tp->t_flags & TF_NOPUSH; 656 break; 657 default: 658 error = ENOPROTOOPT; 659 break; 660 } 661 break; 662 } 663 splx(s); 664 return (error); 665} 666 667/* 668 * tcp_sendspace and tcp_recvspace are the default send and receive window 669 * sizes, respectively. These are obsolescent (this information should 670 * be set by the route). 671 */ 672u_long tcp_sendspace = 1024*16; 673SYSCTL_INT(_net_inet_tcp, TCPCTL_SENDSPACE, sendspace, 674 CTLFLAG_RW, &tcp_sendspace , 0, ""); 675u_long tcp_recvspace = 1024*16; 676SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, 677 CTLFLAG_RW, &tcp_recvspace , 0, ""); 678 679/* 680 * Attach TCP protocol to socket, allocating 681 * internet protocol control block, tcp control block, 682 * bufer space, and entering LISTEN state if to accept connections. 683 */ 684static int 685tcp_attach(so, p) 686 struct socket *so; 687 struct proc *p; 688{ 689 register struct tcpcb *tp; 690 struct inpcb *inp; 691 int error; 692 693 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 694 error = soreserve(so, tcp_sendspace, tcp_recvspace); 695 if (error) 696 return (error); 697 } 698 error = in_pcballoc(so, &tcbinfo, p); 699 if (error) 700 return (error); 701 inp = sotoinpcb(so); 702 tp = tcp_newtcpcb(inp); 703 if (tp == 0) { 704 int nofd = so->so_state & SS_NOFDREF; /* XXX */ 705 706 so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ 707 in_pcbdetach(inp); 708 so->so_state |= nofd; 709 return (ENOBUFS); 710 } 711 tp->t_state = TCPS_CLOSED; 712 return (0); 713} 714 715/* 716 * Initiate (or continue) disconnect. 717 * If embryonic state, just send reset (once). 718 * If in ``let data drain'' option and linger null, just drop. 719 * Otherwise (hard), mark socket disconnecting and drop 720 * current input data; switch states based on user close, and 721 * send segment to peer (with FIN). 722 */ 723static struct tcpcb * 724tcp_disconnect(tp) 725 register struct tcpcb *tp; 726{ 727 struct socket *so = tp->t_inpcb->inp_socket; 728 729 if (tp->t_state < TCPS_ESTABLISHED) 730 tp = tcp_close(tp); 731 else if ((so->so_options & SO_LINGER) && so->so_linger == 0) 732 tp = tcp_drop(tp, 0); 733 else { 734 soisdisconnecting(so); 735 sbflush(&so->so_rcv); 736 tp = tcp_usrclosed(tp); 737 if (tp) 738 (void) tcp_output(tp); 739 } 740 return (tp); 741} 742 743/* 744 * User issued close, and wish to trail through shutdown states: 745 * if never received SYN, just forget it. If got a SYN from peer, 746 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. 747 * If already got a FIN from peer, then almost done; go to LAST_ACK 748 * state. In all other cases, have already sent FIN to peer (e.g. 749 * after PRU_SHUTDOWN), and just have to play tedious game waiting 750 * for peer to send FIN or not respond to keep-alives, etc. 751 * We can let the user exit from the close as soon as the FIN is acked. 752 */ 753static struct tcpcb * 754tcp_usrclosed(tp) 755 register struct tcpcb *tp; 756{ 757 758 switch (tp->t_state) { 759 760 case TCPS_CLOSED: 761 case TCPS_LISTEN: 762 tp->t_state = TCPS_CLOSED; 763 tp = tcp_close(tp); 764 break; 765 766 case TCPS_SYN_SENT: 767 case TCPS_SYN_RECEIVED: 768 tp->t_flags |= TF_NEEDFIN; 769 break; 770 771 case TCPS_ESTABLISHED: 772 tp->t_state = TCPS_FIN_WAIT_1; 773 break; 774 775 case TCPS_CLOSE_WAIT: 776 tp->t_state = TCPS_LAST_ACK; 777 break; 778 } 779 if (tp && tp->t_state >= TCPS_FIN_WAIT_2) { 780 soisdisconnected(tp->t_inpcb->inp_socket); 781 /* To prevent the connection hanging in FIN_WAIT_2 forever. */ 782 if (tp->t_state == TCPS_FIN_WAIT_2) 783 tp->t_timer[TCPT_2MSL] = tcp_maxidle; 784 } 785 return (tp); 786} 787
| 489 if (error) 490 return error; 491 } 492 493 /* 494 * Cannot simply call in_pcbconnect, because there might be an 495 * earlier incarnation of this same connection still in 496 * TIME_WAIT state, creating an ADDRINUSE error. 497 */ 498 error = in_pcbladdr(inp, nam, &ifaddr); 499 if (error) 500 return error; 501 oinp = in_pcblookuphash(inp->inp_pcbinfo, 502 sin->sin_addr, sin->sin_port, 503 inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr 504 : ifaddr->sin_addr, 505 inp->inp_lport, 0); 506 if (oinp) { 507 if (oinp != inp && (otp = intotcpcb(oinp)) != NULL && 508 otp->t_state == TCPS_TIME_WAIT && 509 otp->t_duration < TCPTV_MSL && 510 (otp->t_flags & TF_RCVD_CC)) 511 otp = tcp_close(otp); 512 else 513 return EADDRINUSE; 514 } 515 if (inp->inp_laddr.s_addr == INADDR_ANY) 516 inp->inp_laddr = ifaddr->sin_addr; 517 inp->inp_faddr = sin->sin_addr; 518 inp->inp_fport = sin->sin_port; 519 in_pcbrehash(inp); 520 521 tp->t_template = tcp_template(tp); 522 if (tp->t_template == 0) { 523 in_pcbdisconnect(inp); 524 return ENOBUFS; 525 } 526 527 /* Compute window scaling to request. */ 528 while (tp->request_r_scale < TCP_MAX_WINSHIFT && 529 (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) 530 tp->request_r_scale++; 531 532 soisconnecting(so); 533 tcpstat.tcps_connattempt++; 534 tp->t_state = TCPS_SYN_SENT; 535 tp->t_timer[TCPT_KEEP] = tcp_keepinit; 536 tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; 537 tcp_sendseqinit(tp); 538 539 /* 540 * Generate a CC value for this connection and 541 * check whether CC or CCnew should be used. 542 */ 543 if ((taop = tcp_gettaocache(tp->t_inpcb)) == NULL) { 544 taop = &tao_noncached; 545 bzero(taop, sizeof(*taop)); 546 } 547 548 tp->cc_send = CC_INC(tcp_ccgen); 549 if (taop->tao_ccsent != 0 && 550 CC_GEQ(tp->cc_send, taop->tao_ccsent)) { 551 taop->tao_ccsent = tp->cc_send; 552 } else { 553 taop->tao_ccsent = 0; 554 tp->t_flags |= TF_SENDCCNEW; 555 } 556 557 return 0; 558} 559 560int 561tcp_ctloutput(op, so, level, optname, mp, p) 562 int op; 563 struct socket *so; 564 int level, optname; 565 struct mbuf **mp; 566 struct proc *p; 567{ 568 int error = 0, s; 569 struct inpcb *inp; 570 register struct tcpcb *tp; 571 register struct mbuf *m; 572 register int i; 573 574 s = splnet(); 575 inp = sotoinpcb(so); 576 if (inp == NULL) { 577 splx(s); 578 if (op == PRCO_SETOPT && *mp) 579 (void) m_free(*mp); 580 return (ECONNRESET); 581 } 582 if (level != IPPROTO_TCP) { 583 error = ip_ctloutput(op, so, level, optname, mp, p); 584 splx(s); 585 return (error); 586 } 587 tp = intotcpcb(inp); 588 589 switch (op) { 590 591 case PRCO_SETOPT: 592 m = *mp; 593 switch (optname) { 594 595 case TCP_NODELAY: 596 if (m == NULL || m->m_len < sizeof (int)) 597 error = EINVAL; 598 else if (*mtod(m, int *)) 599 tp->t_flags |= TF_NODELAY; 600 else 601 tp->t_flags &= ~TF_NODELAY; 602 break; 603 604 case TCP_MAXSEG: 605 if (m && (i = *mtod(m, int *)) > 0 && i <= tp->t_maxseg) 606 tp->t_maxseg = i; 607 else 608 error = EINVAL; 609 break; 610 611 case TCP_NOOPT: 612 if (m == NULL || m->m_len < sizeof (int)) 613 error = EINVAL; 614 else if (*mtod(m, int *)) 615 tp->t_flags |= TF_NOOPT; 616 else 617 tp->t_flags &= ~TF_NOOPT; 618 break; 619 620 case TCP_NOPUSH: 621 if (m == NULL || m->m_len < sizeof (int)) 622 error = EINVAL; 623 else if (*mtod(m, int *)) 624 tp->t_flags |= TF_NOPUSH; 625 else 626 tp->t_flags &= ~TF_NOPUSH; 627 break; 628 629 default: 630 error = ENOPROTOOPT; 631 break; 632 } 633 if (m) 634 (void) m_free(m); 635 break; 636 637 case PRCO_GETOPT: 638 *mp = m = m_get(M_WAIT, MT_SOOPTS); 639 m->m_len = sizeof(int); 640 641 switch (optname) { 642 case TCP_NODELAY: 643 *mtod(m, int *) = tp->t_flags & TF_NODELAY; 644 break; 645 case TCP_MAXSEG: 646 *mtod(m, int *) = tp->t_maxseg; 647 break; 648 case TCP_NOOPT: 649 *mtod(m, int *) = tp->t_flags & TF_NOOPT; 650 break; 651 case TCP_NOPUSH: 652 *mtod(m, int *) = tp->t_flags & TF_NOPUSH; 653 break; 654 default: 655 error = ENOPROTOOPT; 656 break; 657 } 658 break; 659 } 660 splx(s); 661 return (error); 662} 663 664/* 665 * tcp_sendspace and tcp_recvspace are the default send and receive window 666 * sizes, respectively. These are obsolescent (this information should 667 * be set by the route). 668 */ 669u_long tcp_sendspace = 1024*16; 670SYSCTL_INT(_net_inet_tcp, TCPCTL_SENDSPACE, sendspace, 671 CTLFLAG_RW, &tcp_sendspace , 0, ""); 672u_long tcp_recvspace = 1024*16; 673SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, 674 CTLFLAG_RW, &tcp_recvspace , 0, ""); 675 676/* 677 * Attach TCP protocol to socket, allocating 678 * internet protocol control block, tcp control block, 679 * bufer space, and entering LISTEN state if to accept connections. 680 */ 681static int 682tcp_attach(so, p) 683 struct socket *so; 684 struct proc *p; 685{ 686 register struct tcpcb *tp; 687 struct inpcb *inp; 688 int error; 689 690 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 691 error = soreserve(so, tcp_sendspace, tcp_recvspace); 692 if (error) 693 return (error); 694 } 695 error = in_pcballoc(so, &tcbinfo, p); 696 if (error) 697 return (error); 698 inp = sotoinpcb(so); 699 tp = tcp_newtcpcb(inp); 700 if (tp == 0) { 701 int nofd = so->so_state & SS_NOFDREF; /* XXX */ 702 703 so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ 704 in_pcbdetach(inp); 705 so->so_state |= nofd; 706 return (ENOBUFS); 707 } 708 tp->t_state = TCPS_CLOSED; 709 return (0); 710} 711 712/* 713 * Initiate (or continue) disconnect. 714 * If embryonic state, just send reset (once). 715 * If in ``let data drain'' option and linger null, just drop. 716 * Otherwise (hard), mark socket disconnecting and drop 717 * current input data; switch states based on user close, and 718 * send segment to peer (with FIN). 719 */ 720static struct tcpcb * 721tcp_disconnect(tp) 722 register struct tcpcb *tp; 723{ 724 struct socket *so = tp->t_inpcb->inp_socket; 725 726 if (tp->t_state < TCPS_ESTABLISHED) 727 tp = tcp_close(tp); 728 else if ((so->so_options & SO_LINGER) && so->so_linger == 0) 729 tp = tcp_drop(tp, 0); 730 else { 731 soisdisconnecting(so); 732 sbflush(&so->so_rcv); 733 tp = tcp_usrclosed(tp); 734 if (tp) 735 (void) tcp_output(tp); 736 } 737 return (tp); 738} 739 740/* 741 * User issued close, and wish to trail through shutdown states: 742 * if never received SYN, just forget it. If got a SYN from peer, 743 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. 744 * If already got a FIN from peer, then almost done; go to LAST_ACK 745 * state. In all other cases, have already sent FIN to peer (e.g. 746 * after PRU_SHUTDOWN), and just have to play tedious game waiting 747 * for peer to send FIN or not respond to keep-alives, etc. 748 * We can let the user exit from the close as soon as the FIN is acked. 749 */ 750static struct tcpcb * 751tcp_usrclosed(tp) 752 register struct tcpcb *tp; 753{ 754 755 switch (tp->t_state) { 756 757 case TCPS_CLOSED: 758 case TCPS_LISTEN: 759 tp->t_state = TCPS_CLOSED; 760 tp = tcp_close(tp); 761 break; 762 763 case TCPS_SYN_SENT: 764 case TCPS_SYN_RECEIVED: 765 tp->t_flags |= TF_NEEDFIN; 766 break; 767 768 case TCPS_ESTABLISHED: 769 tp->t_state = TCPS_FIN_WAIT_1; 770 break; 771 772 case TCPS_CLOSE_WAIT: 773 tp->t_state = TCPS_LAST_ACK; 774 break; 775 } 776 if (tp && tp->t_state >= TCPS_FIN_WAIT_2) { 777 soisdisconnected(tp->t_inpcb->inp_socket); 778 /* To prevent the connection hanging in FIN_WAIT_2 forever. */ 779 if (tp->t_state == TCPS_FIN_WAIT_2) 780 tp->t_timer[TCPT_2MSL] = tcp_maxidle; 781 } 782 return (tp); 783} 784
|