summary refs log tree commit diff
path: root/src/platform/nmp-netns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/nmp-netns.c')
-rw-r--r--src/platform/nmp-netns.c1067
1 files changed, 533 insertions, 534 deletions
diff --git a/src/platform/nmp-netns.c b/src/platform/nmp-netns.c
index bc91d7a8..07f7a7c9 100644
--- a/src/platform/nmp-netns.c
+++ b/src/platform/nmp-netns.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2016 Red Hat, Inc.
  */
@@ -28,103 +28,107 @@
 #define PROC_SELF_NS_MNT "/proc/self/ns/mnt"
 #define PROC_SELF_NS_NET "/proc/self/ns/net"
 
-#define _CLONE_NS_ALL    ((int) (CLONE_NEWNS | CLONE_NEWNET))
-#define _CLONE_NS_ALL_V          CLONE_NEWNS , CLONE_NEWNET
+#define _CLONE_NS_ALL   ((int) (CLONE_NEWNS | CLONE_NEWNET))
+#define _CLONE_NS_ALL_V CLONE_NEWNS, CLONE_NEWNET
 
-static
-NM_UTILS_FLAGS2STR_DEFINE (_clone_ns_to_str, int,
-	NM_UTILS_FLAGS2STR (CLONE_NEWNS,  "mnt"),
-	NM_UTILS_FLAGS2STR (CLONE_NEWNET, "net"),
-);
+static NM_UTILS_FLAGS2STR_DEFINE(_clone_ns_to_str,
+                                 int,
+                                 NM_UTILS_FLAGS2STR(CLONE_NEWNS, "mnt"),
+                                 NM_UTILS_FLAGS2STR(CLONE_NEWNET, "net"), );
 
 static const char *
-__ns_types_to_str (int ns_types, int ns_types_already_set, char *buf, gsize len)
+__ns_types_to_str(int ns_types, int ns_types_already_set, char *buf, gsize len)
 {
-	const char *b = buf;
-	char bb[200];
-
-	nm_utils_strbuf_append_c (&buf, &len, '[');
-	if (ns_types & ~ns_types_already_set) {
-		nm_utils_strbuf_append_str (&buf, &len,
-		                            _clone_ns_to_str (ns_types & ~ns_types_already_set, bb, sizeof (bb)));
-	}
-	if (ns_types & ns_types_already_set) {
-		if (ns_types & ~ns_types_already_set)
-			nm_utils_strbuf_append_c (&buf, &len, '/');
-		nm_utils_strbuf_append_str (&buf, &len,
-		                            _clone_ns_to_str (ns_types & ns_types_already_set, bb, sizeof (bb)));
-	}
-	nm_utils_strbuf_append_c (&buf, &len, ']');
-	return b;
+    const char *b = buf;
+    char        bb[200];
+
+    nm_utils_strbuf_append_c(&buf, &len, '[');
+    if (ns_types & ~ns_types_already_set) {
+        nm_utils_strbuf_append_str(
+            &buf,
+            &len,
+            _clone_ns_to_str(ns_types & ~ns_types_already_set, bb, sizeof(bb)));
+    }
+    if (ns_types & ns_types_already_set) {
+        if (ns_types & ~ns_types_already_set)
+            nm_utils_strbuf_append_c(&buf, &len, '/');
+        nm_utils_strbuf_append_str(
+            &buf,
+            &len,
+            _clone_ns_to_str(ns_types & ns_types_already_set, bb, sizeof(bb)));
+    }
+    nm_utils_strbuf_append_c(&buf, &len, ']');
+    return b;
 }
 #define _ns_types_to_str(ns_types, ns_types_already_set, buf) \
-	__ns_types_to_str (ns_types, ns_types_already_set, buf, sizeof (buf))
+    __ns_types_to_str(ns_types, ns_types_already_set, buf, sizeof(buf))
 
 /*****************************************************************************/
 
