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