@@ -14,8 +14,8 @@ static bool mptcp_cap_flag_sha256(u8 flags)
14
14
return (flags & MPTCP_CAP_FLAG_MASK ) == MPTCP_CAP_HMAC_SHA256 ;
15
15
}
16
16
17
- void mptcp_parse_option (const unsigned char * ptr , int opsize ,
18
- struct tcp_options_received * opt_rx )
17
+ void mptcp_parse_option (const struct sk_buff * skb , const unsigned char * ptr ,
18
+ int opsize , struct tcp_options_received * opt_rx )
19
19
{
20
20
struct mptcp_options_received * mp_opt = & opt_rx -> mptcp ;
21
21
u8 subtype = * ptr >> 4 ;
@@ -25,13 +25,29 @@ void mptcp_parse_option(const unsigned char *ptr, int opsize,
25
25
26
26
switch (subtype ) {
27
27
case MPTCPOPT_MP_CAPABLE :
28
- if (opsize != TCPOLEN_MPTCP_MPC_SYN &&
29
- opsize != TCPOLEN_MPTCP_MPC_ACK )
28
+ /* strict size checking */
29
+ if (!(TCP_SKB_CB (skb )-> tcp_flags & TCPHDR_SYN )) {
30
+ if (skb -> len > tcp_hdr (skb )-> doff << 2 )
31
+ expected_opsize = TCPOLEN_MPTCP_MPC_ACK_DATA ;
32
+ else
33
+ expected_opsize = TCPOLEN_MPTCP_MPC_ACK ;
34
+ } else {
35
+ if (TCP_SKB_CB (skb )-> tcp_flags & TCPHDR_ACK )
36
+ expected_opsize = TCPOLEN_MPTCP_MPC_SYNACK ;
37
+ else
38
+ expected_opsize = TCPOLEN_MPTCP_MPC_SYN ;
39
+ }
40
+ if (opsize != expected_opsize )
30
41
break ;
31
42
43
+ /* try to be gentle vs future versions on the initial syn */
32
44
version = * ptr ++ & MPTCP_VERSION_MASK ;
33
- if (version != MPTCP_SUPPORTED_VERSION )
45
+ if (opsize != TCPOLEN_MPTCP_MPC_SYN ) {
46
+ if (version != MPTCP_SUPPORTED_VERSION )
47
+ break ;
48
+ } else if (version < MPTCP_SUPPORTED_VERSION ) {
34
49
break ;
50
+ }
35
51
36
52
flags = * ptr ++ ;
37
53
if (!mptcp_cap_flag_sha256 (flags ) ||
@@ -55,23 +71,40 @@ void mptcp_parse_option(const unsigned char *ptr, int opsize,
55
71
break ;
56
72
57
73
mp_opt -> mp_capable = 1 ;
58
- mp_opt -> sndr_key = get_unaligned_be64 (ptr );
59
- ptr += 8 ;
60
-
61
- if (opsize == TCPOLEN_MPTCP_MPC_ACK ) {
74
+ if (opsize >= TCPOLEN_MPTCP_MPC_SYNACK ) {
75
+ mp_opt -> sndr_key = get_unaligned_be64 (ptr );
76
+ ptr += 8 ;
77
+ }
78
+ if (opsize >= TCPOLEN_MPTCP_MPC_ACK ) {
62
79
mp_opt -> rcvr_key = get_unaligned_be64 (ptr );
63
80
ptr += 8 ;
64
- pr_debug ("MP_CAPABLE sndr=%llu, rcvr=%llu" ,
65
- mp_opt -> sndr_key , mp_opt -> rcvr_key );
66
- } else {
67
- pr_debug ("MP_CAPABLE sndr=%llu" , mp_opt -> sndr_key );
68
81
}
82
+ if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA ) {
83
+ /* Section 3.1.:
84
+ * "the data parameters in a MP_CAPABLE are semantically
85
+ * equivalent to those in a DSS option and can be used
86
+ * interchangeably."
87
+ */
88
+ mp_opt -> dss = 1 ;
89
+ mp_opt -> use_map = 1 ;
90
+ mp_opt -> mpc_map = 1 ;
91
+ mp_opt -> data_len = get_unaligned_be16 (ptr );
92
+ ptr += 2 ;
93
+ }
94
+ pr_debug ("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d" ,
95
+ version , flags , opsize , mp_opt -> sndr_key ,
96
+ mp_opt -> rcvr_key , mp_opt -> data_len );
69
97
break ;
70
98
71
99
case MPTCPOPT_DSS :
72
100
pr_debug ("DSS" );
73
101
ptr ++ ;
74
102
103
+ /* we must clear 'mpc_map' be able to detect MP_CAPABLE
104
+ * map vs DSS map in mptcp_incoming_options(), and reconstruct
105
+ * map info accordingly
106
+ */
107
+ mp_opt -> mpc_map = 0 ;
75
108
flags = (* ptr ++ ) & MPTCP_DSS_FLAG_MASK ;
76
109
mp_opt -> data_fin = (flags & MPTCP_DSS_DATA_FIN ) != 0 ;
77
110
mp_opt -> dsn64 = (flags & MPTCP_DSS_DSN64 ) != 0 ;
@@ -176,18 +209,22 @@ void mptcp_get_options(const struct sk_buff *skb,
176
209
if (opsize > length )
177
210
return ; /* don't parse partial options */
178
211
if (opcode == TCPOPT_MPTCP )
179
- mptcp_parse_option (ptr , opsize , opt_rx );
212
+ mptcp_parse_option (skb , ptr , opsize , opt_rx );
180
213
ptr += opsize - 2 ;
181
214
length -= opsize ;
182
215
}
183
216
}
184
217
}
185
218
186
- bool mptcp_syn_options (struct sock * sk , unsigned int * size ,
187
- struct mptcp_out_options * opts )
219
+ bool mptcp_syn_options (struct sock * sk , const struct sk_buff * skb ,
220
+ unsigned int * size , struct mptcp_out_options * opts )
188
221
{
189
222
struct mptcp_subflow_context * subflow = mptcp_subflow_ctx (sk );
190
223
224
+ /* we will use snd_isn to detect first pkt [re]transmission
225
+ * in mptcp_established_options_mp()
226
+ */
227
+ subflow -> snd_isn = TCP_SKB_CB (skb )-> end_seq ;
191
228
if (subflow -> request_mptcp ) {
192
229
pr_debug ("local_key=%llu" , subflow -> local_key );
193
230
opts -> suboptions = OPTION_MPTCP_MPC_SYN ;
@@ -212,20 +249,52 @@ void mptcp_rcv_synsent(struct sock *sk)
212
249
}
213
250
}
214
251
215
- static bool mptcp_established_options_mp (struct sock * sk , unsigned int * size ,
252
+ static bool mptcp_established_options_mp (struct sock * sk , struct sk_buff * skb ,
253
+ unsigned int * size ,
216
254
unsigned int remaining ,
217
255
struct mptcp_out_options * opts )
218
256
{
219
257
struct mptcp_subflow_context * subflow = mptcp_subflow_ctx (sk );
258
+ struct mptcp_ext * mpext ;
259
+ unsigned int data_len ;
260
+
261
+ pr_debug ("subflow=%p fourth_ack=%d seq=%x:%x remaining=%d" , subflow ,
262
+ subflow -> fourth_ack , subflow -> snd_isn ,
263
+ skb ? TCP_SKB_CB (skb )-> seq : 0 , remaining );
264
+
265
+ if (subflow -> mp_capable && !subflow -> fourth_ack && skb &&
266
+ subflow -> snd_isn == TCP_SKB_CB (skb )-> seq ) {
267
+ /* When skb is not available, we better over-estimate the
268
+ * emitted options len. A full DSS option is longer than
269
+ * TCPOLEN_MPTCP_MPC_ACK_DATA, so let's the caller try to fit
270
+ * that.
271
+ */
272
+ mpext = mptcp_get_ext (skb );
273
+ data_len = mpext ? mpext -> data_len : 0 ;
220
274
221
- if (!subflow -> fourth_ack ) {
275
+ /* we will check ext_copy.data_len in mptcp_write_options() to
276
+ * discriminate between TCPOLEN_MPTCP_MPC_ACK_DATA and
277
+ * TCPOLEN_MPTCP_MPC_ACK
278
+ */
279
+ opts -> ext_copy .data_len = data_len ;
222
280
opts -> suboptions = OPTION_MPTCP_MPC_ACK ;
223
281
opts -> sndr_key = subflow -> local_key ;
224
282
opts -> rcvr_key = subflow -> remote_key ;
225
- * size = TCPOLEN_MPTCP_MPC_ACK ;
226
- subflow -> fourth_ack = 1 ;
227
- pr_debug ("subflow=%p, local_key=%llu, remote_key=%llu" ,
228
- subflow , subflow -> local_key , subflow -> remote_key );
283
+
284
+ /* Section 3.1.
285
+ * The MP_CAPABLE option is carried on the SYN, SYN/ACK, and ACK
286
+ * packets that start the first subflow of an MPTCP connection,
287
+ * as well as the first packet that carries data
288
+ */
289
+ if (data_len > 0 )
290
+ * size = ALIGN (TCPOLEN_MPTCP_MPC_ACK_DATA , 4 );
291
+ else
292
+ * size = TCPOLEN_MPTCP_MPC_ACK ;
293
+
294
+ pr_debug ("subflow=%p, local_key=%llu, remote_key=%llu map_len=%d" ,
295
+ subflow , subflow -> local_key , subflow -> remote_key ,
296
+ data_len );
297
+
229
298
return true;
230
299
}
231
300
return false;
@@ -319,7 +388,7 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
319
388
unsigned int opt_size = 0 ;
320
389
bool ret = false;
321
390
322
- if (mptcp_established_options_mp (sk , & opt_size , remaining , opts ))
391
+ if (mptcp_established_options_mp (sk , skb , & opt_size , remaining , opts ))
323
392
ret = true;
324
393
else if (mptcp_established_options_dss (sk , skb , & opt_size , remaining ,
325
394
opts ))
@@ -371,11 +440,26 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
371
440
memset (mpext , 0 , sizeof (* mpext ));
372
441
373
442
if (mp_opt -> use_map ) {
374
- mpext -> data_seq = mp_opt -> data_seq ;
375
- mpext -> subflow_seq = mp_opt -> subflow_seq ;
443
+ if (mp_opt -> mpc_map ) {
444
+ struct mptcp_subflow_context * subflow =
445
+ mptcp_subflow_ctx (sk );
446
+
447
+ /* this is an MP_CAPABLE carrying MPTCP data
448
+ * we know this map the first chunk of data
449
+ */
450
+ mptcp_crypto_key_sha (subflow -> remote_key , NULL ,
451
+ & mpext -> data_seq );
452
+ mpext -> data_seq ++ ;
453
+ mpext -> subflow_seq = 1 ;
454
+ mpext -> dsn64 = 1 ;
455
+ mpext -> mpc_map = 1 ;
456
+ } else {
457
+ mpext -> data_seq = mp_opt -> data_seq ;
458
+ mpext -> subflow_seq = mp_opt -> subflow_seq ;
459
+ mpext -> dsn64 = mp_opt -> dsn64 ;
460
+ }
376
461
mpext -> data_len = mp_opt -> data_len ;
377
462
mpext -> use_map = 1 ;
378
- mpext -> dsn64 = mp_opt -> dsn64 ;
379
463
}
380
464
381
465
if (mp_opt -> use_ack ) {
@@ -389,30 +473,44 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
389
473
390
474
void mptcp_write_options (__be32 * ptr , struct mptcp_out_options * opts )
391
475
{
392
- if ((OPTION_MPTCP_MPC_SYN |
393
- OPTION_MPTCP_MPC_SYNACK |
476
+ if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK |
394
477
OPTION_MPTCP_MPC_ACK ) & opts -> suboptions ) {
395
478
u8 len ;
396
479
397
480
if (OPTION_MPTCP_MPC_SYN & opts -> suboptions )
398
481
len = TCPOLEN_MPTCP_MPC_SYN ;
399
482
else if (OPTION_MPTCP_MPC_SYNACK & opts -> suboptions )
400
483
len = TCPOLEN_MPTCP_MPC_SYNACK ;
484
+ else if (opts -> ext_copy .data_len )
485
+ len = TCPOLEN_MPTCP_MPC_ACK_DATA ;
401
486
else
402
487
len = TCPOLEN_MPTCP_MPC_ACK ;
403
488
404
489
* ptr ++ = htonl ((TCPOPT_MPTCP << 24 ) | (len << 16 ) |
405
490
(MPTCPOPT_MP_CAPABLE << 12 ) |
406
491
(MPTCP_SUPPORTED_VERSION << 8 ) |
407
492
MPTCP_CAP_HMAC_SHA256 );
493
+
494
+ if (!((OPTION_MPTCP_MPC_SYNACK | OPTION_MPTCP_MPC_ACK ) &
495
+ opts -> suboptions ))
496
+ goto mp_capable_done ;
497
+
408
498
put_unaligned_be64 (opts -> sndr_key , ptr );
409
499
ptr += 2 ;
410
- if (OPTION_MPTCP_MPC_ACK & opts -> suboptions ) {
411
- put_unaligned_be64 (opts -> rcvr_key , ptr );
412
- ptr += 2 ;
413
- }
500
+ if (!((OPTION_MPTCP_MPC_ACK ) & opts -> suboptions ))
501
+ goto mp_capable_done ;
502
+
503
+ put_unaligned_be64 (opts -> rcvr_key , ptr );
504
+ ptr += 2 ;
505
+ if (!opts -> ext_copy .data_len )
506
+ goto mp_capable_done ;
507
+
508
+ put_unaligned_be32 (opts -> ext_copy .data_len << 16 |
509
+ TCPOPT_NOP << 8 | TCPOPT_NOP , ptr );
510
+ ptr += 1 ;
414
511
}
415
512
513
+ mp_capable_done :
416
514
if (opts -> ext_copy .use_ack || opts -> ext_copy .use_map ) {
417
515
struct mptcp_ext * mpext = & opts -> ext_copy ;
418
516
u8 len = TCPOLEN_MPTCP_DSS_BASE ;
0 commit comments