All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.