[CRIU] [PATCH 04/10] net: add a way to get a network namespace for a socket
Andrei Vagin
avagin at openvz.org
Wed Aug 31 15:55:27 PDT 2016
From: Andrei Vagin <avagin at virtuozzo.com>
Each sockets belongs to one network namespace and operates
in this network namespace.
socket_diag reports informations about sockets from
one network namespace, but it doesn't report sockets which
are not bound or connected to somewhere. So we need to have
a way to get network namespaces for such sockets.
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
criu/include/namespaces.h | 3 +++
criu/namespaces.c | 2 +-
criu/net.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index a163ed1..2b183f2 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -183,4 +183,7 @@ extern int __userns_call(const char *func_name, uns_call_t call, int flags,
extern int add_ns_shared_cb(int (*actor)(void *data), void *data);
+extern struct ns_id *lookup_ns_by_kid(unsigned int kid, struct ns_desc *nd);
+extern struct ns_id *get_socket_ns(int lfd);
+
#endif /* __CR_NS_H__ */
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 151f740..1d54a9f 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -319,7 +319,7 @@ int rst_add_ns_id(unsigned int id, struct pstree_item *i, struct ns_desc *nd)
return 0;
}
-static struct ns_id *lookup_ns_by_kid(unsigned int kid, struct ns_desc *nd)
+struct ns_id *lookup_ns_by_kid(unsigned int kid, struct ns_desc *nd)
{
struct ns_id *nsid;
diff --git a/criu/net.c b/criu/net.c
index d0b71c4..e4a7627 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1703,6 +1703,7 @@ err_nl:
goto out;
}
+static int netns_nr;
static int collect_net_ns(struct ns_id *ns, void *oarg)
{
bool for_dump = (oarg == (void *)1);
@@ -1713,6 +1714,8 @@ static int collect_net_ns(struct ns_id *ns, void *oarg)
if (ret)
return ret;
+ netns_nr++;
+
if (!for_dump)
return 0;
@@ -1727,6 +1730,48 @@ int collect_net_namespaces(bool for_dump)
struct ns_desc net_ns_desc = NS_DESC_ENTRY(CLONE_NEWNET, "net");
+static struct ns_id *get_root_netns()
+{
+ static struct ns_id *root_netns = NULL;
+
+ if (root_item->ids == NULL)
+ return NULL;
+
+ if (root_netns == NULL)
+ root_netns = lookup_ns_by_id(root_item->ids->net_ns_id, &net_ns_desc);
+
+ return root_netns;
+}
+
+struct ns_id *get_socket_ns(int lfd)
+{
+ struct ns_id *ns;
+ struct stat st;
+ int ns_fd;
+
+ ns_fd = ioctl(lfd, SIOCGSKNS);
+ if (ns_fd < 0) {
+ /* backward compatiblity with old kernels */
+ if (netns_nr == 1)
+ return get_root_netns();
+
+ pr_perror("Unable to get a socket net namespace");
+ return NULL;
+ }
+ if (fstat(ns_fd, &st)) {
+ pr_perror("Unable to stat a network namespace");
+ return NULL;
+ }
+
+ ns = lookup_ns_by_kid(st.st_ino, &net_ns_desc);
+ if (ns == NULL) {
+ pr_err("Unable to dump a socket from an external network namespace\n");
+ return NULL;
+ }
+
+ return ns;
+}
+
int kerndat_socket_netns(void)
{
int sk, ns_fd;
--
2.7.4
More information about the CRIU
mailing list