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