aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGeliang Tang <tanggeliang@kylinos.cn>2024-03-01 19:18:36 +0100
committerDavid S. Miller <davem@davemloft.net>2024-03-04 13:07:46 +0000
commitd32c8fb1c881478e4af8e6ac3c922d35c8ba3ca8 (patch)
tree68351234e541cbcfdd63a046c0f3441aee07f55d
parentmptcp: add userspace_pm_lookup_addr_by_id helper (diff)
downloadwireguard-linux-d32c8fb1c881478e4af8e6ac3c922d35c8ba3ca8.tar.xz
wireguard-linux-d32c8fb1c881478e4af8e6ac3c922d35c8ba3ca8.zip
mptcp: implement mptcp_userspace_pm_get_addr
This patch implements mptcp_userspace_pm_get_addr() to get an address from userspace pm address list according the given 'token' and 'id'. Use nla_get_u32() to get the u32 value of 'token', then pass it to mptcp_token_get_sock() to get the msk. Pass 'msk' and 'id' to the helper mptcp_userspace_pm_lookup_addr_by_id() to get the address entry. Put this entry to userspace using mptcp_pm_nl_put_entry_info(). Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Reviewed-by: Mat Martineau <martineau@kernel.org> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/mptcp/pm_userspace.c74
-rw-r--r--net/mptcp/protocol.h2
2 files changed, 76 insertions, 0 deletions
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 20cbcb62cd8c..b9809d988693 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -638,3 +638,77 @@ out:
sock_put(sk);
return ret;
}
+
+int mptcp_userspace_pm_get_addr(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct nlattr *attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR];
+ struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
+ struct mptcp_pm_addr_entry addr, *entry;
+ struct net *net = sock_net(skb->sk);
+ struct mptcp_sock *msk;
+ struct sk_buff *msg;
+ int ret = -EINVAL;
+ struct sock *sk;
+ void *reply;
+
+ msk = mptcp_token_get_sock(net, nla_get_u32(token));
+ if (!msk) {
+ NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ return ret;
+ }
+
+ sk = (struct sock *)msk;
+
+ if (!mptcp_pm_is_userspace(msk)) {
+ GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
+ goto out;
+ }
+
+ ret = mptcp_pm_parse_entry(attr, info, false, &addr);
+ if (ret < 0)
+ goto out;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0,
+ info->genlhdr->cmd);
+ if (!reply) {
+ GENL_SET_ERR_MSG(info, "not enough space in Netlink message");
+ ret = -EMSGSIZE;
+ goto fail;
+ }
+
+ lock_sock(sk);
+ spin_lock_bh(&msk->pm.lock);
+ entry = mptcp_userspace_pm_lookup_addr_by_id(msk, addr.addr.id);
+ if (!entry) {
+ GENL_SET_ERR_MSG(info, "address not found");
+ ret = -EINVAL;
+ goto unlock_fail;
+ }
+
+ ret = mptcp_nl_fill_addr(msg, entry);
+ if (ret)
+ goto unlock_fail;
+
+ genlmsg_end(msg, reply);
+ ret = genlmsg_reply(msg, info);
+ spin_unlock_bh(&msk->pm.lock);
+ release_sock(sk);
+ sock_put(sk);
+ return ret;
+
+unlock_fail:
+ spin_unlock_bh(&msk->pm.lock);
+ release_sock(sk);
+fail:
+ nlmsg_free(msg);
+out:
+ sock_put(sk);
+ return ret;
+}
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index f23ca7645e96..f848e0203e88 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -1069,6 +1069,8 @@ int mptcp_pm_nl_dump_addr(struct sk_buff *msg,
struct netlink_callback *cb);
int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
struct netlink_callback *cb);
+int mptcp_userspace_pm_get_addr(struct sk_buff *skb,
+ struct genl_info *info);
static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflow)
{