aboutsummaryrefslogtreecommitdiff
path: root/src/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils.c')
-rw-r--r--src/utils.c95
1 files changed, 93 insertions, 2 deletions
diff --git a/src/utils.c b/src/utils.c
index 7bbdc1e..049e3d5 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -8,6 +8,7 @@
#include <signal.h>
#include <pwd.h>
#include <grp.h>
+#include <sched.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
@@ -19,6 +20,7 @@
#include "utils.h"
#include "log.h"
+#include "options.h"
#define _POSIX_PATH_MAX 256
@@ -345,9 +347,9 @@ void chk_chroot(void)
void mount_root(void)
{
int s;
- s = mount("none", "/", "", MS_SLAVE|MS_REC, NULL);
+ s = mount("", "/", "none", MS_SLAVE|MS_REC, NULL);
if (s)
- s = mount("none", "/", "", MS_PRIVATE|MS_REC, NULL);
+ s = mount("", "/", "none", MS_PRIVATE|MS_REC, NULL);
if (s)
chk_chroot();
}
@@ -399,6 +401,95 @@ int mount_proc(const char *mount_path)
return 0;
}
+int setup_network_namespace(const char *name)
+{
+ int fd;
+ char netns_path[PATH_MAX];
+ int made_netns_run_dir_mount = 0;
+
+ snprintf(netns_path, sizeof netns_path, "%s/%s",
+ getopt_str(OPT_NETNS_RUN_DIR), name);
+ D2("Network Namespace path '%s'", netns_path);
+
+ if (mkdir(getopt_str(OPT_NETNS_RUN_DIR),
+ S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH))
+ {
+ if (errno != EEXIST) {
+ E_STRERR("Create netns directory '%s'",
+ getopt_str(OPT_NETNS_RUN_DIR));
+ return 1;
+ }
+ }
+
+ while (mount("", getopt_str(OPT_NETNS_RUN_DIR), "none",
+ MS_SHARED|MS_REC, NULL))
+ {
+ /* Fail unless we need to make the mount point */
+ if (errno != EINVAL || made_netns_run_dir_mount) {
+ E_STRERR("Mount netns directory '%s' as shared",
+ getopt_str(OPT_NETNS_RUN_DIR));
+ return 1;
+ }
+
+ /* Upgrade NETNS_RUN_DIR to a mount point */
+ if (mount(getopt_str(OPT_NETNS_RUN_DIR), getopt_str(OPT_NETNS_RUN_DIR),
+ "none", MS_BIND | MS_REC, NULL))
+ {
+ E_STRERR("Bind mount netns directory '%s'",
+ getopt_str(OPT_NETNS_RUN_DIR));
+ return 1;
+ }
+ made_netns_run_dir_mount = 1;
+ }
+
+ /* Create the filesystem state */
+ fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
+ if (fd < 0 && errno != EEXIST) {
+ E_STRERR("Create namespace file '%s'", netns_path);
+ return 1;
+ }
+ close(fd);
+
+ if (unshare(CLONE_NEWNET) < 0) {
+ E_STRERR("Create network namespace '%s'", name);
+ goto error;
+ }
+
+ /* Bind the netns last so I can watch for it */
+ if (mount("/proc/self/ns/net", netns_path, "none", MS_BIND, NULL) < 0) {
+ E_STRERR("Bind /proc/self/ns/net to '%s'", netns_path);
+ goto error;
+ }
+
+ return 0;
+error:
+ /* cleanup netns? */
+ return 1;
+}
+
+int switch_network_namespace(const char *name)
+{
+ char net_path[PATH_MAX];
+ int netns;
+
+ snprintf(net_path, sizeof(net_path), "%s/%s",
+ getopt_str(OPT_NETNS_RUN_DIR), name);
+ netns = open(net_path, O_RDONLY | O_CLOEXEC);
+ if (netns < 0) {
+ E_STRERR("Cannot open network namespace '%s'", name);
+ return 1;
+ }
+
+ if (setns(netns, CLONE_NEWNET) < 0) {
+ E_STRERR("Setting the network namespace '%s'", name);
+ close(netns);
+ return 1;
+ }
+ close(netns);
+
+ return 0;
+}
+
int create_device_file_checked(const char *mount_path, const char *device_file,
mode_t mode, int add_mode, dev_t dev)
{