-#define _NMLOG_DOMAIN        LOGD_PLATFORM
-#define _NMLOG_PREFIX_NAME   "netns"
-#define _NMLOG(level, netns, ...) \
-    G_STMT_START { \
-        NMLogLevel _level = (level); \
-        \
-        if (nm_logging_enabled (_level, _NMLOG_DOMAIN)) { \
-            NMPNetns *_netns = (netns); \
-            char _sbuf[20]; \
-            \
-            _nm_log (_level, _NMLOG_DOMAIN, 0, NULL, NULL, \
-                     "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
-                     _NMLOG_PREFIX_NAME, \
-                     (_netns ? nm_sprintf_buf (_sbuf, "[%p]", _netns) : "") \
-                     _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
-        } \
-    } G_STMT_END
+#define _NMLOG_DOMAIN      LOGD_PLATFORM
+#define _NMLOG_PREFIX_NAME "netns"
+#define _NMLOG(level, netns, ...)                                     \
+    G_STMT_START                                                      \
+    {                                                                 \
+        NMLogLevel _level = (level);                                  \
+                                                                      \
+        if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) {              \
+            NMPNetns *_netns = (netns);                               \
+            char      _sbuf[20];                                      \
+                                                                      \
+            _nm_log(_level,                                           \
+                    _NMLOG_DOMAIN,                                    \
+                    0,                                                \
+                    NULL,                                             \
+                    NULL,                                             \
+                    "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__),      \
+                    _NMLOG_PREFIX_NAME,                               \
+                    (_netns ? nm_sprintf_buf(_sbuf, "[%p]", _netns)   \
+                            : "") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+        }                                                             \
+    }                                                                 \
+    G_STMT_END
 
 /*****************************************************************************/
 
-NM_GOBJECT_PROPERTIES_DEFINE_BASE (
-	PROP_FD_NET,
-	PROP_FD_MNT,
-);
+NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_FD_NET, PROP_FD_MNT, );
 
 typedef struct {
-	int fd_net;
-	int fd_mnt;
+    int fd_net;
+    int fd_mnt;
 } NMPNetnsPrivate;
 
 struct _NMPNetns {
-	GObject parent;
-	NMPNetnsPrivate _priv;
+    GObject         parent;
+    NMPNetnsPrivate _priv;
 };
 
 struct _NMPNetnsClass {
-	GObjectClass parent;
+    GObjectClass parent;
 };
 
-G_DEFINE_TYPE (NMPNetns, nmp_netns, G_TYPE_OBJECT);
+G_DEFINE_TYPE(NMPNetns, nmp_netns, G_TYPE_OBJECT);
 
-#define NMP_NETNS_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMPNetns, NMP_IS_NETNS)
+#define NMP_NETNS_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMPNetns, NMP_IS_NETNS)
 
 /*****************************************************************************/
 
 typedef struct {
-	NMPNetns *netns;
-	int count;
-	int ns_types;
+    NMPNetns *netns;
+    int       count;
+    int       ns_types;
 } NetnsInfo;
 
-static void _stack_push (GArray *netns_stack,
-                         NMPNetns *netns,
-                         int ns_types);
-static NMPNetns *_netns_new (GError **error);
+static void      _stack_push(GArray *netns_stack, NMPNetns *netns, int ns_types);
+static NMPNetns *_netns_new(GError **error);
 
 /*****************************************************************************/
 
 static NMPNetns *
-_netns_get (NetnsInfo *info)
+_netns_get(NetnsInfo *info)
 {
-	nm_assert (!info || NMP_IS_NETNS (info->netns));
-	return info ? info->netns : NULL;
+    nm_assert(!info || NMP_IS_NETNS(info->netns));
+    return info ? info->netns : NULL;
 }
 
 /*****************************************************************************/
@@ -132,634 +136,629 @@ _netns_get (NetnsInfo *info)
 static _nm_thread_local GArray *_netns_stack = NULL;
 
 static void
-_netns_stack_clear_cb (gpointer data)
+_netns_stack_clear_cb(gpointer data)
 {
-	NetnsInfo *info = data;
+    NetnsInfo *info = data;
 
-	nm_assert (NMP_IS_NETNS (info->netns));
-	g_object_unref (info->netns);
+    nm_assert(NMP_IS_NETNS(info->netns));
+    g_object_unref(info->netns);
 }
 
 static GArray *
-_netns_stack_get_impl (void)
+_netns_stack_get_impl(void)
 {
-	gs_unref_object NMPNetns *netns = NULL;
-	gs_free_error GError *error = NULL;
-	pthread_key_t key;
-	GArray *s;
-
-	s = g_array_new (FALSE, FALSE, sizeof (NetnsInfo));
-	g_array_set_clear_func (s, _netns_stack_clear_cb);
-	_netns_stack = s;
-
-	/* at the bottom of the stack we must try to create a netns instance
-	 * that we never pop. It's the base to which we need to return. */
-	netns = _netns_new (&error);
-	if (!netns) {
-		_LOGE (NULL, "failed to create initial netns: %s", error->message);
-		return s;
-	}
-
-	/* we leak this instance inside the stack. */
-	_stack_push (s, netns, _CLONE_NS_ALL);
-
-	/* finally, register a destructor function to cleanup the array. If we fail
-	 * to do so, we will leak NMPNetns instances (and their file descriptor) when the
-	 * thread exits. */
-	if (pthread_key_create (&key, (void (*) (void *)) g_array_unref) != 0)
-		_LOGE (NULL, "failure to initialize thread-local storage");
-	else if (pthread_setspecific (key, s) != 0)
-		_LOGE (NULL, "failure to set thread-local storage");
-
-	return s;
+    gs_unref_object NMPNetns *netns = NULL;
+    gs_free_error GError *error     = NULL;
+    pthread_key_t         key;
+    GArray *              s;
+
+    s = g_array_new(FALSE, FALSE, sizeof(NetnsInfo));
+    g_array_set_clear_func(s, _netns_stack_clear_cb);
+    _netns_stack = s;
+
+    /* at the bottom of the stack we must try to create a netns instance
+     * that we never pop. It's the base to which we need to return. */
+    netns = _netns_new(&error);
+    if (!netns) {
+        _LOGE(NULL, "failed to create initial netns: %s", error->message);
+        return s;
+    }
+
+    /* we leak this instance inside the stack. */
+    _stack_push(s, netns, _CLONE_NS_ALL);
+
+    /* finally, register a destructor function to cleanup the array. If we fail
+     * to do so, we will leak NMPNetns instances (and their file descriptor) when the
+     * thread exits. */
+    if (pthread_key_create(&key, (void (*)(void *)) g_array_unref) != 0)
+        _LOGE(NULL, "failure to initialize thread-local storage");
+    else if (pthread_setspecific(key, s) != 0)
+        _LOGE(NULL, "failure to set thread-local storage");
+
+    return s;
 }
 
-#define _netns_stack_get() \
-	({ \
-		GArray *_s = _netns_stack; \
-		\
-		if (G_UNLIKELY (!_s)) \
-			_s = _netns_stack_get_impl (); \
-		_s; \
-	})
+#define _netns_stack_get()                \
+    ({                                    \
+        GArray *_s = _netns_stack;        \
+                                          \
+        if (G_UNLIKELY(!_s))              \
+            _s = _netns_stack_get_impl(); \
+        _s;                               \
+    })
 
 /*****************************************************************************/
 
 static NMPNetns *
-_stack_current_netns (GArray *netns_stack,
-                      int ns_types)
+_stack_current_netns(GArray *netns_stack, int ns_types)
 {
-	guint j;
+    guint j;
 
-	nm_assert (netns_stack && netns_stack->len > 0);
+    nm_assert(netns_stack && netns_stack->len > 0);
 
-	/* we search the stack top-down to find the netns that has
-	 * all @ns_types set. */
-	for (j = netns_stack->len; ns_types && j >= 1; ) {
-		NetnsInfo *info;
+    /* we search the stack top-down to find the netns that has
+     * all @ns_types set. */
+    for (j = netns_stack->len; ns_types && j >= 1;) {
+        NetnsInfo *info;
 
-		info = &g_array_index (netns_stack, NetnsInfo, --j);
+        info = &g_array_index(netns_stack, NetnsInfo, --j);
 
-		if (NM_FLAGS_ALL (info->ns_types, ns_types))
-			return info->netns;
-	}
+        if (NM_FLAGS_ALL(info->ns_types, ns_types))
+            return info->netns;
+    }
 
-	g_return_val_if_reached (NULL);
+    g_return_val_if_reached(NULL);
 }
 
 static int
-_stack_current_ns_types (GArray *netns_stack,
-                         NMPNetns *netns,
-                         int ns_types)
+_stack_current_ns_types(GArray *netns_stack, NMPNetns *netns, int ns_types)
 {
-	const int ns_types_check[] = { _CLONE_NS_ALL_V };
-	guint i, j;
-	int res = 0;
-
-	nm_assert (netns);
-	nm_assert (netns_stack && netns_stack->len > 0);
-
-	/* we search the stack top-down to check which of @ns_types
-	 * are already set to @netns. */
-	for (j = netns_stack->len; ns_types && j >= 1; ) {
-		NetnsInfo *info;
-
-		info = &g_array_index (netns_stack, NetnsInfo, --j);
-		if (info->netns != netns) {
-			ns_types = NM_FLAGS_UNSET (ns_types, info->ns_types);
-			continue;
-		}
-
-		for (i = 0; i < G_N_ELEMENTS (ns_types_check); i++) {
-			if (   NM_FLAGS_ANY (ns_types, ns_types_check[i])
-			    && NM_FLAGS_ANY (info->ns_types, ns_types_check[i])) {
-				res = NM_FLAGS_SET (res, ns_types_check[i]);
-				ns_types = NM_FLAGS_UNSET (ns_types, ns_types_check[i]);
-			}
-		}
-	}
-
-	return res;
+    const int ns_types_check[] = {_CLONE_NS_ALL_V};
+    guint     i, j;
+    int       res = 0;
+
+    nm_assert(netns);
+    nm_assert(netns_stack && netns_stack->len > 0);
+
+    /* we search the stack top-down to check which of @ns_types
+     * are already set to @netns. */
+    for (j = netns_stack->len; ns_types && j >= 1;) {
+        NetnsInfo *info;
+
+        info = &g_array_index(netns_stack, NetnsInfo, --j);
+        if (info->netns != netns) {
+            ns_types = NM_FLAGS_UNSET(ns_types, info->ns_types);
+            continue;
+        }
+
+        for (i = 0; i < G_N_ELEMENTS(ns_types_check); i++) {
+            if (NM_FLAGS_ANY(ns_types, ns_types_check[i])
+                && NM_FLAGS_ANY(info->ns_types, ns_types_check[i])) {
+                res      = NM_FLAGS_SET(res, ns_types_check[i]);
+                ns_types = NM_FLAGS_UNSET(ns_types, ns_types_check[i]);
+            }
+        }
+    }
+
+    return res;
 }
 
 static NetnsInfo *
-_stack_peek (GArray *netns_stack)
+_stack_peek(GArray *netns_stack)
 {
-	if (netns_stack->len > 0)
-		return &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1));
-	return NULL;
+    if (netns_stack->len > 0)
+        return &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1));
+    return NULL;
 }
 
 static NetnsInfo *
