[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