mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
105 lines
2.5 KiB
C
105 lines
2.5 KiB
C
/* 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 */
|