aboutgitcodebugslistschat
path: root/qrap.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-05-10 12:38:50 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-05-10 12:38:50 +0200
commit6f89dc3650847e970dd9d0d5c986793e22b73a00 (patch)
tree7b110d3cf5374a5cc68274ec31eea12c9f1978dd /qrap.c
parentc8581f3710335ae6be68909c1c8307aa66990428 (diff)
downloadpasst-6f89dc3650847e970dd9d0d5c986793e22b73a00.tar
passt-6f89dc3650847e970dd9d0d5c986793e22b73a00.tar.gz
passt-6f89dc3650847e970dd9d0d5c986793e22b73a00.tar.bz2
passt-6f89dc3650847e970dd9d0d5c986793e22b73a00.tar.lz
passt-6f89dc3650847e970dd9d0d5c986793e22b73a00.tar.xz
passt-6f89dc3650847e970dd9d0d5c986793e22b73a00.tar.zst
passt-6f89dc3650847e970dd9d0d5c986793e22b73a00.zip
qrap: Find qemu command if not passed, patch command line
It might be impractical to pass options to qrap when using libvirt, because the <emulator/> tag expects a path to an executable, without further arguments. If the first argument is not a plausible socket number, and the second argument is not a valid executable, look up a qemu command from a list of possible names, then start it patching the command line to include the -netdev fd= parameter corresponding to the AF_UNIX domain socket we just opened. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'qrap.c')
-rw-r--r--qrap.c90
1 files changed, 81 insertions, 9 deletions
diff --git a/qrap.c b/qrap.c
index 3dc525a..7f27d47 100644
--- a/qrap.c
+++ b/qrap.c
@@ -19,20 +19,36 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
-#include <limits.h>
#include <linux/if_ether.h>
#include <linux/ipv6.h>
+#include <linux/limits.h>
+#include <limits.h>
#include <net/if.h>
#include "passt.h"
+static char *qemu_names[] = {
+ "kvm",
+ "qemu-kvm",
+#ifdef ARCH
+ "qemu-system-" ARCH,
+#endif
+ NULL,
+};
+
+#define DEFAULT_FD 5
+
/**
* usage() - Print usage and exit
* @name: Executable name
*/
void usage(const char *name)
{
- fprintf(stderr, "Usage: %s FDNUM QEMU_CMD ...\n", name);
+ fprintf(stderr, "Usage: %s [FDNUM QEMU_CMD] ...\n", name);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "If first and second arguments aren't a socket number\n"
+ "and a path, %s will try to locate a qemu binary\n"
+ "and directly patch the command line\n", name);
exit(EXIT_FAILURE);
}
@@ -46,20 +62,60 @@ void usage(const char *name)
*/
int main(int argc, char **argv)
{
+ char *qemu_argv[ARG_MAX], net_id[ARG_MAX] = { 0 }, *net_id_end;
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
.sun_path = UNIX_SOCK_PATH,
};
+ int i, s, qemu_argc = 0;
+ char fd_str[ARG_MAX];
long fd;
- int s;
- if (argc < 3)
- usage(argv[0]);
+ if (argc >= 3) {
+ fd = strtol(argv[1], NULL, 0);
+ if (fd >= 3 && fd < INT_MAX && !errno) {
+ char env_path[ARG_MAX], *p, command[ARG_MAX];
+
+ strncpy(env_path, getenv("PATH"), ARG_MAX);
+ p = strtok(env_path, ":");
+ while (p) {
+ snprintf(command, ARG_MAX, "%s/%s", p, argv[2]);
+ if (!access(command, X_OK))
+ goto valid_args;
+
+ p = strtok(NULL, ":");
+ }
+ }
+ }
+
+ fd = DEFAULT_FD;
+ for (qemu_argc = 1, i = 1; i < argc; i++) {
+ char *p;
+
+ if (!strcmp(argv[i], "-net") || (!strcmp(argv[i], "-netdev"))) {
+ i++;
+ continue;
+ }
- fd = strtol(argv[1], NULL, 0);
- if (fd < 3 || fd > INT_MAX || errno)
- usage(argv[0]);
+ if (!*net_id && (p = strstr(argv[i], ",netdev=")))
+ strncpy(net_id, p + strlen(",netdev="), ARG_MAX);
+ qemu_argv[qemu_argc++] = argv[i];
+ }
+
+ if (*net_id) {
+ net_id_end = strpbrk(net_id, ", ");
+ if (net_id_end)
+ *net_id_end = 0;
+ }
+
+ qemu_argv[qemu_argc++] = "-netdev";
+ snprintf(fd_str, ARG_MAX, "socket,fd=%u,id=%s", DEFAULT_FD,
+ *net_id ? net_id : "hostnet0");
+ qemu_argv[qemu_argc++] = fd_str;
+ qemu_argv[qemu_argc] = NULL;
+
+valid_args:
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
perror("socket");
@@ -78,7 +134,23 @@ int main(int argc, char **argv)
close(s);
- execvp(argv[2], argv + 2);
+ if (qemu_argc) {
+ char *name;
+
+ for (name = qemu_names[0]; name; name++) {
+ qemu_argv[0] = name;
+ execvp(name, qemu_argv);
+ if (errno != ENOENT) {
+ perror("execvp");
+ usage(argv[0]);
+ }
+ }
+ if (errno == ENOENT)
+ fprintf(stderr, "Couldn't find qemu command\n");
+ } else {
+ execvp(argv[2], argv + 2);
+ }
+
perror("execvp");
return EXIT_FAILURE;