diff options
Diffstat (limited to 'src/shared/socket-netlink.c')
-rw-r--r-- | src/shared/socket-netlink.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c index 0ba5762..a126d5d 100644 --- a/src/shared/socket-netlink.c +++ b/src/shared/socket-netlink.c @@ -1,15 +1,19 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ +#include <net/if.h> #include <arpa/inet.h> #include <errno.h> -#include <net/if.h> +#include <linux/net_namespace.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 +411,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, + /* ret_pidns_fd = */ NULL, + /* ret_mntns_fd = */ NULL, + &_netns_fd, + /* ret_userns_fd = */ NULL, + /* ret_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; +} |