aboutgitcodebugslistschat
path: root/passt.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-10-11 12:01:31 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-10-14 13:15:12 +0200
commit675174d4ba255383b213437e29b617d8f55dbc69 (patch)
tree7add0cf70e595028f9ca9485eb8e139d3d652bb6 /passt.c
parentdcd3605d14aba011fa6c2f4596cb7494f64d2b93 (diff)
downloadpasst-675174d4ba255383b213437e29b617d8f55dbc69.tar
passt-675174d4ba255383b213437e29b617d8f55dbc69.tar.gz
passt-675174d4ba255383b213437e29b617d8f55dbc69.tar.bz2
passt-675174d4ba255383b213437e29b617d8f55dbc69.tar.lz
passt-675174d4ba255383b213437e29b617d8f55dbc69.tar.xz
passt-675174d4ba255383b213437e29b617d8f55dbc69.tar.zst
passt-675174d4ba255383b213437e29b617d8f55dbc69.zip
conf, tap: Split netlink and pasta functions, allow interface configuration
Move netlink routines to their own file, and use netlink to configure or fetch all the information we need, except for the TUNSETIFF ioctl. Move pasta-specific functions to their own file as well, add parameters and calls to configure the tap interface in the namespace. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'passt.c')
-rw-r--r--passt.c183
1 files changed, 2 insertions, 181 deletions
diff --git a/passt.c b/passt.c
index e0519f6..b411657 100644
--- a/passt.c
+++ b/passt.c
@@ -62,6 +62,7 @@
#include "pcap.h"
#include "tap.h"
#include "conf.h"
+#include "pasta.h"
#define EPOLL_EVENTS 8
@@ -156,178 +157,6 @@ void proto_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s,
udp_update_l2_buf(eth_d, eth_s, ip_da);
}
-static int pasta_child_pid;
-static char pasta_child_ns[PATH_MAX];
-
-/**
- * pasta_ns_cleanup() - Look for processes in namespace, terminate them
- */
-static void pasta_ns_cleanup(void)
-{
- char proc_path[PATH_MAX], ns_link[PATH_MAX];
- int recheck = 0, found = 0, waited = 0;
- struct dirent *dp;
- DIR *dirp;
-
- if (!*pasta_child_ns)
- return;
-
-loop:
- if (!(dirp = opendir("/proc")))
- return;
-
- while ((dp = readdir(dirp))) {
- pid_t pid;
-
- errno = 0;
- pid = strtol(dp->d_name, NULL, 0);
- if (!pid || errno)
- continue;
-
- snprintf(proc_path, PATH_MAX, "/proc/%i/ns/net", pid);
- if (readlink(proc_path, ns_link, PATH_MAX) < 0)
- continue;
-
- if (!strncmp(ns_link, pasta_child_ns, PATH_MAX)) {
- found = 1;
- if (waited)
- kill(pid, SIGKILL);
- else
- kill(pid, SIGQUIT);
- }
- }
-
- closedir(dirp);
-
- if (!found)
- return;
-
- if (waited) {
- if (recheck) {
- info("Some processes in namespace didn't quit");
- } else {
- found = 0;
- recheck = 1;
- goto loop;
- }
- return;
- }
-
- info("Waiting for all processes in namespace to terminate");
- sleep(1);
- waited = 1;
- goto loop;
-}
-
-/**
- * pasta_child_handler() - Exit once shell spawned by pasta_start_ns() exits
- * @signal: Unused, handler deals with SIGCHLD only
- */
-static void pasta_child_handler(int signal)
-{
- siginfo_t infop;
-
- (void)signal;
-
- if (pasta_child_pid &&
- !waitid(P_PID, pasta_child_pid, &infop, WEXITED | WNOHANG)) {
- if (infop.si_pid == pasta_child_pid) {
- pasta_ns_cleanup();
- exit(EXIT_SUCCESS);
- }
- }
-
- waitid(P_ALL, 0, NULL, WEXITED | WNOHANG);
- waitid(P_ALL, 0, NULL, WEXITED | WNOHANG);
-}
-
-/**
- * pasta_wait_for_ns() - Busy loop until we can enter the target namespace
- * @arg: Execution context
- *
- * Return: 0
- */
-static int pasta_wait_for_ns(void *arg)
-{
- struct ctx *c = (struct ctx *)arg;
- char ns[PATH_MAX];
-
- if (c->netns_only)
- goto netns;
-
- snprintf(ns, PATH_MAX, "/proc/%i/ns/user", pasta_child_pid);
- do
- while ((c->pasta_userns_fd = open(ns, O_RDONLY)) < 0);
- while (setns(c->pasta_userns_fd, 0) && !close(c->pasta_userns_fd));
-
-netns:
- snprintf(ns, PATH_MAX, "/proc/%i/ns/net", pasta_child_pid);
- do
- while ((c->pasta_netns_fd = open(ns, O_RDONLY)) < 0);
- while (setns(c->pasta_netns_fd, 0) && !close(c->pasta_netns_fd));
-
- return 0;
-}
-
-/**
- * pasta_start_ns() - Fork shell in new namespace if target ns is not given
- * @c: Execution context
- */
-static void pasta_start_ns(struct ctx *c)
-{
- char buf[BUFSIZ], *shell;
- int euid = geteuid();
- int fd;
-
- c->foreground = 1;
- if (!c->debug)
- c->quiet = 1;
-
- if ((pasta_child_pid = fork()) == -1) {
- perror("fork");
- exit(EXIT_FAILURE);
- }
-
- if (pasta_child_pid) {
- NS_CALL(pasta_wait_for_ns, c);
- return;
- }
-
- if (unshare(CLONE_NEWNET | (c->netns_only ? 0 : CLONE_NEWUSER))) {
- perror("unshare");
- exit(EXIT_FAILURE);
- }
-
- if (!c->netns_only) {
- snprintf(buf, BUFSIZ, "%u %u %u", 0, euid, 1);
-
- fd = open("/proc/self/uid_map", O_WRONLY);
- write(fd, buf, strlen(buf));
- close(fd);
-
- fd = open("/proc/self/setgroups", O_WRONLY);
- write(fd, "deny", sizeof("deny"));
- close(fd);
-
- fd = open("/proc/self/gid_map", O_WRONLY);
- write(fd, buf, strlen(buf));
- close(fd);
- }
-
- fd = open("/proc/sys/net/ipv4/ping_group_range", O_WRONLY);
- write(fd, "0 0", strlen("0 0"));
- close(fd);
-
- shell = getenv("SHELL") ? getenv("SHELL") : "/bin/sh";
- if (strstr(shell, "/bash"))
- execve(shell, ((char *[]) { shell, "-l", NULL }), environ);
- else
- execve(shell, ((char *[]) { shell, NULL }), environ);
-
- perror("execve");
- exit(EXIT_FAILURE);
-}
-
/**
* main() - Entry point and main loop
* @argc: Argument count
@@ -366,20 +195,12 @@ int main(int argc, char **argv)
openlog(log_name, 0, LOG_DAEMON);
setlogmask(LOG_MASK(LOG_EMERG));
+
conf(&c, argc, argv);
if (!c.debug && (c.stderr || isatty(fileno(stdout))))
openlog(log_name, LOG_PERROR, LOG_DAEMON);
- if (c.mode == MODE_PASTA && !c.pasta_netns_fd) {
- char proc_path[PATH_MAX];
-
- pasta_start_ns(&c);
- snprintf(proc_path, PATH_MAX, "/proc/%i/ns/net",
- pasta_child_pid);
- readlink(proc_path, pasta_child_ns, PATH_MAX);
- }
-
c.epollfd = epoll_create1(0);
if (c.epollfd == -1) {
perror("epoll_create1");