-_stack_bottom (GArray *netns_stack)
+_stack_bottom(GArray *netns_stack)
 {
-	if (netns_stack->len > 0)
-		return &g_array_index (netns_stack, NetnsInfo, 0);
-	return NULL;
+    if (netns_stack->len > 0)
+        return &g_array_index(netns_stack, NetnsInfo, 0);
+    return NULL;
 }
 
 static void
-_stack_push (GArray *netns_stack,
-             NMPNetns *netns,
-             int ns_types)
+_stack_push(GArray *netns_stack, NMPNetns *netns, int ns_types)
 {
-	NetnsInfo *info;
+    NetnsInfo *info;
 
-	nm_assert (netns_stack);
-	nm_assert (NMP_IS_NETNS (netns));
-	nm_assert (NM_FLAGS_ANY (ns_types, _CLONE_NS_ALL));
-	nm_assert (!NM_FLAGS_ANY (ns_types, ~_CLONE_NS_ALL));
+    nm_assert(netns_stack);
+    nm_assert(NMP_IS_NETNS(netns));
+    nm_assert(NM_FLAGS_ANY(ns_types, _CLONE_NS_ALL));
+    nm_assert(!NM_FLAGS_ANY(ns_types, ~_CLONE_NS_ALL));
 
-	g_array_set_size (netns_stack, netns_stack->len + 1);
+    g_array_set_size(netns_stack, netns_stack->len + 1);
 
-	info = &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1));
-	*info = (NetnsInfo) {
-		.netns    = g_object_ref (netns),
-		.ns_types = ns_types,
-		.count    = 1,
-	};
+    info  = &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1));
+    *info = (NetnsInfo){
+        .netns    = g_object_ref(netns),
+        .ns_types = ns_types,
+        .count    = 1,
+    };
 }
 
 static void
-_stack_pop (GArray *netns_stack)
+_stack_pop(GArray *netns_stack)
 {
-	NetnsInfo *info;
+    NetnsInfo *info;
 
-	nm_assert (netns_stack);
-	nm_assert (netns_stack->len > 1);
+    nm_assert(netns_stack);
+    nm_assert(netns_stack->len > 1);
 
-	info = &g_array_index (netns_stack, NetnsInfo, (netns_stack->len - 1));
+    info = &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1));
 
-	nm_assert (NMP_IS_NETNS (info->netns));
-	nm_assert (info->count == 1);
+    nm_assert(NMP_IS_NETNS(info->netns));
+    nm_assert(info->count == 1);
 
