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