From 0f5eb79a3fe94740d7efdeb685bc811d5d0f2ee7 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Wed, 15 Feb 2017 02:59:31 +0300 Subject: [PATCH] net: add a way to get a network namespace for a socket 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. Acked-by: Pavel Emelyanov Signed-off-by: Andrei Vagin --- criu/include/namespaces.h | 1 + criu/namespaces.c | 2 +- criu/net.c | 28 ++++++++++++++++++++++++---- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h index 5b39cbdae..1b454e0c1 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 6ad2eed68..1fd3f8a2b 100644 --- a/criu/namespaces.c +++ b/criu/namespaces.c @@ -324,7 +324,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 d1723ec05..6d708f40c 100644 --- a/criu/net.c +++ b/criu/net.c @@ -2290,11 +2290,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)