-	g_array_set_size (netns_stack, netns_stack->len - 1);
+    g_array_set_size(netns_stack, netns_stack->len - 1);
 }
 
 static guint
-_stack_size (GArray *netns_stack)
+_stack_size(GArray *netns_stack)
 {
-	nm_assert (netns_stack);
+    nm_assert(netns_stack);
 
-	return netns_stack->len;
+    return netns_stack->len;
 }
 
 /*****************************************************************************/
 
 static NMPNetns *
-_netns_new (GError **error)
+_netns_new(GError **error)
 {
-	NMPNetns *self;
-	int fd_net, fd_mnt;
-	int errsv;
-
-	fd_net = open (PROC_SELF_NS_NET, O_RDONLY | O_CLOEXEC);
-	if (fd_net == -1) {
-		errsv = errno;
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             "Failed opening netns: %s",
-		             nm_strerror_native (errsv));
-		errno = errsv;
-		return NULL;
-	}
-
-	fd_mnt = open (PROC_SELF_NS_MNT, O_RDONLY | O_CLOEXEC);
-	if (fd_mnt == -1) {
-		errsv = errno;
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             "Failed opening mntns: %s",
-		             nm_strerror_native (errsv));
-		nm_close (fd_net);
-		errno = errsv;
-		return NULL;
-	}
-
-	self = g_object_new (NMP_TYPE_NETNS,
-	                     NMP_NETNS_FD_NET, fd_net,
-	                     NMP_NETNS_FD_MNT, fd_mnt,
-	                     NULL);
-
-	_LOGD (self, "new netns (net:%d, mnt:%d)", fd_net, fd_mnt);
-
-	return self;
+    NMPNetns *self;
+    int       fd_net, fd_mnt;
+    int       errsv;
+
+    fd_net = open(PROC_SELF_NS_NET, O_RDONLY | O_CLOEXEC);
+    if (fd_net == -1) {
+        errsv = errno;
+        g_set_error(error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "Failed opening netns: %s",
+                    nm_strerror_native(errsv));
+        errno = errsv;
+        return NULL;
+    }
+
+    fd_mnt = open(PROC_SELF_NS_MNT, O_RDONLY | O_CLOEXEC);
+    if (fd_mnt == -1) {
+        errsv = errno;
+        g_set_error(error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "Failed opening mntns: %s",
+                    nm_strerror_native(errsv));
+        nm_close(fd_net);
+        errno = errsv;
+        return NULL;
+    }
+
+    self = g_object_new(NMP_TYPE_NETNS, NMP_NETNS_FD_NET, fd_net, NMP_NETNS_FD_MNT, fd_mnt, NULL);
+
+    _LOGD(self, "new netns (net:%d, mnt:%d)", fd_net, fd_mnt);
+
+    return self;
 }
 
 static int
-_setns (NMPNetns *self, int type)
+_setns(NMPNetns *self, int type)
 {
-	char buf[100];
-	int fd;
-	NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE (self);
+    char             buf[100];
+    int              fd;
+    NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self);
 
-	nm_assert (NM_IN_SET (type, _CLONE_NS_ALL_V));
+    nm_assert(NM_IN_SET(type, _CLONE_NS_ALL_V));
 
-	fd = (type == CLONE_NEWNET) ? priv->fd_net : priv->fd_mnt;
+    fd = (type == CLONE_NEWNET) ? priv->fd_net : priv->fd_mnt;
 
-	_LOGt (self, "set netns(%s, %d)", _ns_types_to_str (type, 0, buf), fd);
+    _LOGt(self, "set netns(%s, %d)", _ns_types_to_str(type, 0, buf), fd);
 
-	return setns (fd, type);
+    return setns(fd, type);
 }
 
 static gboolean
