diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2021-10-11 12:01:31 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2021-10-14 13:15:12 +0200 |
commit | 675174d4ba255383b213437e29b617d8f55dbc69 (patch) | |
tree | 7add0cf70e595028f9ca9485eb8e139d3d652bb6 /passt.c | |
parent | dcd3605d14aba011fa6c2f4596cb7494f64d2b93 (diff) | |
download | passt-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.c | 183 |
1 files changed, 2 insertions, 181 deletions
@@ -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"); |