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:
parent
06afe09091
commit
d32c8fb1c8
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user