-_netns_switch_push (GArray *netns_stack,
-                    NMPNetns *self,
-                    int ns_types)
+_netns_switch_push(GArray *netns_stack, NMPNetns *self, int ns_types)
 {
-	int errsv;
-
-	if (   NM_FLAGS_HAS (ns_types, CLONE_NEWNET)
-	    && !_stack_current_ns_types (netns_stack, self, CLONE_NEWNET)
-	    && _setns (self, CLONE_NEWNET) != 0) {
-		errsv = errno;
-		_LOGE (self, "failed to switch netns: %s", nm_strerror_native (errsv));
-		return FALSE;
-	}
-	if (   NM_FLAGS_HAS (ns_types, CLONE_NEWNS)
-	    && !_stack_current_ns_types (netns_stack, self, CLONE_NEWNS)
-	    && _setns (self, CLONE_NEWNS) != 0) {
-		errsv = errno;
-		_LOGE (self, "failed to switch mntns: %s", nm_strerror_native (errsv));
-
-		/* try to fix the mess by returning to the previous netns. */
-		if (   NM_FLAGS_HAS (ns_types, CLONE_NEWNET)
-	        && !_stack_current_ns_types (netns_stack, self, CLONE_NEWNET)) {
-			self = _stack_current_netns (netns_stack, CLONE_NEWNET);
-			if (   self
-			    && _setns (self, CLONE_NEWNET) != 0) {
-				errsv = errno;
-				_LOGE (self, "failed to restore netns: %s", nm_strerror_native (errsv));
-			}
-		}
-		return FALSE;
-	}
-
-	return TRUE;
+    int errsv;
+
+    if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET)
+        && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET)
+        && _setns(self, CLONE_NEWNET) != 0) {
+        errsv = errno;
+        _LOGE(self, "failed to switch netns: %s", nm_strerror_native(errsv));
+        return FALSE;
+    }
+    if (NM_FLAGS_HAS(ns_types, CLONE_NEWNS)
+        && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNS)
+        && _setns(self, CLONE_NEWNS) != 0) {
+        errsv = errno;
+        _LOGE(self, "failed to switch mntns: %s", nm_strerror_native(errsv));
+
+        /* try to fix the mess by returning to the previous netns. */
+        if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET)
+            && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET)) {
+            self = _stack_current_netns(netns_stack, CLONE_NEWNET);
+            if (self && _setns(self, CLONE_NEWNET) != 0) {
+                errsv = errno;
+                _LOGE(self, "failed to restore netns: %s", nm_strerror_native(errsv));
+            }
+        }
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 static gboolean
-_netns_switch_pop (GArray *netns_stack,
-                   NMPNetns *self,
-                   int ns_types)
+_netns_switch_pop(GArray *netns_stack, NMPNetns *self, int ns_types)
 {
-	int errsv;
-	NMPNetns *current;
-	int success = TRUE;
-
-	if (   NM_FLAGS_HAS (ns_types, CLONE_NEWNET)
-	    && (   !self
-	        || !_stack_current_ns_types (netns_stack, self, CLONE_NEWNET))) {
-		current = _stack_current_netns (netns_stack, CLONE_NEWNET);
-		if (!current) {
-			g_warn_if_reached ();
-			success = FALSE;
-		} else if (_setns (current, CLONE_NEWNET) != 0) {
-			errsv = errno;
-			_LOGE (self, "failed to switch netns: %s", nm_strerror_native (errsv));
-			success = FALSE;
-		}
-	}
-	if (   NM_FLAGS_HAS (ns_types, CLONE_NEWNS)
-	    && (!self || !_stack_current_ns_types (netns_stack, self, CLONE_NEWNS))) {
-		current = _stack_current_netns (netns_stack, CLONE_NEWNS);
-		if (!current) {
-			g_warn_if_reached ();
-			success = FALSE;
-		} else if (_setns (current, CLONE_NEWNS) != 0) {
-			errsv = errno;
-			_LOGE (self, "failed to switch mntns: %s", nm_strerror_native (errsv));
-			success = FALSE;
-		}
-	}
-
-	return success;
+    int       errsv;
+    NMPNetns *current;
+    int       success = TRUE;
+
+    if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET)
+        && (!self || !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET))) {
+        current = _stack_current_netns(netns_stack, CLONE_NEWNET);
+        if (!current) {
+            g_warn_if_reached();
+            success = FALSE;
+        } else if (_setns(current, CLONE_NEWNET) != 0) {
+            errsv = errno;
+            _LOGE(self, "failed to switch netns: %s", nm_strerror_native(errsv));
+            success = FALSE;
+        }
+    }
+    if (NM_FLAGS_HAS(ns_types, CLONE_NEWNS)
+        && (!self || !_stack_current_ns_types(netns_stack, self, CLONE_NEWNS))) {
+        current = _stack_current_netns(netns_stack, CLONE_NEWNS);
+        if (!current) {
+            g_warn_if_reached();
+            success = FALSE;
+        } else if (_setns(current, CLONE_NEWNS) != 0) {
+            errsv = errno;
+            _LOGE(self, "failed to switch mntns: %s", nm_strerror_native(errsv));
+            success = FALSE;
+        }
+    }
+
+    return success;
 }
 
 /*****************************************************************************/
 
 int
-nmp_netns_get_fd_net (NMPNetns *self)
+nmp_netns_get_fd_net(NMPNetns *self)
 {
-	g_return_val_if_fail (NMP_IS_NETNS (self), 0);
+    g_return_val_if_fail(NMP_IS_NETNS(self), 0);
 
-	return NMP_NETNS_GET_PRIVATE (self)->fd_net;
+    return NMP_NETNS_GET_PRIVATE(self)->fd_net;
 }
 
 int
-nmp_netns_get_fd_mnt (NMPNetns *self)
+nmp_netns_get_fd_mnt(NMPNetns *self)
 {
-	g_return_val_if_fail (NMP_IS_NETNS (self), 0);
+    g_return_val_if_fail(NMP_IS_NETNS(self), 0);
 
-	return NMP_NETNS_GET_PRIVATE (self)->fd_mnt;
+    return NMP_NETNS_GET_PRIVATE(self)->fd_mnt;
 }
 
 /*****************************************************************************/
 
 static gboolean
-_nmp_netns_push_type (NMPNetns *self, int ns_types)
+_nmp_netns_push_type(NMPNetns *self, int ns_types)
 {
-	GArray *netns_stack = _netns_stack_get ();
-	NetnsInfo *info;
-	char sbuf[100];
-
-	info = _stack_peek (netns_stack);
-	g_return_val_if_fail (info, FALSE);
-
-	if (info->netns == self && info->ns_types == ns_types) {
-		info->count++;
-		_LOGt (self, "push#%u* %s (increase count to %d)",
-		       _stack_size (netns_stack) - 1,
-		       _ns_types_to_str (ns_types, ns_types, sbuf), info->count);
-		return TRUE;
-	}
-
-	_LOGD (self, "push#%u %s",
-	       _stack_size (netns_stack),
-	       _ns_types_to_str (ns_types,
-	                         _stack_current_ns_types (netns_stack, self, ns_types),
-	                         sbuf));
-
-	if (!_netns_switch_push (netns_stack, self, ns_types))
-		return FALSE;
-
-	_stack_push (netns_stack, self, ns_types);
-	return TRUE;
+    GArray *   netns_stack = _netns_stack_get();
+    NetnsInfo *info;
+    char       sbuf[100];
+
+    info = _stack_peek(netns_stack);
+    g_return_val_if_fail(info, FALSE);
+
+    if (info->netns == self && info->ns_types == ns_types) {
+        info->count++;
+        _LOGt(self,
+              "push#%u* %s (increase count to %d)",
+              _stack_size(netns_stack) - 1,
+              _ns_types_to_str(ns_types, ns_types, sbuf),
+              info->count);
+        return TRUE;
+    }
+
+    _LOGD(self,
+          "push#%u %s",
+          _stack_size(netns_stack),
+          _ns_types_to_str(ns_types, _stack_current_ns_types(netns_stack, self, ns_types), sbuf));
+
+    if (!_netns_switch_push(netns_stack, self, ns_types))
+        return FALSE;
+
+    _stack_push(netns_stack, self, ns_types);
+    return TRUE;
 }
 
 gboolean
