/* Source: xio-namespaces.c */ /* Copyright Gerhard Rieger and contributors (see file CHANGES) */ /* Published under the GNU General Public License V.2, see file COPYING */ /* This file contains Linux namespace related code */ #include "xiosysincludes.h" #include "xioopen.h" #include "xio-namespaces.h" #if WITH_NAMESPACES const struct optdesc opt_set_netns = { "netns", NULL, OPT_SET_NETNS, GROUP_PROCESS, PH_INIT, TYPE_STRING, OFUNC_SET_NAMESPACE, 0, 0, 0 }; /* Set the given namespace. Requires root or the appropriate CAP_*- Returns 0 on success, or -1 on error. */ int xio_set_namespace( const char *nstype, const char *nsname) { char nspath[PATH_MAX]; int nsfd; int rc; if (!xioparms.experimental) { Error1("option \"%s\" requires use of --experimental", nstype); } snprintf(nspath, sizeof(nspath)-1, "/run/%s/%s", nstype, nsname); Info1("switching to net namespace \"%s\"", nsname); nsfd = Open(nspath, O_RDONLY|O_CLOEXEC, 000); if (nsfd < 0) { Error2("open(%s, O_RDONLY|O_CLOEXEC): %s", nspath, strerror(errno)); return -1; } rc = Setns(nsfd, CLONE_NEWNET); if (rc < 0) { Error2("setns(%d, CLONE_NEWNET): %s", nsfd, strerror(errno)); Close(nsfd); } Close(nsfd); return 0; } int xio_apply_namespace( struct opt *opts) { int old_netfd; char *netns_name; char old_nspath[PATH_MAX]; int rc; if (retropt_string(opts, OPT_SET_NETNS, &netns_name) < 0) return 0; /* Get path describing current namespace */ snprintf(old_nspath, sizeof(old_nspath)-1, "/proc/"F_pid"/ns/net", Getpid()); /* Get a file descriptor to current ns for later reset */ old_netfd = Open(old_nspath, O_RDONLY|O_CLOEXEC, 000); if (old_netfd < 0) { Error2("open(%s, O_RDONLY|O_CLOEXEC): %s", old_nspath, strerror(errno)); free(netns_name); return -1; } if (old_netfd == 0) { /* 0 means not netns option, oops */ Error1("%s(): INTERNAL", __func__); free(netns_name); Close(old_netfd); return -1; } rc = xio_set_namespace("netns", netns_name); free(netns_name); if (rc < 0) { Close(old_netfd); return -1; } return old_netfd; } /* Sets the given namespace to that of process 1, this is assumed to be the systems default. Returns 0 on success, or -1 on error. */ int xio_reset_namespace( int saved_netfd) { int rc; rc = Setns(saved_netfd, CLONE_NEWNET); if (rc < 0) { Error2("xio_reset_namespace(%d): %s", saved_netfd, strerror(errno)); Close(saved_netfd); return STAT_NORETRY; } Close(saved_netfd); return 0; } #endif /* WITH_NAMESPACES */