]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: add netns_get_nsid() helper to show nsid of netns
authorLennart Poettering <lennart@poettering.net>
Fri, 12 Jan 2024 10:49:35 +0000 (11:49 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 12 Jan 2024 20:43:34 +0000 (21:43 +0100)
src/shared/socket-netlink.c
src/shared/socket-netlink.h
src/test/test-socket-netlink.c

index 0ba57627615d89b773d51e613d4e6348bd232170..94b699a5ee6ae251abac21dbd2ccb12cccc8ad61 100644 (file)
@@ -2,14 +2,17 @@
 
 #include <arpa/inet.h>
 #include <errno.h>
+#include <linux/net_namespace.h>
 #include <net/if.h>
 #include <string.h>
 
 #include "alloc-util.h"
 #include "errno-util.h"
 #include "extract-word.h"
+#include "fd-util.h"
 #include "log.h"
 #include "memory-util.h"
+#include "namespace-util.h"
 #include "netlink-util.h"
 #include "parse-util.h"
 #include "socket-netlink.h"
@@ -407,3 +410,69 @@ const char *in_addr_full_to_string(struct in_addr_full *a) {
 
         return a->cached_server_string;
 }
+
+int netns_get_nsid(int netnsfd, uint32_t *ret) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        _cleanup_close_ int _netns_fd = -EBADF;
+        int r;
+
+        if (netnsfd < 0) {
+                r = namespace_open(
+                                0,
+                                /* pidns_fd= */ NULL,
+                                /* mntns_fd= */ NULL,
+                                &_netns_fd,
+                                /* userns_fd= */ NULL,
+                                /* root_fd= */ NULL);
+                if (r < 0)
+                        return r;
+
+                netnsfd = _netns_fd;
+        }
+
+        r = sd_netlink_open(&rtnl);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_new_nsid(rtnl, &req, RTM_GETNSID);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_append_s32(req, NETNSA_FD, netnsfd);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_call(rtnl, req, 0, &reply);
+        if (r < 0)
+                return r;
+
+        for (sd_netlink_message *m = reply; m; m = sd_netlink_message_next(m)) {
+                uint16_t type;
+
+                r = sd_netlink_message_get_errno(m);
+                if (r < 0)
+                        return r;
+
+                r = sd_netlink_message_get_type(m, &type);
+                if (r < 0)
+                        return r;
+                if (type != RTM_NEWNSID)
+                        continue;
+
+                uint32_t u;
+                r = sd_netlink_message_read_u32(m, NETNSA_NSID, &u);
+                if (r < 0)
+                        return r;
+
+                if (u == UINT32_MAX) /* no NSID assigned yet */
+                        return -ENODATA;
+
+                if (ret)
+                        *ret = u;
+
+                return 0;
+        }
+
+        return -ENXIO;
+}
index 6256a831bac3fefb09cd00e440ca16776b971549..2c06fbe3a7d56fa3dc78a3b90a83a2a7c5ab2330 100644 (file)
@@ -42,3 +42,5 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct in_addr_full*, in_addr_full_free);
 int in_addr_full_new(int family, const union in_addr_union *a, uint16_t port, int ifindex, const char *server_name, struct in_addr_full **ret);
 int in_addr_full_new_from_string(const char *s, struct in_addr_full **ret);
 const char *in_addr_full_to_string(struct in_addr_full *a);
+
+int netns_get_nsid(int netnsfd, uint32_t *ret);
index 6dbd50f4a1bf83bde1c0a1a1b4176293b6dbf6ca..ad642ca4b1facfe47b902bf95c15e8da500385c8 100644 (file)
@@ -369,4 +369,16 @@ TEST(in_addr_port_ifindex_name_from_string_auto) {
         test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo#hoge.com", AF_INET6, 53, 1, "hoge.com", "[fe80::18]:53%1#hoge.com");
 }
 
+TEST(netns_get_nsid) {
+        uint32_t u;
+        int r;
+
+        r = netns_get_nsid(-EBADF, &u);
+        assert_se(r == -ENODATA || r >= 0);
+        if (r == -ENODATA)
+                log_info("Our network namespace has no NSID assigned.");
+        else
+                log_info("Our NSID is %" PRIu32, u);
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);