-nmp_netns_push (NMPNetns *self)
+nmp_netns_push(NMPNetns *self)
 {
-	g_return_val_if_fail (NMP_IS_NETNS (self), FALSE);
+    g_return_val_if_fail(NMP_IS_NETNS(self), FALSE);
 
-	return _nmp_netns_push_type (self, _CLONE_NS_ALL);
+    return _nmp_netns_push_type(self, _CLONE_NS_ALL);
 }
 
 gboolean
-nmp_netns_push_type (NMPNetns *self, int ns_types)
+nmp_netns_push_type(NMPNetns *self, int ns_types)
 {
-	g_return_val_if_fail (NMP_IS_NETNS (self), FALSE);
-	g_return_val_if_fail (!NM_FLAGS_ANY (ns_types, ~_CLONE_NS_ALL), FALSE);
+    g_return_val_if_fail(NMP_IS_NETNS(self), FALSE);
+    g_return_val_if_fail(!NM_FLAGS_ANY(ns_types, ~_CLONE_NS_ALL), FALSE);
 
-	return _nmp_netns_push_type (self, ns_types == 0 ? _CLONE_NS_ALL : ns_types);
+    return _nmp_netns_push_type(self, ns_types == 0 ? _CLONE_NS_ALL : ns_types);
 }
 
 NMPNetns *
-nmp_netns_new (void)
+nmp_netns_new(void)
 {
-	GArray *netns_stack = _netns_stack_get ();
-	NMPNetns *self;
-	int errsv;
-	GError *error = NULL;
-	unsigned long mountflags = 0;
-
-	if (!_stack_peek (netns_stack)) {
-		/* there are no netns instances. We cannot create a new one
-		 * (because after unshare we couldn't return to the original one). */
-		errno = ENOTSUP;
-		return NULL;
-	}
-
-	if (unshare (_CLONE_NS_ALL) != 0) {
-		errsv = errno;
-		_LOGE (NULL, "failed to create new net and mnt namespace: %s", nm_strerror_native (errsv));
-		return NULL;
-	}
-
-	if (mount ("", "/", "none", MS_SLAVE | MS_REC, NULL) != 0) {
-		errsv = errno;
-		_LOGE (NULL, "failed mount --make-rslave: %s", nm_strerror_native (errsv));
-		goto err_out;
-	}
-
-	if (umount2 ("/sys", MNT_DETACH) != 0) {
-		errsv = errno;
-		_LOGE (NULL, "failed umount /sys: %s", nm_strerror_native (errsv));
-		goto err_out;
-	}
-
-	if (access ("/sys", W_OK) == -1)
-		mountflags = MS_RDONLY;
-
-	if (mount ("sysfs", "/sys", "sysfs", mountflags, NULL) != 0) {
-		errsv = errno;
-		_LOGE (NULL, "failed mount /sys: %s", nm_strerror_native (errsv));
-		goto err_out;
-	}
-
-	self = _netns_new (&error);
-	if (!self) {
-		errsv = errno;
-		_LOGE (NULL, "failed to create netns after unshare: %s", error->message);
-		g_clear_error (&error);
-		goto err_out;
-	}
-
-	_stack_push (netns_stack, self, _CLONE_NS_ALL);
-
-	return self;
+    GArray *      netns_stack = _netns_stack_get();
+    NMPNetns *    self;
+    int           errsv;
+    GError *      error      = NULL;
+    unsigned long mountflags = 0;
+
+    if (!_stack_peek(netns_stack)) {
+        /* there are no netns instances. We cannot create a new one
+         * (because after unshare we couldn't return to the original one). */
+        errno = ENOTSUP;
+        return NULL;
+    }
+
+    if (unshare(_CLONE_NS_ALL) != 0) {
+        errsv = errno;
+        _LOGE(NULL, "failed to create new net and mnt namespace: %s", nm_strerror_native(errsv));
+        return NULL;
+    }
+
+    if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL) != 0) {
+        errsv = errno;
+        _LOGE(NULL, "failed mount --make-rslave: %s", nm_strerror_native(errsv));
+        goto err_out;
+    }
+
+    if (umount2("/sys", MNT_DETACH) != 0) {
+        errsv = errno;
+        _LOGE(NULL, "failed umount /sys: %s", nm_strerror_native(errsv));
+        goto err_out;
+    }
+
+    if (access("/sys", W_OK) == -1)
+        mountflags = MS_RDONLY;
+
+    if (mount("sysfs", "/sys", "sysfs", mountflags, NULL) != 0) {
+        errsv = errno;
+        _LOGE(NULL, "failed mount /sys: %s", nm_strerror_native(errsv));
+        goto err_out;
+    }
+
+    self = _netns_new(&error);
+    if (!self) {
+        errsv = errno;
+        _LOGE(NULL, "failed to create netns after unshare: %s", error->message);
+        g_clear_error(&error);
+        goto err_out;
+    }
+
+    _stack_push(netns_stack, self, _CLONE_NS_ALL);
+
+    return self;
 err_out:
-	_netns_switch_pop (netns_stack, NULL, _CLONE_NS_ALL);
-	errno = errsv;
-	return NULL;
+    _netns_switch_pop(netns_stack, NULL, _CLONE_NS_ALL);
+    errno = errsv;
+    return NULL;
 }
 
 gboolean
