summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-03-08 13:08:21 +0100
committerThomas Haller <thaller@redhat.com>2016-03-13 18:50:01 +0100
commite8470dedf9660e1a28f37a59810e2cb63c0178d9 (patch)
tree00700311ca9f81ed837aa31ce031292388e42996
parent1bf8e245507b2dd16cc0053007f6b5f7338161be (diff)
downloadNetworkManager-th/netns-aware-bgo763323.tar.gz
platform: add nmp_netns_bind_to_path() helper functionth/netns-aware-bgo763323
Based-on-patch-by: Stjepan Gros <stjepan.gros@gmail.com>
-rw-r--r--src/platform/nmp-netns.c80
-rw-r--r--src/platform/nmp-netns.h3
2 files changed, 83 insertions, 0 deletions
diff --git a/src/platform/nmp-netns.c b/src/platform/nmp-netns.c
index a68cd44aef..ec182e1fc3 100644
--- a/src/platform/nmp-netns.c
+++ b/src/platform/nmp-netns.c
@@ -24,6 +24,8 @@
#include <fcntl.h>
#include <errno.h>
#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "NetworkManagerUtils.h"
@@ -419,6 +421,84 @@ nmp_netns_is_initial (void)
/*********************************************************************************************/
+gboolean
+nmp_netns_bind_to_path (NMPNetns *self, const char *filename, int *out_fd)
+{
+ nm_auto_pop_netns NMPNetns *restore_netns = NULL;
+ gs_free char *dirname = NULL;
+ int errsv;
+ int fd;
+
+ g_return_val_if_fail (NMP_IS_NETNS (self), FALSE);
+ g_return_val_if_fail (filename && filename[0] == '/', FALSE);
+
+ if (!nmp_netns_push (self))
+ return FALSE;
+ restore_netns = 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, g_strerror (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, g_strerror (errsv));
+ return FALSE;
+ }
+ 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, g_strerror (errsv));
+ unlink (filename);
+ return FALSE;
+ }
+
+ if (out_fd) {
+ if ((fd = open (filename, O_RDONLY)) == -1) {
+ errsv = errno;
+ _LOGE (self, "bind: failed to open %s: %s", filename, g_strerror (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)
+{
+ 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, g_strerror (errsv));
+ return FALSE;
+ }
+ if (unlink (filename) != 0) {
+ errsv = errno;
+ _LOGE (self, "bind: failed to unlink %s: %s", filename, g_strerror (errsv));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/******************************************************************************/
+
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
diff --git a/src/platform/nmp-netns.h b/src/platform/nmp-netns.h
index bdd797daca..7ba7ca4cc2 100644
--- a/src/platform/nmp-netns.h
+++ b/src/platform/nmp-netns.h
@@ -67,4 +67,7 @@ _nm_auto_pop_netns (NMPNetns **p)
#define nm_auto_pop_netns __attribute__((cleanup(_nm_auto_pop_netns)))
+gboolean nmp_netns_bind_to_path (NMPNetns *self, const char *filename, int *out_fd);
+gboolean nmp_netns_bind_to_path_destroy (NMPNetns *self, const char *filename);
+
#endif /* __NMP_NETNS_UTILS_H__ */