diff options
author | Thomas Haller <thaller@redhat.com> | 2016-03-08 13:08:21 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-03-13 18:50:01 +0100 |
commit | e8470dedf9660e1a28f37a59810e2cb63c0178d9 (patch) | |
tree | 00700311ca9f81ed837aa31ce031292388e42996 | |
parent | 1bf8e245507b2dd16cc0053007f6b5f7338161be (diff) | |
download | NetworkManager-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.c | 80 | ||||
-rw-r--r-- | src/platform/nmp-netns.h | 3 |
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__ */ |