-nmp_netns_pop (NMPNetns *self)
+nmp_netns_pop(NMPNetns *self)
 {
-	GArray *netns_stack = _netns_stack_get ();
-	NetnsInfo *info;
-	int ns_types;
+    GArray *   netns_stack = _netns_stack_get();
+    NetnsInfo *info;
+    int        ns_types;
 
-	g_return_val_if_fail (NMP_IS_NETNS (self), FALSE);
+    g_return_val_if_fail(NMP_IS_NETNS(self), FALSE);
 
-	info = _stack_peek (netns_stack);
+    info = _stack_peek(netns_stack);
 
-	g_return_val_if_fail (info, FALSE);
-	g_return_val_if_fail (info->netns == self, FALSE);
+    g_return_val_if_fail(info, FALSE);
+    g_return_val_if_fail(info->netns == self, FALSE);
 
-	if (info->count > 1) {
-		info->count--;
-		_LOGt (self, "pop#%u* (decrease count to %d)",
-		       _stack_size (netns_stack) - 1, info->count);
-		return TRUE;
-	}
-	g_return_val_if_fail (info->count == 1, FALSE);
+    if (info->count > 1) {
+        info->count--;
+        _LOGt(self, "pop#%u* (decrease count to %d)", _stack_size(netns_stack) - 1, info->count);
+        return TRUE;
+    }
+    g_return_val_if_fail(info->count == 1, FALSE);
 
-	/* cannot pop the original netns. */
-	g_return_val_if_fail (_stack_size (netns_stack) > 1, FALSE);
+    /* cannot pop the original netns. */
+    g_return_val_if_fail(_stack_size(netns_stack) > 1, FALSE);
 
-	_LOGD (self, "pop#%u", _stack_size (netns_stack) - 1);
+    _LOGD(self, "pop#%u", _stack_size(netns_stack) - 1);
 
-	ns_types = info->ns_types;
+    ns_types = info->ns_types;
 
-	_stack_pop (netns_stack);
+    _stack_pop(netns_stack);
 
-	return _netns_switch_pop (netns_stack, self, ns_types);
+    return _netns_switch_pop(netns_stack, self, ns_types);
 }
 
 NMPNetns *
-nmp_netns_get_current (void)
+nmp_netns_get_current(void)
 {
-	return _netns_get (_stack_peek (_netns_stack_get ()));
+    return _netns_get(_stack_peek(_netns_stack_get()));
 }
 
 NMPNetns *
-nmp_netns_get_initial (void)
+nmp_netns_get_initial(void)
 {
-	return _netns_get (_stack_bottom (_netns_stack_get ()));
+    return _netns_get(_stack_bottom(_netns_stack_get()));
 }
 
 gboolean
-nmp_netns_is_initial (void)
+nmp_netns_is_initial(void)
 {
-	GArray *netns_stack = _netns_stack_get ();
+    GArray *netns_stack = _netns_stack_get();
 
-	return (   _netns_get (_stack_peek (netns_stack))
-	        == _netns_get (_stack_bottom (netns_stack)));
+    return (_netns_get(_stack_peek(netns_stack)) == _netns_get(_stack_bottom(netns_stack)));
 }
 
 /*****************************************************************************/
 
 gboolean
-nmp_netns_bind_to_path (NMPNetns *self, const char *filename, int *out_fd)
+nmp_netns_bind_to_path(NMPNetns *self, const char *filename, int *out_fd)
 {
-	gs_free char *dirname = NULL;
-	int errsv;
-	int fd;
-	nm_auto_pop_netns NMPNetns *netns_pop = NULL;
-
-	g_return_val_if_fail (NMP_IS_NETNS (self), FALSE);
-	g_return_val_if_fail (filename && filename[0] == '/', FALSE);
-
-	if (!nmp_netns_push_type (self, CLONE_NEWNET))
-		return FALSE;
-	netns_pop = self;
-
-	dirname = g_path_get_dirname (filename);
-	if (mkdir (dirname, 0) != 0) {
-		errsv = errno;
-		if (errsv != EEXIST) {
-			_LOGE (self, "bind: failed to create directory %s: %s",
-			       dirname, nm_strerror_native (errsv));
-			return FALSE;
-		}
-	}
-
-	if ((fd = creat (filename, S_IRUSR | S_IRGRP | S_IROTH)) == -1) {
-		errsv = errno;
-		_LOGE (self, "bind: failed to create %s: %s",
-		       filename, nm_strerror_native (errsv));
-		return FALSE;
-	}
-	nm_close (fd);
-
-	if (mount (PROC_SELF_NS_NET, filename, "none", MS_BIND, NULL) != 0) {
-		errsv = errno;
-		_LOGE (self, "bind: failed to mount %s to %s: %s",
-		       PROC_SELF_NS_NET, filename, nm_strerror_native (errsv));
-		unlink (filename);
-		return FALSE;
-	}
-
-	if (out_fd) {
-		if ((fd = open (filename, O_RDONLY | O_CLOEXEC)) == -1) {
-			errsv = errno;
-			_LOGE (self, "bind: failed to open %s: %s", filename, nm_strerror_native (errsv));
-			umount2 (filename, MNT_DETACH);
-			unlink (filename);
-			return FALSE;
-		}
-		*out_fd = fd;
-	}
-
-	return TRUE;
+    gs_free char *    dirname = NULL;
+    int               errsv;
+    int               fd;
+    nm_auto_pop_netns NMPNetns *netns_pop = NULL;
+
+    g_return_val_if_fail(NMP_IS_NETNS(self), FALSE);
+    g_return_val_if_fail(filename && filename[0] == '/', FALSE);
+
+    if (!nmp_netns_push_type(self, CLONE_NEWNET))
+        return FALSE;
+    netns_pop = self;
+
+    dirname = g_path_get_dirname(filename);
+    if (mkdir(dirname, 0) != 0) {
+        errsv = errno;
+        if (errsv != EEXIST) {
+            _LOGE(self,
+                  "bind: failed to create directory %s: %s",
+                  dirname,
+                  nm_strerror_native(errsv));
+            return FALSE;
+        }
+    }
+
+    if ((fd = creat(filename, S_IRUSR | S_IRGRP | S_IROTH)) == -1) {
+        errsv = errno;
+        _LOGE(self, "bind: failed to create %s: %s", filename, nm_strerror_native(errsv));
+        return FALSE;
+    }
+    nm_close(fd);
+
+    if (mount(PROC_SELF_NS_NET, filename, "none", MS_BIND, NULL) != 0) {
+        errsv = errno;
+        _LOGE(self,
+              "bind: failed to mount %s to %s: %s",
+              PROC_SELF_NS_NET,
+              filename,
+              nm_strerror_native(errsv));
+        unlink(filename);
+        return FALSE;
+    }
+
+    if (out_fd) {
+        if ((fd = open(filename, O_RDONLY | O_CLOEXEC)) == -1) {
+            errsv = errno;
+            _LOGE(self, "bind: failed to open %s: %s", filename, nm_strerror_native(errsv));
+            umount2(filename, MNT_DETACH);
+            unlink(filename);
+            return FALSE;
+        }
+        *out_fd = fd;
+    }
+
+    return TRUE;
 }
 
 gboolean
