core-extra/netns/netns.c

111 lines
1.9 KiB
C
Raw Normal View History

/*
* CORE
* Copyright (c)2010-2012 the Boeing Company.
* See the LICENSE file included in this distribution.
*
* author: Tom Goff <thomas.goff@boeing.com>
*
* netns.c
*
* Implements nsfork() and nsexecvp() for forking and executing processes
* within a network namespace.
*
*/
#include <signal.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mount.h>
#include <sys/utsname.h>
#include "myerr.h"
#include "netns.h"
#define NSCLONEFLGS \
( \
SIGCHLD | \
CLONE_NEWNS | \
CLONE_NEWUTS | \
CLONE_NEWIPC | \
CLONE_NEWPID | \
CLONE_NEWNET \
)
#define MOUNT_SYS_MIN_VERSION "2.6.35"
static void nssetup(void)
{
int r;
struct utsname uts;
/* Taken from systemd-nspawn. Not sure why needed, but without this,
* the host system goes a bit crazy under systemd. */
r = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL);
if (r)
WARN("mounting / failed");
/* mount per-namespace /proc */
r = mount(NULL, "/proc", "proc", 0, NULL);
if (r)
WARN("mounting /proc failed");
r = uname(&uts);
if (r)
{
WARN("uname() failed");
return;
}
r = strncmp(uts.release, MOUNT_SYS_MIN_VERSION,
sizeof(MOUNT_SYS_MIN_VERSION) - 1);
if (r >= 0)
{
/* mount per-namespace /sys */
r = mount(NULL, "/sys", "sysfs", 0, NULL);
if (r)
WARN("mounting /sys failed");
}
}
pid_t nsfork(int flags)
{
int pid;
pid = syscall(SYS_clone, flags | NSCLONEFLGS, NULL, NULL, NULL, NULL);
if (pid == 0) /* child */
{
nssetup();
}
return pid;
}
pid_t nsexecvp(char *argv[])
{
pid_t pid;
pid = nsfork(CLONE_VFORK);
switch (pid)
{
case -1:
WARN("nsfork() failed");
break;
case 0:
/* child */
execvp(argv[0], argv);
WARN("execvp() failed for '%s'", argv[0]);
_exit(1);
break;
default:
/* parent */
if (kill(pid, 0))
pid = -1;
break;
}
return pid;
}