diff options
author | Peter Krystad <peter.krystad@linux.intel.com> | 2020-03-27 22:48:38 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-30 07:14:48 +0200 |
commit | 1b1c7a0ef7f323f37281b134ade17baa94779787 (patch) | |
tree | 8fddc2a7ad56b081558cf89950a646ec9c4afab5 /net/mptcp/options.c | |
parent | mptcp: Add ADD_ADDR handling (diff) | |
download | linux-1b1c7a0ef7f323f37281b134ade17baa94779787.tar.xz linux-1b1c7a0ef7f323f37281b134ade17baa94779787.zip |
mptcp: Add path manager interface
Add enough of a path manager interface to allow sending of ADD_ADDR
when an incoming MPTCP connection is created. Capable of sending only
a single IPv4 ADD_ADDR option. The 'pm_data' element of the connection
sock will need to be expanded to handle multiple interfaces and IPv6.
Partial processing of the incoming ADD_ADDR is included so the path
manager notification of that event happens at the proper time, which
involves validating the incoming address information.
This is a skeleton interface definition for events generated by
MPTCP.
Co-developed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Co-developed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Florian Westphal <fw@strlen.de>
Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Peter Krystad <peter.krystad@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mptcp/options.c')
-rw-r--r-- | net/mptcp/options.c | 80 |
1 files changed, 64 insertions, 16 deletions
diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 6c6c18a09a40..a3661318a7af 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -492,36 +492,35 @@ static bool mptcp_established_options_addr(struct sock *sk, { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct mptcp_sock *msk = mptcp_sk(subflow->conn); - struct sockaddr_storage saddr; - u8 id; + struct mptcp_addr_info saddr; + int len; - id = 0; - memset(&saddr, 0, sizeof(saddr)); + if (!mptcp_pm_should_signal(msk) || + !(mptcp_pm_addr_signal(msk, remaining, &saddr))) + return false; + + len = mptcp_add_addr_len(saddr.family); + if (remaining < len) + return false; - if (saddr.ss_family == AF_INET) { - if (remaining < TCPOLEN_MPTCP_ADD_ADDR) - return false; + *size = len; + opts->addr_id = saddr.id; + if (saddr.family == AF_INET) { opts->suboptions |= OPTION_MPTCP_ADD_ADDR; - opts->addr_id = id; - opts->addr = ((struct sockaddr_in *)&saddr)->sin_addr; + opts->addr = saddr.addr; opts->ahmac = add_addr_generate_hmac(msk->local_key, msk->remote_key, opts->addr_id, &opts->addr); - *size = TCPOLEN_MPTCP_ADD_ADDR; } #if IS_ENABLED(CONFIG_MPTCP_IPV6) - else if (saddr.ss_family == AF_INET6) { - if (remaining < TCPOLEN_MPTCP_ADD_ADDR6) - return false; + else if (saddr.family == AF_INET6) { opts->suboptions |= OPTION_MPTCP_ADD_ADDR6; - opts->addr_id = id; + opts->addr6 = saddr.addr6; opts->ahmac = add_addr6_generate_hmac(msk->local_key, msk->remote_key, opts->addr_id, &opts->addr6); - opts->addr6 = ((struct sockaddr_in6 *)&saddr)->sin6_addr; - *size = TCPOLEN_MPTCP_ADD_ADDR6; } #endif pr_debug("addr_id=%d, ahmac=%llu", opts->addr_id, opts->ahmac); @@ -607,10 +606,37 @@ static bool check_fully_established(struct mptcp_subflow_context *subflow, return true; } +static bool add_addr_hmac_valid(struct mptcp_sock *msk, + struct mptcp_options_received *mp_opt) +{ + u64 hmac = 0; + + if (mp_opt->echo) + return true; + + if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) + hmac = add_addr_generate_hmac(msk->remote_key, + msk->local_key, + mp_opt->addr_id, &mp_opt->addr); +#if IS_ENABLED(CONFIG_MPTCP_IPV6) + else + hmac = add_addr6_generate_hmac(msk->remote_key, + msk->local_key, + mp_opt->addr_id, &mp_opt->addr6); +#endif + + pr_debug("msk=%p, ahmac=%llu, mp_opt->ahmac=%llu\n", + msk, (unsigned long long)hmac, + (unsigned long long)mp_opt->ahmac); + + return hmac == mp_opt->ahmac; +} + void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, struct tcp_options_received *opt_rx) { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); + struct mptcp_sock *msk = mptcp_sk(subflow->conn); struct mptcp_options_received *mp_opt; struct mptcp_ext *mpext; @@ -618,6 +644,26 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, if (!check_fully_established(subflow, skb, mp_opt)) return; + if (mp_opt->add_addr && add_addr_hmac_valid(msk, mp_opt)) { + struct mptcp_addr_info addr; + + addr.port = htons(mp_opt->port); + addr.id = mp_opt->addr_id; + if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) { + addr.family = AF_INET; + addr.addr = mp_opt->addr; + } +#if IS_ENABLED(CONFIG_MPTCP_IPV6) + else if (mp_opt->family == MPTCP_ADDR_IPVERSION_6) { + addr.family = AF_INET6; + addr.addr6 = mp_opt->addr6; + } +#endif + if (!mp_opt->echo) + mptcp_pm_add_addr_received(msk, &addr); + mp_opt->add_addr = 0; + } + if (!mp_opt->dss) return; @@ -654,6 +700,8 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, } mpext->data_fin = mp_opt->data_fin; + + mptcp_pm_fully_established(msk); } void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts) |