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>
This commit is contained in:
Geliang Tang 2024-03-01 19:18:36 +01:00 committed by David S. Miller
parent 06afe09091
commit d32c8fb1c8
2 changed files with 76 additions and 0 deletions

View file

@ -638,3 +638,77 @@ int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
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;
}

View file

@ -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)
{