-nmp_netns_bind_to_path_destroy (NMPNetns *self, const char *filename)
+nmp_netns_bind_to_path_destroy(NMPNetns *self, const char *filename)
 {
-	int errsv;
-
-	g_return_val_if_fail (NMP_IS_NETNS (self), FALSE);
-	g_return_val_if_fail (filename && filename[0] == '/', FALSE);
-
-	if (umount2 (filename, MNT_DETACH) != 0) {
-		errsv = errno;
-		_LOGE (self, "bind: failed to unmount2 %s: %s", filename, nm_strerror_native (errsv));
-		return FALSE;
-	}
-	if (unlink (filename) != 0) {
-		errsv = errno;
-		_LOGE (self, "bind: failed to unlink %s: %s", filename, nm_strerror_native (errsv));
-		return FALSE;
-	}
-	return TRUE;
+    int errsv;
+
+    g_return_val_if_fail(NMP_IS_NETNS(self), FALSE);
+    g_return_val_if_fail(filename && filename[0] == '/', FALSE);
+
+    if (umount2(filename, MNT_DETACH) != 0) {
+        errsv = errno;
+        _LOGE(self, "bind: failed to unmount2 %s: %s", filename, nm_strerror_native(errsv));
+        return FALSE;
+    }
+    if (unlink(filename) != 0) {
+        errsv = errno;
+        _LOGE(self, "bind: failed to unlink %s: %s", filename, nm_strerror_native(errsv));
+        return FALSE;
+    }
+    return TRUE;
 }
 
 /*****************************************************************************/
 
 static void
-set_property (GObject *object, guint prop_id,
-              const GValue *value, GParamSpec *pspec)
+set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
-	NMPNetns *self = NMP_NETNS (object);
-	NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE (self);
-
-	switch (prop_id) {
-	case PROP_FD_NET:
-		/* construct-only */
-		priv->fd_net = g_value_get_int (value);
-		g_return_if_fail (priv->fd_net > 0);
-		break;
-	case PROP_FD_MNT:
-		/* construct-only */
-		priv->fd_mnt = g_value_get_int (value);
-		g_return_if_fail (priv->fd_mnt > 0);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
+    NMPNetns *       self = NMP_NETNS(object);
+    NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self);
+
+    switch (prop_id) {
+    case PROP_FD_NET:
+        /* construct-only */
+        priv->fd_net = g_value_get_int(value);
+        g_return_if_fail(priv->fd_net > 0);
+        break;
+    case PROP_FD_MNT:
+        /* construct-only */
+        priv->fd_mnt = g_value_get_int(value);
+        g_return_if_fail(priv->fd_mnt > 0);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
 }
 
 static void
-nmp_netns_init (NMPNetns *self)
-{
-}
+nmp_netns_init(NMPNetns *self)
+{}
 
 static void
-dispose (GObject *object)
+dispose(GObject *object)
 {
-	NMPNetns *self = NMP_NETNS (object);
-	NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE (self);
+    NMPNetns *       self = NMP_NETNS(object);
+    NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self);
 
-	nm_close (priv->fd_net);
-	priv->fd_net = -1;
+    nm_close(priv->fd_net);
+    priv->fd_net = -1;
 
-	nm_close (priv->fd_mnt);
-	priv->fd_mnt = -1;
+    nm_close(priv->fd_mnt);
+    priv->fd_mnt = -1;
 
-	G_OBJECT_CLASS (nmp_netns_parent_class)->dispose (object);
+    G_OBJECT_CLASS(nmp_netns_parent_class)->dispose(object);
 }
 
 static void
-nmp_netns_class_init (NMPNetnsClass *klass)
+nmp_netns_class_init(NMPNetnsClass *klass)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	object_class->set_property = set_property;
-	object_class->dispose = dispose;
-
-	obj_properties[PROP_FD_NET]
-	    = g_param_spec_int (NMP_NETNS_FD_NET, "", "",
-	                        0, G_MAXINT, 0,
-	                        G_PARAM_WRITABLE |
-	                        G_PARAM_CONSTRUCT_ONLY |
-	                        G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_FD_MNT]
-	    = g_param_spec_int (NMP_NETNS_FD_MNT, "", "",
-	                        0, G_MAXINT, 0,
-	                        G_PARAM_WRITABLE |
-	                        G_PARAM_CONSTRUCT_ONLY |
-	                        G_PARAM_STATIC_STRINGS);
-	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+    object_class->set_property = set_property;
+    object_class->dispose      = dispose;
+
+    obj_properties[PROP_FD_NET] =
+        g_param_spec_int(NMP_NETNS_FD_NET,
+                         "",
+                         "",
+                         0,
+                         G_MAXINT,
+                         0,
+                         G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_FD_MNT] =
+        g_param_spec_int(NMP_NETNS_FD_MNT,
+                         "",
+                         "",
+                         0,
+                         G_MAXINT,
+                         0,
+                         G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 }