xref: /xnu-11215.41.3/bsd/netinet/mptcp_opt.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
1*33de042dSApple OSS Distributions /*
2*33de042dSApple OSS Distributions  * Copyright (c) 2012-2017 Apple Inc. All rights reserved.
3*33de042dSApple OSS Distributions  *
4*33de042dSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*33de042dSApple OSS Distributions  *
6*33de042dSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*33de042dSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*33de042dSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*33de042dSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*33de042dSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*33de042dSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*33de042dSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*33de042dSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*33de042dSApple OSS Distributions  *
15*33de042dSApple OSS Distributions  * Please obtain a copy of the License at
16*33de042dSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*33de042dSApple OSS Distributions  *
18*33de042dSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*33de042dSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*33de042dSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*33de042dSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*33de042dSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*33de042dSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*33de042dSApple OSS Distributions  * limitations under the License.
25*33de042dSApple OSS Distributions  *
26*33de042dSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*33de042dSApple OSS Distributions  */
28*33de042dSApple OSS Distributions #include <sys/param.h>
29*33de042dSApple OSS Distributions #include <sys/systm.h>
30*33de042dSApple OSS Distributions #include <netinet/in_systm.h>
31*33de042dSApple OSS Distributions #include <sys/socket.h>
32*33de042dSApple OSS Distributions #include <sys/socketvar.h>
33*33de042dSApple OSS Distributions #include <sys/syslog.h>
34*33de042dSApple OSS Distributions #include <net/route.h>
35*33de042dSApple OSS Distributions #include <netinet/in.h>
36*33de042dSApple OSS Distributions #include <net/if.h>
37*33de042dSApple OSS Distributions 
38*33de042dSApple OSS Distributions #include <netinet/ip.h>
39*33de042dSApple OSS Distributions #include <netinet/ip_var.h>
40*33de042dSApple OSS Distributions #include <netinet/in_var.h>
41*33de042dSApple OSS Distributions #include <netinet/tcp.h>
42*33de042dSApple OSS Distributions #include <netinet/tcp_cache.h>
43*33de042dSApple OSS Distributions #include <netinet/tcp_seq.h>
44*33de042dSApple OSS Distributions #include <netinet/tcpip.h>
45*33de042dSApple OSS Distributions #include <netinet/tcp_fsm.h>
46*33de042dSApple OSS Distributions #include <netinet/mptcp_var.h>
47*33de042dSApple OSS Distributions #include <netinet/mptcp.h>
48*33de042dSApple OSS Distributions #include <netinet/mptcp_opt.h>
49*33de042dSApple OSS Distributions #include <netinet/mptcp_seq.h>
50*33de042dSApple OSS Distributions 
51*33de042dSApple OSS Distributions #include <libkern/crypto/sha1.h>
52*33de042dSApple OSS Distributions #include <libkern/crypto/sha2.h>
53*33de042dSApple OSS Distributions #include <netinet/mptcp_timer.h>
54*33de042dSApple OSS Distributions 
55*33de042dSApple OSS Distributions #include <mach/sdt.h>
56*33de042dSApple OSS Distributions 
57*33de042dSApple OSS Distributions static int mptcp_validate_join_hmac(struct tcpcb *, u_char*, int);
58*33de042dSApple OSS Distributions static int mptcp_snd_mpprio(struct tcpcb *tp, u_char *cp, int optlen);
59*33de042dSApple OSS Distributions static void mptcp_send_remaddr_opt(struct tcpcb *, struct mptcp_remaddr_opt *);
60*33de042dSApple OSS Distributions static int mptcp_echo_add_addr(struct tcpcb *, u_char *, unsigned int);
61*33de042dSApple OSS Distributions 
62*33de042dSApple OSS Distributions /*
63*33de042dSApple OSS Distributions  * MPTCP Options Output Processing
64*33de042dSApple OSS Distributions  */
65*33de042dSApple OSS Distributions 
66*33de042dSApple OSS Distributions static unsigned
mptcp_setup_first_subflow_syn_opts(struct socket * so,u_char * opt,unsigned optlen)67*33de042dSApple OSS Distributions mptcp_setup_first_subflow_syn_opts(struct socket *so, u_char *opt, unsigned optlen)
68*33de042dSApple OSS Distributions {
69*33de042dSApple OSS Distributions 	struct mptcp_mpcapable_opt_rsp mptcp_opt;
70*33de042dSApple OSS Distributions 	struct tcpcb *tp = sototcpcb(so);
71*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
72*33de042dSApple OSS Distributions 	struct mptses *mpte = mp_tp->mpt_mpte;
73*33de042dSApple OSS Distributions 	int ret;
74*33de042dSApple OSS Distributions 
75*33de042dSApple OSS Distributions 	uint8_t mmco_len = mp_tp->mpt_version == MPTCP_VERSION_0 ?
76*33de042dSApple OSS Distributions 	    sizeof(struct mptcp_mpcapable_opt_rsp) :
77*33de042dSApple OSS Distributions 	    sizeof(struct mptcp_mpcapable_opt_common);
78*33de042dSApple OSS Distributions 
79*33de042dSApple OSS Distributions 	ret = tcp_heuristic_do_mptcp(tp);
80*33de042dSApple OSS Distributions 	if (ret > 0) {
81*33de042dSApple OSS Distributions 		os_log(mptcp_log_handle, "%s - %lx: Not doing MPTCP due to heuristics",
82*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mp_tp->mpt_mpte));
83*33de042dSApple OSS Distributions 		mp_tp->mpt_flags |= MPTCPF_FALLBACK_HEURISTIC;
84*33de042dSApple OSS Distributions 		return optlen;
85*33de042dSApple OSS Distributions 	}
86*33de042dSApple OSS Distributions 
87*33de042dSApple OSS Distributions 	/*
88*33de042dSApple OSS Distributions 	 * Avoid retransmitting the MP_CAPABLE option.
89*33de042dSApple OSS Distributions 	 */
90*33de042dSApple OSS Distributions 	if (ret == 0 &&
91*33de042dSApple OSS Distributions 	    tp->t_rxtshift > mptcp_mpcap_retries &&
92*33de042dSApple OSS Distributions 	    !(mpte->mpte_flags & MPTE_FORCE_ENABLE)) {
93*33de042dSApple OSS Distributions 		if (!(mp_tp->mpt_flags & (MPTCPF_FALLBACK_HEURISTIC | MPTCPF_HEURISTIC_TRAC))) {
94*33de042dSApple OSS Distributions 			mp_tp->mpt_flags |= MPTCPF_HEURISTIC_TRAC;
95*33de042dSApple OSS Distributions 			tcp_heuristic_mptcp_loss(tp);
96*33de042dSApple OSS Distributions 		}
97*33de042dSApple OSS Distributions 		return optlen;
98*33de042dSApple OSS Distributions 	}
99*33de042dSApple OSS Distributions 
100*33de042dSApple OSS Distributions 	bzero(&mptcp_opt, sizeof(struct mptcp_mpcapable_opt_rsp));
101*33de042dSApple OSS Distributions 
102*33de042dSApple OSS Distributions 	mptcp_opt.mmc_common.mmco_kind = TCPOPT_MULTIPATH;
103*33de042dSApple OSS Distributions 	mptcp_opt.mmc_common.mmco_len = mmco_len;
104*33de042dSApple OSS Distributions 	mptcp_opt.mmc_common.mmco_subtype = MPO_CAPABLE;
105*33de042dSApple OSS Distributions 	mptcp_opt.mmc_common.mmco_version = mp_tp->mpt_version;
106*33de042dSApple OSS Distributions 	mptcp_opt.mmc_common.mmco_flags |= MPCAP_PROPOSAL_SBIT;
107*33de042dSApple OSS Distributions 	if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) {
108*33de042dSApple OSS Distributions 		mptcp_opt.mmc_common.mmco_flags |= MPCAP_CHECKSUM_CBIT;
109*33de042dSApple OSS Distributions 	}
110*33de042dSApple OSS Distributions 	mptcp_opt.mmc_localkey = mp_tp->mpt_localkey;
111*33de042dSApple OSS Distributions 
112*33de042dSApple OSS Distributions 	memcpy(opt + optlen, &mptcp_opt, mmco_len);
113*33de042dSApple OSS Distributions 	optlen += mmco_len;
114*33de042dSApple OSS Distributions 
115*33de042dSApple OSS Distributions 	return optlen;
116*33de042dSApple OSS Distributions }
117*33de042dSApple OSS Distributions 
118*33de042dSApple OSS Distributions static unsigned
mptcp_setup_join_subflow_syn_opts(struct socket * so,u_char * opt,unsigned optlen)119*33de042dSApple OSS Distributions mptcp_setup_join_subflow_syn_opts(struct socket *so, u_char *opt, unsigned optlen)
120*33de042dSApple OSS Distributions {
121*33de042dSApple OSS Distributions 	struct mptcp_mpjoin_opt_req mpjoin_req;
122*33de042dSApple OSS Distributions 	struct inpcb *inp = sotoinpcb(so);
123*33de042dSApple OSS Distributions 	struct tcpcb *tp = NULL;
124*33de042dSApple OSS Distributions 	struct mptsub *mpts;
125*33de042dSApple OSS Distributions 
126*33de042dSApple OSS Distributions 	if (!inp) {
127*33de042dSApple OSS Distributions 		return optlen;
128*33de042dSApple OSS Distributions 	}
129*33de042dSApple OSS Distributions 
130*33de042dSApple OSS Distributions 	tp = intotcpcb(inp);
131*33de042dSApple OSS Distributions 	if (!tp) {
132*33de042dSApple OSS Distributions 		return optlen;
133*33de042dSApple OSS Distributions 	}
134*33de042dSApple OSS Distributions 
135*33de042dSApple OSS Distributions 	mpts = tp->t_mpsub;
136*33de042dSApple OSS Distributions 
137*33de042dSApple OSS Distributions 	bzero(&mpjoin_req, sizeof(mpjoin_req));
138*33de042dSApple OSS Distributions 	mpjoin_req.mmjo_kind = TCPOPT_MULTIPATH;
139*33de042dSApple OSS Distributions 	mpjoin_req.mmjo_len = sizeof(mpjoin_req);
140*33de042dSApple OSS Distributions 	mpjoin_req.mmjo_subtype_bkp = MPO_JOIN << 4;
141*33de042dSApple OSS Distributions 
142*33de042dSApple OSS Distributions 	if (tp->t_mpflags & TMPF_BACKUP_PATH) {
143*33de042dSApple OSS Distributions 		mpjoin_req.mmjo_subtype_bkp |= MPTCP_BACKUP;
144*33de042dSApple OSS Distributions 	} else if (inp->inp_boundifp && IFNET_IS_CELLULAR(inp->inp_boundifp) &&
145*33de042dSApple OSS Distributions 	    mptcp_subflows_need_backup_flag(mpts->mpts_mpte)) {
146*33de042dSApple OSS Distributions 		mpjoin_req.mmjo_subtype_bkp |= MPTCP_BACKUP;
147*33de042dSApple OSS Distributions 		tp->t_mpflags |= TMPF_BACKUP_PATH;
148*33de042dSApple OSS Distributions 	} else {
149*33de042dSApple OSS Distributions 		mpts->mpts_flags |= MPTSF_PREFERRED;
150*33de042dSApple OSS Distributions 	}
151*33de042dSApple OSS Distributions 
152*33de042dSApple OSS Distributions 	mpjoin_req.mmjo_addr_id = tp->t_local_aid;
153*33de042dSApple OSS Distributions 	mpjoin_req.mmjo_peer_token = tptomptp(tp)->mpt_remotetoken;
154*33de042dSApple OSS Distributions 	mptcp_get_rands(tp->t_local_aid, tptomptp(tp),
155*33de042dSApple OSS Distributions 	    &mpjoin_req.mmjo_rand, NULL);
156*33de042dSApple OSS Distributions 	memcpy(opt + optlen, &mpjoin_req, mpjoin_req.mmjo_len);
157*33de042dSApple OSS Distributions 	optlen += mpjoin_req.mmjo_len;
158*33de042dSApple OSS Distributions 
159*33de042dSApple OSS Distributions 	return optlen;
160*33de042dSApple OSS Distributions }
161*33de042dSApple OSS Distributions 
162*33de042dSApple OSS Distributions unsigned
mptcp_setup_join_ack_opts(struct tcpcb * tp,u_char * opt,unsigned optlen)163*33de042dSApple OSS Distributions mptcp_setup_join_ack_opts(struct tcpcb *tp, u_char *opt, unsigned optlen)
164*33de042dSApple OSS Distributions {
165*33de042dSApple OSS Distributions 	unsigned new_optlen;
166*33de042dSApple OSS Distributions 	struct mptcp_mpjoin_opt_rsp2 join_rsp2;
167*33de042dSApple OSS Distributions 
168*33de042dSApple OSS Distributions 	if ((MAX_TCPOPTLEN - optlen) < sizeof(struct mptcp_mpjoin_opt_rsp2)) {
169*33de042dSApple OSS Distributions 		printf("%s: no space left %d \n", __func__, optlen);
170*33de042dSApple OSS Distributions 		return optlen;
171*33de042dSApple OSS Distributions 	}
172*33de042dSApple OSS Distributions 
173*33de042dSApple OSS Distributions 	bzero(&join_rsp2, sizeof(struct mptcp_mpjoin_opt_rsp2));
174*33de042dSApple OSS Distributions 	join_rsp2.mmjo_kind = TCPOPT_MULTIPATH;
175*33de042dSApple OSS Distributions 	join_rsp2.mmjo_len = sizeof(struct mptcp_mpjoin_opt_rsp2);
176*33de042dSApple OSS Distributions 	join_rsp2.mmjo_subtype = MPO_JOIN;
177*33de042dSApple OSS Distributions 	mptcp_get_mpjoin_hmac(tp->t_local_aid, tptomptp(tp),
178*33de042dSApple OSS Distributions 	    (u_char*)&join_rsp2.mmjo_mac, HMAC_TRUNCATED_ACK);
179*33de042dSApple OSS Distributions 	memcpy(opt + optlen, &join_rsp2, join_rsp2.mmjo_len);
180*33de042dSApple OSS Distributions 	new_optlen = optlen + join_rsp2.mmjo_len;
181*33de042dSApple OSS Distributions 	return new_optlen;
182*33de042dSApple OSS Distributions }
183*33de042dSApple OSS Distributions 
184*33de042dSApple OSS Distributions unsigned
mptcp_setup_syn_opts(struct socket * so,u_char * opt,unsigned optlen)185*33de042dSApple OSS Distributions mptcp_setup_syn_opts(struct socket *so, u_char *opt, unsigned optlen)
186*33de042dSApple OSS Distributions {
187*33de042dSApple OSS Distributions 	unsigned new_optlen;
188*33de042dSApple OSS Distributions 
189*33de042dSApple OSS Distributions 	if (!(so->so_flags & SOF_MP_SEC_SUBFLOW)) {
190*33de042dSApple OSS Distributions 		new_optlen = mptcp_setup_first_subflow_syn_opts(so, opt, optlen);
191*33de042dSApple OSS Distributions 	} else {
192*33de042dSApple OSS Distributions 		new_optlen = mptcp_setup_join_subflow_syn_opts(so, opt, optlen);
193*33de042dSApple OSS Distributions 	}
194*33de042dSApple OSS Distributions 
195*33de042dSApple OSS Distributions 	return new_optlen;
196*33de042dSApple OSS Distributions }
197*33de042dSApple OSS Distributions 
198*33de042dSApple OSS Distributions static int
mptcp_send_mpfail(struct tcpcb * tp,u_char * opt,unsigned int optlen)199*33de042dSApple OSS Distributions mptcp_send_mpfail(struct tcpcb *tp, u_char *opt, unsigned int optlen)
200*33de042dSApple OSS Distributions {
201*33de042dSApple OSS Distributions #pragma unused(tp, opt, optlen)
202*33de042dSApple OSS Distributions 
203*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = NULL;
204*33de042dSApple OSS Distributions 	struct mptcp_mpfail_opt fail_opt;
205*33de042dSApple OSS Distributions 	uint64_t dsn;
206*33de042dSApple OSS Distributions 	uint8_t len = sizeof(struct mptcp_mpfail_opt);
207*33de042dSApple OSS Distributions 
208*33de042dSApple OSS Distributions 	mp_tp = tptomptp(tp);
209*33de042dSApple OSS Distributions 	if (mp_tp == NULL) {
210*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_SND_MPFAIL;
211*33de042dSApple OSS Distributions 		return optlen;
212*33de042dSApple OSS Distributions 	}
213*33de042dSApple OSS Distributions 
214*33de042dSApple OSS Distributions 	/* if option space low give up */
215*33de042dSApple OSS Distributions 	if ((MAX_TCPOPTLEN - optlen) < sizeof(struct mptcp_mpfail_opt)) {
216*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_SND_MPFAIL;
217*33de042dSApple OSS Distributions 		return optlen;
218*33de042dSApple OSS Distributions 	}
219*33de042dSApple OSS Distributions 
220*33de042dSApple OSS Distributions 	dsn = mp_tp->mpt_rcvnxt;
221*33de042dSApple OSS Distributions 
222*33de042dSApple OSS Distributions 	bzero(&fail_opt, sizeof(fail_opt));
223*33de042dSApple OSS Distributions 	fail_opt.mfail_kind = TCPOPT_MULTIPATH;
224*33de042dSApple OSS Distributions 	fail_opt.mfail_len = len;
225*33de042dSApple OSS Distributions 	fail_opt.mfail_subtype = MPO_FAIL;
226*33de042dSApple OSS Distributions 	fail_opt.mfail_dsn = mptcp_hton64(dsn);
227*33de042dSApple OSS Distributions 	memcpy(opt + optlen, &fail_opt, len);
228*33de042dSApple OSS Distributions 	optlen += len;
229*33de042dSApple OSS Distributions 	tp->t_mpflags &= ~TMPF_SND_MPFAIL;
230*33de042dSApple OSS Distributions 	return optlen;
231*33de042dSApple OSS Distributions }
232*33de042dSApple OSS Distributions 
233*33de042dSApple OSS Distributions static int
mptcp_send_infinite_mapping(struct tcpcb * tp,u_char * opt,unsigned int optlen)234*33de042dSApple OSS Distributions mptcp_send_infinite_mapping(struct tcpcb *tp, u_char *opt, unsigned int optlen)
235*33de042dSApple OSS Distributions {
236*33de042dSApple OSS Distributions 	struct socket *so = tp->t_inpcb->inp_socket;
237*33de042dSApple OSS Distributions 	uint8_t len = sizeof(struct mptcp_dsn_opt);
238*33de042dSApple OSS Distributions 	struct mptcp_dsn_opt infin_opt;
239*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = NULL;
240*33de042dSApple OSS Distributions 	uint8_t csum_len = 0;
241*33de042dSApple OSS Distributions 
242*33de042dSApple OSS Distributions 	if (!so) {
243*33de042dSApple OSS Distributions 		return optlen;
244*33de042dSApple OSS Distributions 	}
245*33de042dSApple OSS Distributions 
246*33de042dSApple OSS Distributions 	mp_tp = tptomptp(tp);
247*33de042dSApple OSS Distributions 	if (mp_tp == NULL) {
248*33de042dSApple OSS Distributions 		return optlen;
249*33de042dSApple OSS Distributions 	}
250*33de042dSApple OSS Distributions 
251*33de042dSApple OSS Distributions 	if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) {
252*33de042dSApple OSS Distributions 		csum_len = 2;
253*33de042dSApple OSS Distributions 	}
254*33de042dSApple OSS Distributions 
255*33de042dSApple OSS Distributions 	/* try later */
256*33de042dSApple OSS Distributions 	if ((MAX_TCPOPTLEN - optlen) < (len + csum_len)) {
257*33de042dSApple OSS Distributions 		return optlen;
258*33de042dSApple OSS Distributions 	}
259*33de042dSApple OSS Distributions 
260*33de042dSApple OSS Distributions 	bzero(&infin_opt, sizeof(infin_opt));
261*33de042dSApple OSS Distributions 	infin_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
262*33de042dSApple OSS Distributions 	infin_opt.mdss_copt.mdss_len = len + csum_len;
263*33de042dSApple OSS Distributions 	infin_opt.mdss_copt.mdss_subtype = MPO_DSS;
264*33de042dSApple OSS Distributions 	infin_opt.mdss_copt.mdss_flags |= MDSS_M;
265*33de042dSApple OSS Distributions 	if (mp_tp->mpt_flags & MPTCPF_RECVD_MPFAIL) {
266*33de042dSApple OSS Distributions 		infin_opt.mdss_dsn = (u_int32_t)
267*33de042dSApple OSS Distributions 		    MPTCP_DATASEQ_LOW32(mp_tp->mpt_dsn_at_csum_fail);
268*33de042dSApple OSS Distributions 		infin_opt.mdss_subflow_seqn = mp_tp->mpt_ssn_at_csum_fail;
269*33de042dSApple OSS Distributions 	} else {
270*33de042dSApple OSS Distributions 		/*
271*33de042dSApple OSS Distributions 		 * If MPTCP fallback happens, but TFO succeeds, the data on the
272*33de042dSApple OSS Distributions 		 * SYN does not belong to the MPTCP data sequence space.
273*33de042dSApple OSS Distributions 		 */
274*33de042dSApple OSS Distributions 		if ((tp->t_tfo_stats & TFO_S_SYN_DATA_ACKED) &&
275*33de042dSApple OSS Distributions 		    ((mp_tp->mpt_local_idsn + 1) == mp_tp->mpt_snduna)) {
276*33de042dSApple OSS Distributions 			infin_opt.mdss_subflow_seqn = 1;
277*33de042dSApple OSS Distributions 		} else {
278*33de042dSApple OSS Distributions 			infin_opt.mdss_subflow_seqn = tp->snd_una - tp->t_mpsub->mpts_iss;
279*33de042dSApple OSS Distributions 		}
280*33de042dSApple OSS Distributions 		infin_opt.mdss_dsn = (u_int32_t)
281*33de042dSApple OSS Distributions 		    MPTCP_DATASEQ_LOW32(mp_tp->mpt_snduna);
282*33de042dSApple OSS Distributions 	}
283*33de042dSApple OSS Distributions 
284*33de042dSApple OSS Distributions 	if ((infin_opt.mdss_dsn == 0) || (infin_opt.mdss_subflow_seqn == 0)) {
285*33de042dSApple OSS Distributions 		return optlen;
286*33de042dSApple OSS Distributions 	}
287*33de042dSApple OSS Distributions 	infin_opt.mdss_dsn = htonl(infin_opt.mdss_dsn);
288*33de042dSApple OSS Distributions 	infin_opt.mdss_subflow_seqn = htonl(infin_opt.mdss_subflow_seqn);
289*33de042dSApple OSS Distributions 	infin_opt.mdss_data_len = 0;
290*33de042dSApple OSS Distributions 
291*33de042dSApple OSS Distributions 	memcpy(opt + optlen, &infin_opt, len);
292*33de042dSApple OSS Distributions 	optlen += len;
293*33de042dSApple OSS Distributions 	if (csum_len != 0) {
294*33de042dSApple OSS Distributions 		/* The checksum field is set to 0 for infinite mapping */
295*33de042dSApple OSS Distributions 		uint16_t csum = 0;
296*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &csum, csum_len);
297*33de042dSApple OSS Distributions 		optlen += csum_len;
298*33de042dSApple OSS Distributions 	}
299*33de042dSApple OSS Distributions 
300*33de042dSApple OSS Distributions 	tp->t_mpflags |= TMPF_INFIN_SENT;
301*33de042dSApple OSS Distributions 	tcpstat.tcps_estab_fallback++;
302*33de042dSApple OSS Distributions 	return optlen;
303*33de042dSApple OSS Distributions }
304*33de042dSApple OSS Distributions 
305*33de042dSApple OSS Distributions 
306*33de042dSApple OSS Distributions static int
mptcp_ok_to_fin(struct tcpcb * tp,u_int64_t dsn,u_int32_t datalen)307*33de042dSApple OSS Distributions mptcp_ok_to_fin(struct tcpcb *tp, u_int64_t dsn, u_int32_t datalen)
308*33de042dSApple OSS Distributions {
309*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
310*33de042dSApple OSS Distributions 
311*33de042dSApple OSS Distributions 	dsn = (mp_tp->mpt_sndmax & MPTCP_DATASEQ_LOW32_MASK) | dsn;
312*33de042dSApple OSS Distributions 	if ((dsn + datalen) == mp_tp->mpt_sndmax) {
313*33de042dSApple OSS Distributions 		return 1;
314*33de042dSApple OSS Distributions 	}
315*33de042dSApple OSS Distributions 
316*33de042dSApple OSS Distributions 	return 0;
317*33de042dSApple OSS Distributions }
318*33de042dSApple OSS Distributions 
319*33de042dSApple OSS Distributions unsigned int
mptcp_setup_opts(struct tcpcb * tp,int32_t off,u_char * opt,unsigned int optlen,int flags,int len,boolean_t * p_mptcp_acknow,boolean_t * do_not_compress)320*33de042dSApple OSS Distributions mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt,
321*33de042dSApple OSS Distributions     unsigned int optlen, int flags, int len,
322*33de042dSApple OSS Distributions     boolean_t *p_mptcp_acknow, boolean_t *do_not_compress)
323*33de042dSApple OSS Distributions {
324*33de042dSApple OSS Distributions 	struct inpcb *inp = (struct inpcb *)tp->t_inpcb;
325*33de042dSApple OSS Distributions 	struct socket *so = inp->inp_socket;
326*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
327*33de042dSApple OSS Distributions 	boolean_t do_csum = FALSE;
328*33de042dSApple OSS Distributions 	boolean_t send_64bit_dsn = FALSE;
329*33de042dSApple OSS Distributions 	boolean_t send_64bit_ack = FALSE;
330*33de042dSApple OSS Distributions 	uint32_t old_mpt_flags = tp->t_mpflags & TMPF_MPTCP_SIGNALS;
331*33de042dSApple OSS Distributions 	boolean_t initial_data = FALSE;
332*33de042dSApple OSS Distributions 
333*33de042dSApple OSS Distributions 	/* There is a case where offset can become negative. tcp_output()
334*33de042dSApple OSS Distributions 	 * gracefully handles this. So, let's make MPTCP more robust as well.
335*33de042dSApple OSS Distributions 	 */
336*33de042dSApple OSS Distributions 	if (off < 0) {
337*33de042dSApple OSS Distributions 		off = 0;
338*33de042dSApple OSS Distributions 	}
339*33de042dSApple OSS Distributions 
340*33de042dSApple OSS Distributions 	if (mptcp_enable == 0 || mp_tp == NULL || tp->t_state == TCPS_CLOSED) {
341*33de042dSApple OSS Distributions 		/* do nothing */
342*33de042dSApple OSS Distributions 		goto ret_optlen;
343*33de042dSApple OSS Distributions 	}
344*33de042dSApple OSS Distributions 
345*33de042dSApple OSS Distributions 	socket_lock_assert_owned(mptetoso(mp_tp->mpt_mpte));
346*33de042dSApple OSS Distributions 
347*33de042dSApple OSS Distributions 	if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) {
348*33de042dSApple OSS Distributions 		do_csum = TRUE;
349*33de042dSApple OSS Distributions 	}
350*33de042dSApple OSS Distributions 
351*33de042dSApple OSS Distributions 	/* tcp_output handles the SYN path separately */
352*33de042dSApple OSS Distributions 	if (flags & TH_SYN) {
353*33de042dSApple OSS Distributions 		goto ret_optlen;
354*33de042dSApple OSS Distributions 	}
355*33de042dSApple OSS Distributions 
356*33de042dSApple OSS Distributions 	if ((MAX_TCPOPTLEN - optlen) <
357*33de042dSApple OSS Distributions 	    sizeof(struct mptcp_mpcapable_opt_common)) {
358*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: no space left %d flags %x tp->t_mpflags %x len %d\n",
359*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mp_tp->mpt_mpte),
360*33de042dSApple OSS Distributions 		    optlen, flags, tp->t_mpflags, len);
361*33de042dSApple OSS Distributions 		goto ret_optlen;
362*33de042dSApple OSS Distributions 	}
363*33de042dSApple OSS Distributions 
364*33de042dSApple OSS Distributions 	if (tp->t_mpflags & TMPF_TCP_FALLBACK) {
365*33de042dSApple OSS Distributions 		if (tp->t_mpflags & TMPF_SND_MPFAIL) {
366*33de042dSApple OSS Distributions 			optlen = mptcp_send_mpfail(tp, opt, optlen);
367*33de042dSApple OSS Distributions 		} else if (!(tp->t_mpflags & TMPF_INFIN_SENT)) {
368*33de042dSApple OSS Distributions 			optlen = mptcp_send_infinite_mapping(tp, opt, optlen);
369*33de042dSApple OSS Distributions 		}
370*33de042dSApple OSS Distributions 
371*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
372*33de042dSApple OSS Distributions 
373*33de042dSApple OSS Distributions 		goto ret_optlen;
374*33de042dSApple OSS Distributions 	}
375*33de042dSApple OSS Distributions 
376*33de042dSApple OSS Distributions 	if (len > 0 && off == 0 && tp->t_mpflags & TMPF_SEND_DSN && tp->t_mpflags & TMPF_SND_KEYS) {
377*33de042dSApple OSS Distributions 		uint64_t dsn = 0;
378*33de042dSApple OSS Distributions 		uint32_t relseq = 0;
379*33de042dSApple OSS Distributions 		uint16_t data_len = 0, dss_csum = 0;
380*33de042dSApple OSS Distributions 		mptcp_output_getm_dsnmap64(so, off, &dsn, &relseq, &data_len, &dss_csum);
381*33de042dSApple OSS Distributions 		if (dsn == mp_tp->mpt_local_idsn + 1) {
382*33de042dSApple OSS Distributions 			initial_data = TRUE;
383*33de042dSApple OSS Distributions 		}
384*33de042dSApple OSS Distributions 	}
385*33de042dSApple OSS Distributions 
386*33de042dSApple OSS Distributions 	/* send MP_CAPABLE when it's the INITIAL ACK or data */
387*33de042dSApple OSS Distributions 	if (tp->t_mpflags & TMPF_SND_KEYS &&
388*33de042dSApple OSS Distributions 	    (mp_tp->mpt_version == MPTCP_VERSION_0 || initial_data ||
389*33de042dSApple OSS Distributions 	    (mp_tp->mpt_sndnxt == mp_tp->mpt_local_idsn + 1 && len == 0))) {
390*33de042dSApple OSS Distributions 		struct mptcp_mpcapable_opt_rsp2 mptcp_opt;
391*33de042dSApple OSS Distributions 		boolean_t send_data_level_details = tp->t_mpflags & TMPF_SEND_DSN ? TRUE : FALSE;
392*33de042dSApple OSS Distributions 
393*33de042dSApple OSS Distributions 		uint8_t mmco_len = sizeof(struct mptcp_mpcapable_opt_rsp1);
394*33de042dSApple OSS Distributions 		if (send_data_level_details) {
395*33de042dSApple OSS Distributions 			mmco_len += 2;
396*33de042dSApple OSS Distributions 			if (do_csum) {
397*33de042dSApple OSS Distributions 				mmco_len += 2;
398*33de042dSApple OSS Distributions 			}
399*33de042dSApple OSS Distributions 		}
400*33de042dSApple OSS Distributions 		if ((MAX_TCPOPTLEN - optlen) < mmco_len) {
401*33de042dSApple OSS Distributions 			os_log_error(mptcp_log_handle, "%s - %lx: not enough space in TCP option, "
402*33de042dSApple OSS Distributions 			    "optlen: %u, mmco_len: %d\n", __func__,
403*33de042dSApple OSS Distributions 			    (unsigned long)VM_KERNEL_ADDRPERM(mp_tp->mpt_mpte),
404*33de042dSApple OSS Distributions 			    optlen, mmco_len);
405*33de042dSApple OSS Distributions 			goto ret_optlen;
406*33de042dSApple OSS Distributions 		}
407*33de042dSApple OSS Distributions 
408*33de042dSApple OSS Distributions 		bzero(&mptcp_opt, sizeof(struct mptcp_mpcapable_opt_rsp2));
409*33de042dSApple OSS Distributions 		mptcp_opt.mmc_rsp1.mmc_common.mmco_kind = TCPOPT_MULTIPATH;
410*33de042dSApple OSS Distributions 		mptcp_opt.mmc_rsp1.mmc_common.mmco_len = mmco_len;
411*33de042dSApple OSS Distributions 		mptcp_opt.mmc_rsp1.mmc_common.mmco_subtype = MPO_CAPABLE;
412*33de042dSApple OSS Distributions 		mptcp_opt.mmc_rsp1.mmc_common.mmco_version = mp_tp->mpt_version;
413*33de042dSApple OSS Distributions 		mptcp_opt.mmc_rsp1.mmc_common.mmco_flags |= MPCAP_PROPOSAL_SBIT;
414*33de042dSApple OSS Distributions 		if (do_csum) {
415*33de042dSApple OSS Distributions 			mptcp_opt.mmc_rsp1.mmc_common.mmco_flags |= MPCAP_CHECKSUM_CBIT;
416*33de042dSApple OSS Distributions 		}
417*33de042dSApple OSS Distributions 		mptcp_opt.mmc_rsp1.mmc_localkey = mp_tp->mpt_localkey;
418*33de042dSApple OSS Distributions 		mptcp_opt.mmc_rsp1.mmc_remotekey = mp_tp->mpt_remotekey;
419*33de042dSApple OSS Distributions 		if (send_data_level_details) {
420*33de042dSApple OSS Distributions 			mptcp_output_getm_data_level_details(so, off, &mptcp_opt.data_len, &mptcp_opt.csum);
421*33de042dSApple OSS Distributions 			mptcp_opt.data_len = htons(mptcp_opt.data_len);
422*33de042dSApple OSS Distributions 		}
423*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &mptcp_opt, mmco_len);
424*33de042dSApple OSS Distributions 
425*33de042dSApple OSS Distributions 		if (mp_tp->mpt_version == MPTCP_VERSION_0) {
426*33de042dSApple OSS Distributions 			tp->t_mpflags &= ~TMPF_SND_KEYS;
427*33de042dSApple OSS Distributions 		}
428*33de042dSApple OSS Distributions 		optlen += mmco_len;
429*33de042dSApple OSS Distributions 
430*33de042dSApple OSS Distributions 		if (!tp->t_mpuna) {
431*33de042dSApple OSS Distributions 			tp->t_mpuna = tp->snd_una;
432*33de042dSApple OSS Distributions 		} else {
433*33de042dSApple OSS Distributions 			/* its a retransmission of the MP_CAPABLE ACK */
434*33de042dSApple OSS Distributions 		}
435*33de042dSApple OSS Distributions 
436*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
437*33de042dSApple OSS Distributions 
438*33de042dSApple OSS Distributions 		goto ret_optlen;
439*33de042dSApple OSS Distributions 	}
440*33de042dSApple OSS Distributions 
441*33de042dSApple OSS Distributions 	if (tp->t_mpflags & TMPF_SND_JACK) {
442*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
443*33de042dSApple OSS Distributions 		optlen = mptcp_setup_join_ack_opts(tp, opt, optlen);
444*33de042dSApple OSS Distributions 		if (!tp->t_mpuna) {
445*33de042dSApple OSS Distributions 			tp->t_mpuna = tp->snd_una;
446*33de042dSApple OSS Distributions 		}
447*33de042dSApple OSS Distributions 		/* Start a timer to retransmit the ACK */
448*33de042dSApple OSS Distributions 		tp->t_timer[TCPT_JACK_RXMT] =
449*33de042dSApple OSS Distributions 		    OFFSET_FROM_START(tp, tcp_jack_rxmt);
450*33de042dSApple OSS Distributions 
451*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_SND_JACK;
452*33de042dSApple OSS Distributions 		goto ret_optlen;
453*33de042dSApple OSS Distributions 	}
454*33de042dSApple OSS Distributions 
455*33de042dSApple OSS Distributions 	if (!(tp->t_mpflags & (TMPF_MPTCP_TRUE | TMPF_PREESTABLISHED))) {
456*33de042dSApple OSS Distributions 		goto ret_optlen;
457*33de042dSApple OSS Distributions 	}
458*33de042dSApple OSS Distributions 	/*
459*33de042dSApple OSS Distributions 	 * From here on, all options are sent only if MPTCP_TRUE
460*33de042dSApple OSS Distributions 	 * or when data is sent early on as in Fast Join
461*33de042dSApple OSS Distributions 	 */
462*33de042dSApple OSS Distributions 
463*33de042dSApple OSS Distributions 	if ((tp->t_mpflags & TMPF_MPTCP_TRUE) &&
464*33de042dSApple OSS Distributions 	    (tp->t_mpflags & TMPF_SND_REM_ADDR)) {
465*33de042dSApple OSS Distributions 		int rem_opt_len = sizeof(struct mptcp_remaddr_opt);
466*33de042dSApple OSS Distributions 		if (optlen + rem_opt_len <= MAX_TCPOPTLEN) {
467*33de042dSApple OSS Distributions 			mptcp_send_remaddr_opt(tp,
468*33de042dSApple OSS Distributions 			    (struct mptcp_remaddr_opt *)(opt + optlen));
469*33de042dSApple OSS Distributions 			optlen += rem_opt_len;
470*33de042dSApple OSS Distributions 		} else {
471*33de042dSApple OSS Distributions 			tp->t_mpflags &= ~TMPF_SND_REM_ADDR;
472*33de042dSApple OSS Distributions 		}
473*33de042dSApple OSS Distributions 
474*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
475*33de042dSApple OSS Distributions 	}
476*33de042dSApple OSS Distributions 
477*33de042dSApple OSS Distributions 	if (tp->t_mpflags & TMPF_MPTCP_ECHO_ADDR) {
478*33de042dSApple OSS Distributions 		optlen = mptcp_echo_add_addr(tp, opt, optlen);
479*33de042dSApple OSS Distributions 	}
480*33de042dSApple OSS Distributions 
481*33de042dSApple OSS Distributions 	if (tp->t_mpflags & TMPF_SND_MPPRIO) {
482*33de042dSApple OSS Distributions 		optlen = mptcp_snd_mpprio(tp, opt, optlen);
483*33de042dSApple OSS Distributions 
484*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
485*33de042dSApple OSS Distributions 	}
486*33de042dSApple OSS Distributions 
487*33de042dSApple OSS Distributions 	if (mp_tp->mpt_flags & MPTCPF_SND_64BITDSN) {
488*33de042dSApple OSS Distributions 		send_64bit_dsn = TRUE;
489*33de042dSApple OSS Distributions 	}
490*33de042dSApple OSS Distributions 	if (mp_tp->mpt_flags & MPTCPF_SND_64BITACK) {
491*33de042dSApple OSS Distributions 		send_64bit_ack = TRUE;
492*33de042dSApple OSS Distributions 	}
493*33de042dSApple OSS Distributions 
494*33de042dSApple OSS Distributions #define CHECK_OPTLEN    {                                                                   \
495*33de042dSApple OSS Distributions 	if (MAX_TCPOPTLEN - optlen < dssoptlen) {                                         \
496*33de042dSApple OSS Distributions 	        os_log_error(mptcp_log_handle, "%s: dssoptlen %d optlen %d \n", __func__,   \
497*33de042dSApple OSS Distributions 	            dssoptlen, optlen);                                                     \
498*33de042dSApple OSS Distributions 	            goto ret_optlen;                                                        \
499*33de042dSApple OSS Distributions 	}                                                                                   \
500*33de042dSApple OSS Distributions }
501*33de042dSApple OSS Distributions 
502*33de042dSApple OSS Distributions #define DO_FIN(dsn_opt) {                                               \
503*33de042dSApple OSS Distributions 	int sndfin = 0;                                                 \
504*33de042dSApple OSS Distributions 	sndfin = mptcp_ok_to_fin(tp, dsn_opt.mdss_dsn, len);            \
505*33de042dSApple OSS Distributions 	if (sndfin) {                                                   \
506*33de042dSApple OSS Distributions 	        dsn_opt.mdss_copt.mdss_flags |= MDSS_F;                 \
507*33de042dSApple OSS Distributions 	        dsn_opt.mdss_data_len += 1;                             \
508*33de042dSApple OSS Distributions 	        if (do_csum)                                            \
509*33de042dSApple OSS Distributions 	                dss_csum = in_addword(dss_csum, 1);             \
510*33de042dSApple OSS Distributions 	}                                                               \
511*33de042dSApple OSS Distributions }
512*33de042dSApple OSS Distributions 
513*33de042dSApple OSS Distributions #define CHECK_DATALEN {                                                             \
514*33de042dSApple OSS Distributions 	/* MPTCP socket does not support IP options */                              \
515*33de042dSApple OSS Distributions 	if ((len + optlen + dssoptlen) > tp->t_maxopd) {                            \
516*33de042dSApple OSS Distributions 	        os_log_error(mptcp_log_handle, "%s: nosp %d len %d opt %d %d %d\n", \
517*33de042dSApple OSS Distributions 	            __func__, len, dssoptlen, optlen,                               \
518*33de042dSApple OSS Distributions 	            tp->t_maxseg, tp->t_maxopd);                                    \
519*33de042dSApple OSS Distributions 	/* remove option length from payload len */                         \
520*33de042dSApple OSS Distributions 	        len = tp->t_maxopd - optlen - dssoptlen;                            \
521*33de042dSApple OSS Distributions 	}                                                                           \
522*33de042dSApple OSS Distributions }
523*33de042dSApple OSS Distributions 
524*33de042dSApple OSS Distributions 	if ((tp->t_mpflags & TMPF_SEND_DSN) &&
525*33de042dSApple OSS Distributions 	    (send_64bit_dsn)) {
526*33de042dSApple OSS Distributions 		/*
527*33de042dSApple OSS Distributions 		 * If there was the need to send 64-bit Data ACK along
528*33de042dSApple OSS Distributions 		 * with 64-bit DSN, then 26 or 28 bytes would be used.
529*33de042dSApple OSS Distributions 		 * With timestamps and NOOP padding that will cause
530*33de042dSApple OSS Distributions 		 * overflow. Hence, in the rare event that both 64-bit
531*33de042dSApple OSS Distributions 		 * DSN and 64-bit ACK have to be sent, delay the send of
532*33de042dSApple OSS Distributions 		 * 64-bit ACK until our 64-bit DSN is acked with a 64-bit ack.
533*33de042dSApple OSS Distributions 		 * XXX If this delay causes issue, remove the 2-byte padding.
534*33de042dSApple OSS Distributions 		 */
535*33de042dSApple OSS Distributions 		struct mptcp_dss64_ack32_opt dsn_ack_opt;
536*33de042dSApple OSS Distributions 		uint8_t dssoptlen = sizeof(dsn_ack_opt);
537*33de042dSApple OSS Distributions 		uint16_t dss_csum;
538*33de042dSApple OSS Distributions 
539*33de042dSApple OSS Distributions 		if (do_csum) {
540*33de042dSApple OSS Distributions 			dssoptlen += 2;
541*33de042dSApple OSS Distributions 		}
542*33de042dSApple OSS Distributions 
543*33de042dSApple OSS Distributions 		CHECK_OPTLEN;
544*33de042dSApple OSS Distributions 
545*33de042dSApple OSS Distributions 		bzero(&dsn_ack_opt, sizeof(dsn_ack_opt));
546*33de042dSApple OSS Distributions 		dsn_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
547*33de042dSApple OSS Distributions 		dsn_ack_opt.mdss_copt.mdss_subtype = MPO_DSS;
548*33de042dSApple OSS Distributions 		dsn_ack_opt.mdss_copt.mdss_len = dssoptlen;
549*33de042dSApple OSS Distributions 		dsn_ack_opt.mdss_copt.mdss_flags |=
550*33de042dSApple OSS Distributions 		    MDSS_M | MDSS_m | MDSS_A;
551*33de042dSApple OSS Distributions 
552*33de042dSApple OSS Distributions 		CHECK_DATALEN;
553*33de042dSApple OSS Distributions 
554*33de042dSApple OSS Distributions 		mptcp_output_getm_dsnmap64(so, off,
555*33de042dSApple OSS Distributions 		    &dsn_ack_opt.mdss_dsn,
556*33de042dSApple OSS Distributions 		    &dsn_ack_opt.mdss_subflow_seqn,
557*33de042dSApple OSS Distributions 		    &dsn_ack_opt.mdss_data_len,
558*33de042dSApple OSS Distributions 		    &dss_csum);
559*33de042dSApple OSS Distributions 
560*33de042dSApple OSS Distributions 		if ((dsn_ack_opt.mdss_data_len == 0) ||
561*33de042dSApple OSS Distributions 		    (dsn_ack_opt.mdss_dsn == 0)) {
562*33de042dSApple OSS Distributions 			goto ret_optlen;
563*33de042dSApple OSS Distributions 		}
564*33de042dSApple OSS Distributions 
565*33de042dSApple OSS Distributions 		if (tp->t_mpflags & TMPF_SEND_DFIN) {
566*33de042dSApple OSS Distributions 			DO_FIN(dsn_ack_opt);
567*33de042dSApple OSS Distributions 		}
568*33de042dSApple OSS Distributions 
569*33de042dSApple OSS Distributions 		dsn_ack_opt.mdss_ack =
570*33de042dSApple OSS Distributions 		    htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt));
571*33de042dSApple OSS Distributions 
572*33de042dSApple OSS Distributions 		dsn_ack_opt.mdss_dsn = mptcp_hton64(dsn_ack_opt.mdss_dsn);
573*33de042dSApple OSS Distributions 		dsn_ack_opt.mdss_subflow_seqn = htonl(
574*33de042dSApple OSS Distributions 			dsn_ack_opt.mdss_subflow_seqn);
575*33de042dSApple OSS Distributions 		dsn_ack_opt.mdss_data_len = htons(
576*33de042dSApple OSS Distributions 			dsn_ack_opt.mdss_data_len);
577*33de042dSApple OSS Distributions 
578*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &dsn_ack_opt, sizeof(dsn_ack_opt));
579*33de042dSApple OSS Distributions 		if (do_csum) {
580*33de042dSApple OSS Distributions 			*((uint16_t *)(void *)(opt + optlen + sizeof(dsn_ack_opt))) = dss_csum;
581*33de042dSApple OSS Distributions 		}
582*33de042dSApple OSS Distributions 
583*33de042dSApple OSS Distributions 		optlen += dssoptlen;
584*33de042dSApple OSS Distributions 
585*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW;
586*33de042dSApple OSS Distributions 
587*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
588*33de042dSApple OSS Distributions 
589*33de042dSApple OSS Distributions 		goto ret_optlen;
590*33de042dSApple OSS Distributions 	}
591*33de042dSApple OSS Distributions 
592*33de042dSApple OSS Distributions 	if ((tp->t_mpflags & TMPF_SEND_DSN) &&
593*33de042dSApple OSS Distributions 	    (!send_64bit_dsn) &&
594*33de042dSApple OSS Distributions 	    !(tp->t_mpflags & TMPF_MPTCP_ACKNOW)) {
595*33de042dSApple OSS Distributions 		struct mptcp_dsn_opt dsn_opt;
596*33de042dSApple OSS Distributions 		uint8_t dssoptlen = sizeof(struct mptcp_dsn_opt);
597*33de042dSApple OSS Distributions 		uint16_t dss_csum;
598*33de042dSApple OSS Distributions 
599*33de042dSApple OSS Distributions 		if (do_csum) {
600*33de042dSApple OSS Distributions 			dssoptlen += 2;
601*33de042dSApple OSS Distributions 		}
602*33de042dSApple OSS Distributions 
603*33de042dSApple OSS Distributions 		CHECK_OPTLEN;
604*33de042dSApple OSS Distributions 
605*33de042dSApple OSS Distributions 		bzero(&dsn_opt, sizeof(dsn_opt));
606*33de042dSApple OSS Distributions 		dsn_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
607*33de042dSApple OSS Distributions 		dsn_opt.mdss_copt.mdss_subtype = MPO_DSS;
608*33de042dSApple OSS Distributions 		dsn_opt.mdss_copt.mdss_len = dssoptlen;
609*33de042dSApple OSS Distributions 		dsn_opt.mdss_copt.mdss_flags |= MDSS_M;
610*33de042dSApple OSS Distributions 
611*33de042dSApple OSS Distributions 		CHECK_DATALEN;
612*33de042dSApple OSS Distributions 
613*33de042dSApple OSS Distributions 		mptcp_output_getm_dsnmap32(so, off, &dsn_opt.mdss_dsn,
614*33de042dSApple OSS Distributions 		    &dsn_opt.mdss_subflow_seqn,
615*33de042dSApple OSS Distributions 		    &dsn_opt.mdss_data_len,
616*33de042dSApple OSS Distributions 		    &dss_csum);
617*33de042dSApple OSS Distributions 
618*33de042dSApple OSS Distributions 		if ((dsn_opt.mdss_data_len == 0) ||
619*33de042dSApple OSS Distributions 		    (dsn_opt.mdss_dsn == 0)) {
620*33de042dSApple OSS Distributions 			goto ret_optlen;
621*33de042dSApple OSS Distributions 		}
622*33de042dSApple OSS Distributions 
623*33de042dSApple OSS Distributions 		if (tp->t_mpflags & TMPF_SEND_DFIN) {
624*33de042dSApple OSS Distributions 			DO_FIN(dsn_opt);
625*33de042dSApple OSS Distributions 		}
626*33de042dSApple OSS Distributions 
627*33de042dSApple OSS Distributions 		dsn_opt.mdss_dsn = htonl(dsn_opt.mdss_dsn);
628*33de042dSApple OSS Distributions 		dsn_opt.mdss_subflow_seqn = htonl(dsn_opt.mdss_subflow_seqn);
629*33de042dSApple OSS Distributions 		dsn_opt.mdss_data_len = htons(dsn_opt.mdss_data_len);
630*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &dsn_opt, sizeof(dsn_opt));
631*33de042dSApple OSS Distributions 		if (do_csum) {
632*33de042dSApple OSS Distributions 			*((uint16_t *)(void *)(opt + optlen + sizeof(dsn_opt))) = dss_csum;
633*33de042dSApple OSS Distributions 		}
634*33de042dSApple OSS Distributions 
635*33de042dSApple OSS Distributions 		optlen += dssoptlen;
636*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW;
637*33de042dSApple OSS Distributions 
638*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
639*33de042dSApple OSS Distributions 
640*33de042dSApple OSS Distributions 		goto ret_optlen;
641*33de042dSApple OSS Distributions 	}
642*33de042dSApple OSS Distributions 
643*33de042dSApple OSS Distributions 	/* 32-bit Data ACK option */
644*33de042dSApple OSS Distributions 	if ((tp->t_mpflags & TMPF_MPTCP_ACKNOW) &&
645*33de042dSApple OSS Distributions 	    (!send_64bit_ack) &&
646*33de042dSApple OSS Distributions 	    !(tp->t_mpflags & TMPF_SEND_DSN) &&
647*33de042dSApple OSS Distributions 	    !(tp->t_mpflags & TMPF_SEND_DFIN)) {
648*33de042dSApple OSS Distributions 		struct mptcp_data_ack_opt dack_opt;
649*33de042dSApple OSS Distributions 		uint8_t dssoptlen = 0;
650*33de042dSApple OSS Distributions do_ack32_only:
651*33de042dSApple OSS Distributions 		dssoptlen = sizeof(dack_opt);
652*33de042dSApple OSS Distributions 
653*33de042dSApple OSS Distributions 		CHECK_OPTLEN;
654*33de042dSApple OSS Distributions 
655*33de042dSApple OSS Distributions 		bzero(&dack_opt, dssoptlen);
656*33de042dSApple OSS Distributions 		dack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
657*33de042dSApple OSS Distributions 		dack_opt.mdss_copt.mdss_len = dssoptlen;
658*33de042dSApple OSS Distributions 		dack_opt.mdss_copt.mdss_subtype = MPO_DSS;
659*33de042dSApple OSS Distributions 		dack_opt.mdss_copt.mdss_flags |= MDSS_A;
660*33de042dSApple OSS Distributions 		dack_opt.mdss_ack =
661*33de042dSApple OSS Distributions 		    htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt));
662*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &dack_opt, dssoptlen);
663*33de042dSApple OSS Distributions 		optlen += dssoptlen;
664*33de042dSApple OSS Distributions 		VERIFY(optlen <= MAX_TCPOPTLEN);
665*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW;
666*33de042dSApple OSS Distributions 		goto ret_optlen;
667*33de042dSApple OSS Distributions 	}
668*33de042dSApple OSS Distributions 
669*33de042dSApple OSS Distributions 	/* 64-bit Data ACK option */
670*33de042dSApple OSS Distributions 	if ((tp->t_mpflags & TMPF_MPTCP_ACKNOW) &&
671*33de042dSApple OSS Distributions 	    (send_64bit_ack) &&
672*33de042dSApple OSS Distributions 	    !(tp->t_mpflags & TMPF_SEND_DSN) &&
673*33de042dSApple OSS Distributions 	    !(tp->t_mpflags & TMPF_SEND_DFIN)) {
674*33de042dSApple OSS Distributions 		struct mptcp_data_ack64_opt dack_opt;
675*33de042dSApple OSS Distributions 		uint8_t dssoptlen = 0;
676*33de042dSApple OSS Distributions do_ack64_only:
677*33de042dSApple OSS Distributions 		dssoptlen = sizeof(dack_opt);
678*33de042dSApple OSS Distributions 
679*33de042dSApple OSS Distributions 		CHECK_OPTLEN;
680*33de042dSApple OSS Distributions 
681*33de042dSApple OSS Distributions 		bzero(&dack_opt, dssoptlen);
682*33de042dSApple OSS Distributions 		dack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
683*33de042dSApple OSS Distributions 		dack_opt.mdss_copt.mdss_len = dssoptlen;
684*33de042dSApple OSS Distributions 		dack_opt.mdss_copt.mdss_subtype = MPO_DSS;
685*33de042dSApple OSS Distributions 		dack_opt.mdss_copt.mdss_flags |= (MDSS_A | MDSS_a);
686*33de042dSApple OSS Distributions 		dack_opt.mdss_ack = mptcp_hton64(mp_tp->mpt_rcvnxt);
687*33de042dSApple OSS Distributions 		/*
688*33de042dSApple OSS Distributions 		 * The other end should retransmit 64-bit DSN until it
689*33de042dSApple OSS Distributions 		 * receives a 64-bit ACK.
690*33de042dSApple OSS Distributions 		 */
691*33de042dSApple OSS Distributions 		mp_tp->mpt_flags &= ~MPTCPF_SND_64BITACK;
692*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &dack_opt, dssoptlen);
693*33de042dSApple OSS Distributions 		optlen += dssoptlen;
694*33de042dSApple OSS Distributions 		VERIFY(optlen <= MAX_TCPOPTLEN);
695*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW;
696*33de042dSApple OSS Distributions 		goto ret_optlen;
697*33de042dSApple OSS Distributions 	}
698*33de042dSApple OSS Distributions 
699*33de042dSApple OSS Distributions 	/* 32-bit DSS+Data ACK option */
700*33de042dSApple OSS Distributions 	if ((tp->t_mpflags & TMPF_SEND_DSN) &&
701*33de042dSApple OSS Distributions 	    (!send_64bit_dsn) &&
702*33de042dSApple OSS Distributions 	    (!send_64bit_ack) &&
703*33de042dSApple OSS Distributions 	    (tp->t_mpflags & TMPF_MPTCP_ACKNOW)) {
704*33de042dSApple OSS Distributions 		struct mptcp_dss_ack_opt dss_ack_opt;
705*33de042dSApple OSS Distributions 		uint8_t dssoptlen = sizeof(dss_ack_opt);
706*33de042dSApple OSS Distributions 		uint16_t dss_csum;
707*33de042dSApple OSS Distributions 
708*33de042dSApple OSS Distributions 		if (do_csum) {
709*33de042dSApple OSS Distributions 			dssoptlen += 2;
710*33de042dSApple OSS Distributions 		}
711*33de042dSApple OSS Distributions 
712*33de042dSApple OSS Distributions 		CHECK_OPTLEN;
713*33de042dSApple OSS Distributions 
714*33de042dSApple OSS Distributions 		bzero(&dss_ack_opt, sizeof(dss_ack_opt));
715*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
716*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_len = dssoptlen;
717*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_subtype = MPO_DSS;
718*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_flags |= MDSS_A | MDSS_M;
719*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_ack =
720*33de042dSApple OSS Distributions 		    htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt));
721*33de042dSApple OSS Distributions 
722*33de042dSApple OSS Distributions 		CHECK_DATALEN;
723*33de042dSApple OSS Distributions 
724*33de042dSApple OSS Distributions 		mptcp_output_getm_dsnmap32(so, off, &dss_ack_opt.mdss_dsn,
725*33de042dSApple OSS Distributions 		    &dss_ack_opt.mdss_subflow_seqn,
726*33de042dSApple OSS Distributions 		    &dss_ack_opt.mdss_data_len,
727*33de042dSApple OSS Distributions 		    &dss_csum);
728*33de042dSApple OSS Distributions 
729*33de042dSApple OSS Distributions 		if ((dss_ack_opt.mdss_data_len == 0) ||
730*33de042dSApple OSS Distributions 		    (dss_ack_opt.mdss_dsn == 0)) {
731*33de042dSApple OSS Distributions 			goto do_ack32_only;
732*33de042dSApple OSS Distributions 		}
733*33de042dSApple OSS Distributions 
734*33de042dSApple OSS Distributions 		if (tp->t_mpflags & TMPF_SEND_DFIN) {
735*33de042dSApple OSS Distributions 			DO_FIN(dss_ack_opt);
736*33de042dSApple OSS Distributions 		}
737*33de042dSApple OSS Distributions 
738*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_dsn = htonl(dss_ack_opt.mdss_dsn);
739*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_subflow_seqn =
740*33de042dSApple OSS Distributions 		    htonl(dss_ack_opt.mdss_subflow_seqn);
741*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_data_len = htons(dss_ack_opt.mdss_data_len);
742*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &dss_ack_opt, sizeof(dss_ack_opt));
743*33de042dSApple OSS Distributions 		if (do_csum) {
744*33de042dSApple OSS Distributions 			*((uint16_t *)(void *)(opt + optlen + sizeof(dss_ack_opt))) = dss_csum;
745*33de042dSApple OSS Distributions 		}
746*33de042dSApple OSS Distributions 
747*33de042dSApple OSS Distributions 		optlen += dssoptlen;
748*33de042dSApple OSS Distributions 
749*33de042dSApple OSS Distributions 		if (optlen > MAX_TCPOPTLEN) {
750*33de042dSApple OSS Distributions 			panic("optlen too large");
751*33de042dSApple OSS Distributions 		}
752*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW;
753*33de042dSApple OSS Distributions 		goto ret_optlen;
754*33de042dSApple OSS Distributions 	}
755*33de042dSApple OSS Distributions 
756*33de042dSApple OSS Distributions 	/* 32-bit DSS + 64-bit DACK option */
757*33de042dSApple OSS Distributions 	if ((tp->t_mpflags & TMPF_SEND_DSN) &&
758*33de042dSApple OSS Distributions 	    (!send_64bit_dsn) &&
759*33de042dSApple OSS Distributions 	    (send_64bit_ack) &&
760*33de042dSApple OSS Distributions 	    (tp->t_mpflags & TMPF_MPTCP_ACKNOW)) {
761*33de042dSApple OSS Distributions 		struct mptcp_dss32_ack64_opt dss_ack_opt;
762*33de042dSApple OSS Distributions 		uint8_t dssoptlen = sizeof(dss_ack_opt);
763*33de042dSApple OSS Distributions 		uint16_t dss_csum;
764*33de042dSApple OSS Distributions 
765*33de042dSApple OSS Distributions 		if (do_csum) {
766*33de042dSApple OSS Distributions 			dssoptlen += 2;
767*33de042dSApple OSS Distributions 		}
768*33de042dSApple OSS Distributions 
769*33de042dSApple OSS Distributions 		CHECK_OPTLEN;
770*33de042dSApple OSS Distributions 
771*33de042dSApple OSS Distributions 		bzero(&dss_ack_opt, sizeof(dss_ack_opt));
772*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
773*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_len = dssoptlen;
774*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_subtype = MPO_DSS;
775*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_flags |= MDSS_M | MDSS_A | MDSS_a;
776*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_ack =
777*33de042dSApple OSS Distributions 		    mptcp_hton64(mp_tp->mpt_rcvnxt);
778*33de042dSApple OSS Distributions 
779*33de042dSApple OSS Distributions 		CHECK_DATALEN;
780*33de042dSApple OSS Distributions 
781*33de042dSApple OSS Distributions 		mptcp_output_getm_dsnmap32(so, off, &dss_ack_opt.mdss_dsn,
782*33de042dSApple OSS Distributions 		    &dss_ack_opt.mdss_subflow_seqn,
783*33de042dSApple OSS Distributions 		    &dss_ack_opt.mdss_data_len,
784*33de042dSApple OSS Distributions 		    &dss_csum);
785*33de042dSApple OSS Distributions 
786*33de042dSApple OSS Distributions 		if ((dss_ack_opt.mdss_data_len == 0) ||
787*33de042dSApple OSS Distributions 		    (dss_ack_opt.mdss_dsn == 0)) {
788*33de042dSApple OSS Distributions 			goto do_ack64_only;
789*33de042dSApple OSS Distributions 		}
790*33de042dSApple OSS Distributions 
791*33de042dSApple OSS Distributions 		if (tp->t_mpflags & TMPF_SEND_DFIN) {
792*33de042dSApple OSS Distributions 			DO_FIN(dss_ack_opt);
793*33de042dSApple OSS Distributions 		}
794*33de042dSApple OSS Distributions 
795*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_dsn = htonl(dss_ack_opt.mdss_dsn);
796*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_subflow_seqn =
797*33de042dSApple OSS Distributions 		    htonl(dss_ack_opt.mdss_subflow_seqn);
798*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_data_len = htons(dss_ack_opt.mdss_data_len);
799*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &dss_ack_opt, sizeof(dss_ack_opt));
800*33de042dSApple OSS Distributions 		if (do_csum) {
801*33de042dSApple OSS Distributions 			*((uint16_t *)(void *)(opt + optlen + sizeof(dss_ack_opt))) = dss_csum;
802*33de042dSApple OSS Distributions 		}
803*33de042dSApple OSS Distributions 
804*33de042dSApple OSS Distributions 		optlen += dssoptlen;
805*33de042dSApple OSS Distributions 
806*33de042dSApple OSS Distributions 		if (optlen > MAX_TCPOPTLEN) {
807*33de042dSApple OSS Distributions 			panic("optlen too large");
808*33de042dSApple OSS Distributions 		}
809*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_MPTCP_ACKNOW;
810*33de042dSApple OSS Distributions 
811*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
812*33de042dSApple OSS Distributions 
813*33de042dSApple OSS Distributions 		goto ret_optlen;
814*33de042dSApple OSS Distributions 	}
815*33de042dSApple OSS Distributions 
816*33de042dSApple OSS Distributions 	if (tp->t_mpflags & TMPF_SEND_DFIN) {
817*33de042dSApple OSS Distributions 		uint8_t dssoptlen = sizeof(struct mptcp_dss_ack_opt);
818*33de042dSApple OSS Distributions 		struct mptcp_dss_ack_opt dss_ack_opt;
819*33de042dSApple OSS Distributions 		uint16_t dss_csum;
820*33de042dSApple OSS Distributions 
821*33de042dSApple OSS Distributions 		if (do_csum) {
822*33de042dSApple OSS Distributions 			uint64_t dss_val = mptcp_hton64(mp_tp->mpt_sndmax - 1);
823*33de042dSApple OSS Distributions 			uint16_t dlen = htons(1);
824*33de042dSApple OSS Distributions 			uint32_t sseq = 0;
825*33de042dSApple OSS Distributions 			uint32_t sum;
826*33de042dSApple OSS Distributions 
827*33de042dSApple OSS Distributions 
828*33de042dSApple OSS Distributions 			dssoptlen += 2;
829*33de042dSApple OSS Distributions 
830*33de042dSApple OSS Distributions 			sum = in_pseudo64(dss_val, sseq, dlen);
831*33de042dSApple OSS Distributions 			ADDCARRY(sum);
832*33de042dSApple OSS Distributions 			dss_csum = ~sum & 0xffff;
833*33de042dSApple OSS Distributions 		}
834*33de042dSApple OSS Distributions 
835*33de042dSApple OSS Distributions 		CHECK_OPTLEN;
836*33de042dSApple OSS Distributions 
837*33de042dSApple OSS Distributions 		bzero(&dss_ack_opt, sizeof(dss_ack_opt));
838*33de042dSApple OSS Distributions 
839*33de042dSApple OSS Distributions 		/*
840*33de042dSApple OSS Distributions 		 * Data FIN occupies one sequence space.
841*33de042dSApple OSS Distributions 		 * Don't send it if it has been Acked.
842*33de042dSApple OSS Distributions 		 */
843*33de042dSApple OSS Distributions 		if ((mp_tp->mpt_sndnxt + 1 != mp_tp->mpt_sndmax) ||
844*33de042dSApple OSS Distributions 		    (mp_tp->mpt_snduna == mp_tp->mpt_sndmax)) {
845*33de042dSApple OSS Distributions 			goto ret_optlen;
846*33de042dSApple OSS Distributions 		}
847*33de042dSApple OSS Distributions 
848*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_kind = TCPOPT_MULTIPATH;
849*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_len = dssoptlen;
850*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_subtype = MPO_DSS;
851*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_copt.mdss_flags |= MDSS_A | MDSS_M | MDSS_F;
852*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_ack =
853*33de042dSApple OSS Distributions 		    htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt));
854*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_dsn =
855*33de042dSApple OSS Distributions 		    htonl(MPTCP_DATASEQ_LOW32(mp_tp->mpt_sndmax - 1));
856*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_subflow_seqn = 0;
857*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_data_len = 1;
858*33de042dSApple OSS Distributions 		dss_ack_opt.mdss_data_len = htons(dss_ack_opt.mdss_data_len);
859*33de042dSApple OSS Distributions 		memcpy(opt + optlen, &dss_ack_opt, sizeof(dss_ack_opt));
860*33de042dSApple OSS Distributions 		if (do_csum) {
861*33de042dSApple OSS Distributions 			*((uint16_t *)(void *)(opt + optlen + sizeof(dss_ack_opt))) = dss_csum;
862*33de042dSApple OSS Distributions 		}
863*33de042dSApple OSS Distributions 
864*33de042dSApple OSS Distributions 		optlen += dssoptlen;
865*33de042dSApple OSS Distributions 
866*33de042dSApple OSS Distributions 		*do_not_compress = TRUE;
867*33de042dSApple OSS Distributions 	}
868*33de042dSApple OSS Distributions 
869*33de042dSApple OSS Distributions ret_optlen:
870*33de042dSApple OSS Distributions 	if (TRUE == *p_mptcp_acknow) {
871*33de042dSApple OSS Distributions 		uint32_t new_mpt_flags = tp->t_mpflags & TMPF_MPTCP_SIGNALS;
872*33de042dSApple OSS Distributions 
873*33de042dSApple OSS Distributions 		/*
874*33de042dSApple OSS Distributions 		 * If none of the above mpflags were acted on by
875*33de042dSApple OSS Distributions 		 * this routine, reset these flags and set p_mptcp_acknow
876*33de042dSApple OSS Distributions 		 * to false.
877*33de042dSApple OSS Distributions 		 *
878*33de042dSApple OSS Distributions 		 * XXX The reset value of p_mptcp_acknow can be used
879*33de042dSApple OSS Distributions 		 * to communicate tcp_output to NOT send a pure ack without any
880*33de042dSApple OSS Distributions 		 * MPTCP options as it will be treated as a dup ack.
881*33de042dSApple OSS Distributions 		 * Since the instances of mptcp_setup_opts not acting on
882*33de042dSApple OSS Distributions 		 * these options are mostly corner cases and sending a dup
883*33de042dSApple OSS Distributions 		 * ack here would only have an impact if the system
884*33de042dSApple OSS Distributions 		 * has sent consecutive dup acks before this false one,
885*33de042dSApple OSS Distributions 		 * we haven't modified the logic in tcp_output to avoid
886*33de042dSApple OSS Distributions 		 * that.
887*33de042dSApple OSS Distributions 		 */
888*33de042dSApple OSS Distributions 		if (old_mpt_flags == new_mpt_flags) {
889*33de042dSApple OSS Distributions 			tp->t_mpflags &= ~TMPF_MPTCP_SIGNALS;
890*33de042dSApple OSS Distributions 			*p_mptcp_acknow = FALSE;
891*33de042dSApple OSS Distributions 		}
892*33de042dSApple OSS Distributions 	}
893*33de042dSApple OSS Distributions 
894*33de042dSApple OSS Distributions 	return optlen;
895*33de042dSApple OSS Distributions }
896*33de042dSApple OSS Distributions 
897*33de042dSApple OSS Distributions /*
898*33de042dSApple OSS Distributions  * MPTCP Options Input Processing
899*33de042dSApple OSS Distributions  */
900*33de042dSApple OSS Distributions 
901*33de042dSApple OSS Distributions static int
mptcp_sanitize_option(struct tcpcb * tp,int mptcp_subtype)902*33de042dSApple OSS Distributions mptcp_sanitize_option(struct tcpcb *tp, int mptcp_subtype)
903*33de042dSApple OSS Distributions {
904*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
905*33de042dSApple OSS Distributions 	int ret = 1;
906*33de042dSApple OSS Distributions 
907*33de042dSApple OSS Distributions 	switch (mptcp_subtype) {
908*33de042dSApple OSS Distributions 	case MPO_CAPABLE:
909*33de042dSApple OSS Distributions 		break;
910*33de042dSApple OSS Distributions 	case MPO_JOIN:                  /* fall through */
911*33de042dSApple OSS Distributions 	case MPO_DSS:                   /* fall through */
912*33de042dSApple OSS Distributions 	case MPO_FASTCLOSE:             /* fall through */
913*33de042dSApple OSS Distributions 	case MPO_FAIL:                  /* fall through */
914*33de042dSApple OSS Distributions 	case MPO_REMOVE_ADDR:           /* fall through */
915*33de042dSApple OSS Distributions 	case MPO_ADD_ADDR:              /* fall through */
916*33de042dSApple OSS Distributions 	case MPO_PRIO:                  /* fall through */
917*33de042dSApple OSS Distributions 		if (mp_tp->mpt_state < MPTCPS_ESTABLISHED) {
918*33de042dSApple OSS Distributions 			ret = 0;
919*33de042dSApple OSS Distributions 		}
920*33de042dSApple OSS Distributions 		break;
921*33de042dSApple OSS Distributions 	default:
922*33de042dSApple OSS Distributions 		ret = 0;
923*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: type = %d \n", __func__,
924*33de042dSApple OSS Distributions 		    (unsigned long)VM_KERNEL_ADDRPERM(mp_tp->mpt_mpte), mptcp_subtype);
925*33de042dSApple OSS Distributions 		break;
926*33de042dSApple OSS Distributions 	}
927*33de042dSApple OSS Distributions 	return ret;
928*33de042dSApple OSS Distributions }
929*33de042dSApple OSS Distributions 
930*33de042dSApple OSS Distributions static int
mptcp_valid_mpcapable_common_opt(u_char * cp)931*33de042dSApple OSS Distributions mptcp_valid_mpcapable_common_opt(u_char *cp)
932*33de042dSApple OSS Distributions {
933*33de042dSApple OSS Distributions 	struct mptcp_mpcapable_opt_common *rsp =
934*33de042dSApple OSS Distributions 	    (struct mptcp_mpcapable_opt_common *)cp;
935*33de042dSApple OSS Distributions 
936*33de042dSApple OSS Distributions 	/* mmco_kind, mmco_len and mmco_subtype are validated before */
937*33de042dSApple OSS Distributions 
938*33de042dSApple OSS Distributions 	if (!(rsp->mmco_flags & MPCAP_PROPOSAL_SBIT)) {
939*33de042dSApple OSS Distributions 		return 0;
940*33de042dSApple OSS Distributions 	}
941*33de042dSApple OSS Distributions 
942*33de042dSApple OSS Distributions 	if (rsp->mmco_flags & (MPCAP_BBIT | MPCAP_DBIT |
943*33de042dSApple OSS Distributions 	    MPCAP_EBIT | MPCAP_FBIT | MPCAP_GBIT)) {
944*33de042dSApple OSS Distributions 		return 0;
945*33de042dSApple OSS Distributions 	}
946*33de042dSApple OSS Distributions 
947*33de042dSApple OSS Distributions 	return 1;
948*33de042dSApple OSS Distributions }
949*33de042dSApple OSS Distributions 
950*33de042dSApple OSS Distributions 
951*33de042dSApple OSS Distributions static void
mptcp_do_mpcapable_opt(struct tcpcb * tp,u_char * cp,struct tcphdr * th,uint8_t optlen)952*33de042dSApple OSS Distributions mptcp_do_mpcapable_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th,
953*33de042dSApple OSS Distributions     uint8_t optlen)
954*33de042dSApple OSS Distributions {
955*33de042dSApple OSS Distributions 	struct mptcp_mpcapable_opt_rsp *rsp = NULL;
956*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
957*33de042dSApple OSS Distributions 	struct mptses *mpte = mp_tp->mpt_mpte;
958*33de042dSApple OSS Distributions 
959*33de042dSApple OSS Distributions 	/* Only valid on SYN/ACK */
960*33de042dSApple OSS Distributions 	if ((th->th_flags & (TH_SYN | TH_ACK)) != (TH_SYN | TH_ACK)) {
961*33de042dSApple OSS Distributions 		return;
962*33de042dSApple OSS Distributions 	}
963*33de042dSApple OSS Distributions 
964*33de042dSApple OSS Distributions 	/* Validate the kind, len, flags */
965*33de042dSApple OSS Distributions 	if (mptcp_valid_mpcapable_common_opt(cp) != 1) {
966*33de042dSApple OSS Distributions 		tcpstat.tcps_invalid_mpcap++;
967*33de042dSApple OSS Distributions 		return;
968*33de042dSApple OSS Distributions 	}
969*33de042dSApple OSS Distributions 
970*33de042dSApple OSS Distributions 	/* handle SYN/ACK retransmission by acknowledging with ACK */
971*33de042dSApple OSS Distributions 	if (mp_tp->mpt_state >= MPTCPS_ESTABLISHED) {
972*33de042dSApple OSS Distributions 		return;
973*33de042dSApple OSS Distributions 	}
974*33de042dSApple OSS Distributions 
975*33de042dSApple OSS Distributions 	/* A SYN/ACK contains peer's key and flags */
976*33de042dSApple OSS Distributions 	if (optlen != sizeof(struct mptcp_mpcapable_opt_rsp)) {
977*33de042dSApple OSS Distributions 		/* complain */
978*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: SYN_ACK optlen = %u, sizeof mp opt = %lu \n",
979*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte), optlen,
980*33de042dSApple OSS Distributions 		    sizeof(struct mptcp_mpcapable_opt_rsp));
981*33de042dSApple OSS Distributions 		tcpstat.tcps_invalid_mpcap++;
982*33de042dSApple OSS Distributions 		return;
983*33de042dSApple OSS Distributions 	}
984*33de042dSApple OSS Distributions 
985*33de042dSApple OSS Distributions 	/*
986*33de042dSApple OSS Distributions 	 * If checksum flag is set, enable MPTCP checksum, even if
987*33de042dSApple OSS Distributions 	 * it was not negotiated on the first SYN.
988*33de042dSApple OSS Distributions 	 */
989*33de042dSApple OSS Distributions 	if (((struct mptcp_mpcapable_opt_common *)cp)->mmco_flags &
990*33de042dSApple OSS Distributions 	    MPCAP_CHECKSUM_CBIT) {
991*33de042dSApple OSS Distributions 		mp_tp->mpt_flags |= MPTCPF_CHECKSUM;
992*33de042dSApple OSS Distributions 	}
993*33de042dSApple OSS Distributions 
994*33de042dSApple OSS Distributions 	if (((struct mptcp_mpcapable_opt_common *)cp)->mmco_flags &
995*33de042dSApple OSS Distributions 	    MPCAP_UNICAST_IPBIT) {
996*33de042dSApple OSS Distributions 		mpte->mpte_flags |= MPTE_UNICAST_IP;
997*33de042dSApple OSS Distributions 
998*33de042dSApple OSS Distributions 		/* We need an explicit signal for the addresses - zero the existing ones */
999*33de042dSApple OSS Distributions 		memset(&mpte->mpte_sub_dst_v4, 0, sizeof(mpte->mpte_sub_dst_v4));
1000*33de042dSApple OSS Distributions 		memset(&mpte->mpte_sub_dst_v6, 0, sizeof(mpte->mpte_sub_dst_v6));
1001*33de042dSApple OSS Distributions 	}
1002*33de042dSApple OSS Distributions 
1003*33de042dSApple OSS Distributions 	rsp = (struct mptcp_mpcapable_opt_rsp *)cp;
1004*33de042dSApple OSS Distributions 	mp_tp->mpt_remotekey = rsp->mmc_localkey;
1005*33de042dSApple OSS Distributions 	/* For now just downgrade to the peer's version */
1006*33de042dSApple OSS Distributions 	if (rsp->mmc_common.mmco_version < mp_tp->mpt_version) {
1007*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "local version: %d > peer version %d", mp_tp->mpt_version, rsp->mmc_common.mmco_version);
1008*33de042dSApple OSS Distributions 		mp_tp->mpt_version = rsp->mmc_common.mmco_version;
1009*33de042dSApple OSS Distributions 		tcpstat.tcps_mp_verdowngrade++;
1010*33de042dSApple OSS Distributions 		return;
1011*33de042dSApple OSS Distributions 	}
1012*33de042dSApple OSS Distributions 	if (mptcp_init_remote_parms(mp_tp) != 0) {
1013*33de042dSApple OSS Distributions 		tcpstat.tcps_invalid_mpcap++;
1014*33de042dSApple OSS Distributions 		return;
1015*33de042dSApple OSS Distributions 	}
1016*33de042dSApple OSS Distributions 	tcp_heuristic_mptcp_success(tp);
1017*33de042dSApple OSS Distributions 	tcp_cache_update_mptcp_version(tp, TRUE);
1018*33de042dSApple OSS Distributions 	tp->t_mpflags |= (TMPF_SND_KEYS | TMPF_MPTCP_TRUE);
1019*33de042dSApple OSS Distributions }
1020*33de042dSApple OSS Distributions 
1021*33de042dSApple OSS Distributions 
1022*33de042dSApple OSS Distributions static void
mptcp_do_mpjoin_opt(struct tcpcb * tp,u_char * cp,struct tcphdr * th,uint8_t optlen)1023*33de042dSApple OSS Distributions mptcp_do_mpjoin_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, uint8_t optlen)
1024*33de042dSApple OSS Distributions {
1025*33de042dSApple OSS Distributions #define MPTCP_JOPT_ERROR_PATH(tp) {                                     \
1026*33de042dSApple OSS Distributions 	tcpstat.tcps_invalid_joins++;                                   \
1027*33de042dSApple OSS Distributions 	if (tp->t_inpcb->inp_socket != NULL) {                          \
1028*33de042dSApple OSS Distributions 	        soevent(tp->t_inpcb->inp_socket,                        \
1029*33de042dSApple OSS Distributions 	            SO_FILT_HINT_LOCKED | SO_FILT_HINT_MUSTRST);        \
1030*33de042dSApple OSS Distributions 	}                                                               \
1031*33de042dSApple OSS Distributions }
1032*33de042dSApple OSS Distributions 	int error = 0;
1033*33de042dSApple OSS Distributions 	struct mptcp_mpjoin_opt_rsp *join_rsp =
1034*33de042dSApple OSS Distributions 	    (struct mptcp_mpjoin_opt_rsp *)cp;
1035*33de042dSApple OSS Distributions 
1036*33de042dSApple OSS Distributions 	/* Only valid on SYN/ACK */
1037*33de042dSApple OSS Distributions 	if ((th->th_flags & (TH_SYN | TH_ACK)) != (TH_SYN | TH_ACK)) {
1038*33de042dSApple OSS Distributions 		return;
1039*33de042dSApple OSS Distributions 	}
1040*33de042dSApple OSS Distributions 
1041*33de042dSApple OSS Distributions 	if (optlen != sizeof(struct mptcp_mpjoin_opt_rsp)) {
1042*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: SYN_ACK: unexpected optlen = %u mp option = %lu\n",
1043*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(tptomptp(tp)->mpt_mpte),
1044*33de042dSApple OSS Distributions 		    optlen, sizeof(struct mptcp_mpjoin_opt_rsp));
1045*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_PREESTABLISHED;
1046*33de042dSApple OSS Distributions 		/* send RST and close */
1047*33de042dSApple OSS Distributions 		MPTCP_JOPT_ERROR_PATH(tp);
1048*33de042dSApple OSS Distributions 		return;
1049*33de042dSApple OSS Distributions 	}
1050*33de042dSApple OSS Distributions 
1051*33de042dSApple OSS Distributions 	mptcp_set_raddr_rand(tp->t_local_aid, tptomptp(tp),
1052*33de042dSApple OSS Distributions 	    join_rsp->mmjo_addr_id, join_rsp->mmjo_rand);
1053*33de042dSApple OSS Distributions 	error = mptcp_validate_join_hmac(tp,
1054*33de042dSApple OSS Distributions 	    (u_char*)&join_rsp->mmjo_mac, HMAC_TRUNCATED_SYNACK);
1055*33de042dSApple OSS Distributions 	if (error) {
1056*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: SYN_ACK error = %d \n",
1057*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(tptomptp(tp)->mpt_mpte),
1058*33de042dSApple OSS Distributions 		    error);
1059*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_PREESTABLISHED;
1060*33de042dSApple OSS Distributions 		/* send RST and close */
1061*33de042dSApple OSS Distributions 		MPTCP_JOPT_ERROR_PATH(tp);
1062*33de042dSApple OSS Distributions 		return;
1063*33de042dSApple OSS Distributions 	}
1064*33de042dSApple OSS Distributions 	tp->t_mpflags |= (TMPF_SENT_JOIN | TMPF_SND_JACK);
1065*33de042dSApple OSS Distributions }
1066*33de042dSApple OSS Distributions 
1067*33de042dSApple OSS Distributions static int
mptcp_validate_join_hmac(struct tcpcb * tp,u_char * hmac,int mac_len)1068*33de042dSApple OSS Distributions mptcp_validate_join_hmac(struct tcpcb *tp, u_char* hmac, int mac_len)
1069*33de042dSApple OSS Distributions {
1070*33de042dSApple OSS Distributions 	u_char digest[MAX(SHA1_RESULTLEN, SHA256_DIGEST_LENGTH)] = {0};
1071*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1072*33de042dSApple OSS Distributions 	u_int32_t rem_rand, loc_rand;
1073*33de042dSApple OSS Distributions 
1074*33de042dSApple OSS Distributions 	rem_rand = loc_rand = 0;
1075*33de042dSApple OSS Distributions 
1076*33de042dSApple OSS Distributions 	mptcp_get_rands(tp->t_local_aid, mp_tp, &loc_rand, &rem_rand);
1077*33de042dSApple OSS Distributions 	if ((rem_rand == 0) || (loc_rand == 0)) {
1078*33de042dSApple OSS Distributions 		return -1;
1079*33de042dSApple OSS Distributions 	}
1080*33de042dSApple OSS Distributions 
1081*33de042dSApple OSS Distributions 	if (mp_tp->mpt_version == MPTCP_VERSION_0) {
1082*33de042dSApple OSS Distributions 		mptcp_hmac_sha1(mp_tp->mpt_remotekey, mp_tp->mpt_localkey, rem_rand, loc_rand,
1083*33de042dSApple OSS Distributions 		    digest);
1084*33de042dSApple OSS Distributions 	} else {
1085*33de042dSApple OSS Distributions 		uint32_t data[2];
1086*33de042dSApple OSS Distributions 		data[0] = rem_rand;
1087*33de042dSApple OSS Distributions 		data[1] = loc_rand;
1088*33de042dSApple OSS Distributions 		mptcp_hmac_sha256(mp_tp->mpt_remotekey, mp_tp->mpt_localkey, (u_char *)data, 8, digest);
1089*33de042dSApple OSS Distributions 	}
1090*33de042dSApple OSS Distributions 
1091*33de042dSApple OSS Distributions 	if (bcmp(digest, hmac, mac_len) == 0) {
1092*33de042dSApple OSS Distributions 		return 0; /* matches */
1093*33de042dSApple OSS Distributions 	} else {
1094*33de042dSApple OSS Distributions 		printf("%s: remote key %llx local key %llx remote rand %x "
1095*33de042dSApple OSS Distributions 		    "local rand %x \n", __func__, mp_tp->mpt_remotekey, mp_tp->mpt_localkey,
1096*33de042dSApple OSS Distributions 		    rem_rand, loc_rand);
1097*33de042dSApple OSS Distributions 		return -1;
1098*33de042dSApple OSS Distributions 	}
1099*33de042dSApple OSS Distributions }
1100*33de042dSApple OSS Distributions 
1101*33de042dSApple OSS Distributions /*
1102*33de042dSApple OSS Distributions  * Update the mptcb send state variables, but the actual sbdrop occurs
1103*33de042dSApple OSS Distributions  * in MPTCP layer
1104*33de042dSApple OSS Distributions  */
1105*33de042dSApple OSS Distributions void
mptcp_data_ack_rcvd(struct mptcb * mp_tp,struct tcpcb * tp,u_int64_t full_dack)1106*33de042dSApple OSS Distributions mptcp_data_ack_rcvd(struct mptcb *mp_tp, struct tcpcb *tp, u_int64_t full_dack)
1107*33de042dSApple OSS Distributions {
1108*33de042dSApple OSS Distributions 	uint64_t acked = full_dack - mp_tp->mpt_snduna;
1109*33de042dSApple OSS Distributions 
1110*33de042dSApple OSS Distributions 	VERIFY(acked <= INT_MAX);
1111*33de042dSApple OSS Distributions 
1112*33de042dSApple OSS Distributions 	if (acked) {
1113*33de042dSApple OSS Distributions 		struct socket *mp_so = mptetoso(mp_tp->mpt_mpte);
1114*33de042dSApple OSS Distributions 
1115*33de042dSApple OSS Distributions 		if (acked > mp_so->so_snd.sb_cc) {
1116*33de042dSApple OSS Distributions 			if (acked > mp_so->so_snd.sb_cc + 1 ||
1117*33de042dSApple OSS Distributions 			    mp_tp->mpt_state < MPTCPS_FIN_WAIT_1) {
1118*33de042dSApple OSS Distributions 				os_log_error(mptcp_log_handle, "%s - %lx: acked %u, sb_cc %u full %u suna %u state %u\n",
1119*33de042dSApple OSS Distributions 				    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mp_tp->mpt_mpte),
1120*33de042dSApple OSS Distributions 				    (uint32_t)acked, mp_so->so_snd.sb_cc,
1121*33de042dSApple OSS Distributions 				    (uint32_t)full_dack, (uint32_t)mp_tp->mpt_snduna,
1122*33de042dSApple OSS Distributions 				    mp_tp->mpt_state);
1123*33de042dSApple OSS Distributions 			}
1124*33de042dSApple OSS Distributions 
1125*33de042dSApple OSS Distributions 			sbdrop(&mp_so->so_snd, (int)mp_so->so_snd.sb_cc);
1126*33de042dSApple OSS Distributions 		} else {
1127*33de042dSApple OSS Distributions 			sbdrop(&mp_so->so_snd, (int)acked);
1128*33de042dSApple OSS Distributions 		}
1129*33de042dSApple OSS Distributions 
1130*33de042dSApple OSS Distributions 		mp_tp->mpt_snduna += acked;
1131*33de042dSApple OSS Distributions 		/* In degraded mode, we may get some Data ACKs */
1132*33de042dSApple OSS Distributions 		if ((tp->t_mpflags & TMPF_TCP_FALLBACK) &&
1133*33de042dSApple OSS Distributions 		    !(mp_tp->mpt_flags & MPTCPF_POST_FALLBACK_SYNC) &&
1134*33de042dSApple OSS Distributions 		    MPTCP_SEQ_GT(mp_tp->mpt_sndnxt, mp_tp->mpt_snduna)) {
1135*33de042dSApple OSS Distributions 			/* bring back sndnxt to retransmit MPTCP data */
1136*33de042dSApple OSS Distributions 			mp_tp->mpt_sndnxt = mp_tp->mpt_dsn_at_csum_fail;
1137*33de042dSApple OSS Distributions 			mp_tp->mpt_flags |= MPTCPF_POST_FALLBACK_SYNC;
1138*33de042dSApple OSS Distributions 			tp->t_inpcb->inp_socket->so_flags1 |=
1139*33de042dSApple OSS Distributions 			    SOF1_POST_FALLBACK_SYNC;
1140*33de042dSApple OSS Distributions 		}
1141*33de042dSApple OSS Distributions 
1142*33de042dSApple OSS Distributions 		mptcp_clean_reinjectq(mp_tp->mpt_mpte);
1143*33de042dSApple OSS Distributions 
1144*33de042dSApple OSS Distributions 		sowwakeup(mp_so);
1145*33de042dSApple OSS Distributions 	}
1146*33de042dSApple OSS Distributions 	if (full_dack == mp_tp->mpt_sndmax &&
1147*33de042dSApple OSS Distributions 	    mp_tp->mpt_state >= MPTCPS_FIN_WAIT_1) {
1148*33de042dSApple OSS Distributions 		mptcp_close_fsm(mp_tp, MPCE_RECV_DATA_ACK);
1149*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_SEND_DFIN;
1150*33de042dSApple OSS Distributions 	}
1151*33de042dSApple OSS Distributions 
1152*33de042dSApple OSS Distributions 	if ((tp->t_mpflags & TMPF_SND_KEYS) &&
1153*33de042dSApple OSS Distributions 	    MPTCP_SEQ_GT(mp_tp->mpt_snduna, mp_tp->mpt_local_idsn + 1)) {
1154*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_SND_KEYS;
1155*33de042dSApple OSS Distributions 	}
1156*33de042dSApple OSS Distributions }
1157*33de042dSApple OSS Distributions 
1158*33de042dSApple OSS Distributions void
mptcp_update_window_wakeup(struct tcpcb * tp)1159*33de042dSApple OSS Distributions mptcp_update_window_wakeup(struct tcpcb *tp)
1160*33de042dSApple OSS Distributions {
1161*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1162*33de042dSApple OSS Distributions 
1163*33de042dSApple OSS Distributions 	socket_lock_assert_owned(mptetoso(mp_tp->mpt_mpte));
1164*33de042dSApple OSS Distributions 
1165*33de042dSApple OSS Distributions 	if (mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP) {
1166*33de042dSApple OSS Distributions 		mp_tp->mpt_sndwnd = tp->snd_wnd;
1167*33de042dSApple OSS Distributions 		mp_tp->mpt_sndwl1 = mp_tp->mpt_rcvnxt;
1168*33de042dSApple OSS Distributions 		mp_tp->mpt_sndwl2 = mp_tp->mpt_snduna;
1169*33de042dSApple OSS Distributions 	}
1170*33de042dSApple OSS Distributions 
1171*33de042dSApple OSS Distributions 	sowwakeup(tp->t_inpcb->inp_socket);
1172*33de042dSApple OSS Distributions }
1173*33de042dSApple OSS Distributions 
1174*33de042dSApple OSS Distributions static void
mptcp_update_window(struct mptcb * mp_tp,u_int64_t ack,u_int64_t seq,u_int32_t tiwin)1175*33de042dSApple OSS Distributions mptcp_update_window(struct mptcb *mp_tp, u_int64_t ack, u_int64_t seq, u_int32_t tiwin)
1176*33de042dSApple OSS Distributions {
1177*33de042dSApple OSS Distributions 	if (MPTCP_SEQ_LT(mp_tp->mpt_sndwl1, seq) ||
1178*33de042dSApple OSS Distributions 	    (mp_tp->mpt_sndwl1 == seq &&
1179*33de042dSApple OSS Distributions 	    (MPTCP_SEQ_LT(mp_tp->mpt_sndwl2, ack) ||
1180*33de042dSApple OSS Distributions 	    (mp_tp->mpt_sndwl2 == ack && tiwin > mp_tp->mpt_sndwnd)))) {
1181*33de042dSApple OSS Distributions 		mp_tp->mpt_sndwnd = tiwin;
1182*33de042dSApple OSS Distributions 		mp_tp->mpt_sndwl1 = seq;
1183*33de042dSApple OSS Distributions 		mp_tp->mpt_sndwl2 = ack;
1184*33de042dSApple OSS Distributions 	}
1185*33de042dSApple OSS Distributions }
1186*33de042dSApple OSS Distributions 
1187*33de042dSApple OSS Distributions static void
mptcp_do_dss_opt_ack_meat(u_int64_t full_dack,u_int64_t full_dsn,struct tcpcb * tp,u_int32_t tiwin)1188*33de042dSApple OSS Distributions mptcp_do_dss_opt_ack_meat(u_int64_t full_dack, u_int64_t full_dsn,
1189*33de042dSApple OSS Distributions     struct tcpcb *tp, u_int32_t tiwin)
1190*33de042dSApple OSS Distributions {
1191*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1192*33de042dSApple OSS Distributions 	int close_notify = 0;
1193*33de042dSApple OSS Distributions 
1194*33de042dSApple OSS Distributions 	tp->t_mpflags |= TMPF_RCVD_DACK;
1195*33de042dSApple OSS Distributions 
1196*33de042dSApple OSS Distributions 	if (MPTCP_SEQ_LEQ(full_dack, mp_tp->mpt_sndmax) &&
1197*33de042dSApple OSS Distributions 	    MPTCP_SEQ_GEQ(full_dack, mp_tp->mpt_snduna)) {
1198*33de042dSApple OSS Distributions 		mptcp_data_ack_rcvd(mp_tp, tp, full_dack);
1199*33de042dSApple OSS Distributions 		if (mp_tp->mpt_state > MPTCPS_FIN_WAIT_2) {
1200*33de042dSApple OSS Distributions 			close_notify = 1;
1201*33de042dSApple OSS Distributions 		}
1202*33de042dSApple OSS Distributions 		if (mp_tp->mpt_flags & MPTCPF_RCVD_64BITACK) {
1203*33de042dSApple OSS Distributions 			mp_tp->mpt_flags &= ~MPTCPF_RCVD_64BITACK;
1204*33de042dSApple OSS Distributions 			mp_tp->mpt_flags &= ~MPTCPF_SND_64BITDSN;
1205*33de042dSApple OSS Distributions 		}
1206*33de042dSApple OSS Distributions 		mptcp_notify_mpready(tp->t_inpcb->inp_socket);
1207*33de042dSApple OSS Distributions 		if (close_notify) {
1208*33de042dSApple OSS Distributions 			mptcp_notify_close(tp->t_inpcb->inp_socket);
1209*33de042dSApple OSS Distributions 		}
1210*33de042dSApple OSS Distributions 	}
1211*33de042dSApple OSS Distributions 
1212*33de042dSApple OSS Distributions 	mptcp_update_window(mp_tp, full_dack, full_dsn, tiwin);
1213*33de042dSApple OSS Distributions }
1214*33de042dSApple OSS Distributions 
1215*33de042dSApple OSS Distributions static void
mptcp_do_dss_opt_meat(u_char * cp,struct tcpcb * tp,struct tcphdr * th)1216*33de042dSApple OSS Distributions mptcp_do_dss_opt_meat(u_char *cp, struct tcpcb *tp, struct tcphdr *th)
1217*33de042dSApple OSS Distributions {
1218*33de042dSApple OSS Distributions 	struct mptcp_dss_copt *dss_rsp = (struct mptcp_dss_copt *)cp;
1219*33de042dSApple OSS Distributions 	u_int64_t full_dack = 0;
1220*33de042dSApple OSS Distributions 	u_int32_t tiwin = th->th_win << tp->snd_scale;
1221*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1222*33de042dSApple OSS Distributions 	int csum_len = 0;
1223*33de042dSApple OSS Distributions 
1224*33de042dSApple OSS Distributions #define MPTCP_DSS_OPT_SZ_CHK(len, expected_len) {                                 \
1225*33de042dSApple OSS Distributions 	if (len != expected_len) {                                                \
1226*33de042dSApple OSS Distributions 	        os_log_error(mptcp_log_handle, "%s - %lx: bad len = %d dss: %x\n",\
1227*33de042dSApple OSS Distributions 	            __func__, (unsigned long)VM_KERNEL_ADDRPERM(mp_tp->mpt_mpte), \
1228*33de042dSApple OSS Distributions 	            len, dss_rsp->mdss_flags);                                    \
1229*33de042dSApple OSS Distributions 	        return;                                                           \
1230*33de042dSApple OSS Distributions 	}                                                                         \
1231*33de042dSApple OSS Distributions }
1232*33de042dSApple OSS Distributions 
1233*33de042dSApple OSS Distributions 	if (mp_tp->mpt_flags & MPTCPF_CHECKSUM) {
1234*33de042dSApple OSS Distributions 		csum_len = 2;
1235*33de042dSApple OSS Distributions 	}
1236*33de042dSApple OSS Distributions 
1237*33de042dSApple OSS Distributions 	dss_rsp->mdss_flags &= (MDSS_A | MDSS_a | MDSS_M | MDSS_m);
1238*33de042dSApple OSS Distributions 	switch (dss_rsp->mdss_flags) {
1239*33de042dSApple OSS Distributions 	case (MDSS_M):
1240*33de042dSApple OSS Distributions 	{
1241*33de042dSApple OSS Distributions 		/* 32-bit DSS, No Data ACK */
1242*33de042dSApple OSS Distributions 		struct mptcp_dsn_opt *dss_rsp1;
1243*33de042dSApple OSS Distributions 		dss_rsp1 = (struct mptcp_dsn_opt *)cp;
1244*33de042dSApple OSS Distributions 
1245*33de042dSApple OSS Distributions 		MPTCP_DSS_OPT_SZ_CHK(dss_rsp1->mdss_copt.mdss_len,
1246*33de042dSApple OSS Distributions 		    sizeof(struct mptcp_dsn_opt) + csum_len);
1247*33de042dSApple OSS Distributions 		if (csum_len == 0) {
1248*33de042dSApple OSS Distributions 			mptcp_update_dss_rcv_state(dss_rsp1, tp, 0);
1249*33de042dSApple OSS Distributions 		} else {
1250*33de042dSApple OSS Distributions 			mptcp_update_dss_rcv_state(dss_rsp1, tp,
1251*33de042dSApple OSS Distributions 			    *(uint16_t *)(void *)(cp +
1252*33de042dSApple OSS Distributions 			    (dss_rsp1->mdss_copt.mdss_len - csum_len)));
1253*33de042dSApple OSS Distributions 		}
1254*33de042dSApple OSS Distributions 		break;
1255*33de042dSApple OSS Distributions 	}
1256*33de042dSApple OSS Distributions 	case (MDSS_A):
1257*33de042dSApple OSS Distributions 	{
1258*33de042dSApple OSS Distributions 		/* 32-bit Data ACK, no DSS */
1259*33de042dSApple OSS Distributions 		struct mptcp_data_ack_opt *dack_opt;
1260*33de042dSApple OSS Distributions 		dack_opt = (struct mptcp_data_ack_opt *)cp;
1261*33de042dSApple OSS Distributions 
1262*33de042dSApple OSS Distributions 		MPTCP_DSS_OPT_SZ_CHK(dack_opt->mdss_copt.mdss_len,
1263*33de042dSApple OSS Distributions 		    sizeof(struct mptcp_data_ack_opt));
1264*33de042dSApple OSS Distributions 
1265*33de042dSApple OSS Distributions 		u_int32_t dack = dack_opt->mdss_ack;
1266*33de042dSApple OSS Distributions 		NTOHL(dack);
1267*33de042dSApple OSS Distributions 		MPTCP_EXTEND_DSN(mp_tp->mpt_snduna, dack, full_dack);
1268*33de042dSApple OSS Distributions 		mptcp_do_dss_opt_ack_meat(full_dack, mp_tp->mpt_sndwl1, tp, tiwin);
1269*33de042dSApple OSS Distributions 		break;
1270*33de042dSApple OSS Distributions 	}
1271*33de042dSApple OSS Distributions 	case (MDSS_M | MDSS_A):
1272*33de042dSApple OSS Distributions 	{
1273*33de042dSApple OSS Distributions 		/* 32-bit Data ACK + 32-bit DSS */
1274*33de042dSApple OSS Distributions 		struct mptcp_dss_ack_opt *dss_ack_rsp;
1275*33de042dSApple OSS Distributions 		dss_ack_rsp = (struct mptcp_dss_ack_opt *)cp;
1276*33de042dSApple OSS Distributions 		u_int64_t full_dsn;
1277*33de042dSApple OSS Distributions 		uint16_t csum = 0;
1278*33de042dSApple OSS Distributions 
1279*33de042dSApple OSS Distributions 		MPTCP_DSS_OPT_SZ_CHK(dss_ack_rsp->mdss_copt.mdss_len,
1280*33de042dSApple OSS Distributions 		    sizeof(struct mptcp_dss_ack_opt) + csum_len);
1281*33de042dSApple OSS Distributions 
1282*33de042dSApple OSS Distributions 		u_int32_t dack = dss_ack_rsp->mdss_ack;
1283*33de042dSApple OSS Distributions 		NTOHL(dack);
1284*33de042dSApple OSS Distributions 		MPTCP_EXTEND_DSN(mp_tp->mpt_snduna, dack, full_dack);
1285*33de042dSApple OSS Distributions 
1286*33de042dSApple OSS Distributions 		NTOHL(dss_ack_rsp->mdss_dsn);
1287*33de042dSApple OSS Distributions 		NTOHL(dss_ack_rsp->mdss_subflow_seqn);
1288*33de042dSApple OSS Distributions 		NTOHS(dss_ack_rsp->mdss_data_len);
1289*33de042dSApple OSS Distributions 		MPTCP_EXTEND_DSN(mp_tp->mpt_rcvnxt, dss_ack_rsp->mdss_dsn, full_dsn);
1290*33de042dSApple OSS Distributions 
1291*33de042dSApple OSS Distributions 		mptcp_do_dss_opt_ack_meat(full_dack, full_dsn, tp, tiwin);
1292*33de042dSApple OSS Distributions 
1293*33de042dSApple OSS Distributions 		if (csum_len != 0) {
1294*33de042dSApple OSS Distributions 			csum = *(uint16_t *)(void *)(cp + (dss_ack_rsp->mdss_copt.mdss_len - csum_len));
1295*33de042dSApple OSS Distributions 		}
1296*33de042dSApple OSS Distributions 
1297*33de042dSApple OSS Distributions 		mptcp_update_rcv_state_meat(mp_tp, tp,
1298*33de042dSApple OSS Distributions 		    full_dsn,
1299*33de042dSApple OSS Distributions 		    dss_ack_rsp->mdss_subflow_seqn,
1300*33de042dSApple OSS Distributions 		    dss_ack_rsp->mdss_data_len,
1301*33de042dSApple OSS Distributions 		    csum);
1302*33de042dSApple OSS Distributions 		break;
1303*33de042dSApple OSS Distributions 	}
1304*33de042dSApple OSS Distributions 	case (MDSS_M | MDSS_m):
1305*33de042dSApple OSS Distributions 	{
1306*33de042dSApple OSS Distributions 		/* 64-bit DSS , No Data ACK */
1307*33de042dSApple OSS Distributions 		struct mptcp_dsn64_opt *dsn64;
1308*33de042dSApple OSS Distributions 		dsn64 = (struct mptcp_dsn64_opt *)cp;
1309*33de042dSApple OSS Distributions 		u_int64_t full_dsn;
1310*33de042dSApple OSS Distributions 		uint16_t csum = 0;
1311*33de042dSApple OSS Distributions 
1312*33de042dSApple OSS Distributions 		MPTCP_DSS_OPT_SZ_CHK(dsn64->mdss_copt.mdss_len,
1313*33de042dSApple OSS Distributions 		    sizeof(struct mptcp_dsn64_opt) + csum_len);
1314*33de042dSApple OSS Distributions 
1315*33de042dSApple OSS Distributions 		mp_tp->mpt_flags |= MPTCPF_SND_64BITACK;
1316*33de042dSApple OSS Distributions 
1317*33de042dSApple OSS Distributions 		full_dsn = mptcp_ntoh64(dsn64->mdss_dsn);
1318*33de042dSApple OSS Distributions 		NTOHL(dsn64->mdss_subflow_seqn);
1319*33de042dSApple OSS Distributions 		NTOHS(dsn64->mdss_data_len);
1320*33de042dSApple OSS Distributions 
1321*33de042dSApple OSS Distributions 		if (csum_len != 0) {
1322*33de042dSApple OSS Distributions 			csum = *(uint16_t *)(void *)(cp + dsn64->mdss_copt.mdss_len - csum_len);
1323*33de042dSApple OSS Distributions 		}
1324*33de042dSApple OSS Distributions 
1325*33de042dSApple OSS Distributions 		mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn,
1326*33de042dSApple OSS Distributions 		    dsn64->mdss_subflow_seqn,
1327*33de042dSApple OSS Distributions 		    dsn64->mdss_data_len,
1328*33de042dSApple OSS Distributions 		    csum);
1329*33de042dSApple OSS Distributions 		break;
1330*33de042dSApple OSS Distributions 	}
1331*33de042dSApple OSS Distributions 	case (MDSS_A | MDSS_a):
1332*33de042dSApple OSS Distributions 	{
1333*33de042dSApple OSS Distributions 		/* 64-bit Data ACK, no DSS */
1334*33de042dSApple OSS Distributions 		struct mptcp_data_ack64_opt *dack64;
1335*33de042dSApple OSS Distributions 		dack64 = (struct mptcp_data_ack64_opt *)cp;
1336*33de042dSApple OSS Distributions 
1337*33de042dSApple OSS Distributions 		MPTCP_DSS_OPT_SZ_CHK(dack64->mdss_copt.mdss_len,
1338*33de042dSApple OSS Distributions 		    sizeof(struct mptcp_data_ack64_opt));
1339*33de042dSApple OSS Distributions 
1340*33de042dSApple OSS Distributions 		mp_tp->mpt_flags |= MPTCPF_RCVD_64BITACK;
1341*33de042dSApple OSS Distributions 
1342*33de042dSApple OSS Distributions 		full_dack = mptcp_ntoh64(dack64->mdss_ack);
1343*33de042dSApple OSS Distributions 		mptcp_do_dss_opt_ack_meat(full_dack, mp_tp->mpt_sndwl1, tp, tiwin);
1344*33de042dSApple OSS Distributions 		break;
1345*33de042dSApple OSS Distributions 	}
1346*33de042dSApple OSS Distributions 	case (MDSS_M | MDSS_m | MDSS_A):
1347*33de042dSApple OSS Distributions 	{
1348*33de042dSApple OSS Distributions 		/* 64-bit DSS + 32-bit Data ACK */
1349*33de042dSApple OSS Distributions 		struct mptcp_dss64_ack32_opt *dss_ack_rsp;
1350*33de042dSApple OSS Distributions 		dss_ack_rsp = (struct mptcp_dss64_ack32_opt *)cp;
1351*33de042dSApple OSS Distributions 		u_int64_t full_dsn;
1352*33de042dSApple OSS Distributions 		uint16_t csum = 0;
1353*33de042dSApple OSS Distributions 
1354*33de042dSApple OSS Distributions 		MPTCP_DSS_OPT_SZ_CHK(dss_ack_rsp->mdss_copt.mdss_len,
1355*33de042dSApple OSS Distributions 		    sizeof(struct mptcp_dss64_ack32_opt) + csum_len);
1356*33de042dSApple OSS Distributions 
1357*33de042dSApple OSS Distributions 		u_int32_t dack = dss_ack_rsp->mdss_ack;
1358*33de042dSApple OSS Distributions 		NTOHL(dack);
1359*33de042dSApple OSS Distributions 		mp_tp->mpt_flags |= MPTCPF_SND_64BITACK;
1360*33de042dSApple OSS Distributions 		MPTCP_EXTEND_DSN(mp_tp->mpt_snduna, dack, full_dack);
1361*33de042dSApple OSS Distributions 
1362*33de042dSApple OSS Distributions 		full_dsn = mptcp_ntoh64(dss_ack_rsp->mdss_dsn);
1363*33de042dSApple OSS Distributions 		NTOHL(dss_ack_rsp->mdss_subflow_seqn);
1364*33de042dSApple OSS Distributions 		NTOHS(dss_ack_rsp->mdss_data_len);
1365*33de042dSApple OSS Distributions 
1366*33de042dSApple OSS Distributions 		mptcp_do_dss_opt_ack_meat(full_dack, full_dsn, tp, tiwin);
1367*33de042dSApple OSS Distributions 
1368*33de042dSApple OSS Distributions 		if (csum_len != 0) {
1369*33de042dSApple OSS Distributions 			csum = *(uint16_t *)(void *)(cp + dss_ack_rsp->mdss_copt.mdss_len - csum_len);
1370*33de042dSApple OSS Distributions 		}
1371*33de042dSApple OSS Distributions 
1372*33de042dSApple OSS Distributions 		mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn,
1373*33de042dSApple OSS Distributions 		    dss_ack_rsp->mdss_subflow_seqn,
1374*33de042dSApple OSS Distributions 		    dss_ack_rsp->mdss_data_len,
1375*33de042dSApple OSS Distributions 		    csum);
1376*33de042dSApple OSS Distributions 
1377*33de042dSApple OSS Distributions 		break;
1378*33de042dSApple OSS Distributions 	}
1379*33de042dSApple OSS Distributions 	case (MDSS_M | MDSS_A | MDSS_a):
1380*33de042dSApple OSS Distributions 	{
1381*33de042dSApple OSS Distributions 		/* 32-bit DSS + 64-bit Data ACK */
1382*33de042dSApple OSS Distributions 		struct mptcp_dss32_ack64_opt *dss32_ack64_opt;
1383*33de042dSApple OSS Distributions 		dss32_ack64_opt = (struct mptcp_dss32_ack64_opt *)cp;
1384*33de042dSApple OSS Distributions 		u_int64_t full_dsn;
1385*33de042dSApple OSS Distributions 
1386*33de042dSApple OSS Distributions 		MPTCP_DSS_OPT_SZ_CHK(
1387*33de042dSApple OSS Distributions 			dss32_ack64_opt->mdss_copt.mdss_len,
1388*33de042dSApple OSS Distributions 			sizeof(struct mptcp_dss32_ack64_opt) + csum_len);
1389*33de042dSApple OSS Distributions 
1390*33de042dSApple OSS Distributions 		full_dack = mptcp_ntoh64(dss32_ack64_opt->mdss_ack);
1391*33de042dSApple OSS Distributions 		NTOHL(dss32_ack64_opt->mdss_dsn);
1392*33de042dSApple OSS Distributions 		mp_tp->mpt_flags |= MPTCPF_RCVD_64BITACK;
1393*33de042dSApple OSS Distributions 		MPTCP_EXTEND_DSN(mp_tp->mpt_rcvnxt,
1394*33de042dSApple OSS Distributions 		    dss32_ack64_opt->mdss_dsn, full_dsn);
1395*33de042dSApple OSS Distributions 		NTOHL(dss32_ack64_opt->mdss_subflow_seqn);
1396*33de042dSApple OSS Distributions 		NTOHS(dss32_ack64_opt->mdss_data_len);
1397*33de042dSApple OSS Distributions 
1398*33de042dSApple OSS Distributions 		mptcp_do_dss_opt_ack_meat(full_dack, full_dsn, tp, tiwin);
1399*33de042dSApple OSS Distributions 		if (csum_len == 0) {
1400*33de042dSApple OSS Distributions 			mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn,
1401*33de042dSApple OSS Distributions 			    dss32_ack64_opt->mdss_subflow_seqn,
1402*33de042dSApple OSS Distributions 			    dss32_ack64_opt->mdss_data_len, 0);
1403*33de042dSApple OSS Distributions 		} else {
1404*33de042dSApple OSS Distributions 			mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn,
1405*33de042dSApple OSS Distributions 			    dss32_ack64_opt->mdss_subflow_seqn,
1406*33de042dSApple OSS Distributions 			    dss32_ack64_opt->mdss_data_len,
1407*33de042dSApple OSS Distributions 			    *(uint16_t *)(void *)(cp +
1408*33de042dSApple OSS Distributions 			    dss32_ack64_opt->mdss_copt.mdss_len -
1409*33de042dSApple OSS Distributions 			    csum_len));
1410*33de042dSApple OSS Distributions 		}
1411*33de042dSApple OSS Distributions 		break;
1412*33de042dSApple OSS Distributions 	}
1413*33de042dSApple OSS Distributions 	case (MDSS_M | MDSS_m | MDSS_A | MDSS_a):
1414*33de042dSApple OSS Distributions 	{
1415*33de042dSApple OSS Distributions 		/* 64-bit DSS + 64-bit Data ACK */
1416*33de042dSApple OSS Distributions 		struct mptcp_dss64_ack64_opt *dss64_ack64;
1417*33de042dSApple OSS Distributions 		dss64_ack64 = (struct mptcp_dss64_ack64_opt *)cp;
1418*33de042dSApple OSS Distributions 		u_int64_t full_dsn;
1419*33de042dSApple OSS Distributions 
1420*33de042dSApple OSS Distributions 		MPTCP_DSS_OPT_SZ_CHK(dss64_ack64->mdss_copt.mdss_len,
1421*33de042dSApple OSS Distributions 		    sizeof(struct mptcp_dss64_ack64_opt) + csum_len);
1422*33de042dSApple OSS Distributions 
1423*33de042dSApple OSS Distributions 		mp_tp->mpt_flags |= MPTCPF_RCVD_64BITACK;
1424*33de042dSApple OSS Distributions 		mp_tp->mpt_flags |= MPTCPF_SND_64BITACK;
1425*33de042dSApple OSS Distributions 		full_dsn = mptcp_ntoh64(dss64_ack64->mdss_dsn);
1426*33de042dSApple OSS Distributions 		full_dack = mptcp_ntoh64(dss64_ack64->mdss_dsn);
1427*33de042dSApple OSS Distributions 		mptcp_do_dss_opt_ack_meat(full_dack, full_dsn, tp, tiwin);
1428*33de042dSApple OSS Distributions 		NTOHL(dss64_ack64->mdss_subflow_seqn);
1429*33de042dSApple OSS Distributions 		NTOHS(dss64_ack64->mdss_data_len);
1430*33de042dSApple OSS Distributions 		if (csum_len == 0) {
1431*33de042dSApple OSS Distributions 			mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn,
1432*33de042dSApple OSS Distributions 			    dss64_ack64->mdss_subflow_seqn,
1433*33de042dSApple OSS Distributions 			    dss64_ack64->mdss_data_len, 0);
1434*33de042dSApple OSS Distributions 		} else {
1435*33de042dSApple OSS Distributions 			mptcp_update_rcv_state_meat(mp_tp, tp, full_dsn,
1436*33de042dSApple OSS Distributions 			    dss64_ack64->mdss_subflow_seqn,
1437*33de042dSApple OSS Distributions 			    dss64_ack64->mdss_data_len,
1438*33de042dSApple OSS Distributions 			    *(uint16_t *)(void *)(cp +
1439*33de042dSApple OSS Distributions 			    dss64_ack64->mdss_copt.mdss_len -
1440*33de042dSApple OSS Distributions 			    csum_len));
1441*33de042dSApple OSS Distributions 		}
1442*33de042dSApple OSS Distributions 		break;
1443*33de042dSApple OSS Distributions 	}
1444*33de042dSApple OSS Distributions 	default:
1445*33de042dSApple OSS Distributions 		break;
1446*33de042dSApple OSS Distributions 	}
1447*33de042dSApple OSS Distributions }
1448*33de042dSApple OSS Distributions 
1449*33de042dSApple OSS Distributions static void
mptcp_do_dss_opt(struct tcpcb * tp,u_char * cp,struct tcphdr * th)1450*33de042dSApple OSS Distributions mptcp_do_dss_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th)
1451*33de042dSApple OSS Distributions {
1452*33de042dSApple OSS Distributions 	struct mptcp_dss_copt *dss_rsp = (struct mptcp_dss_copt *)cp;
1453*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1454*33de042dSApple OSS Distributions 
1455*33de042dSApple OSS Distributions 	if (!mp_tp) {
1456*33de042dSApple OSS Distributions 		return;
1457*33de042dSApple OSS Distributions 	}
1458*33de042dSApple OSS Distributions 
1459*33de042dSApple OSS Distributions 	if (dss_rsp->mdss_subtype == MPO_DSS) {
1460*33de042dSApple OSS Distributions 		if (dss_rsp->mdss_flags & MDSS_F) {
1461*33de042dSApple OSS Distributions 			tp->t_rcv_map.mpt_dfin = 1;
1462*33de042dSApple OSS Distributions 		} else {
1463*33de042dSApple OSS Distributions 			tp->t_rcv_map.mpt_dfin = 0;
1464*33de042dSApple OSS Distributions 		}
1465*33de042dSApple OSS Distributions 
1466*33de042dSApple OSS Distributions 		mptcp_do_dss_opt_meat(cp, tp, th);
1467*33de042dSApple OSS Distributions 	}
1468*33de042dSApple OSS Distributions }
1469*33de042dSApple OSS Distributions 
1470*33de042dSApple OSS Distributions static void
mptcp_do_fastclose_opt(struct tcpcb * tp,u_char * cp,struct tcphdr * th)1471*33de042dSApple OSS Distributions mptcp_do_fastclose_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th)
1472*33de042dSApple OSS Distributions {
1473*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = NULL;
1474*33de042dSApple OSS Distributions 	struct mptcp_fastclose_opt *fc_opt = (struct mptcp_fastclose_opt *)cp;
1475*33de042dSApple OSS Distributions 
1476*33de042dSApple OSS Distributions 	if (th->th_flags != TH_ACK) {
1477*33de042dSApple OSS Distributions 		return;
1478*33de042dSApple OSS Distributions 	}
1479*33de042dSApple OSS Distributions 
1480*33de042dSApple OSS Distributions 	if (fc_opt->mfast_len != sizeof(struct mptcp_fastclose_opt)) {
1481*33de042dSApple OSS Distributions 		tcpstat.tcps_invalid_opt++;
1482*33de042dSApple OSS Distributions 		return;
1483*33de042dSApple OSS Distributions 	}
1484*33de042dSApple OSS Distributions 
1485*33de042dSApple OSS Distributions 	mp_tp = tptomptp(tp);
1486*33de042dSApple OSS Distributions 	if (!mp_tp) {
1487*33de042dSApple OSS Distributions 		return;
1488*33de042dSApple OSS Distributions 	}
1489*33de042dSApple OSS Distributions 
1490*33de042dSApple OSS Distributions 	if (fc_opt->mfast_key != mp_tp->mpt_localkey) {
1491*33de042dSApple OSS Distributions 		tcpstat.tcps_invalid_opt++;
1492*33de042dSApple OSS Distributions 		return;
1493*33de042dSApple OSS Distributions 	}
1494*33de042dSApple OSS Distributions 
1495*33de042dSApple OSS Distributions 	/*
1496*33de042dSApple OSS Distributions 	 * fastclose could make us more vulnerable to attacks, hence
1497*33de042dSApple OSS Distributions 	 * accept only those that are at the next expected sequence number.
1498*33de042dSApple OSS Distributions 	 */
1499*33de042dSApple OSS Distributions 	if (th->th_seq != tp->rcv_nxt) {
1500*33de042dSApple OSS Distributions 		tcpstat.tcps_invalid_opt++;
1501*33de042dSApple OSS Distributions 		return;
1502*33de042dSApple OSS Distributions 	}
1503*33de042dSApple OSS Distributions 
1504*33de042dSApple OSS Distributions 	/* Reset this flow */
1505*33de042dSApple OSS Distributions 	tp->t_mpflags |= TMPF_FASTCLOSERCV;
1506*33de042dSApple OSS Distributions 
1507*33de042dSApple OSS Distributions 	if (tp->t_inpcb->inp_socket != NULL) {
1508*33de042dSApple OSS Distributions 		soevent(tp->t_inpcb->inp_socket,
1509*33de042dSApple OSS Distributions 		    SO_FILT_HINT_LOCKED | SO_FILT_HINT_MUSTRST);
1510*33de042dSApple OSS Distributions 	}
1511*33de042dSApple OSS Distributions }
1512*33de042dSApple OSS Distributions 
1513*33de042dSApple OSS Distributions 
1514*33de042dSApple OSS Distributions static void
mptcp_do_mpfail_opt(struct tcpcb * tp,u_char * cp,struct tcphdr * th)1515*33de042dSApple OSS Distributions mptcp_do_mpfail_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th)
1516*33de042dSApple OSS Distributions {
1517*33de042dSApple OSS Distributions 	struct mptcp_mpfail_opt *fail_opt = (struct mptcp_mpfail_opt *)cp;
1518*33de042dSApple OSS Distributions 	u_int32_t mdss_subflow_seqn = 0;
1519*33de042dSApple OSS Distributions 	struct mptcb *mp_tp;
1520*33de042dSApple OSS Distributions 	int error = 0;
1521*33de042dSApple OSS Distributions 
1522*33de042dSApple OSS Distributions 	/*
1523*33de042dSApple OSS Distributions 	 * mpfail could make us more vulnerable to attacks. Hence accept
1524*33de042dSApple OSS Distributions 	 * only those that are the next expected sequence number.
1525*33de042dSApple OSS Distributions 	 */
1526*33de042dSApple OSS Distributions 	if (th->th_seq != tp->rcv_nxt) {
1527*33de042dSApple OSS Distributions 		tcpstat.tcps_invalid_opt++;
1528*33de042dSApple OSS Distributions 		return;
1529*33de042dSApple OSS Distributions 	}
1530*33de042dSApple OSS Distributions 
1531*33de042dSApple OSS Distributions 	/* A packet without RST, must atleast have the ACK bit set */
1532*33de042dSApple OSS Distributions 	if ((th->th_flags != TH_ACK) && (th->th_flags != TH_RST)) {
1533*33de042dSApple OSS Distributions 		return;
1534*33de042dSApple OSS Distributions 	}
1535*33de042dSApple OSS Distributions 
1536*33de042dSApple OSS Distributions 	if (fail_opt->mfail_len != sizeof(struct mptcp_mpfail_opt)) {
1537*33de042dSApple OSS Distributions 		return;
1538*33de042dSApple OSS Distributions 	}
1539*33de042dSApple OSS Distributions 
1540*33de042dSApple OSS Distributions 	mp_tp = tptomptp(tp);
1541*33de042dSApple OSS Distributions 
1542*33de042dSApple OSS Distributions 	mp_tp->mpt_flags |= MPTCPF_RECVD_MPFAIL;
1543*33de042dSApple OSS Distributions 	mp_tp->mpt_dsn_at_csum_fail = mptcp_hton64(fail_opt->mfail_dsn);
1544*33de042dSApple OSS Distributions 	error = mptcp_get_map_for_dsn(tp->t_inpcb->inp_socket,
1545*33de042dSApple OSS Distributions 	    mp_tp->mpt_dsn_at_csum_fail, &mdss_subflow_seqn);
1546*33de042dSApple OSS Distributions 	if (error == 0) {
1547*33de042dSApple OSS Distributions 		mp_tp->mpt_ssn_at_csum_fail = mdss_subflow_seqn;
1548*33de042dSApple OSS Distributions 	}
1549*33de042dSApple OSS Distributions 
1550*33de042dSApple OSS Distributions 	mptcp_notify_mpfail(tp->t_inpcb->inp_socket);
1551*33de042dSApple OSS Distributions }
1552*33de042dSApple OSS Distributions 
1553*33de042dSApple OSS Distributions static boolean_t
mptcp_validate_add_addr_hmac(struct tcpcb * tp,u_char * hmac,u_char * msg,uint16_t msg_len,uint16_t mac_len)1554*33de042dSApple OSS Distributions mptcp_validate_add_addr_hmac(struct tcpcb *tp, u_char *hmac,
1555*33de042dSApple OSS Distributions     u_char *msg, uint16_t msg_len, uint16_t mac_len)
1556*33de042dSApple OSS Distributions {
1557*33de042dSApple OSS Distributions 	u_char digest[SHA256_DIGEST_LENGTH] = {0};
1558*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1559*33de042dSApple OSS Distributions 
1560*33de042dSApple OSS Distributions 	VERIFY(mac_len <= SHA256_DIGEST_LENGTH);
1561*33de042dSApple OSS Distributions 	mptcp_hmac_sha256(mp_tp->mpt_remotekey, mp_tp->mpt_localkey, msg, msg_len, digest);
1562*33de042dSApple OSS Distributions 
1563*33de042dSApple OSS Distributions 	if (bcmp(digest + SHA256_DIGEST_LENGTH - mac_len, hmac, mac_len) == 0) {
1564*33de042dSApple OSS Distributions 		return true; /* matches */
1565*33de042dSApple OSS Distributions 	} else {
1566*33de042dSApple OSS Distributions 		return false;
1567*33de042dSApple OSS Distributions 	}
1568*33de042dSApple OSS Distributions }
1569*33de042dSApple OSS Distributions 
1570*33de042dSApple OSS Distributions static void
mptcp_do_add_addr_opt_v1(struct tcpcb * tp,u_char * cp)1571*33de042dSApple OSS Distributions mptcp_do_add_addr_opt_v1(struct tcpcb *tp, u_char *cp)
1572*33de042dSApple OSS Distributions {
1573*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1574*33de042dSApple OSS Distributions 	struct mptses *mpte = mp_tp->mpt_mpte;
1575*33de042dSApple OSS Distributions 
1576*33de042dSApple OSS Distributions 	struct mptcp_add_addr_opt *addr_opt = (struct mptcp_add_addr_opt *)cp;
1577*33de042dSApple OSS Distributions 
1578*33de042dSApple OSS Distributions 	if (addr_opt->maddr_len != MPTCP_V1_ADD_ADDR_OPT_LEN_V4 &&
1579*33de042dSApple OSS Distributions 	    addr_opt->maddr_len != MPTCP_V1_ADD_ADDR_OPT_LEN_V4 + 2 &&
1580*33de042dSApple OSS Distributions 	    addr_opt->maddr_len != MPTCP_V1_ADD_ADDR_OPT_LEN_V6 &&
1581*33de042dSApple OSS Distributions 	    addr_opt->maddr_len != MPTCP_V1_ADD_ADDR_OPT_LEN_V6 + 2) {
1582*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: Wrong ADD_ADDR length %u\n",
1583*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1584*33de042dSApple OSS Distributions 		    addr_opt->maddr_len);
1585*33de042dSApple OSS Distributions 
1586*33de042dSApple OSS Distributions 		return;
1587*33de042dSApple OSS Distributions 	}
1588*33de042dSApple OSS Distributions 
1589*33de042dSApple OSS Distributions 	if ((addr_opt->maddr_flags & MPTCP_V1_ADD_ADDR_ECHO) != 0) {
1590*33de042dSApple OSS Distributions 		os_log(mptcp_log_handle, "%s - %lx: Received ADD_ADDR with echo bit\n",
1591*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte));
1592*33de042dSApple OSS Distributions 
1593*33de042dSApple OSS Distributions 		return;
1594*33de042dSApple OSS Distributions 	}
1595*33de042dSApple OSS Distributions 
1596*33de042dSApple OSS Distributions 	if (addr_opt->maddr_len < MPTCP_V1_ADD_ADDR_OPT_LEN_V6) {
1597*33de042dSApple OSS Distributions 		struct sockaddr_in *dst = &mpte->mpte_sub_dst_v4;
1598*33de042dSApple OSS Distributions 		struct in_addr *addr = &addr_opt->maddr_u.maddr_addrv4;
1599*33de042dSApple OSS Distributions 		in_addr_t haddr = ntohl(addr->s_addr);
1600*33de042dSApple OSS Distributions 
1601*33de042dSApple OSS Distributions 		if (IN_ZERONET(haddr) ||
1602*33de042dSApple OSS Distributions 		    IN_LOOPBACK(haddr) ||
1603*33de042dSApple OSS Distributions 		    IN_LINKLOCAL(haddr) ||
1604*33de042dSApple OSS Distributions 		    IN_DS_LITE(haddr) ||
1605*33de042dSApple OSS Distributions 		    IN_6TO4_RELAY_ANYCAST(haddr) ||
1606*33de042dSApple OSS Distributions 		    IN_MULTICAST(haddr) ||
1607*33de042dSApple OSS Distributions 		    INADDR_BROADCAST == haddr ||
1608*33de042dSApple OSS Distributions 		    IN_PRIVATE(haddr) ||
1609*33de042dSApple OSS Distributions 		    IN_SHARED_ADDRESS_SPACE(haddr)) {
1610*33de042dSApple OSS Distributions 			os_log_error(mptcp_log_handle, "%s - %lx: ADD_ADDR invalid addr: %x\n",
1611*33de042dSApple OSS Distributions 			    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1612*33de042dSApple OSS Distributions 			    addr->s_addr);
1613*33de042dSApple OSS Distributions 
1614*33de042dSApple OSS Distributions 			return;
1615*33de042dSApple OSS Distributions 		}
1616*33de042dSApple OSS Distributions 
1617*33de042dSApple OSS Distributions 		u_char *hmac = (void *)(cp + addr_opt->maddr_len - HMAC_TRUNCATED_ADD_ADDR);
1618*33de042dSApple OSS Distributions 		uint16_t msg_len = sizeof(struct mptcp_add_addr_hmac_msg_v4);
1619*33de042dSApple OSS Distributions 		struct mptcp_add_addr_hmac_msg_v4 msg  = {0};
1620*33de042dSApple OSS Distributions 		msg.maddr_addrid = addr_opt->maddr_addrid;
1621*33de042dSApple OSS Distributions 		msg.maddr_addr = addr_opt->maddr_u.maddr_addrv4;
1622*33de042dSApple OSS Distributions 		if (addr_opt->maddr_len > MPTCP_V1_ADD_ADDR_OPT_LEN_V4) {
1623*33de042dSApple OSS Distributions 			msg.maddr_port = *(uint16_t *)(void *)(cp + addr_opt->maddr_len - HMAC_TRUNCATED_ADD_ADDR - 2);
1624*33de042dSApple OSS Distributions 		}
1625*33de042dSApple OSS Distributions 		if (!mptcp_validate_add_addr_hmac(tp, hmac, (u_char *)&msg, msg_len, HMAC_TRUNCATED_ADD_ADDR)) {
1626*33de042dSApple OSS Distributions 			os_log_error(mptcp_log_handle, "%s - %lx: ADD_ADDR addr: %x invalid HMAC\n",
1627*33de042dSApple OSS Distributions 			    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1628*33de042dSApple OSS Distributions 			    addr->s_addr);
1629*33de042dSApple OSS Distributions 			return;
1630*33de042dSApple OSS Distributions 		}
1631*33de042dSApple OSS Distributions 
1632*33de042dSApple OSS Distributions 		dst->sin_len = sizeof(*dst);
1633*33de042dSApple OSS Distributions 		dst->sin_family = AF_INET;
1634*33de042dSApple OSS Distributions 		if (addr_opt->maddr_len > MPTCP_V1_ADD_ADDR_OPT_LEN_V4) {
1635*33de042dSApple OSS Distributions 			dst->sin_port = *(uint16_t *)(void *)(cp + addr_opt->maddr_len - HMAC_TRUNCATED_ADD_ADDR - 2);
1636*33de042dSApple OSS Distributions 		} else {
1637*33de042dSApple OSS Distributions 			dst->sin_port = mpte->__mpte_dst_v4.sin_port;
1638*33de042dSApple OSS Distributions 		}
1639*33de042dSApple OSS Distributions 		dst->sin_addr.s_addr = addr->s_addr;
1640*33de042dSApple OSS Distributions 		mpte->sub_dst_addr_id_v4 = addr_opt->maddr_addrid;
1641*33de042dSApple OSS Distributions 		mpte->mpte_last_added_addr_is_v4 = TRUE;
1642*33de042dSApple OSS Distributions 	} else {
1643*33de042dSApple OSS Distributions 		struct sockaddr_in6 *dst = &mpte->mpte_sub_dst_v6;
1644*33de042dSApple OSS Distributions 		struct in6_addr *addr = &addr_opt->maddr_u.maddr_addrv6;
1645*33de042dSApple OSS Distributions 
1646*33de042dSApple OSS Distributions 		if (IN6_IS_ADDR_LINKLOCAL(addr) ||
1647*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_MULTICAST(addr) ||
1648*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_UNSPECIFIED(addr) ||
1649*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_LOOPBACK(addr) ||
1650*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_V4COMPAT(addr) ||
1651*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_V4MAPPED(addr)) {
1652*33de042dSApple OSS Distributions 			char dbuf[MAX_IPv6_STR_LEN];
1653*33de042dSApple OSS Distributions 
1654*33de042dSApple OSS Distributions 			inet_ntop(AF_INET6, addr, dbuf, sizeof(dbuf));
1655*33de042dSApple OSS Distributions 			os_log_error(mptcp_log_handle, "%s - %lx: ADD_ADDRv6 invalid addr: %s\n",
1656*33de042dSApple OSS Distributions 			    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1657*33de042dSApple OSS Distributions 			    dbuf);
1658*33de042dSApple OSS Distributions 
1659*33de042dSApple OSS Distributions 			return;
1660*33de042dSApple OSS Distributions 		}
1661*33de042dSApple OSS Distributions 
1662*33de042dSApple OSS Distributions 		u_char *hmac = (void *)(cp + addr_opt->maddr_len - HMAC_TRUNCATED_ADD_ADDR);
1663*33de042dSApple OSS Distributions 		uint16_t msg_len = sizeof(struct mptcp_add_addr_hmac_msg_v6);
1664*33de042dSApple OSS Distributions 		struct mptcp_add_addr_hmac_msg_v6 msg  = {0};
1665*33de042dSApple OSS Distributions 		msg.maddr_addrid = addr_opt->maddr_addrid;
1666*33de042dSApple OSS Distributions 		msg.maddr_addr = addr_opt->maddr_u.maddr_addrv6;
1667*33de042dSApple OSS Distributions 		if (addr_opt->maddr_len > MPTCP_V1_ADD_ADDR_OPT_LEN_V6) {
1668*33de042dSApple OSS Distributions 			msg.maddr_port = *(uint16_t *)(void *)(cp + addr_opt->maddr_len - HMAC_TRUNCATED_ADD_ADDR - 2);
1669*33de042dSApple OSS Distributions 		}
1670*33de042dSApple OSS Distributions 		if (!mptcp_validate_add_addr_hmac(tp, hmac, (u_char *)&msg, msg_len, HMAC_TRUNCATED_ADD_ADDR)) {
1671*33de042dSApple OSS Distributions 			char dbuf[MAX_IPv6_STR_LEN];
1672*33de042dSApple OSS Distributions 
1673*33de042dSApple OSS Distributions 			inet_ntop(AF_INET6, addr, dbuf, sizeof(dbuf));
1674*33de042dSApple OSS Distributions 			os_log_error(mptcp_log_handle, "%s - %lx: ADD_ADDR addr: %s invalid HMAC\n",
1675*33de042dSApple OSS Distributions 			    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1676*33de042dSApple OSS Distributions 			    dbuf);
1677*33de042dSApple OSS Distributions 			return;
1678*33de042dSApple OSS Distributions 		}
1679*33de042dSApple OSS Distributions 
1680*33de042dSApple OSS Distributions 		dst->sin6_len = sizeof(*dst);
1681*33de042dSApple OSS Distributions 		dst->sin6_family = AF_INET6;
1682*33de042dSApple OSS Distributions 		if (addr_opt->maddr_len > MPTCP_V1_ADD_ADDR_OPT_LEN_V6) {
1683*33de042dSApple OSS Distributions 			dst->sin6_port = *(uint16_t *)(void *)(cp + addr_opt->maddr_len - HMAC_TRUNCATED_ADD_ADDR - 2);
1684*33de042dSApple OSS Distributions 		} else {
1685*33de042dSApple OSS Distributions 			dst->sin6_port = mpte->__mpte_dst_v6.sin6_port;
1686*33de042dSApple OSS Distributions 		}
1687*33de042dSApple OSS Distributions 		memcpy(&dst->sin6_addr, addr, sizeof(*addr));
1688*33de042dSApple OSS Distributions 		mpte->sub_dst_addr_id_v6 = addr_opt->maddr_addrid;
1689*33de042dSApple OSS Distributions 		mpte->mpte_last_added_addr_is_v4 = FALSE;
1690*33de042dSApple OSS Distributions 	}
1691*33de042dSApple OSS Distributions 
1692*33de042dSApple OSS Distributions 	os_log(mptcp_log_handle, "%s - %lx: Received ADD_ADDRv1\n",
1693*33de042dSApple OSS Distributions 	    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte));
1694*33de042dSApple OSS Distributions 
1695*33de042dSApple OSS Distributions 	/* Once an incoming ADD_ADDR for v1 is valid, it means that the peer
1696*33de042dSApple OSS Distributions 	 * receiver our keys.
1697*33de042dSApple OSS Distributions 	 */
1698*33de042dSApple OSS Distributions 	tp->t_mpflags &= ~TMPF_SND_KEYS;
1699*33de042dSApple OSS Distributions 	tp->t_mpflags |= TMPF_MPTCP_ECHO_ADDR;
1700*33de042dSApple OSS Distributions 	tp->t_flags |= TF_ACKNOW;
1701*33de042dSApple OSS Distributions 	mptcp_sched_create_subflows(mpte);
1702*33de042dSApple OSS Distributions }
1703*33de042dSApple OSS Distributions 
1704*33de042dSApple OSS Distributions static void
mptcp_do_add_addr_opt_v0(struct mptses * mpte,u_char * cp)1705*33de042dSApple OSS Distributions mptcp_do_add_addr_opt_v0(struct mptses *mpte, u_char *cp)
1706*33de042dSApple OSS Distributions {
1707*33de042dSApple OSS Distributions 	struct mptcp_add_addr_opt *addr_opt = (struct mptcp_add_addr_opt *)cp;
1708*33de042dSApple OSS Distributions 
1709*33de042dSApple OSS Distributions 	if (addr_opt->maddr_len != MPTCP_V0_ADD_ADDR_OPT_LEN_V4 &&
1710*33de042dSApple OSS Distributions 	    addr_opt->maddr_len != MPTCP_V0_ADD_ADDR_OPT_LEN_V6) {
1711*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: Wrong ADD_ADDR length %u\n",
1712*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1713*33de042dSApple OSS Distributions 		    addr_opt->maddr_len);
1714*33de042dSApple OSS Distributions 
1715*33de042dSApple OSS Distributions 		return;
1716*33de042dSApple OSS Distributions 	}
1717*33de042dSApple OSS Distributions 
1718*33de042dSApple OSS Distributions 	if (addr_opt->maddr_len == MPTCP_V0_ADD_ADDR_OPT_LEN_V4 &&
1719*33de042dSApple OSS Distributions 	    addr_opt->maddr_flags != MPTCP_V0_ADD_ADDR_IPV4) {
1720*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: ADD_ADDR length for v4 but version is %u\n",
1721*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1722*33de042dSApple OSS Distributions 		    addr_opt->maddr_flags);
1723*33de042dSApple OSS Distributions 
1724*33de042dSApple OSS Distributions 		return;
1725*33de042dSApple OSS Distributions 	}
1726*33de042dSApple OSS Distributions 
1727*33de042dSApple OSS Distributions 	if (addr_opt->maddr_len == MPTCP_V0_ADD_ADDR_OPT_LEN_V6 &&
1728*33de042dSApple OSS Distributions 	    addr_opt->maddr_flags != MPTCP_V0_ADD_ADDR_IPV6) {
1729*33de042dSApple OSS Distributions 		os_log_error(mptcp_log_handle, "%s - %lx: ADD_ADDR length for v6 but version is %u\n",
1730*33de042dSApple OSS Distributions 		    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1731*33de042dSApple OSS Distributions 		    addr_opt->maddr_flags);
1732*33de042dSApple OSS Distributions 
1733*33de042dSApple OSS Distributions 		return;
1734*33de042dSApple OSS Distributions 	}
1735*33de042dSApple OSS Distributions 
1736*33de042dSApple OSS Distributions 	if (addr_opt->maddr_len == MPTCP_V0_ADD_ADDR_OPT_LEN_V4) {
1737*33de042dSApple OSS Distributions 		struct sockaddr_in *dst = &mpte->mpte_sub_dst_v4;
1738*33de042dSApple OSS Distributions 		struct in_addr *addr = &addr_opt->maddr_u.maddr_addrv4;
1739*33de042dSApple OSS Distributions 		in_addr_t haddr = ntohl(addr->s_addr);
1740*33de042dSApple OSS Distributions 
1741*33de042dSApple OSS Distributions 		if (IN_ZERONET(haddr) ||
1742*33de042dSApple OSS Distributions 		    IN_LOOPBACK(haddr) ||
1743*33de042dSApple OSS Distributions 		    IN_LINKLOCAL(haddr) ||
1744*33de042dSApple OSS Distributions 		    IN_DS_LITE(haddr) ||
1745*33de042dSApple OSS Distributions 		    IN_6TO4_RELAY_ANYCAST(haddr) ||
1746*33de042dSApple OSS Distributions 		    IN_MULTICAST(haddr) ||
1747*33de042dSApple OSS Distributions 		    INADDR_BROADCAST == haddr ||
1748*33de042dSApple OSS Distributions 		    IN_PRIVATE(haddr) ||
1749*33de042dSApple OSS Distributions 		    IN_SHARED_ADDRESS_SPACE(haddr)) {
1750*33de042dSApple OSS Distributions 			os_log_error(mptcp_log_handle, "%s - %lx: ADD_ADDR invalid addr: %x\n",
1751*33de042dSApple OSS Distributions 			    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1752*33de042dSApple OSS Distributions 			    addr->s_addr);
1753*33de042dSApple OSS Distributions 
1754*33de042dSApple OSS Distributions 			return;
1755*33de042dSApple OSS Distributions 		}
1756*33de042dSApple OSS Distributions 
1757*33de042dSApple OSS Distributions 		dst->sin_len = sizeof(*dst);
1758*33de042dSApple OSS Distributions 		dst->sin_family = AF_INET;
1759*33de042dSApple OSS Distributions 		dst->sin_port = mpte->__mpte_dst_v4.sin_port;
1760*33de042dSApple OSS Distributions 		dst->sin_addr.s_addr = addr->s_addr;
1761*33de042dSApple OSS Distributions 		mpte->mpte_last_added_addr_is_v4 = TRUE;
1762*33de042dSApple OSS Distributions 	} else {
1763*33de042dSApple OSS Distributions 		struct sockaddr_in6 *dst = &mpte->mpte_sub_dst_v6;
1764*33de042dSApple OSS Distributions 		struct in6_addr *addr = &addr_opt->maddr_u.maddr_addrv6;
1765*33de042dSApple OSS Distributions 
1766*33de042dSApple OSS Distributions 		if (IN6_IS_ADDR_LINKLOCAL(addr) ||
1767*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_MULTICAST(addr) ||
1768*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_UNSPECIFIED(addr) ||
1769*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_LOOPBACK(addr) ||
1770*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_V4COMPAT(addr) ||
1771*33de042dSApple OSS Distributions 		    IN6_IS_ADDR_V4MAPPED(addr)) {
1772*33de042dSApple OSS Distributions 			char dbuf[MAX_IPv6_STR_LEN];
1773*33de042dSApple OSS Distributions 
1774*33de042dSApple OSS Distributions 			inet_ntop(AF_INET6, addr, dbuf, sizeof(dbuf));
1775*33de042dSApple OSS Distributions 			os_log_error(mptcp_log_handle, "%s - %lx: ADD_ADDRv6 invalid addr: %s\n",
1776*33de042dSApple OSS Distributions 			    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte),
1777*33de042dSApple OSS Distributions 			    dbuf);
1778*33de042dSApple OSS Distributions 
1779*33de042dSApple OSS Distributions 			return;
1780*33de042dSApple OSS Distributions 		}
1781*33de042dSApple OSS Distributions 
1782*33de042dSApple OSS Distributions 		dst->sin6_len = sizeof(*dst);
1783*33de042dSApple OSS Distributions 		dst->sin6_family = AF_INET6;
1784*33de042dSApple OSS Distributions 		dst->sin6_port = mpte->__mpte_dst_v6.sin6_port;
1785*33de042dSApple OSS Distributions 		dst->sin6_addr = *addr;
1786*33de042dSApple OSS Distributions 		mpte->mpte_last_added_addr_is_v4 = FALSE;
1787*33de042dSApple OSS Distributions 	}
1788*33de042dSApple OSS Distributions 
1789*33de042dSApple OSS Distributions 	os_log(mptcp_log_handle, "%s - %lx: Received ADD_ADDRv0\n",
1790*33de042dSApple OSS Distributions 	    __func__, (unsigned long)VM_KERNEL_ADDRPERM(mpte));
1791*33de042dSApple OSS Distributions 
1792*33de042dSApple OSS Distributions 	mptcp_sched_create_subflows(mpte);
1793*33de042dSApple OSS Distributions }
1794*33de042dSApple OSS Distributions 
1795*33de042dSApple OSS Distributions void
tcp_do_mptcp_options(struct tcpcb * tp,u_char * cp,struct tcphdr * th,struct tcpopt * to,uint8_t optlen)1796*33de042dSApple OSS Distributions tcp_do_mptcp_options(struct tcpcb *tp, u_char *cp, struct tcphdr *th,
1797*33de042dSApple OSS Distributions     struct tcpopt *to, uint8_t optlen)
1798*33de042dSApple OSS Distributions {
1799*33de042dSApple OSS Distributions 	int mptcp_subtype;
1800*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1801*33de042dSApple OSS Distributions 
1802*33de042dSApple OSS Distributions 	if (mp_tp == NULL) {
1803*33de042dSApple OSS Distributions 		return;
1804*33de042dSApple OSS Distributions 	}
1805*33de042dSApple OSS Distributions 
1806*33de042dSApple OSS Distributions 	socket_lock_assert_owned(mptetoso(mp_tp->mpt_mpte));
1807*33de042dSApple OSS Distributions 
1808*33de042dSApple OSS Distributions 	/* All MPTCP options have atleast 4 bytes */
1809*33de042dSApple OSS Distributions 	if (optlen < 4) {
1810*33de042dSApple OSS Distributions 		return;
1811*33de042dSApple OSS Distributions 	}
1812*33de042dSApple OSS Distributions 
1813*33de042dSApple OSS Distributions 	mptcp_subtype = (cp[2] >> 4);
1814*33de042dSApple OSS Distributions 
1815*33de042dSApple OSS Distributions 	if (mptcp_sanitize_option(tp, mptcp_subtype) == 0) {
1816*33de042dSApple OSS Distributions 		return;
1817*33de042dSApple OSS Distributions 	}
1818*33de042dSApple OSS Distributions 
1819*33de042dSApple OSS Distributions 	switch (mptcp_subtype) {
1820*33de042dSApple OSS Distributions 	case MPO_CAPABLE:
1821*33de042dSApple OSS Distributions 		mptcp_do_mpcapable_opt(tp, cp, th, optlen);
1822*33de042dSApple OSS Distributions 		break;
1823*33de042dSApple OSS Distributions 	case MPO_JOIN:
1824*33de042dSApple OSS Distributions 		mptcp_do_mpjoin_opt(tp, cp, th, optlen);
1825*33de042dSApple OSS Distributions 		break;
1826*33de042dSApple OSS Distributions 	case MPO_DSS:
1827*33de042dSApple OSS Distributions 		mptcp_do_dss_opt(tp, cp, th);
1828*33de042dSApple OSS Distributions 		break;
1829*33de042dSApple OSS Distributions 	case MPO_FASTCLOSE:
1830*33de042dSApple OSS Distributions 		mptcp_do_fastclose_opt(tp, cp, th);
1831*33de042dSApple OSS Distributions 		break;
1832*33de042dSApple OSS Distributions 	case MPO_FAIL:
1833*33de042dSApple OSS Distributions 		mptcp_do_mpfail_opt(tp, cp, th);
1834*33de042dSApple OSS Distributions 		break;
1835*33de042dSApple OSS Distributions 	case MPO_ADD_ADDR:
1836*33de042dSApple OSS Distributions 		if (mp_tp->mpt_version == MPTCP_VERSION_0) {
1837*33de042dSApple OSS Distributions 			mptcp_do_add_addr_opt_v0(mp_tp->mpt_mpte, cp);
1838*33de042dSApple OSS Distributions 		} else {
1839*33de042dSApple OSS Distributions 			mptcp_do_add_addr_opt_v1(tp, cp);
1840*33de042dSApple OSS Distributions 		}
1841*33de042dSApple OSS Distributions 		break;
1842*33de042dSApple OSS Distributions 	case MPO_REMOVE_ADDR:           /* fall through */
1843*33de042dSApple OSS Distributions 	case MPO_PRIO:
1844*33de042dSApple OSS Distributions 		to->to_flags |= TOF_MPTCP;
1845*33de042dSApple OSS Distributions 		break;
1846*33de042dSApple OSS Distributions 	default:
1847*33de042dSApple OSS Distributions 		break;
1848*33de042dSApple OSS Distributions 	}
1849*33de042dSApple OSS Distributions 	return;
1850*33de042dSApple OSS Distributions }
1851*33de042dSApple OSS Distributions 
1852*33de042dSApple OSS Distributions /* REMOVE_ADDR option is sent when a source address goes away */
1853*33de042dSApple OSS Distributions static void
mptcp_send_remaddr_opt(struct tcpcb * tp,struct mptcp_remaddr_opt * opt)1854*33de042dSApple OSS Distributions mptcp_send_remaddr_opt(struct tcpcb *tp, struct mptcp_remaddr_opt *opt)
1855*33de042dSApple OSS Distributions {
1856*33de042dSApple OSS Distributions 	bzero(opt, sizeof(*opt));
1857*33de042dSApple OSS Distributions 	opt->mr_kind = TCPOPT_MULTIPATH;
1858*33de042dSApple OSS Distributions 	opt->mr_len = sizeof(*opt);
1859*33de042dSApple OSS Distributions 	opt->mr_subtype = MPO_REMOVE_ADDR;
1860*33de042dSApple OSS Distributions 	opt->mr_addr_id = tp->t_rem_aid;
1861*33de042dSApple OSS Distributions 	tp->t_mpflags &= ~TMPF_SND_REM_ADDR;
1862*33de042dSApple OSS Distributions }
1863*33de042dSApple OSS Distributions 
1864*33de042dSApple OSS Distributions static int
mptcp_echo_add_addr(struct tcpcb * tp,u_char * cp,unsigned int optlen)1865*33de042dSApple OSS Distributions mptcp_echo_add_addr(struct tcpcb *tp, u_char *cp, unsigned int optlen)
1866*33de042dSApple OSS Distributions {
1867*33de042dSApple OSS Distributions 	struct mptcp_add_addr_opt mpaddr;
1868*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1869*33de042dSApple OSS Distributions 	struct mptses *mpte = mp_tp->mpt_mpte;
1870*33de042dSApple OSS Distributions 
1871*33de042dSApple OSS Distributions 	// MPTCP v0 doesn't require echoing add_addr
1872*33de042dSApple OSS Distributions 	if (mp_tp->mpt_version == MPTCP_VERSION_0) {
1873*33de042dSApple OSS Distributions 		return optlen;
1874*33de042dSApple OSS Distributions 	}
1875*33de042dSApple OSS Distributions 
1876*33de042dSApple OSS Distributions 	size_t mpaddr_size = mpte->mpte_last_added_addr_is_v4 ? MPTCP_V1_ADD_ADDR_ECHO_OPT_LEN_V4 : MPTCP_V1_ADD_ADDR_ECHO_OPT_LEN_V6;
1877*33de042dSApple OSS Distributions 	if ((MAX_TCPOPTLEN - optlen) < mpaddr_size) {
1878*33de042dSApple OSS Distributions 		return optlen;
1879*33de042dSApple OSS Distributions 	}
1880*33de042dSApple OSS Distributions 
1881*33de042dSApple OSS Distributions 	bzero(&mpaddr, sizeof(mpaddr));
1882*33de042dSApple OSS Distributions 	mpaddr.maddr_kind = TCPOPT_MULTIPATH;
1883*33de042dSApple OSS Distributions 	mpaddr.maddr_len = (uint8_t)mpaddr_size;
1884*33de042dSApple OSS Distributions 	mpaddr.maddr_subtype = MPO_ADD_ADDR;
1885*33de042dSApple OSS Distributions 	mpaddr.maddr_flags = MPTCP_V1_ADD_ADDR_ECHO;
1886*33de042dSApple OSS Distributions 	if (mpte->mpte_last_added_addr_is_v4) {
1887*33de042dSApple OSS Distributions 		mpaddr.maddr_u.maddr_addrv4.s_addr = mpte->mpte_sub_dst_v4.sin_addr.s_addr;
1888*33de042dSApple OSS Distributions 		mpaddr.maddr_addrid = mpte->sub_dst_addr_id_v4;
1889*33de042dSApple OSS Distributions 	} else {
1890*33de042dSApple OSS Distributions 		mpaddr.maddr_u.maddr_addrv6 = mpte->mpte_sub_dst_v6.sin6_addr;
1891*33de042dSApple OSS Distributions 		mpaddr.maddr_addrid = mpte->sub_dst_addr_id_v6;
1892*33de042dSApple OSS Distributions 	}
1893*33de042dSApple OSS Distributions 
1894*33de042dSApple OSS Distributions 	memcpy(cp + optlen, &mpaddr, mpaddr_size);
1895*33de042dSApple OSS Distributions 	optlen += mpaddr_size;
1896*33de042dSApple OSS Distributions 	tp->t_mpflags &= ~TMPF_MPTCP_ECHO_ADDR;
1897*33de042dSApple OSS Distributions 	return optlen;
1898*33de042dSApple OSS Distributions }
1899*33de042dSApple OSS Distributions 
1900*33de042dSApple OSS Distributions /* We send MP_PRIO option based on the values set by the SIOCSCONNORDER ioctl */
1901*33de042dSApple OSS Distributions static int
mptcp_snd_mpprio(struct tcpcb * tp,u_char * cp,int optlen)1902*33de042dSApple OSS Distributions mptcp_snd_mpprio(struct tcpcb *tp, u_char *cp, int optlen)
1903*33de042dSApple OSS Distributions {
1904*33de042dSApple OSS Distributions 	struct mptcp_mpprio_addr_opt mpprio;
1905*33de042dSApple OSS Distributions 	struct mptcb *mp_tp = tptomptp(tp);
1906*33de042dSApple OSS Distributions 	size_t mpprio_size = sizeof(mpprio);
1907*33de042dSApple OSS Distributions 	// MP_PRIO of MPTCPv1 doesn't include AddrID
1908*33de042dSApple OSS Distributions 	if (mp_tp->mpt_version == MPTCP_VERSION_1) {
1909*33de042dSApple OSS Distributions 		mpprio_size -= sizeof(uint8_t);
1910*33de042dSApple OSS Distributions 	}
1911*33de042dSApple OSS Distributions 
1912*33de042dSApple OSS Distributions 	if (tp->t_state != TCPS_ESTABLISHED) {
1913*33de042dSApple OSS Distributions 		tp->t_mpflags &= ~TMPF_SND_MPPRIO;
1914*33de042dSApple OSS Distributions 		return optlen;
1915*33de042dSApple OSS Distributions 	}
1916*33de042dSApple OSS Distributions 
1917*33de042dSApple OSS Distributions 	if ((MAX_TCPOPTLEN - optlen) < (int)mpprio_size) {
1918*33de042dSApple OSS Distributions 		return optlen;
1919*33de042dSApple OSS Distributions 	}
1920*33de042dSApple OSS Distributions 
1921*33de042dSApple OSS Distributions 	bzero(&mpprio, sizeof(mpprio));
1922*33de042dSApple OSS Distributions 	mpprio.mpprio_kind = TCPOPT_MULTIPATH;
1923*33de042dSApple OSS Distributions 	mpprio.mpprio_len = (uint8_t)mpprio_size;
1924*33de042dSApple OSS Distributions 	mpprio.mpprio_subtype = MPO_PRIO;
1925*33de042dSApple OSS Distributions 	if (tp->t_mpflags & TMPF_BACKUP_PATH) {
1926*33de042dSApple OSS Distributions 		mpprio.mpprio_flags |= MPTCP_MPPRIO_BKP;
1927*33de042dSApple OSS Distributions 	}
1928*33de042dSApple OSS Distributions 	mpprio.mpprio_addrid = tp->t_local_aid;
1929*33de042dSApple OSS Distributions 	memcpy(cp + optlen, &mpprio, mpprio_size);
1930*33de042dSApple OSS Distributions 	optlen += mpprio_size;
1931*33de042dSApple OSS Distributions 	tp->t_mpflags &= ~TMPF_SND_MPPRIO;
1932*33de042dSApple OSS Distributions 	return optlen;
1933*33de042dSApple OSS Distributions }
1934