subflow.c (603ea288dc53dfabf823bf7d38e401a945309492) | subflow.c (d39dceca388ad0e4f748836806349ebe09282283) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* Multipath TCP 3 * 4 * Copyright (c) 2017 - 2019, Intel Corporation. 5 */ 6 7#define pr_fmt(fmt) "MPTCP: " fmt 8 --- 55 unchanged lines hidden (view full) --- 64} 65 66static void subflow_req_destructor(struct request_sock *req) 67{ 68 struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); 69 70 pr_debug("subflow_req=%p", subflow_req); 71 | 1// SPDX-License-Identifier: GPL-2.0 2/* Multipath TCP 3 * 4 * Copyright (c) 2017 - 2019, Intel Corporation. 5 */ 6 7#define pr_fmt(fmt) "MPTCP: " fmt 8 --- 55 unchanged lines hidden (view full) --- 64} 65 66static void subflow_req_destructor(struct request_sock *req) 67{ 68 struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); 69 70 pr_debug("subflow_req=%p", subflow_req); 71 |
72 if (subflow_req->msk) 73 sock_put((struct sock *)subflow_req->msk); 74 |
|
72 if (subflow_req->mp_capable) 73 mptcp_token_destroy_request(subflow_req->token); 74 tcp_request_sock_ops.destructor(req); 75} 76 77static void subflow_generate_hmac(u64 key1, u64 key2, u32 nonce1, u32 nonce2, 78 void *hmac) 79{ 80 u8 msg[8]; 81 82 put_unaligned_be32(nonce1, &msg[0]); 83 put_unaligned_be32(nonce2, &msg[4]); 84 85 mptcp_crypto_hmac_sha(key1, key2, msg, 8, hmac); 86} 87 88/* validate received token and create truncated hmac and nonce for SYN-ACK */ | 75 if (subflow_req->mp_capable) 76 mptcp_token_destroy_request(subflow_req->token); 77 tcp_request_sock_ops.destructor(req); 78} 79 80static void subflow_generate_hmac(u64 key1, u64 key2, u32 nonce1, u32 nonce2, 81 void *hmac) 82{ 83 u8 msg[8]; 84 85 put_unaligned_be32(nonce1, &msg[0]); 86 put_unaligned_be32(nonce2, &msg[4]); 87 88 mptcp_crypto_hmac_sha(key1, key2, msg, 8, hmac); 89} 90 91/* validate received token and create truncated hmac and nonce for SYN-ACK */ |
89static bool subflow_token_join_request(struct request_sock *req, 90 const struct sk_buff *skb) | 92static struct mptcp_sock *subflow_token_join_request(struct request_sock *req, 93 const struct sk_buff *skb) |
91{ 92 struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); 93 u8 hmac[SHA256_DIGEST_SIZE]; 94 struct mptcp_sock *msk; 95 int local_id; 96 97 msk = mptcp_token_get_sock(subflow_req->token); 98 if (!msk) { 99 SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINNOTOKEN); | 94{ 95 struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); 96 u8 hmac[SHA256_DIGEST_SIZE]; 97 struct mptcp_sock *msk; 98 int local_id; 99 100 msk = mptcp_token_get_sock(subflow_req->token); 101 if (!msk) { 102 SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINNOTOKEN); |
100 return false; | 103 return NULL; |
101 } 102 103 local_id = mptcp_pm_get_local_id(msk, (struct sock_common *)req); 104 if (local_id < 0) { 105 sock_put((struct sock *)msk); | 104 } 105 106 local_id = mptcp_pm_get_local_id(msk, (struct sock_common *)req); 107 if (local_id < 0) { 108 sock_put((struct sock *)msk); |
106 return false; | 109 return NULL; |
107 } 108 subflow_req->local_id = local_id; 109 110 get_random_bytes(&subflow_req->local_nonce, sizeof(u32)); 111 112 subflow_generate_hmac(msk->local_key, msk->remote_key, 113 subflow_req->local_nonce, 114 subflow_req->remote_nonce, hmac); 115 116 subflow_req->thmac = get_unaligned_be64(hmac); | 110 } 111 subflow_req->local_id = local_id; 112 113 get_random_bytes(&subflow_req->local_nonce, sizeof(u32)); 114 115 subflow_generate_hmac(msk->local_key, msk->remote_key, 116 subflow_req->local_nonce, 117 subflow_req->remote_nonce, hmac); 118 119 subflow_req->thmac = get_unaligned_be64(hmac); |
117 118 sock_put((struct sock *)msk); 119 return true; | 120 return msk; |
120} 121 122static void subflow_init_req(struct request_sock *req, 123 const struct sock *sk_listener, 124 struct sk_buff *skb) 125{ 126 struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener); 127 struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); 128 struct mptcp_options_received mp_opt; 129 130 pr_debug("subflow_req=%p, listener=%p", subflow_req, listener); 131 132 mptcp_get_options(skb, &mp_opt); 133 134 subflow_req->mp_capable = 0; 135 subflow_req->mp_join = 0; | 121} 122 123static void subflow_init_req(struct request_sock *req, 124 const struct sock *sk_listener, 125 struct sk_buff *skb) 126{ 127 struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener); 128 struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); 129 struct mptcp_options_received mp_opt; 130 131 pr_debug("subflow_req=%p, listener=%p", subflow_req, listener); 132 133 mptcp_get_options(skb, &mp_opt); 134 135 subflow_req->mp_capable = 0; 136 subflow_req->mp_join = 0; |
137 subflow_req->msk = NULL; |
|
136 137#ifdef CONFIG_TCP_MD5SIG 138 /* no MPTCP if MD5SIG is enabled on this socket or we may run out of 139 * TCP option space. 140 */ 141 if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info)) 142 return; 143#endif --- 17 unchanged lines hidden (view full) --- 161 subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; 162 } else if (mp_opt.mp_join && listener->request_mptcp) { 163 subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; 164 subflow_req->mp_join = 1; 165 subflow_req->backup = mp_opt.backup; 166 subflow_req->remote_id = mp_opt.join_id; 167 subflow_req->token = mp_opt.token; 168 subflow_req->remote_nonce = mp_opt.nonce; | 138 139#ifdef CONFIG_TCP_MD5SIG 140 /* no MPTCP if MD5SIG is enabled on this socket or we may run out of 141 * TCP option space. 142 */ 143 if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info)) 144 return; 145#endif --- 17 unchanged lines hidden (view full) --- 163 subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; 164 } else if (mp_opt.mp_join && listener->request_mptcp) { 165 subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq; 166 subflow_req->mp_join = 1; 167 subflow_req->backup = mp_opt.backup; 168 subflow_req->remote_id = mp_opt.join_id; 169 subflow_req->token = mp_opt.token; 170 subflow_req->remote_nonce = mp_opt.nonce; |
169 pr_debug("token=%u, remote_nonce=%u", subflow_req->token, 170 subflow_req->remote_nonce); 171 if (!subflow_token_join_request(req, skb)) { 172 subflow_req->mp_join = 0; 173 // @@ need to trigger RST 174 } | 171 subflow_req->msk = subflow_token_join_request(req, skb); 172 pr_debug("token=%u, remote_nonce=%u msk=%p", subflow_req->token, 173 subflow_req->remote_nonce, subflow_req->msk); |
175 } 176} 177 178static void subflow_v4_init_req(struct request_sock *req, 179 const struct sock *sk_listener, 180 struct sk_buff *skb) 181{ 182 tcp_rsk(req)->is_mptcp = 1; --- 166 unchanged lines hidden (view full) --- 349 350/* validate hmac received in third ACK */ 351static bool subflow_hmac_valid(const struct request_sock *req, 352 const struct mptcp_options_received *mp_opt) 353{ 354 const struct mptcp_subflow_request_sock *subflow_req; 355 u8 hmac[SHA256_DIGEST_SIZE]; 356 struct mptcp_sock *msk; | 174 } 175} 176 177static void subflow_v4_init_req(struct request_sock *req, 178 const struct sock *sk_listener, 179 struct sk_buff *skb) 180{ 181 tcp_rsk(req)->is_mptcp = 1; --- 166 unchanged lines hidden (view full) --- 348 349/* validate hmac received in third ACK */ 350static bool subflow_hmac_valid(const struct request_sock *req, 351 const struct mptcp_options_received *mp_opt) 352{ 353 const struct mptcp_subflow_request_sock *subflow_req; 354 u8 hmac[SHA256_DIGEST_SIZE]; 355 struct mptcp_sock *msk; |
357 bool ret; | |
358 359 subflow_req = mptcp_subflow_rsk(req); | 356 357 subflow_req = mptcp_subflow_rsk(req); |
360 msk = mptcp_token_get_sock(subflow_req->token); | 358 msk = subflow_req->msk; |
361 if (!msk) 362 return false; 363 364 subflow_generate_hmac(msk->remote_key, msk->local_key, 365 subflow_req->remote_nonce, 366 subflow_req->local_nonce, hmac); 367 | 359 if (!msk) 360 return false; 361 362 subflow_generate_hmac(msk->remote_key, msk->local_key, 363 subflow_req->remote_nonce, 364 subflow_req->local_nonce, hmac); 365 |
368 ret = true; 369 if (crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN)) 370 ret = false; 371 372 sock_put((struct sock *)msk); 373 return ret; | 366 return !crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN); |
374} 375 376static void mptcp_sock_destruct(struct sock *sk) 377{ 378 /* if new mptcp socket isn't accepted, it is free'd 379 * from the tcp listener sockets request queue, linked 380 * from req->sk. The tcp socket is released. 381 * This calls the ULP release function which will --- 51 unchanged lines hidden (view full) --- 433 struct request_sock *req, 434 struct dst_entry *dst, 435 struct request_sock *req_unhash, 436 bool *own_req) 437{ 438 struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk); 439 struct mptcp_subflow_request_sock *subflow_req; 440 struct mptcp_options_received mp_opt; | 367} 368 369static void mptcp_sock_destruct(struct sock *sk) 370{ 371 /* if new mptcp socket isn't accepted, it is free'd 372 * from the tcp listener sockets request queue, linked 373 * from req->sk. The tcp socket is released. 374 * This calls the ULP release function which will --- 51 unchanged lines hidden (view full) --- 426 struct request_sock *req, 427 struct dst_entry *dst, 428 struct request_sock *req_unhash, 429 bool *own_req) 430{ 431 struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk); 432 struct mptcp_subflow_request_sock *subflow_req; 433 struct mptcp_options_received mp_opt; |
441 bool fallback_is_fatal = false; | 434 bool fallback, fallback_is_fatal; |
442 struct sock *new_msk = NULL; | 435 struct sock *new_msk = NULL; |
443 bool fallback = false; | |
444 struct sock *child; 445 446 pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn); 447 | 436 struct sock *child; 437 438 pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn); 439 |
448 /* we need later a valid 'mp_capable' value even when options are not 449 * parsed | 440 /* After child creation we must look for 'mp_capable' even when options 441 * are not parsed |
450 */ 451 mp_opt.mp_capable = 0; | 442 */ 443 mp_opt.mp_capable = 0; |
452 if (tcp_rsk(req)->is_mptcp == 0) | 444 445 /* hopefully temporary handling for MP_JOIN+syncookie */ 446 subflow_req = mptcp_subflow_rsk(req); 447 fallback_is_fatal = subflow_req->mp_join; 448 fallback = !tcp_rsk(req)->is_mptcp; 449 if (fallback) |
453 goto create_child; 454 455 /* if the sk is MP_CAPABLE, we try to fetch the client key */ | 450 goto create_child; 451 452 /* if the sk is MP_CAPABLE, we try to fetch the client key */ |
456 subflow_req = mptcp_subflow_rsk(req); | |
457 if (subflow_req->mp_capable) { 458 if (TCP_SKB_CB(skb)->seq != subflow_req->ssn_offset + 1) { 459 /* here we can receive and accept an in-window, 460 * out-of-order pkt, which will not carry the MP_CAPABLE 461 * opt even on mptcp enabled paths 462 */ 463 goto create_msk; 464 } --- 4 unchanged lines hidden (view full) --- 469 goto create_child; 470 } 471 472create_msk: 473 new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req); 474 if (!new_msk) 475 fallback = true; 476 } else if (subflow_req->mp_join) { | 453 if (subflow_req->mp_capable) { 454 if (TCP_SKB_CB(skb)->seq != subflow_req->ssn_offset + 1) { 455 /* here we can receive and accept an in-window, 456 * out-of-order pkt, which will not carry the MP_CAPABLE 457 * opt even on mptcp enabled paths 458 */ 459 goto create_msk; 460 } --- 4 unchanged lines hidden (view full) --- 465 goto create_child; 466 } 467 468create_msk: 469 new_msk = mptcp_sk_clone(listener->conn, &mp_opt, req); 470 if (!new_msk) 471 fallback = true; 472 } else if (subflow_req->mp_join) { |
477 fallback_is_fatal = true; | |
478 mptcp_get_options(skb, &mp_opt); 479 if (!mp_opt.mp_join || 480 !subflow_hmac_valid(req, &mp_opt)) { 481 SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); | 473 mptcp_get_options(skb, &mp_opt); 474 if (!mp_opt.mp_join || 475 !subflow_hmac_valid(req, &mp_opt)) { 476 SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); |
482 return NULL; | 477 fallback = true; |
483 } 484 } 485 486create_child: 487 child = listener->icsk_af_ops->syn_recv_sock(sk, skb, req, dst, 488 req_unhash, own_req); 489 490 if (child && *own_req) { --- 26 unchanged lines hidden (view full) --- 517 * mpc option 518 */ 519 ctx->remote_key = mp_opt.sndr_key; 520 ctx->fully_established = mp_opt.mp_capable; 521 ctx->can_ack = mp_opt.mp_capable; 522 } else if (ctx->mp_join) { 523 struct mptcp_sock *owner; 524 | 478 } 479 } 480 481create_child: 482 child = listener->icsk_af_ops->syn_recv_sock(sk, skb, req, dst, 483 req_unhash, own_req); 484 485 if (child && *own_req) { --- 26 unchanged lines hidden (view full) --- 512 * mpc option 513 */ 514 ctx->remote_key = mp_opt.sndr_key; 515 ctx->fully_established = mp_opt.mp_capable; 516 ctx->can_ack = mp_opt.mp_capable; 517 } else if (ctx->mp_join) { 518 struct mptcp_sock *owner; 519 |
525 owner = mptcp_token_get_sock(ctx->token); | 520 owner = subflow_req->msk; |
526 if (!owner) 527 goto dispose_child; 528 | 521 if (!owner) 522 goto dispose_child; 523 |
524 /* move the msk reference ownership to the subflow */ 525 subflow_req->msk = NULL; |
|
529 ctx->conn = (struct sock *)owner; 530 if (!mptcp_finish_join(child)) 531 goto dispose_child; 532 533 SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKRX); 534 tcp_rsk(req)->drop_req = true; 535 } 536 } --- 716 unchanged lines hidden (view full) --- 1253 if (!subflow_ops->slab) 1254 return -ENOMEM; 1255 1256 subflow_ops->destructor = subflow_req_destructor; 1257 1258 return 0; 1259} 1260 | 526 ctx->conn = (struct sock *)owner; 527 if (!mptcp_finish_join(child)) 528 goto dispose_child; 529 530 SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKRX); 531 tcp_rsk(req)->drop_req = true; 532 } 533 } --- 716 unchanged lines hidden (view full) --- 1250 if (!subflow_ops->slab) 1251 return -ENOMEM; 1252 1253 subflow_ops->destructor = subflow_req_destructor; 1254 1255 return 0; 1256} 1257 |
1261void mptcp_subflow_init(void) | 1258void __init mptcp_subflow_init(void) |
1262{ 1263 subflow_request_sock_ops = tcp_request_sock_ops; 1264 if (subflow_ops_init(&subflow_request_sock_ops) != 0) 1265 panic("MPTCP: failed to init subflow request sock ops\n"); 1266 1267 subflow_request_sock_ipv4_ops = tcp_request_sock_ipv4_ops; 1268 subflow_request_sock_ipv4_ops.init_req = subflow_v4_init_req; 1269 --- 29 unchanged lines hidden --- | 1259{ 1260 subflow_request_sock_ops = tcp_request_sock_ops; 1261 if (subflow_ops_init(&subflow_request_sock_ops) != 0) 1262 panic("MPTCP: failed to init subflow request sock ops\n"); 1263 1264 subflow_request_sock_ipv4_ops = tcp_request_sock_ipv4_ops; 1265 subflow_request_sock_ipv4_ops.init_req = subflow_v4_init_req; 1266 --- 29 unchanged lines hidden --- |