[09/10] net: add a way to get a network namespace for a socket

Submitted by Andrei Vagin on Feb. 13, 2017, 5:49 a.m.

Details

Message ID 1486964960-4872-10-git-send-email-avagin@openvz.org
State New
Series "Dump and restore nested network namespaces"
Headers show

Commit Message

Andrei Vagin Feb. 13, 2017, 5:49 a.m.
From: Andrei Vagin <avagin@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@virtuozzo.com>
---
 criu/include/namespaces.h |  1 +
 criu/namespaces.c         |  2 +-
 criu/net.c                | 28 ++++++++++++++++++++++++----
 criu/sockets.c            |  3 ++-
 4 files changed, 28 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index 5b39cbd..1b454e0 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -187,5 +187,6 @@  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 *get_socket_ns(int lfd);
+extern struct ns_id *lookup_ns_by_kid(unsigned int kid, struct ns_desc *nd);
 
 #endif /* __CR_NS_H__ */
diff --git a/criu/namespaces.c b/criu/namespaces.c
index d796888..9e61c94 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -327,7 +327,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 7000923..2001998 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -2054,11 +2054,31 @@  static struct ns_id *get_root_netns()
  */
 struct ns_id *get_socket_ns(int lfd)
 {
-	if (netns_nr == 1)
-		return get_root_netns();
+	struct ns_id *ns;
+	struct stat st;
+	int ns_fd;
 
-	pr_perror("Unable to get a socket net namespace");
-	return NULL;
+	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)
diff --git a/criu/sockets.c b/criu/sockets.c
index 95da999..420eee8 100644
--- a/criu/sockets.c
+++ b/criu/sockets.c
@@ -27,6 +27,7 @@ 
 #include "fs-magic.h"
 #include "pstree.h"
 #include "util.h"
+#include "fdstore.h"
 
 #ifndef SOCK_DIAG_BY_FAMILY
 #define SOCK_DIAG_BY_FAMILY 20
@@ -762,7 +763,7 @@  int set_netns(uint32_t ns_id)
 		pr_err("Unable to find a network namespace");
 		return -1;
 	}
-	nsfd = open_proc(root_item->pid->ns[0].virt, "fd/%d", ns->net.ns_fd);
+	nsfd = fdstore_get(ns->net.nsfd_id);
 	if (nsfd < 0)
 		return -1;
 	if (setns(nsfd, CLONE_NEWNET)) {

Comments

Pavel Emelianov Feb. 13, 2017, 1:17 p.m.
> @@ -762,7 +763,7 @@ int set_netns(uint32_t ns_id)
>  		pr_err("Unable to find a network namespace");
>  		return -1;
>  	}
> -	nsfd = open_proc(root_item->pid->ns[0].virt, "fd/%d", ns->net.ns_fd);
> +	nsfd = fdstore_get(ns->net.nsfd_id);

Ah... run away hunk from patch number ... 7? ;)

>  	if (nsfd < 0)
>  		return -1;
>  	if (setns(nsfd, CLONE_NEWNET)) {
>