* [MPTCP] [PATCH v3 08/10] mptcp: Add handling of outgoing MP_JOIN requests
@ 2019-08-07 22:44 Peter Krystad
0 siblings, 0 replies; 5+ messages in thread
From: Peter Krystad @ 2019-08-07 22:44 UTC (permalink / raw)
To: mptcp
[-- Attachment #1: Type: text/plain, Size: 13177 bytes --]
Subflow creation may be initiated by the path manager when
the primary connection is fully established and a remote
address has been received via ADD_ADDR.
Create an in-kernel sock and use kernel_connect() to
initiate connection. When a valid SYN-ACK is received the
new sock is added to the tail of the mptcp sock conn_list
where it will not interfere with data flow on the original
connection.
Data flow and connection failover not addressed by this commit.
Signed-off-by: Peter Krystad <peter.krystad(a)linux.intel.com>
---
include/net/mptcp.h | 2 ++
net/mptcp/options.c | 51 ++++++++++++++++++++++++++++++---
net/mptcp/protocol.c | 1 +
net/mptcp/protocol.h | 11 +++++++
net/mptcp/subflow.c | 68 +++++++++++++++++++++++++++++++++++++++++++-
net/mptcp/token.c | 48 +++++++++++++++++++++++++++++++
6 files changed, 176 insertions(+), 5 deletions(-)
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index bb2dd193c0c5..50cd1b31ebdd 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -40,6 +40,8 @@ struct mptcp_out_options {
u8 backup;
u32 nonce;
u64 thmac;
+ u32 token;
+ u8 hmac[20];
struct mptcp_ext ext_copy;
#endif
};
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 01f59ad629e5..be7afa5aac6a 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -300,6 +300,16 @@ bool mptcp_syn_options(struct sock *sk, unsigned int *size,
opts->sndr_key = subflow->local_key;
*size = TCPOLEN_MPTCP_MPC_SYN;
return true;
+ } else if (subflow->request_join) {
+ pr_debug("remote_token=%u, nonce=%u", subflow->remote_token,
+ subflow->local_nonce);
+ opts->suboptions = OPTION_MPTCP_MPJ_SYN;
+ opts->join_id = subflow->remote_id;
+ opts->token = subflow->remote_token;
+ opts->nonce = subflow->local_nonce;
+ opts->backup = subflow->request_bkup;
+ *size = TCPOLEN_MPTCP_MPJ_SYN;
+ return true;
}
return false;
}
@@ -309,10 +319,17 @@ void mptcp_rcv_synsent(struct sock *sk)
struct tcp_sock *tp = tcp_sk(sk);
struct subflow_context *subflow = subflow_ctx(sk);
- pr_debug("subflow=%p", subflow);
if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) {
subflow->mp_capable = 1;
subflow->remote_key = tp->rx_opt.mptcp.sndr_key;
+ pr_debug("subflow=%p, remote_key=%llu", subflow,
+ subflow->remote_key);
+ } else if (subflow->request_join && tp->rx_opt.mptcp.mp_join) {
+ subflow->mp_join = 1;
+ subflow->thmac = tp->rx_opt.mptcp.thmac;
+ subflow->remote_nonce = tp->rx_opt.mptcp.nonce;
+ pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow,
+ subflow->thmac, subflow->remote_nonce);
}
}
@@ -322,7 +339,8 @@ static bool mptcp_established_options_mp(struct sock *sk, unsigned int *size,
{
struct subflow_context *subflow = subflow_ctx(sk);
- if (!subflow->fourth_ack && remaining >= TCPOLEN_MPTCP_MPC_ACK) {
+ if (subflow->mp_capable && !subflow->fourth_ack &&
+ remaining >= TCPOLEN_MPTCP_MPC_ACK) {
opts->suboptions = OPTION_MPTCP_MPC_ACK;
opts->sndr_key = subflow->local_key;
opts->rcvr_key = subflow->remote_key;
@@ -331,6 +349,14 @@ static bool mptcp_established_options_mp(struct sock *sk, unsigned int *size,
pr_debug("subflow=%p, local_key=%llu, remote_key=%llu",
subflow, subflow->local_key, subflow->remote_key);
return true;
+ } else if (subflow->mp_join && !subflow->fourth_ack &&
+ remaining >= TCPOLEN_MPTCP_MPJ_ACK) {
+ opts->suboptions = OPTION_MPTCP_MPJ_ACK;
+ memcpy(opts->hmac, subflow->hmac, MPTCPOPT_HMAC_LEN);
+ *size = TCPOLEN_MPTCP_MPJ_ACK;
+ subflow->fourth_ack = 1;
+ pr_debug("subflow=%p", subflow);
+ return true;
}
return false;
}
@@ -443,10 +469,11 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
unsigned int *size, unsigned int remaining,
struct mptcp_out_options *opts)
{
+ struct subflow_context *subflow = subflow_ctx(sk);
unsigned int opt_size = 0;
bool ret = false;
- if (!subflow_ctx(sk)->mp_capable)
+ if (!subflow->mp_capable && !subflow->mp_join)
return false;
opts->suboptions = 0;
@@ -546,7 +573,6 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
if (msk)
pm_fully_established(msk);
-
}
void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
@@ -595,6 +621,16 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
0, opts->addr_id);
}
+ if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
+ *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
+ TCPOLEN_MPTCP_MPJ_SYN,
+ opts->backup, opts->join_id);
+ put_unaligned_be32(opts->token, ptr);
+ ptr += 1;
+ put_unaligned_be32(opts->nonce, ptr);
+ ptr += 1;
+ }
+
if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) {
*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
TCPOLEN_MPTCP_MPJ_SYNACK,
@@ -605,6 +641,13 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
ptr += 1;
}
+ if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) {
+ *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
+ TCPOLEN_MPTCP_MPJ_ACK, 0, 0);
+ memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN);
+ ptr += 5;
+ }
+
if (opts->ext_copy.use_ack || opts->ext_copy.use_map) {
struct mptcp_ext *mpext = &opts->ext_copy;
u8 len = TCPOLEN_MPTCP_DSS_BASE;
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index fce5eea729ba..80a8c7e5a3e7 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -797,6 +797,7 @@ void mptcp_finish_connect(struct sock *sk, int mp_capable)
msk->local_key = subflow->local_key;
msk->token = subflow->token;
pr_debug("msk=%p, token=%u", msk, msk->token);
+ msk->dport = ntohs(inet_sk(msk->subflow->sk)->inet_dport);
pm_new_connection(msk, 0);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 9774ff5a5481..243d896d9e42 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -49,8 +49,10 @@
#define TCPOLEN_MPTCP_ADD_ADDR6 20
#define TCPOLEN_MPTCP_RM_ADDR 4
+/* MPTCP MP_JOIN flags */
#define MPTCPOPT_BACKUP BIT(0)
#define MPTCPOPT_HMAC_LEN 20
+#define MPTCPOPT_THMAC_LEN 8
/* MPTCP MP_CAPABLE flags */
#define MPTCP_VERSION_MASK (0x0F)
@@ -115,6 +117,7 @@ struct mptcp_sock {
u64 write_seq;
u64 ack_seq;
u32 token;
+ u16 dport;
struct list_head conn_list;
struct socket *subflow; /* outgoing connect/listener/!mp_capable */
struct mptcp_pm_data pm;
@@ -167,7 +170,9 @@ struct subflow_context {
u32 ssn_offset;
u16 map_data_len;
u16 request_mptcp : 1, /* send MP_CAPABLE */
+ request_join : 1, /* send MP_JOIN */
request_cksum : 1,
+ request_bkup : 1,
request_version : 4,
mp_capable : 1, /* remote is MPTCP capable */
mp_join : 1, /* remote is JOINing */
@@ -179,6 +184,8 @@ struct subflow_context {
u32 remote_nonce;
u64 thmac;
u32 local_nonce;
+ u32 remote_token;
+ u8 hmac[MPTCPOPT_HMAC_LEN];
u8 local_id;
u8 remote_id;
@@ -202,6 +209,8 @@ mptcp_subflow_tcp_socket(const struct subflow_context *subflow)
}
void subflow_init(void);
+int subflow_connect(struct sock *sk, struct sockaddr_in *local,
+ struct sockaddr_in *remote, u8 remote_id);
int subflow_create_socket(struct sock *sk, struct socket **new_sock);
extern const struct inet_connection_sock_af_ops ipv4_specific;
@@ -215,10 +224,12 @@ void mptcp_finish_join(struct sock *sk);
void token_init(void);
void token_new_request(struct request_sock *req, const struct sk_buff *skb);
int token_join_request(struct request_sock *req, const struct sk_buff *skb);
+int token_join_response(struct sock *sk);
int token_join_valid(struct request_sock *req,
struct tcp_options_received *rx_opt);
void token_destroy_request(u32 token);
void token_new_connect(struct sock *sk);
+void token_new_subflow(struct sock *sk);
void token_new_accept(struct sock *sk);
int token_new_join(struct sock *sk);
void token_update_accept(struct sock *sk, struct sock *conn);
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 678fca99c23a..448c9e7f567a 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -22,6 +22,9 @@ static int subflow_rebuild_header(struct sock *sk)
if (subflow->request_mptcp && !subflow->token) {
pr_debug("subflow=%p", sk);
token_new_connect(sk);
+ } else if (subflow->request_join && !subflow->local_nonce) {
+ pr_debug("subflow=%p", sk);
+ token_new_subflow(sk);
}
return inet_sk_rebuild_header(sk);
@@ -95,7 +98,10 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
inet_sk_rx_dst_set(sk, skb);
- if (subflow->conn && !subflow->conn_finished) {
+ if (!subflow->conn)
+ return;
+
+ if (subflow->mp_capable && !subflow->conn_finished) {
pr_debug("subflow=%p, remote_key=%llu", subflow_ctx(sk),
subflow->remote_key);
mptcp_finish_connect(subflow->conn, subflow->mp_capable);
@@ -105,6 +111,17 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
pr_debug("synack seq=%u", TCP_SKB_CB(skb)->seq);
subflow->ssn_offset = TCP_SKB_CB(skb)->seq;
}
+ } else if (subflow->mp_join && !subflow->conn_finished) {
+ pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u",
+ subflow_ctx(sk), subflow->thmac,
+ subflow->remote_nonce);
+ if (token_join_response(sk)) {
+ subflow->mp_join = 0;
+ // @@ need to trigger RST
+ } else {
+ mptcp_finish_join(sk);
+ subflow->conn_finished = 1;
+ }
}
}
@@ -195,6 +212,55 @@ static void subflow_data_ready(struct sock *sk)
}
}
+int subflow_connect(struct sock *sk, struct sockaddr_in *local,
+ struct sockaddr_in *remote, u8 remote_id)
+{
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ struct subflow_context *subflow;
+ struct socket *sf;
+ u32 remote_token;
+ int err;
+
+ lock_sock(sk);
+ err = subflow_create_socket(sk, &sf);
+ if (err) {
+ release_sock(sk);
+ return err;
+ }
+
+ subflow = subflow_ctx(sf->sk);
+ subflow->remote_key = msk->remote_key;
+ subflow->local_key = msk->local_key;
+ subflow->token = msk->token;
+
+ sock_hold(sf->sk);
+ release_sock(sk);
+
+ err = kernel_bind(sf, (struct sockaddr *)local,
+ sizeof(struct sockaddr_in));
+ if (err)
+ goto failed;
+
+ crypto_key_sha1(subflow->remote_key, &remote_token, NULL);
+ pr_debug("msk=%p remote_token=%u", msk, remote_token);
+ subflow->remote_token = remote_token;
+ subflow->remote_id = remote_id;
+ subflow->request_join = 1;
+ subflow->request_bkup = 1;
+
+ err = kernel_connect(sf, (struct sockaddr *)remote,
+ sizeof(struct sockaddr_in), O_NONBLOCK);
+ if (err && err != -EINPROGRESS)
+ goto failed;
+
+ sock_put(sf->sk);
+ return err;
+
+failed:
+ sock_release(sf);
+ return err;
+}
+
int subflow_create_socket(struct sock *sk, struct socket **new_sock)
{
struct subflow_context *subflow;
diff --git a/net/mptcp/token.c b/net/mptcp/token.c
index ef03ef19af98..d7cf40b40beb 100644
--- a/net/mptcp/token.c
+++ b/net/mptcp/token.c
@@ -93,6 +93,28 @@ static void new_req_join(struct request_sock *req, struct sock *sk,
subflow_req->thmac);
}
+static int new_rsp_join(struct sock *sk)
+{
+ struct subflow_context *subflow = subflow_ctx(sk);
+ u8 hmac[MPTCPOPT_HMAC_LEN];
+ u64 thmac;
+
+ crypto_hmac_sha1(subflow->remote_key, subflow->local_key,
+ subflow->remote_nonce, subflow->local_nonce,
+ (u32 *)hmac);
+
+ thmac = get_unaligned_be64(hmac);
+ pr_debug("thmac=%llu", thmac);
+ if (thmac != subflow->thmac)
+ return -1;
+
+ crypto_hmac_sha1(subflow->local_key, subflow->remote_key,
+ subflow->local_nonce, subflow->remote_nonce,
+ (u32 *)subflow->hmac);
+
+ return 0;
+}
+
static int new_join_valid(struct request_sock *req, struct sock *sk,
struct tcp_options_received *rx_opt)
{
@@ -210,6 +232,15 @@ int token_join_request(struct request_sock *req, const struct sk_buff *skb)
return -1;
}
+/* validate received truncated hmac and create hmac for third ACK */
+int token_join_response(struct sock *sk)
+{
+ struct subflow_context *subflow = subflow_ctx(sk);
+
+ pr_debug("subflow=%p, token=%u", subflow, subflow->token);
+ return new_rsp_join(sk);
+}
+
/* validate hmac received in third ACK */
int token_join_valid(struct request_sock *req,
struct tcp_options_received *rx_opt)
@@ -247,6 +278,23 @@ void token_new_connect(struct sock *sk)
spin_unlock_bh(&token_tree_lock);
}
+/* take reference to connection and create nonce for secondary subflow */
+void token_new_subflow(struct sock *sk)
+{
+ struct subflow_context *subflow = subflow_ctx(sk);
+ struct sock *conn;
+
+ pr_debug("subflow=%p", subflow);
+
+ spin_lock_bh(&token_tree_lock);
+ conn = lookup_token(subflow->token);
+ if (conn)
+ sock_hold(conn);
+ spin_unlock_bh(&token_tree_lock);
+
+ get_random_bytes(&subflow->local_nonce, sizeof(u32));
+}
+
void token_new_accept(struct sock *sk)
{
struct subflow_context *subflow = subflow_ctx(sk);
--
2.17.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [MPTCP] [PATCH v3 08/10] mptcp: Add handling of outgoing MP_JOIN requests
@ 2019-08-12 18:33 Mat Martineau
0 siblings, 0 replies; 5+ messages in thread
From: Mat Martineau @ 2019-08-12 18:33 UTC (permalink / raw)
To: mptcp
[-- Attachment #1: Type: text/plain, Size: 14178 bytes --]
On Wed, 7 Aug 2019, Peter Krystad wrote:
> Subflow creation may be initiated by the path manager when
> the primary connection is fully established and a remote
> address has been received via ADD_ADDR.
>
> Create an in-kernel sock and use kernel_connect() to
> initiate connection. When a valid SYN-ACK is received the
> new sock is added to the tail of the mptcp sock conn_list
> where it will not interfere with data flow on the original
> connection.
>
> Data flow and connection failover not addressed by this commit.
>
> Signed-off-by: Peter Krystad <peter.krystad(a)linux.intel.com>
> ---
> include/net/mptcp.h | 2 ++
> net/mptcp/options.c | 51 ++++++++++++++++++++++++++++++---
> net/mptcp/protocol.c | 1 +
> net/mptcp/protocol.h | 11 +++++++
> net/mptcp/subflow.c | 68 +++++++++++++++++++++++++++++++++++++++++++-
> net/mptcp/token.c | 48 +++++++++++++++++++++++++++++++
> 6 files changed, 176 insertions(+), 5 deletions(-)
>
> diff --git a/include/net/mptcp.h b/include/net/mptcp.h
> index bb2dd193c0c5..50cd1b31ebdd 100644
> --- a/include/net/mptcp.h
> +++ b/include/net/mptcp.h
> @@ -40,6 +40,8 @@ struct mptcp_out_options {
> u8 backup;
> u32 nonce;
> u64 thmac;
> + u32 token;
> + u8 hmac[20];
> struct mptcp_ext ext_copy;
> #endif
> };
> diff --git a/net/mptcp/options.c b/net/mptcp/options.c
> index 01f59ad629e5..be7afa5aac6a 100644
> --- a/net/mptcp/options.c
> +++ b/net/mptcp/options.c
> @@ -300,6 +300,16 @@ bool mptcp_syn_options(struct sock *sk, unsigned int *size,
> opts->sndr_key = subflow->local_key;
> *size = TCPOLEN_MPTCP_MPC_SYN;
> return true;
> + } else if (subflow->request_join) {
> + pr_debug("remote_token=%u, nonce=%u", subflow->remote_token,
> + subflow->local_nonce);
> + opts->suboptions = OPTION_MPTCP_MPJ_SYN;
> + opts->join_id = subflow->remote_id;
> + opts->token = subflow->remote_token;
> + opts->nonce = subflow->local_nonce;
> + opts->backup = subflow->request_bkup;
> + *size = TCPOLEN_MPTCP_MPJ_SYN;
> + return true;
> }
> return false;
> }
> @@ -309,10 +319,17 @@ void mptcp_rcv_synsent(struct sock *sk)
> struct tcp_sock *tp = tcp_sk(sk);
> struct subflow_context *subflow = subflow_ctx(sk);
>
> - pr_debug("subflow=%p", subflow);
> if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) {
> subflow->mp_capable = 1;
> subflow->remote_key = tp->rx_opt.mptcp.sndr_key;
> + pr_debug("subflow=%p, remote_key=%llu", subflow,
> + subflow->remote_key);
> + } else if (subflow->request_join && tp->rx_opt.mptcp.mp_join) {
> + subflow->mp_join = 1;
> + subflow->thmac = tp->rx_opt.mptcp.thmac;
> + subflow->remote_nonce = tp->rx_opt.mptcp.nonce;
> + pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow,
> + subflow->thmac, subflow->remote_nonce);
> }
> }
>
> @@ -322,7 +339,8 @@ static bool mptcp_established_options_mp(struct sock *sk, unsigned int *size,
> {
> struct subflow_context *subflow = subflow_ctx(sk);
>
> - if (!subflow->fourth_ack && remaining >= TCPOLEN_MPTCP_MPC_ACK) {
> + if (subflow->mp_capable && !subflow->fourth_ack &&
> + remaining >= TCPOLEN_MPTCP_MPC_ACK) {
> opts->suboptions = OPTION_MPTCP_MPC_ACK;
> opts->sndr_key = subflow->local_key;
> opts->rcvr_key = subflow->remote_key;
> @@ -331,6 +349,14 @@ static bool mptcp_established_options_mp(struct sock *sk, unsigned int *size,
> pr_debug("subflow=%p, local_key=%llu, remote_key=%llu",
> subflow, subflow->local_key, subflow->remote_key);
> return true;
> + } else if (subflow->mp_join && !subflow->fourth_ack &&
> + remaining >= TCPOLEN_MPTCP_MPJ_ACK) {
> + opts->suboptions = OPTION_MPTCP_MPJ_ACK;
> + memcpy(opts->hmac, subflow->hmac, MPTCPOPT_HMAC_LEN);
> + *size = TCPOLEN_MPTCP_MPJ_ACK;
> + subflow->fourth_ack = 1;
> + pr_debug("subflow=%p", subflow);
> + return true;
> }
> return false;
> }
> @@ -443,10 +469,11 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
> unsigned int *size, unsigned int remaining,
> struct mptcp_out_options *opts)
> {
> + struct subflow_context *subflow = subflow_ctx(sk);
> unsigned int opt_size = 0;
> bool ret = false;
>
> - if (!subflow_ctx(sk)->mp_capable)
> + if (!subflow->mp_capable && !subflow->mp_join)
> return false;
>
> opts->suboptions = 0;
> @@ -546,7 +573,6 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
>
> if (msk)
> pm_fully_established(msk);
> -
> }
>
> void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
> @@ -595,6 +621,16 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
> 0, opts->addr_id);
> }
>
> + if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
> + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
> + TCPOLEN_MPTCP_MPJ_SYN,
> + opts->backup, opts->join_id);
> + put_unaligned_be32(opts->token, ptr);
> + ptr += 1;
> + put_unaligned_be32(opts->nonce, ptr);
> + ptr += 1;
> + }
> +
> if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) {
> *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
> TCPOLEN_MPTCP_MPJ_SYNACK,
> @@ -605,6 +641,13 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
> ptr += 1;
> }
>
> + if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) {
> + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
> + TCPOLEN_MPTCP_MPJ_ACK, 0, 0);
> + memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN);
> + ptr += 5;
> + }
> +
> if (opts->ext_copy.use_ack || opts->ext_copy.use_map) {
> struct mptcp_ext *mpext = &opts->ext_copy;
> u8 len = TCPOLEN_MPTCP_DSS_BASE;
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index fce5eea729ba..80a8c7e5a3e7 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -797,6 +797,7 @@ void mptcp_finish_connect(struct sock *sk, int mp_capable)
> msk->local_key = subflow->local_key;
> msk->token = subflow->token;
> pr_debug("msk=%p, token=%u", msk, msk->token);
> + msk->dport = ntohs(inet_sk(msk->subflow->sk)->inet_dport);
>
> pm_new_connection(msk, 0);
>
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 9774ff5a5481..243d896d9e42 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -49,8 +49,10 @@
> #define TCPOLEN_MPTCP_ADD_ADDR6 20
> #define TCPOLEN_MPTCP_RM_ADDR 4
>
> +/* MPTCP MP_JOIN flags */
> #define MPTCPOPT_BACKUP BIT(0)
> #define MPTCPOPT_HMAC_LEN 20
> +#define MPTCPOPT_THMAC_LEN 8
>
> /* MPTCP MP_CAPABLE flags */
> #define MPTCP_VERSION_MASK (0x0F)
> @@ -115,6 +117,7 @@ struct mptcp_sock {
> u64 write_seq;
> u64 ack_seq;
> u32 token;
> + u16 dport;
> struct list_head conn_list;
> struct socket *subflow; /* outgoing connect/listener/!mp_capable */
> struct mptcp_pm_data pm;
> @@ -167,7 +170,9 @@ struct subflow_context {
> u32 ssn_offset;
> u16 map_data_len;
> u16 request_mptcp : 1, /* send MP_CAPABLE */
> + request_join : 1, /* send MP_JOIN */
> request_cksum : 1,
> + request_bkup : 1,
> request_version : 4,
> mp_capable : 1, /* remote is MPTCP capable */
> mp_join : 1, /* remote is JOINing */
> @@ -179,6 +184,8 @@ struct subflow_context {
> u32 remote_nonce;
> u64 thmac;
> u32 local_nonce;
> + u32 remote_token;
> + u8 hmac[MPTCPOPT_HMAC_LEN];
> u8 local_id;
> u8 remote_id;
>
> @@ -202,6 +209,8 @@ mptcp_subflow_tcp_socket(const struct subflow_context *subflow)
> }
>
> void subflow_init(void);
> +int subflow_connect(struct sock *sk, struct sockaddr_in *local,
> + struct sockaddr_in *remote, u8 remote_id);
> int subflow_create_socket(struct sock *sk, struct socket **new_sock);
>
> extern const struct inet_connection_sock_af_ops ipv4_specific;
> @@ -215,10 +224,12 @@ void mptcp_finish_join(struct sock *sk);
> void token_init(void);
> void token_new_request(struct request_sock *req, const struct sk_buff *skb);
> int token_join_request(struct request_sock *req, const struct sk_buff *skb);
> +int token_join_response(struct sock *sk);
> int token_join_valid(struct request_sock *req,
> struct tcp_options_received *rx_opt);
> void token_destroy_request(u32 token);
> void token_new_connect(struct sock *sk);
> +void token_new_subflow(struct sock *sk);
> void token_new_accept(struct sock *sk);
> int token_new_join(struct sock *sk);
> void token_update_accept(struct sock *sk, struct sock *conn);
> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> index 678fca99c23a..448c9e7f567a 100644
> --- a/net/mptcp/subflow.c
> +++ b/net/mptcp/subflow.c
> @@ -22,6 +22,9 @@ static int subflow_rebuild_header(struct sock *sk)
> if (subflow->request_mptcp && !subflow->token) {
> pr_debug("subflow=%p", sk);
> token_new_connect(sk);
> + } else if (subflow->request_join && !subflow->local_nonce) {
> + pr_debug("subflow=%p", sk);
> + token_new_subflow(sk);
> }
>
> return inet_sk_rebuild_header(sk);
> @@ -95,7 +98,10 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
>
> inet_sk_rx_dst_set(sk, skb);
>
> - if (subflow->conn && !subflow->conn_finished) {
> + if (!subflow->conn)
> + return;
> +
> + if (subflow->mp_capable && !subflow->conn_finished) {
> pr_debug("subflow=%p, remote_key=%llu", subflow_ctx(sk),
> subflow->remote_key);
> mptcp_finish_connect(subflow->conn, subflow->mp_capable);
> @@ -105,6 +111,17 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
> pr_debug("synack seq=%u", TCP_SKB_CB(skb)->seq);
> subflow->ssn_offset = TCP_SKB_CB(skb)->seq;
> }
> + } else if (subflow->mp_join && !subflow->conn_finished) {
> + pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u",
> + subflow_ctx(sk), subflow->thmac,
> + subflow->remote_nonce);
> + if (token_join_response(sk)) {
> + subflow->mp_join = 0;
> + // @@ need to trigger RST
> + } else {
> + mptcp_finish_join(sk);
> + subflow->conn_finished = 1;
> + }
> }
> }
>
> @@ -195,6 +212,55 @@ static void subflow_data_ready(struct sock *sk)
> }
> }
>
> +int subflow_connect(struct sock *sk, struct sockaddr_in *local,
> + struct sockaddr_in *remote, u8 remote_id)
> +{
> + struct mptcp_sock *msk = mptcp_sk(sk);
> + struct subflow_context *subflow;
> + struct socket *sf;
> + u32 remote_token;
> + int err;
> +
> + lock_sock(sk);
> + err = subflow_create_socket(sk, &sf);
> + if (err) {
> + release_sock(sk);
> + return err;
> + }
> +
> + subflow = subflow_ctx(sf->sk);
> + subflow->remote_key = msk->remote_key;
> + subflow->local_key = msk->local_key;
> + subflow->token = msk->token;
> +
> + sock_hold(sf->sk);
> + release_sock(sk);
> +
> + err = kernel_bind(sf, (struct sockaddr *)local,
> + sizeof(struct sockaddr_in));
> + if (err)
> + goto failed;
> +
> + crypto_key_sha1(subflow->remote_key, &remote_token, NULL);
> + pr_debug("msk=%p remote_token=%u", msk, remote_token);
> + subflow->remote_token = remote_token;
> + subflow->remote_id = remote_id;
> + subflow->request_join = 1;
> + subflow->request_bkup = 1;
> +
> + err = kernel_connect(sf, (struct sockaddr *)remote,
> + sizeof(struct sockaddr_in), O_NONBLOCK);
> + if (err && err != -EINPROGRESS)
> + goto failed;
> +
> + sock_put(sf->sk);
> + return err;
> +
> +failed:
> + sock_release(sf);
Should there be a sock_put(sf->sk) on this path too? Looks like
sock_release() will free the subflow context but not the struct sock
itself.
Mat
> + return err;
> +}
> +
> int subflow_create_socket(struct sock *sk, struct socket **new_sock)
> {
> struct subflow_context *subflow;
> diff --git a/net/mptcp/token.c b/net/mptcp/token.c
> index ef03ef19af98..d7cf40b40beb 100644
> --- a/net/mptcp/token.c
> +++ b/net/mptcp/token.c
> @@ -93,6 +93,28 @@ static void new_req_join(struct request_sock *req, struct sock *sk,
> subflow_req->thmac);
> }
>
> +static int new_rsp_join(struct sock *sk)
> +{
> + struct subflow_context *subflow = subflow_ctx(sk);
> + u8 hmac[MPTCPOPT_HMAC_LEN];
> + u64 thmac;
> +
> + crypto_hmac_sha1(subflow->remote_key, subflow->local_key,
> + subflow->remote_nonce, subflow->local_nonce,
> + (u32 *)hmac);
> +
> + thmac = get_unaligned_be64(hmac);
> + pr_debug("thmac=%llu", thmac);
> + if (thmac != subflow->thmac)
> + return -1;
> +
> + crypto_hmac_sha1(subflow->local_key, subflow->remote_key,
> + subflow->local_nonce, subflow->remote_nonce,
> + (u32 *)subflow->hmac);
> +
> + return 0;
> +}
> +
> static int new_join_valid(struct request_sock *req, struct sock *sk,
> struct tcp_options_received *rx_opt)
> {
> @@ -210,6 +232,15 @@ int token_join_request(struct request_sock *req, const struct sk_buff *skb)
> return -1;
> }
>
> +/* validate received truncated hmac and create hmac for third ACK */
> +int token_join_response(struct sock *sk)
> +{
> + struct subflow_context *subflow = subflow_ctx(sk);
> +
> + pr_debug("subflow=%p, token=%u", subflow, subflow->token);
> + return new_rsp_join(sk);
> +}
> +
> /* validate hmac received in third ACK */
> int token_join_valid(struct request_sock *req,
> struct tcp_options_received *rx_opt)
> @@ -247,6 +278,23 @@ void token_new_connect(struct sock *sk)
> spin_unlock_bh(&token_tree_lock);
> }
>
> +/* take reference to connection and create nonce for secondary subflow */
> +void token_new_subflow(struct sock *sk)
> +{
> + struct subflow_context *subflow = subflow_ctx(sk);
> + struct sock *conn;
> +
> + pr_debug("subflow=%p", subflow);
> +
> + spin_lock_bh(&token_tree_lock);
> + conn = lookup_token(subflow->token);
> + if (conn)
> + sock_hold(conn);
> + spin_unlock_bh(&token_tree_lock);
> +
> + get_random_bytes(&subflow->local_nonce, sizeof(u32));
> +}
> +
> void token_new_accept(struct sock *sk)
> {
> struct subflow_context *subflow = subflow_ctx(sk);
> --
> 2.17.2
>
> _______________________________________________
> mptcp mailing list
> mptcp(a)lists.01.org
> https://lists.01.org/mailman/listinfo/mptcp
>
--
Mat Martineau
Intel
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [MPTCP] [PATCH v3 08/10] mptcp: Add handling of outgoing MP_JOIN requests
@ 2019-08-12 19:36 Matthieu Baerts
0 siblings, 0 replies; 5+ messages in thread
From: Matthieu Baerts @ 2019-08-12 19:36 UTC (permalink / raw)
To: mptcp
[-- Attachment #1: Type: text/plain, Size: 961 bytes --]
Hi Peter, Paolo, Mat,
On 08/08/2019 00:44, Peter Krystad wrote:
> Subflow creation may be initiated by the path manager when
> the primary connection is fully established and a remote
> address has been received via ADD_ADDR.
>
> Create an in-kernel sock and use kernel_connect() to
> initiate connection. When a valid SYN-ACK is received the
> new sock is added to the tail of the mptcp sock conn_list
> where it will not interfere with data flow on the original
> connection.
>
> Data flow and connection failover not addressed by this commit.
Thank you for the patch and the reviews!
Added at the end of the series:
- 31bf10533d43: "new commit" in
t/mptcp-Add-handling-of-outgoing-MP_JOIN-requests
- 417bdddfeedd..f7d9e8ce4717: result
Cheers,
Matt
--
Matthieu Baerts | R&D Engineer
matthieu.baerts(a)tessares.net
Tessares SA | Hybrid Access Solutions
www.tessares.net
1 Avenue Jean Monnet, 1348 Louvain-la-Neuve, Belgium
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [MPTCP] [PATCH v3 08/10] mptcp: Add handling of outgoing MP_JOIN requests
@ 2019-08-12 19:36 Matthieu Baerts
0 siblings, 0 replies; 5+ messages in thread
From: Matthieu Baerts @ 2019-08-12 19:36 UTC (permalink / raw)
To: mptcp
[-- Attachment #1: Type: text/plain, Size: 2461 bytes --]
Hi Mat, Peter,
On 12/08/2019 20:33, Mat Martineau wrote:
> On Wed, 7 Aug 2019, Peter Krystad wrote:
(...)
>> diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
>> index 678fca99c23a..448c9e7f567a 100644
>> --- a/net/mptcp/subflow.c
>> +++ b/net/mptcp/subflow.c
(...)
>> @@ -195,6 +212,55 @@ static void subflow_data_ready(struct sock *sk)
>> }
>> }
>>
>> +int subflow_connect(struct sock *sk, struct sockaddr_in *local,
>> + struct sockaddr_in *remote, u8 remote_id)
>> +{
>> + struct mptcp_sock *msk = mptcp_sk(sk);
>> + struct subflow_context *subflow;
>> + struct socket *sf;
>> + u32 remote_token;
>> + int err;
>> +
>> + lock_sock(sk);
>> + err = subflow_create_socket(sk, &sf);
>> + if (err) {
>> + release_sock(sk);
>> + return err;
>> + }
>> +
>> + subflow = subflow_ctx(sf->sk);
>> + subflow->remote_key = msk->remote_key;
>> + subflow->local_key = msk->local_key;
>> + subflow->token = msk->token;
>> +
>> + sock_hold(sf->sk);
>> + release_sock(sk);
>> +
>> + err = kernel_bind(sf, (struct sockaddr *)local,
>> + sizeof(struct sockaddr_in));
>> + if (err)
>> + goto failed;
>> +
>> + crypto_key_sha1(subflow->remote_key, &remote_token, NULL);
>> + pr_debug("msk=%p remote_token=%u", msk, remote_token);
>> + subflow->remote_token = remote_token;
>> + subflow->remote_id = remote_id;
>> + subflow->request_join = 1;
>> + subflow->request_bkup = 1;
>> +
>> + err = kernel_connect(sf, (struct sockaddr *)remote,
>> + sizeof(struct sockaddr_in), O_NONBLOCK);
>> + if (err && err != -EINPROGRESS)
>> + goto failed;
>> +
>> + sock_put(sf->sk);
>> + return err;
>> +
>> +failed:
>> + sock_release(sf);
>
> Should there be a sock_put(sf->sk) on this path too? Looks like
> sock_release() will free the subflow context but not the struct sock
> itself.
Please note that I just applied this patch series. But do not hesitate
to create a new patch to fix this if needed!
Cheers,
Matt
--
Matthieu Baerts | R&D Engineer
matthieu.baerts(a)tessares.net
Tessares SA | Hybrid Access Solutions
www.tessares.net
1 Avenue Jean Monnet, 1348 Louvain-la-Neuve, Belgium
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [MPTCP] [PATCH v3 08/10] mptcp: Add handling of outgoing MP_JOIN requests
@ 2019-08-12 22:36 Peter Krystad
0 siblings, 0 replies; 5+ messages in thread
From: Peter Krystad @ 2019-08-12 22:36 UTC (permalink / raw)
To: mptcp
[-- Attachment #1: Type: text/plain, Size: 15190 bytes --]
On Mon, 2019-08-12 at 11:33 -0700, Mat Martineau wrote:
> On Wed, 7 Aug 2019, Peter Krystad wrote:
>
> > Subflow creation may be initiated by the path manager when
> > the primary connection is fully established and a remote
> > address has been received via ADD_ADDR.
> >
> > Create an in-kernel sock and use kernel_connect() to
> > initiate connection. When a valid SYN-ACK is received the
> > new sock is added to the tail of the mptcp sock conn_list
> > where it will not interfere with data flow on the original
> > connection.
> >
> > Data flow and connection failover not addressed by this commit.
> >
> > Signed-off-by: Peter Krystad <peter.krystad(a)linux.intel.com>
> > ---
> > include/net/mptcp.h | 2 ++
> > net/mptcp/options.c | 51 ++++++++++++++++++++++++++++++---
> > net/mptcp/protocol.c | 1 +
> > net/mptcp/protocol.h | 11 +++++++
> > net/mptcp/subflow.c | 68 +++++++++++++++++++++++++++++++++++++++++++-
> > net/mptcp/token.c | 48 +++++++++++++++++++++++++++++++
> > 6 files changed, 176 insertions(+), 5 deletions(-)
> >
> > diff --git a/include/net/mptcp.h b/include/net/mptcp.h
> > index bb2dd193c0c5..50cd1b31ebdd 100644
> > --- a/include/net/mptcp.h
> > +++ b/include/net/mptcp.h
> > @@ -40,6 +40,8 @@ struct mptcp_out_options {
> > u8 backup;
> > u32 nonce;
> > u64 thmac;
> > + u32 token;
> > + u8 hmac[20];
> > struct mptcp_ext ext_copy;
> > #endif
> > };
> > diff --git a/net/mptcp/options.c b/net/mptcp/options.c
> > index 01f59ad629e5..be7afa5aac6a 100644
> > --- a/net/mptcp/options.c
> > +++ b/net/mptcp/options.c
> > @@ -300,6 +300,16 @@ bool mptcp_syn_options(struct sock *sk, unsigned int *size,
> > opts->sndr_key = subflow->local_key;
> > *size = TCPOLEN_MPTCP_MPC_SYN;
> > return true;
> > + } else if (subflow->request_join) {
> > + pr_debug("remote_token=%u, nonce=%u", subflow->remote_token,
> > + subflow->local_nonce);
> > + opts->suboptions = OPTION_MPTCP_MPJ_SYN;
> > + opts->join_id = subflow->remote_id;
> > + opts->token = subflow->remote_token;
> > + opts->nonce = subflow->local_nonce;
> > + opts->backup = subflow->request_bkup;
> > + *size = TCPOLEN_MPTCP_MPJ_SYN;
> > + return true;
> > }
> > return false;
> > }
> > @@ -309,10 +319,17 @@ void mptcp_rcv_synsent(struct sock *sk)
> > struct tcp_sock *tp = tcp_sk(sk);
> > struct subflow_context *subflow = subflow_ctx(sk);
> >
> > - pr_debug("subflow=%p", subflow);
> > if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) {
> > subflow->mp_capable = 1;
> > subflow->remote_key = tp->rx_opt.mptcp.sndr_key;
> > + pr_debug("subflow=%p, remote_key=%llu", subflow,
> > + subflow->remote_key);
> > + } else if (subflow->request_join && tp->rx_opt.mptcp.mp_join) {
> > + subflow->mp_join = 1;
> > + subflow->thmac = tp->rx_opt.mptcp.thmac;
> > + subflow->remote_nonce = tp->rx_opt.mptcp.nonce;
> > + pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u", subflow,
> > + subflow->thmac, subflow->remote_nonce);
> > }
> > }
> >
> > @@ -322,7 +339,8 @@ static bool mptcp_established_options_mp(struct sock *sk, unsigned int *size,
> > {
> > struct subflow_context *subflow = subflow_ctx(sk);
> >
> > - if (!subflow->fourth_ack && remaining >= TCPOLEN_MPTCP_MPC_ACK) {
> > + if (subflow->mp_capable && !subflow->fourth_ack &&
> > + remaining >= TCPOLEN_MPTCP_MPC_ACK) {
> > opts->suboptions = OPTION_MPTCP_MPC_ACK;
> > opts->sndr_key = subflow->local_key;
> > opts->rcvr_key = subflow->remote_key;
> > @@ -331,6 +349,14 @@ static bool mptcp_established_options_mp(struct sock *sk, unsigned int *size,
> > pr_debug("subflow=%p, local_key=%llu, remote_key=%llu",
> > subflow, subflow->local_key, subflow->remote_key);
> > return true;
> > + } else if (subflow->mp_join && !subflow->fourth_ack &&
> > + remaining >= TCPOLEN_MPTCP_MPJ_ACK) {
> > + opts->suboptions = OPTION_MPTCP_MPJ_ACK;
> > + memcpy(opts->hmac, subflow->hmac, MPTCPOPT_HMAC_LEN);
> > + *size = TCPOLEN_MPTCP_MPJ_ACK;
> > + subflow->fourth_ack = 1;
> > + pr_debug("subflow=%p", subflow);
> > + return true;
> > }
> > return false;
> > }
> > @@ -443,10 +469,11 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
> > unsigned int *size, unsigned int remaining,
> > struct mptcp_out_options *opts)
> > {
> > + struct subflow_context *subflow = subflow_ctx(sk);
> > unsigned int opt_size = 0;
> > bool ret = false;
> >
> > - if (!subflow_ctx(sk)->mp_capable)
> > + if (!subflow->mp_capable && !subflow->mp_join)
> > return false;
> >
> > opts->suboptions = 0;
> > @@ -546,7 +573,6 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
> >
> > if (msk)
> > pm_fully_established(msk);
> > -
> > }
> >
> > void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
> > @@ -595,6 +621,16 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
> > 0, opts->addr_id);
> > }
> >
> > + if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
> > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
> > + TCPOLEN_MPTCP_MPJ_SYN,
> > + opts->backup, opts->join_id);
> > + put_unaligned_be32(opts->token, ptr);
> > + ptr += 1;
> > + put_unaligned_be32(opts->nonce, ptr);
> > + ptr += 1;
> > + }
> > +
> > if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) {
> > *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
> > TCPOLEN_MPTCP_MPJ_SYNACK,
> > @@ -605,6 +641,13 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
> > ptr += 1;
> > }
> >
> > + if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) {
> > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
> > + TCPOLEN_MPTCP_MPJ_ACK, 0, 0);
> > + memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN);
> > + ptr += 5;
> > + }
> > +
> > if (opts->ext_copy.use_ack || opts->ext_copy.use_map) {
> > struct mptcp_ext *mpext = &opts->ext_copy;
> > u8 len = TCPOLEN_MPTCP_DSS_BASE;
> > diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> > index fce5eea729ba..80a8c7e5a3e7 100644
> > --- a/net/mptcp/protocol.c
> > +++ b/net/mptcp/protocol.c
> > @@ -797,6 +797,7 @@ void mptcp_finish_connect(struct sock *sk, int mp_capable)
> > msk->local_key = subflow->local_key;
> > msk->token = subflow->token;
> > pr_debug("msk=%p, token=%u", msk, msk->token);
> > + msk->dport = ntohs(inet_sk(msk->subflow->sk)->inet_dport);
> >
> > pm_new_connection(msk, 0);
> >
> > diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> > index 9774ff5a5481..243d896d9e42 100644
> > --- a/net/mptcp/protocol.h
> > +++ b/net/mptcp/protocol.h
> > @@ -49,8 +49,10 @@
> > #define TCPOLEN_MPTCP_ADD_ADDR6 20
> > #define TCPOLEN_MPTCP_RM_ADDR 4
> >
> > +/* MPTCP MP_JOIN flags */
> > #define MPTCPOPT_BACKUP BIT(0)
> > #define MPTCPOPT_HMAC_LEN 20
> > +#define MPTCPOPT_THMAC_LEN 8
> >
> > /* MPTCP MP_CAPABLE flags */
> > #define MPTCP_VERSION_MASK (0x0F)
> > @@ -115,6 +117,7 @@ struct mptcp_sock {
> > u64 write_seq;
> > u64 ack_seq;
> > u32 token;
> > + u16 dport;
> > struct list_head conn_list;
> > struct socket *subflow; /* outgoing connect/listener/!mp_capable */
> > struct mptcp_pm_data pm;
> > @@ -167,7 +170,9 @@ struct subflow_context {
> > u32 ssn_offset;
> > u16 map_data_len;
> > u16 request_mptcp : 1, /* send MP_CAPABLE */
> > + request_join : 1, /* send MP_JOIN */
> > request_cksum : 1,
> > + request_bkup : 1,
> > request_version : 4,
> > mp_capable : 1, /* remote is MPTCP capable */
> > mp_join : 1, /* remote is JOINing */
> > @@ -179,6 +184,8 @@ struct subflow_context {
> > u32 remote_nonce;
> > u64 thmac;
> > u32 local_nonce;
> > + u32 remote_token;
> > + u8 hmac[MPTCPOPT_HMAC_LEN];
> > u8 local_id;
> > u8 remote_id;
> >
> > @@ -202,6 +209,8 @@ mptcp_subflow_tcp_socket(const struct subflow_context *subflow)
> > }
> >
> > void subflow_init(void);
> > +int subflow_connect(struct sock *sk, struct sockaddr_in *local,
> > + struct sockaddr_in *remote, u8 remote_id);
> > int subflow_create_socket(struct sock *sk, struct socket **new_sock);
> >
> > extern const struct inet_connection_sock_af_ops ipv4_specific;
> > @@ -215,10 +224,12 @@ void mptcp_finish_join(struct sock *sk);
> > void token_init(void);
> > void token_new_request(struct request_sock *req, const struct sk_buff *skb);
> > int token_join_request(struct request_sock *req, const struct sk_buff *skb);
> > +int token_join_response(struct sock *sk);
> > int token_join_valid(struct request_sock *req,
> > struct tcp_options_received *rx_opt);
> > void token_destroy_request(u32 token);
> > void token_new_connect(struct sock *sk);
> > +void token_new_subflow(struct sock *sk);
> > void token_new_accept(struct sock *sk);
> > int token_new_join(struct sock *sk);
> > void token_update_accept(struct sock *sk, struct sock *conn);
> > diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
> > index 678fca99c23a..448c9e7f567a 100644
> > --- a/net/mptcp/subflow.c
> > +++ b/net/mptcp/subflow.c
> > @@ -22,6 +22,9 @@ static int subflow_rebuild_header(struct sock *sk)
> > if (subflow->request_mptcp && !subflow->token) {
> > pr_debug("subflow=%p", sk);
> > token_new_connect(sk);
> > + } else if (subflow->request_join && !subflow->local_nonce) {
> > + pr_debug("subflow=%p", sk);
> > + token_new_subflow(sk);
> > }
> >
> > return inet_sk_rebuild_header(sk);
> > @@ -95,7 +98,10 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
> >
> > inet_sk_rx_dst_set(sk, skb);
> >
> > - if (subflow->conn && !subflow->conn_finished) {
> > + if (!subflow->conn)
> > + return;
> > +
> > + if (subflow->mp_capable && !subflow->conn_finished) {
> > pr_debug("subflow=%p, remote_key=%llu", subflow_ctx(sk),
> > subflow->remote_key);
> > mptcp_finish_connect(subflow->conn, subflow->mp_capable);
> > @@ -105,6 +111,17 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
> > pr_debug("synack seq=%u", TCP_SKB_CB(skb)->seq);
> > subflow->ssn_offset = TCP_SKB_CB(skb)->seq;
> > }
> > + } else if (subflow->mp_join && !subflow->conn_finished) {
> > + pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u",
> > + subflow_ctx(sk), subflow->thmac,
> > + subflow->remote_nonce);
> > + if (token_join_response(sk)) {
> > + subflow->mp_join = 0;
> > + // @@ need to trigger RST
> > + } else {
> > + mptcp_finish_join(sk);
> > + subflow->conn_finished = 1;
> > + }
> > }
> > }
> >
> > @@ -195,6 +212,55 @@ static void subflow_data_ready(struct sock *sk)
> > }
> > }
> >
> > +int subflow_connect(struct sock *sk, struct sockaddr_in *local,
> > + struct sockaddr_in *remote, u8 remote_id)
> > +{
> > + struct mptcp_sock *msk = mptcp_sk(sk);
> > + struct subflow_context *subflow;
> > + struct socket *sf;
> > + u32 remote_token;
> > + int err;
> > +
> > + lock_sock(sk);
> > + err = subflow_create_socket(sk, &sf);
> > + if (err) {
> > + release_sock(sk);
> > + return err;
> > + }
> > +
> > + subflow = subflow_ctx(sf->sk);
> > + subflow->remote_key = msk->remote_key;
> > + subflow->local_key = msk->local_key;
> > + subflow->token = msk->token;
> > +
> > + sock_hold(sf->sk);
> > + release_sock(sk);
> > +
> > + err = kernel_bind(sf, (struct sockaddr *)local,
> > + sizeof(struct sockaddr_in));
> > + if (err)
> > + goto failed;
> > +
> > + crypto_key_sha1(subflow->remote_key, &remote_token, NULL);
> > + pr_debug("msk=%p remote_token=%u", msk, remote_token);
> > + subflow->remote_token = remote_token;
> > + subflow->remote_id = remote_id;
> > + subflow->request_join = 1;
> > + subflow->request_bkup = 1;
> > +
> > + err = kernel_connect(sf, (struct sockaddr *)remote,
> > + sizeof(struct sockaddr_in), O_NONBLOCK);
> > + if (err && err != -EINPROGRESS)
> > + goto failed;
> > +
> > + sock_put(sf->sk);
> > + return err;
> > +
> > +failed:
> > + sock_release(sf);
>
> Should there be a sock_put(sf->sk) on this path too? Looks like
> sock_release() will free the subflow context but not the struct sock
> itself.
>
Yes. Since this is already merged I'll submit a separate patch.
Peter.
> Mat
>
>
> > + return err;
> > +}
> > +
> > int subflow_create_socket(struct sock *sk, struct socket **new_sock)
> > {
> > struct subflow_context *subflow;
> > diff --git a/net/mptcp/token.c b/net/mptcp/token.c
> > index ef03ef19af98..d7cf40b40beb 100644
> > --- a/net/mptcp/token.c
> > +++ b/net/mptcp/token.c
> > @@ -93,6 +93,28 @@ static void new_req_join(struct request_sock *req, struct sock *sk,
> > subflow_req->thmac);
> > }
> >
> > +static int new_rsp_join(struct sock *sk)
> > +{
> > + struct subflow_context *subflow = subflow_ctx(sk);
> > + u8 hmac[MPTCPOPT_HMAC_LEN];
> > + u64 thmac;
> > +
> > + crypto_hmac_sha1(subflow->remote_key, subflow->local_key,
> > + subflow->remote_nonce, subflow->local_nonce,
> > + (u32 *)hmac);
> > +
> > + thmac = get_unaligned_be64(hmac);
> > + pr_debug("thmac=%llu", thmac);
> > + if (thmac != subflow->thmac)
> > + return -1;
> > +
> > + crypto_hmac_sha1(subflow->local_key, subflow->remote_key,
> > + subflow->local_nonce, subflow->remote_nonce,
> > + (u32 *)subflow->hmac);
> > +
> > + return 0;
> > +}
> > +
> > static int new_join_valid(struct request_sock *req, struct sock *sk,
> > struct tcp_options_received *rx_opt)
> > {
> > @@ -210,6 +232,15 @@ int token_join_request(struct request_sock *req, const struct sk_buff *skb)
> > return -1;
> > }
> >
> > +/* validate received truncated hmac and create hmac for third ACK */
> > +int token_join_response(struct sock *sk)
> > +{
> > + struct subflow_context *subflow = subflow_ctx(sk);
> > +
> > + pr_debug("subflow=%p, token=%u", subflow, subflow->token);
> > + return new_rsp_join(sk);
> > +}
> > +
> > /* validate hmac received in third ACK */
> > int token_join_valid(struct request_sock *req,
> > struct tcp_options_received *rx_opt)
> > @@ -247,6 +278,23 @@ void token_new_connect(struct sock *sk)
> > spin_unlock_bh(&token_tree_lock);
> > }
> >
> > +/* take reference to connection and create nonce for secondary subflow */
> > +void token_new_subflow(struct sock *sk)
> > +{
> > + struct subflow_context *subflow = subflow_ctx(sk);
> > + struct sock *conn;
> > +
> > + pr_debug("subflow=%p", subflow);
> > +
> > + spin_lock_bh(&token_tree_lock);
> > + conn = lookup_token(subflow->token);
> > + if (conn)
> > + sock_hold(conn);
> > + spin_unlock_bh(&token_tree_lock);
> > +
> > + get_random_bytes(&subflow->local_nonce, sizeof(u32));
> > +}
> > +
> > void token_new_accept(struct sock *sk)
> > {
> > struct subflow_context *subflow = subflow_ctx(sk);
> > --
> > 2.17.2
> >
> > _______________________________________________
> > mptcp mailing list
> > mptcp(a)lists.01.org
> > https://lists.01.org/mailman/listinfo/mptcp
> >
>
> --
> Mat Martineau
> Intel
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-08-12 22:36 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-08-07 22:44 [MPTCP] [PATCH v3 08/10] mptcp: Add handling of outgoing MP_JOIN requests Peter Krystad
-- strict thread matches above, loose matches on Subject: below --
2019-08-12 18:33 Mat Martineau
2019-08-12 19:36 Matthieu Baerts
2019-08-12 19:36 Matthieu Baerts
2019-08-12 22:36 Peter Krystad
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.