A crude way of cloning an eth interface
This commit is contained in:
parent
470bbb9a5d
commit
9960304cab
@ -198,6 +198,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
{{"silent", no_argument, NULL, 0x0504}, "Redirect child's fd:0/1/2 to /dev/null (default: false)"},
|
{{"silent", no_argument, NULL, 0x0504}, "Redirect child's fd:0/1/2 to /dev/null (default: false)"},
|
||||||
{{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind inside the container. Can be specified multiple times (default: none)"},
|
{{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind inside the container. Can be specified multiple times (default: none)"},
|
||||||
{{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times (default: none)"},
|
{{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times (default: none)"},
|
||||||
|
{{"iface", required_argument, NULL, 'I'}, "Interface which will be cloned (MACVTAP) and put inside the subprocess' namespace"},
|
||||||
{{0, 0, 0, 0}, NULL},
|
{{0, 0, 0, 0}, NULL},
|
||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
@ -209,7 +210,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
|
|
||||||
int opt_index = 0;
|
int opt_index = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int c = getopt_long(argc, argv, "H:c:p:i:u:g:l:t:M:Ndveh?B:T:", opts, &opt_index);
|
int c = getopt_long(argc, argv, "H:c:p:i:u:g:l:t:M:Ndveh?B:T:I:", opts, &opt_index);
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -356,6 +357,9 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'I':
|
||||||
|
nsjconf->iface = optarg;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cmdlineUsage(argv[0], custom_opts);
|
cmdlineUsage(argv[0], custom_opts);
|
||||||
return false;
|
return false;
|
||||||
|
1
common.h
1
common.h
@ -81,6 +81,7 @@ struct nsjconf_t {
|
|||||||
bool is_silent;
|
bool is_silent;
|
||||||
struct mountfs_t *bindmountpts;
|
struct mountfs_t *bindmountpts;
|
||||||
struct mountfs_t *tmpfsmountpts;
|
struct mountfs_t *tmpfsmountpts;
|
||||||
|
char *iface;
|
||||||
uid_t initial_uid;
|
uid_t initial_uid;
|
||||||
gid_t initial_gid;
|
gid_t initial_gid;
|
||||||
unsigned int max_conns_per_ip;
|
unsigned int max_conns_per_ip;
|
||||||
|
63
net.c
63
net.c
@ -30,12 +30,75 @@
|
|||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <netinet/ip6.h>
|
#include <netinet/ip6.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
static bool netSystem(const char *bin, char *const *argv)
|
||||||
|
{
|
||||||
|
int pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
PLOG_E("fork()");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pid == 0) {
|
||||||
|
execv(bin, argv);
|
||||||
|
PLOG_E("execve('%s')", bin);
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int status;
|
||||||
|
while (wait4(pid, &status, __WALL, NULL) != pid) ;
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
if (WEXITSTATUS(status) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG_W("'%s' returned with exit status: %d", bin, WEXITSTATUS(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (WIFSIGNALED(status)) {
|
||||||
|
LOG_W("'%s' killed with signal: %d", bin, WTERMSIG(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOG_E("Unknown exit status for '%s' (pid=%d): %d", bin, pid, status);
|
||||||
|
kill(pid, SIGKILL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool netCloneMacVtapAndNS(struct nsjconf_t * nsjconf, int pid)
|
||||||
|
{
|
||||||
|
if (nsjconf->iface == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char iface[512];
|
||||||
|
snprintf(iface, sizeof(iface), "%s.ns.%d", nsjconf->iface, pid);
|
||||||
|
|
||||||
|
#define SBIN_IP_PATH "/sbin/ip"
|
||||||
|
char *const argv_add[] =
|
||||||
|
{ SBIN_IP_PATH, "link", "add", "link", nsjconf->iface, iface, "type", "macvtap", NULL };
|
||||||
|
if (netSystem(SBIN_IP_PATH, argv_add) == false) {
|
||||||
|
LOG_E("Couldn't create MACVTAP interface for '%s'", nsjconf->iface);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char pid_str[512];
|
||||||
|
snprintf(pid_str, sizeof(pid_str), "%d", pid);
|
||||||
|
char *const argv_netns[] = { SBIN_IP_PATH, "link", "set", "dev", iface, "netns", pid_str, NULL };
|
||||||
|
if (netSystem(SBIN_IP_PATH, argv_netns) == false) {
|
||||||
|
LOG_E("Couldn't put interface '%s' into NS of PID '%d'", iface, pid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool netIsSocket(int fd)
|
static bool netIsSocket(int fd)
|
||||||
{
|
{
|
||||||
int optval;
|
int optval;
|
||||||
|
1
net.h
1
net.h
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
bool netCloneMacVtapAndNS(struct nsjconf_t *nsjconf, int pid);
|
||||||
bool netLimitConns(struct nsjconf_t *nsjconf, int connsock);
|
bool netLimitConns(struct nsjconf_t *nsjconf, int connsock);
|
||||||
int netGetRecvSocket(int port);
|
int netGetRecvSocket(int port);
|
||||||
int netAcceptConn(int listenfd);
|
int netAcceptConn(int listenfd);
|
||||||
|
1
nsjail.c
1
nsjail.c
@ -187,6 +187,7 @@ int main(int argc, char *argv[])
|
|||||||
.is_silent = false,
|
.is_silent = false,
|
||||||
.bindmountpts = NULL,
|
.bindmountpts = NULL,
|
||||||
.tmpfsmountpts = NULL,
|
.tmpfsmountpts = NULL,
|
||||||
|
.iface = NULL,
|
||||||
.initial_uid = getuid(),
|
.initial_uid = getuid(),
|
||||||
.initial_gid = getgid(),
|
.initial_gid = getgid(),
|
||||||
.max_conns_per_ip = 0,
|
.max_conns_per_ip = 0,
|
||||||
|
@ -223,6 +223,10 @@ void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_er
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netCloneMacVtapAndNS(nsjconf, pid) == false) {
|
||||||
|
LOG_E("Couldn't create and put MACVTAP interface into NS of PID '%d'", pid);
|
||||||
|
}
|
||||||
|
|
||||||
char log_buf[4096];
|
char log_buf[4096];
|
||||||
|
|
||||||
close(pipefd[1]);
|
close(pipefd[1]);
|
||||||
|
Loading…
Reference in New Issue
Block a user