]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/tcp_usrreq.c
2dd2747fee5be3731b39cb48b5f95677c0193788
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1982, 1986, 1988, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
58 #include "opt_tcpdebug.h"
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/kernel.h>
64 #include <sys/sysctl.h>
67 #include <sys/domain.h>
69 #include <sys/socket.h>
70 #include <sys/socketvar.h>
71 #include <sys/protosw.h>
74 #include <net/route.h>
76 #include <netinet/in.h>
77 #include <netinet/in_systm.h>
78 #include <netinet/ip.h>
79 #include <netinet/in_pcb.h>
80 #include <netinet/in_var.h>
81 #include <netinet/ip_var.h>
83 #include <netinet/ip6.h>
84 #include <netinet6/ip6_var.h>
85 #include <netinet6/in6_pcb.h>
86 #include <netinet6/ip6_var.h>
88 #include <netinet/tcp.h>
89 #include <netinet/tcp_fsm.h>
90 #include <netinet/tcp_seq.h>
91 #include <netinet/tcp_timer.h>
92 #include <netinet/tcp_var.h>
93 #include <netinet/tcpip.h>
95 #include <netinet/tcp_debug.h>
99 #include <netinet6/ipsec.h>
103 * TCP protocol interface to socket abstraction.
105 extern char *tcpstates
[]; /* XXX ??? */
107 static int tcp_attach
__P((struct socket
*, struct proc
*));
108 static int tcp_connect
__P((struct tcpcb
*, struct sockaddr
*,
111 static int tcp6_connect
__P((struct tcpcb
*, struct sockaddr
*,
114 static struct tcpcb
* tcp_disconnect
__P((struct tcpcb
*));
115 static struct tcpcb
*
116 tcp_usrclosed
__P((struct tcpcb
*));
119 #define TCPDEBUG0 int ostate
120 #define TCPDEBUG1() ostate = tp ? tp->t_state : 0
121 #define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \
122 tcp_trace(TA_USER, ostate, tp, 0, req)
126 #define TCPDEBUG2(req)
130 * TCP attaches to socket via pru_attach(), reserving space,
131 * and an internet control block.
134 tcp_usr_attach(struct socket
*so
, int proto
, struct proc
*p
)
138 struct inpcb
*inp
= sotoinpcb(so
);
139 struct tcpcb
*tp
= 0;
148 error
= tcp_attach(so
, p
);
152 if ((so
->so_options
& SO_LINGER
) && so
->so_linger
== 0)
153 so
->so_linger
= TCP_LINGERTIME
* hz
;
156 TCPDEBUG2(PRU_ATTACH
);
162 * pru_detach() detaches the TCP protocol from the socket.
163 * If the protocol state is non-embryonic, then can't
164 * do this directly: have to initiate a pru_disconnect(),
165 * which may finish later; embryonic TCB's can just
169 tcp_usr_detach(struct socket
*so
)
173 struct inpcb
*inp
= sotoinpcb(so
);
179 return EINVAL
; /* XXX */
182 /* In case we got disconnected from the peer */
186 tp
= tcp_disconnect(tp
);
188 TCPDEBUG2(PRU_DETACH
);
193 #define COMMON_START() TCPDEBUG0; \
199 tp = intotcpcb(inp); \
203 #define COMMON_END(req) out: TCPDEBUG2(req); splx(s); return error; goto out
207 * Give the socket an address.
210 tcp_usr_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
214 struct inpcb
*inp
= sotoinpcb(so
);
216 struct sockaddr_in
*sinp
;
221 * Must check for multicast addresses and disallow binding
224 sinp
= (struct sockaddr_in
*)nam
;
225 if (sinp
->sin_family
== AF_INET
&&
226 IN_MULTICAST(ntohl(sinp
->sin_addr
.s_addr
))) {
227 error
= EAFNOSUPPORT
;
230 error
= in_pcbbind(inp
, nam
, p
);
233 COMMON_END(PRU_BIND
);
239 tcp6_usr_bind(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
243 struct inpcb
*inp
= sotoinpcb(so
);
245 struct sockaddr_in6
*sin6p
;
250 * Must check for multicast addresses and disallow binding
253 sin6p
= (struct sockaddr_in6
*)nam
;
254 if (sin6p
->sin6_family
== AF_INET6
&&
255 IN6_IS_ADDR_MULTICAST(&sin6p
->sin6_addr
)) {
256 error
= EAFNOSUPPORT
;
259 inp
->inp_vflag
&= ~INP_IPV4
;
260 inp
->inp_vflag
|= INP_IPV6
;
261 if (ip6_mapped_addr_on
&& (inp
->inp_flags
& IN6P_BINDV6ONLY
) == NULL
) {
263 if (IN6_IS_ADDR_UNSPECIFIED(&sin6p
->sin6_addr
))
264 inp
->inp_vflag
|= INP_IPV4
;
265 else if (IN6_IS_ADDR_V4MAPPED(&sin6p
->sin6_addr
)) {
266 struct sockaddr_in sin
;
268 in6_sin6_2_sin(&sin
, sin6p
);
269 inp
->inp_vflag
|= INP_IPV4
;
270 inp
->inp_vflag
&= ~INP_IPV6
;
271 error
= in_pcbbind(inp
, (struct sockaddr
*)&sin
, p
);
275 error
= in6_pcbbind(inp
, nam
, p
);
276 COMMON_END(PRU_BIND
);
281 * Prepare to accept connections.
284 tcp_usr_listen(struct socket
*so
, struct proc
*p
)
288 struct inpcb
*inp
= sotoinpcb(so
);
292 if (inp
->inp_lport
== 0)
293 error
= in_pcbbind(inp
, (struct sockaddr
*)0, p
);
295 tp
->t_state
= TCPS_LISTEN
;
296 COMMON_END(PRU_LISTEN
);
301 tcp6_usr_listen(struct socket
*so
, struct proc
*p
)
305 struct inpcb
*inp
= sotoinpcb(so
);
309 if (inp
->inp_lport
== 0) {
310 inp
->inp_vflag
&= ~INP_IPV4
;
311 if (ip6_mapped_addr_on
&&
312 (inp
->inp_flags
& IN6P_BINDV6ONLY
) == NULL
)
313 inp
->inp_vflag
|= INP_IPV4
;
314 error
= in6_pcbbind(inp
, (struct sockaddr
*)0, p
);
317 tp
->t_state
= TCPS_LISTEN
;
318 COMMON_END(PRU_LISTEN
);
323 * Initiate connection to peer.
324 * Create a template for use in transmissions on this connection.
325 * Enter SYN_SENT state, and mark socket as connecting.
326 * Start keep-alive timer, and seed output sequence space.
327 * Send initial segment on connection.
330 tcp_usr_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
334 struct inpcb
*inp
= sotoinpcb(so
);
336 struct sockaddr_in
*sinp
;
341 * Must disallow TCP ``connections'' to multicast addresses.
343 sinp
= (struct sockaddr_in
*)nam
;
344 if (sinp
->sin_family
== AF_INET
345 && IN_MULTICAST(ntohl(sinp
->sin_addr
.s_addr
))) {
346 error
= EAFNOSUPPORT
;
350 if ((error
= tcp_connect(tp
, nam
, p
)) != 0)
352 error
= tcp_output(tp
);
353 COMMON_END(PRU_CONNECT
);
358 tcp6_usr_connect(struct socket
*so
, struct sockaddr
*nam
, struct proc
*p
)
362 struct inpcb
*inp
= sotoinpcb(so
);
364 struct sockaddr_in6
*sin6p
;
369 * Must disallow TCP ``connections'' to multicast addresses.
371 sin6p
= (struct sockaddr_in6
*)nam
;
372 if (sin6p
->sin6_family
== AF_INET6
373 && IN6_IS_ADDR_MULTICAST(&sin6p
->sin6_addr
)) {
374 error
= EAFNOSUPPORT
;
377 inp
->inp_vflag
&= ~INP_IPV4
;
378 inp
->inp_vflag
|= INP_IPV6
;
379 if (ip6_mapped_addr_on
&&
380 IN6_IS_ADDR_V4MAPPED(&sin6p
->sin6_addr
)) {
381 struct sockaddr_in sin
;
383 in6_sin6_2_sin(&sin
, sin6p
);
384 inp
->inp_vflag
|= INP_IPV4
;
385 inp
->inp_vflag
&= ~INP_IPV6
;
386 if ((error
= tcp_connect(tp
, (struct sockaddr
*)&sin
, p
)) != 0)
388 error
= tcp_output(tp
);
391 if ((error
= tcp6_connect(tp
, nam
, p
)) != 0)
393 error
= tcp_output(tp
);
396 if (ip6_mapped_addr_on
)
397 inp
->inp_vflag
|= INP_IPV6
;
398 COMMON_END(PRU_CONNECT
);
403 * Initiate disconnect from peer.
404 * If connection never passed embryonic stage, just drop;
405 * else if don't need to let data drain, then can just drop anyways,
406 * else have to begin TCP shutdown process: mark socket disconnecting,
407 * drain unread data, state switch to reflect user close, and
408 * send segment (e.g. FIN) to peer. Socket will be really disconnected
409 * when peer sends FIN and acks ours.
411 * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
414 tcp_usr_disconnect(struct socket
*so
)
418 struct inpcb
*inp
= sotoinpcb(so
);
422 /* In case we got disconnected from the peer */
425 tp
= tcp_disconnect(tp
);
426 COMMON_END(PRU_DISCONNECT
);
430 * Accept a connection. Essentially all the work is
431 * done at higher levels; just return the address
432 * of the peer, storing through addr.
435 tcp_usr_accept(struct socket
*so
, struct sockaddr
**nam
)
439 struct inpcb
*inp
= sotoinpcb(so
);
443 in_setpeeraddr(so
, nam
);
444 COMMON_END(PRU_ACCEPT
);
449 tcp6_usr_accept(struct socket
*so
, struct sockaddr
**nam
)
453 struct inpcb
*inp
= sotoinpcb(so
);
457 in6_mapped_peeraddr(so
, nam
);
458 COMMON_END(PRU_ACCEPT
);
463 * Mark the connection as being incapable of further output.
466 tcp_usr_shutdown(struct socket
*so
)
470 struct inpcb
*inp
= sotoinpcb(so
);
475 /* In case we got disconnected from the peer */
478 tp
= tcp_usrclosed(tp
);
480 error
= tcp_output(tp
);
481 COMMON_END(PRU_SHUTDOWN
);
485 * After a receive, possibly send window update to peer.
488 tcp_usr_rcvd(struct socket
*so
, int flags
)
492 struct inpcb
*inp
= sotoinpcb(so
);
496 /* In case we got disconnected from the peer */
500 COMMON_END(PRU_RCVD
);
504 * Do a send by putting data in output queue and updating urgent
505 * marker if URG set. Possibly send more data.
508 tcp_usr_send(struct socket
*so
, int flags
, struct mbuf
*m
,
509 struct sockaddr
*nam
, struct mbuf
*control
, struct proc
*p
)
513 struct inpcb
*inp
= sotoinpcb(so
);
520 if (control
&& control
->m_len
) {
521 m_freem(control
); /* XXX shouldn't caller do this??? */
529 isipv6
= nam
&& nam
->sa_family
== AF_INET6
;
532 if(!(flags
& PRUS_OOB
)) {
533 sbappend(&so
->so_snd
, m
);
534 if (nam
&& tp
->t_state
< TCPS_SYN_SENT
) {
536 * Do implied connect if not yet connected,
537 * initialize window to default value, and
538 * initialize maxseg/maxopd using peer's cached
543 error
= tcp6_connect(tp
, nam
, p
);
546 error
= tcp_connect(tp
, nam
, p
);
549 tp
->snd_wnd
= TTCP_CLIENT_SND_WND
;
550 tcp_mss(tp
, -1, isipv6
);
553 if (flags
& PRUS_EOF
) {
555 * Close the send side of the connection after
559 tp
= tcp_usrclosed(tp
);
562 if (flags
& PRUS_MORETOCOME
)
563 tp
->t_flags
|= TF_MORETOCOME
;
564 error
= tcp_output(tp
);
565 if (flags
& PRUS_MORETOCOME
)
566 tp
->t_flags
&= ~TF_MORETOCOME
;
569 if (sbspace(&so
->so_snd
) < -512) {
575 * According to RFC961 (Assigned Protocols),
576 * the urgent pointer points to the last octet
577 * of urgent data. We continue, however,
578 * to consider it to indicate the first octet
579 * of data past the urgent section.
580 * Otherwise, snd_up should be one lower.
582 sbappend(&so
->so_snd
, m
);
583 if (nam
&& tp
->t_state
< TCPS_SYN_SENT
) {
585 * Do implied connect if not yet connected,
586 * initialize window to default value, and
587 * initialize maxseg/maxopd using peer's cached
592 error
= tcp6_connect(tp
, nam
, p
);
595 error
= tcp_connect(tp
, nam
, p
);
598 tp
->snd_wnd
= TTCP_CLIENT_SND_WND
;
599 tcp_mss(tp
, -1, isipv6
);
601 tp
->snd_up
= tp
->snd_una
+ so
->so_snd
.sb_cc
;
603 error
= tcp_output(tp
);
606 COMMON_END((flags
& PRUS_OOB
) ? PRU_SENDOOB
:
607 ((flags
& PRUS_EOF
) ? PRU_SEND_EOF
: PRU_SEND
));
614 tcp_usr_abort(struct socket
*so
)
618 struct inpcb
*inp
= sotoinpcb(so
);
622 /* In case we got disconnected from the peer */
625 tp
= tcp_drop(tp
, ECONNABORTED
);
626 COMMON_END(PRU_ABORT
);
630 * Receive out-of-band data.
633 tcp_usr_rcvoob(struct socket
*so
, struct mbuf
*m
, int flags
)
637 struct inpcb
*inp
= sotoinpcb(so
);
641 if ((so
->so_oobmark
== 0 &&
642 (so
->so_state
& SS_RCVATMARK
) == 0) ||
643 so
->so_options
& SO_OOBINLINE
||
644 tp
->t_oobflags
& TCPOOB_HADDATA
) {
648 if ((tp
->t_oobflags
& TCPOOB_HAVEDATA
) == 0) {
653 *mtod(m
, caddr_t
) = tp
->t_iobc
;
654 if ((flags
& MSG_PEEK
) == 0)
655 tp
->t_oobflags
^= (TCPOOB_HAVEDATA
| TCPOOB_HADDATA
);
656 COMMON_END(PRU_RCVOOB
);
659 /* xxx - should be const */
660 struct pr_usrreqs tcp_usrreqs
= {
661 tcp_usr_abort
, tcp_usr_accept
, tcp_usr_attach
, tcp_usr_bind
,
662 tcp_usr_connect
, pru_connect2_notsupp
, in_control
, tcp_usr_detach
,
663 tcp_usr_disconnect
, tcp_usr_listen
, in_setpeeraddr
, tcp_usr_rcvd
,
664 tcp_usr_rcvoob
, tcp_usr_send
, pru_sense_null
, tcp_usr_shutdown
,
665 in_setsockaddr
, sosend
, soreceive
, sopoll
669 struct pr_usrreqs tcp6_usrreqs
= {
670 tcp_usr_abort
, tcp6_usr_accept
, tcp_usr_attach
, tcp6_usr_bind
,
671 tcp6_usr_connect
, pru_connect2_notsupp
, in6_control
, tcp_usr_detach
,
672 tcp_usr_disconnect
, tcp6_usr_listen
, in6_mapped_peeraddr
, tcp_usr_rcvd
,
673 tcp_usr_rcvoob
, tcp_usr_send
, pru_sense_null
, tcp_usr_shutdown
,
674 in6_mapped_sockaddr
, sosend
, soreceive
, sopoll
679 * Common subroutine to open a TCP connection to remote host specified
680 * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local
681 * port number if needed. Call in_pcbladdr to do the routing and to choose
682 * a local host address (interface). If there is an existing incarnation
683 * of the same connection in TIME-WAIT state and if the remote host was
684 * sending CC options and if the connection duration was < MSL, then
685 * truncate the previous TIME-WAIT state and proceed.
686 * Initialize connection parameters and enter SYN-SENT state.
689 tcp_connect(tp
, nam
, p
)
690 register struct tcpcb
*tp
;
691 struct sockaddr
*nam
;
694 struct inpcb
*inp
= tp
->t_inpcb
, *oinp
;
695 struct socket
*so
= inp
->inp_socket
;
697 struct sockaddr_in
*sin
= (struct sockaddr_in
*)nam
;
698 struct sockaddr_in
*ifaddr
;
699 struct rmxp_tao
*taop
;
700 struct rmxp_tao tao_noncached
;
703 if (inp
->inp_lport
== 0) {
704 error
= in_pcbbind(inp
, (struct sockaddr
*)0, p
);
710 * Cannot simply call in_pcbconnect, because there might be an
711 * earlier incarnation of this same connection still in
712 * TIME_WAIT state, creating an ADDRINUSE error.
714 error
= in_pcbladdr(inp
, nam
, &ifaddr
);
717 oinp
= in_pcblookup_hash(inp
->inp_pcbinfo
,
718 sin
->sin_addr
, sin
->sin_port
,
719 inp
->inp_laddr
.s_addr
!= INADDR_ANY
? inp
->inp_laddr
721 inp
->inp_lport
, 0, NULL
);
723 if (oinp
!= inp
&& (otp
= intotcpcb(oinp
)) != NULL
&&
724 otp
->t_state
== TCPS_TIME_WAIT
&&
725 otp
->t_duration
< TCPTV_MSL
&&
726 (otp
->t_flags
& TF_RCVD_CC
))
727 otp
= tcp_close(otp
);
731 if ((inp
->inp_laddr
.s_addr
== INADDR_ANY
? ifaddr
->sin_addr
.s_addr
:
732 inp
->inp_laddr
.s_addr
) == sin
->sin_addr
.s_addr
&&
733 inp
->inp_lport
== sin
->sin_port
)
735 if (inp
->inp_laddr
.s_addr
== INADDR_ANY
)
736 inp
->inp_laddr
= ifaddr
->sin_addr
;
737 inp
->inp_faddr
= sin
->sin_addr
;
738 inp
->inp_fport
= sin
->sin_port
;
741 tp
->t_template
= tcp_template(tp
);
742 if (tp
->t_template
== 0) {
743 in_pcbdisconnect(inp
);
747 /* Compute window scaling to request. */
748 while (tp
->request_r_scale
< TCP_MAX_WINSHIFT
&&
749 (TCP_MAXWIN
<< tp
->request_r_scale
) < so
->so_rcv
.sb_hiwat
)
750 tp
->request_r_scale
++;
753 tcpstat
.tcps_connattempt
++;
754 tp
->t_state
= TCPS_SYN_SENT
;
755 tp
->t_timer
[TCPT_KEEP
] = tcp_keepinit
;
758 tcp_iss
=+ TCP_ISSINCR
/2;
759 #else /* TCP_COMPAT_42 */
760 tp
->iss
= tcp_rndiss_next();
761 #endif /* !TCP_COMPAT_42 */
766 * Generate a CC value for this connection and
767 * check whether CC or CCnew should be used.
769 if ((taop
= tcp_gettaocache(tp
->t_inpcb
)) == NULL
) {
770 taop
= &tao_noncached
;
771 bzero(taop
, sizeof(*taop
));
774 tp
->cc_send
= CC_INC(tcp_ccgen
);
775 if (taop
->tao_ccsent
!= 0 &&
776 CC_GEQ(tp
->cc_send
, taop
->tao_ccsent
)) {
777 taop
->tao_ccsent
= tp
->cc_send
;
779 taop
->tao_ccsent
= 0;
780 tp
->t_flags
|= TF_SENDCCNEW
;
788 tcp6_connect(tp
, nam
, p
)
789 register struct tcpcb
*tp
;
790 struct sockaddr
*nam
;
793 struct inpcb
*inp
= tp
->t_inpcb
, *oinp
;
794 struct socket
*so
= inp
->inp_socket
;
796 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)nam
;
797 struct in6_addr
*addr6
;
798 struct rmxp_tao
*taop
;
799 struct rmxp_tao tao_noncached
;
802 if (inp
->inp_lport
== 0) {
803 error
= in6_pcbbind(inp
, (struct sockaddr
*)0, p
);
809 * Cannot simply call in_pcbconnect, because there might be an
810 * earlier incarnation of this same connection still in
811 * TIME_WAIT state, creating an ADDRINUSE error.
813 error
= in6_pcbladdr(inp
, nam
, &addr6
);
816 oinp
= in6_pcblookup_hash(inp
->inp_pcbinfo
,
817 &sin6
->sin6_addr
, sin6
->sin6_port
,
818 IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_laddr
)
821 inp
->inp_lport
, 0, NULL
);
823 if (oinp
!= inp
&& (otp
= intotcpcb(oinp
)) != NULL
&&
824 otp
->t_state
== TCPS_TIME_WAIT
&&
825 otp
->t_duration
< TCPTV_MSL
&&
826 (otp
->t_flags
& TF_RCVD_CC
))
827 otp
= tcp_close(otp
);
831 if (IN6_IS_ADDR_UNSPECIFIED(&inp
->in6p_laddr
))
832 inp
->in6p_laddr
= *addr6
;
833 inp
->in6p_faddr
= sin6
->sin6_addr
;
834 inp
->inp_fport
= sin6
->sin6_port
;
836 * xxx kazu flowlabel is necessary for connect?
837 * but if this line is missing, the garbage value remains.
839 inp
->in6p_flowinfo
= sin6
->sin6_flowinfo
;
843 tp
->t_template
= tcp_template(tp
);
844 if (tp
->t_template
== 0) {
845 in6_pcbdisconnect(inp
);
849 /* Compute window scaling to request. */
850 while (tp
->request_r_scale
< TCP_MAX_WINSHIFT
&&
851 (TCP_MAXWIN
<< tp
->request_r_scale
) < so
->so_rcv
.sb_hiwat
)
852 tp
->request_r_scale
++;
855 tcpstat
.tcps_connattempt
++;
856 tp
->t_state
= TCPS_SYN_SENT
;
857 tp
->t_timer
[TCPT_KEEP
] = tcp_keepinit
;
859 tp
->iss
= tcp_iss
; tcp_iss
+= TCP_ISSINCR
/2;
861 tp
->iss
= tcp_rndiss_next();
862 #endif /* TCP_COMPAT_42 */
866 * Generate a CC value for this connection and
867 * check whether CC or CCnew should be used.
869 if ((taop
= tcp_gettaocache(tp
->t_inpcb
)) == NULL
) {
870 taop
= &tao_noncached
;
871 bzero(taop
, sizeof(*taop
));
874 tp
->cc_send
= CC_INC(tcp_ccgen
);
875 if (taop
->tao_ccsent
!= 0 &&
876 CC_GEQ(tp
->cc_send
, taop
->tao_ccsent
)) {
877 taop
->tao_ccsent
= tp
->cc_send
;
879 taop
->tao_ccsent
= 0;
880 tp
->t_flags
|= TF_SENDCCNEW
;
888 * The new sockopt interface makes it possible for us to block in the
889 * copyin/out step (if we take a page fault). Taking a page fault at
890 * splnet() is probably a Bad Thing. (Since sockets and pcbs both now
891 * use TSM, there probably isn't any need for this function to run at
892 * splnet() any more. This needs more examination.)
895 tcp_ctloutput(so
, sopt
)
897 struct sockopt
*sopt
;
899 int error
, opt
, optval
, s
;
904 s
= splnet(); /* XXX */
910 if (sopt
->sopt_level
!= IPPROTO_TCP
) {
912 if (INP_CHECK_SOCKAF(so
, AF_INET6
))
913 error
= ip6_ctloutput(so
, sopt
);
916 error
= ip_ctloutput(so
, sopt
);
926 switch (sopt
->sopt_dir
) {
928 switch (sopt
->sopt_name
) {
932 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
937 switch (sopt
->sopt_name
) {
948 opt
= 0; /* dead code to fool gcc */
959 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
964 if (optval
> 0 && optval
<= tp
->t_maxseg
)
965 tp
->t_maxseg
= optval
;
977 switch (sopt
->sopt_name
) {
979 optval
= tp
->t_flags
& TF_NODELAY
;
982 optval
= tp
->t_maxseg
;
985 optval
= tp
->t_flags
& TF_NOOPT
;
988 optval
= tp
->t_flags
& TF_NOPUSH
;
995 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
1003 * tcp_sendspace and tcp_recvspace are the default send and receive window
1004 * sizes, respectively. These are obsolescent (this information should
1005 * be set by the route).
1007 u_long tcp_sendspace
= 1024*16;
1008 SYSCTL_INT(_net_inet_tcp
, TCPCTL_SENDSPACE
, sendspace
,
1009 CTLFLAG_RW
, &tcp_sendspace
, 0, "");
1010 u_long tcp_recvspace
= 1024*16;
1011 SYSCTL_INT(_net_inet_tcp
, TCPCTL_RECVSPACE
, recvspace
,
1012 CTLFLAG_RW
, &tcp_recvspace
, 0, "");
1015 * Attach TCP protocol to socket, allocating
1016 * internet protocol control block, tcp control block,
1017 * bufer space, and entering LISTEN state if to accept connections.
1024 register struct tcpcb
*tp
;
1028 int isipv6
= INP_CHECK_SOCKAF(so
, AF_INET
) == NULL
;
1031 if (so
->so_snd
.sb_hiwat
== 0 || so
->so_rcv
.sb_hiwat
== 0) {
1032 error
= soreserve(so
, tcp_sendspace
, tcp_recvspace
);
1036 error
= in_pcballoc(so
, &tcbinfo
, p
);
1039 inp
= sotoinpcb(so
);
1041 error
= ipsec_init_policy(so
, &inp
->inp_sp
);
1054 inp
->inp_vflag
|= INP_IPV6
;
1055 inp
->in6p_hops
= -1; /* use kernel default */
1059 inp
->inp_vflag
|= INP_IPV4
;
1060 tp
= tcp_newtcpcb(inp
);
1062 int nofd
= so
->so_state
& SS_NOFDREF
; /* XXX */
1064 so
->so_state
&= ~SS_NOFDREF
; /* don't free the socket yet */
1071 so
->so_state
|= nofd
;
1074 tp
->t_state
= TCPS_CLOSED
;
1079 * Initiate (or continue) disconnect.
1080 * If embryonic state, just send reset (once).
1081 * If in ``let data drain'' option and linger null, just drop.
1082 * Otherwise (hard), mark socket disconnecting and drop
1083 * current input data; switch states based on user close, and
1084 * send segment to peer (with FIN).
1086 static struct tcpcb
*
1088 register struct tcpcb
*tp
;
1090 struct socket
*so
= tp
->t_inpcb
->inp_socket
;
1092 if (tp
->t_state
< TCPS_ESTABLISHED
)
1094 else if ((so
->so_options
& SO_LINGER
) && so
->so_linger
== 0)
1095 tp
= tcp_drop(tp
, 0);
1097 soisdisconnecting(so
);
1098 sbflush(&so
->so_rcv
);
1099 tp
= tcp_usrclosed(tp
);
1101 (void) tcp_output(tp
);
1107 * User issued close, and wish to trail through shutdown states:
1108 * if never received SYN, just forget it. If got a SYN from peer,
1109 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
1110 * If already got a FIN from peer, then almost done; go to LAST_ACK
1111 * state. In all other cases, have already sent FIN to peer (e.g.
1112 * after PRU_SHUTDOWN), and just have to play tedious game waiting
1113 * for peer to send FIN or not respond to keep-alives, etc.
1114 * We can let the user exit from the close as soon as the FIN is acked.
1116 static struct tcpcb
*
1118 register struct tcpcb
*tp
;
1121 switch (tp
->t_state
) {
1125 tp
->t_state
= TCPS_CLOSED
;
1130 case TCPS_SYN_RECEIVED
:
1131 tp
->t_flags
|= TF_NEEDFIN
;
1134 case TCPS_ESTABLISHED
:
1135 tp
->t_state
= TCPS_FIN_WAIT_1
;
1138 case TCPS_CLOSE_WAIT
:
1139 tp
->t_state
= TCPS_LAST_ACK
;
1142 if (tp
&& tp
->t_state
>= TCPS_FIN_WAIT_2
) {
1143 soisdisconnected(tp
->t_inpcb
->inp_socket
);
1144 /* To prevent the connection hanging in FIN_WAIT_2 forever. */
1145 if (tp
->t_state
== TCPS_FIN_WAIT_2
)
1146 tp
->t_timer
[TCPT_2MSL
] = tcp_maxidle
;