From fa2d20908d061fc7a4c56e793487da861af58aca Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Sat, 18 Jul 2020 01:02:39 +0200 Subject: merd: Switch to AF_UNIX for qemu tap, provide wrapper We can bypass a full-fledged network interface between qemu and merd by connecting the qemu tap file descriptor to a provided UNIX domain socket: this could be implemented in qemu eventually, qrap covers this meanwhile. This also avoids the need for the AF_PACKET socket towards the guest. Signed-off-by: Stefano Brivio --- qrap.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 qrap.c (limited to 'qrap.c') diff --git a/qrap.c b/qrap.c new file mode 100644 index 0000000..b246a7e --- /dev/null +++ b/qrap.c @@ -0,0 +1,79 @@ +/* MERD - MacVTap Egress and Routing Daemon + * + * qrap.c - qemu wrapper connecting UNIX domain socket to tap file descriptor + * + * Author: Stefano Brivio + * License: GPLv2 + * + * TODO: Implement this functionality directly in qemu: we have TCP and UDP + * socket back-ends already. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "merd.h" + +/** + * usage() - Print usage and exit + * @name: Executable name + */ +void usage(const char *name) +{ + fprintf(stderr, "Usage: %s FDNUM QEMU_CMD ...\n", name); + + exit(EXIT_FAILURE); +} + +/** + * main() - Entry point and main loop + * @argc: Argument count + * @argv: File descriptor number, then qemu with arguments + * + * Return: 0 once interrupted, non-zero on failure + */ +int main(int argc, char **argv) +{ + struct sockaddr_un addr = { + .sun_family = AF_UNIX, + .sun_path = UNIX_SOCK_PATH, + }; + long fd; + int s; + + if (argc < 3) + usage(argv[0]); + + fd = strtol(argv[1], NULL, 0); + if (fd < 3 || fd > INT_MAX || errno) + usage(argv[0]); + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) { + perror("socket"); + exit(EXIT_FAILURE); + } + + if (connect(s, (const struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + + if (dup2(s, (int)fd) < 0) { + perror("dup"); + exit(EXIT_FAILURE); + } + + close(s); + + execvp(argv[2], argv + 2); + perror("execvp"); + + return EXIT_FAILURE; +} -- cgit v1.2.3