]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
mptcp: implement mptcp_userspace_pm_dump_addr
authorGeliang Tang <tanggeliang@kylinos.cn>
Fri, 1 Mar 2024 18:18:27 +0000 (19:18 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 4 Mar 2024 13:07:45 +0000 (13:07 +0000)
This patch implements mptcp_userspace_pm_dump_addr() to dump addresses
from userspace pm address list. Use mptcp_token_get_sock() to get the
msk from the given token, if userspace PM is enabled in it, traverse
each address entry in address list, put every entry to userspace using
mptcp_pm_nl_put_entry_msg().

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>
net/mptcp/pm_userspace.c
net/mptcp/protocol.h

index bc97cc30f013abdba076aa93596dd213e9353eb8..d6b7be3afbe5135c199b5e04e92235aaca4dfa32 100644 (file)
@@ -572,3 +572,63 @@ set_flags_err:
        sock_put(sk);
        return ret;
 }
+
+int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
+                                struct netlink_callback *cb)
+{
+       struct id_bitmap {
+               DECLARE_BITMAP(map, MPTCP_PM_MAX_ADDR_ID + 1);
+       } *bitmap;
+       const struct genl_info *info = genl_info_dump(cb);
+       struct net *net = sock_net(msg->sk);
+       struct mptcp_pm_addr_entry *entry;
+       struct mptcp_sock *msk;
+       struct nlattr *token;
+       int ret = -EINVAL;
+       struct sock *sk;
+       void *hdr;
+
+       bitmap = (struct id_bitmap *)cb->ctx;
+       token = info->attrs[MPTCP_PM_ATTR_TOKEN];
+
+       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;
+       }
+
+       lock_sock(sk);
+       spin_lock_bh(&msk->pm.lock);
+       list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
+               if (test_bit(entry->addr.id, bitmap->map))
+                       continue;
+
+               hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
+                                 cb->nlh->nlmsg_seq, &mptcp_genl_family,
+                                 NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
+               if (!hdr)
+                       break;
+
+               if (mptcp_nl_fill_addr(msg, entry) < 0) {
+                       genlmsg_cancel(msg, hdr);
+                       break;
+               }
+
+               __set_bit(entry->addr.id, bitmap->map);
+               genlmsg_end(msg, hdr);
+       }
+       spin_unlock_bh(&msk->pm.lock);
+       release_sock(sk);
+       ret = msg->len;
+
+out:
+       sock_put(sk);
+       return ret;
+}
index 10117715c57f1b3723dfda39826fec64aa4c479d..829a492c8d19dfacb83f48d18f3081178a67b3bc 100644 (file)
@@ -1064,6 +1064,8 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
 int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
+int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
+                                struct netlink_callback *cb);
 
 static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflow)
 {