aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--qrap.c90
2 files changed, 82 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index 326e717..213020b 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ passt: passt.c passt.h arp.c arp.h dhcp.c dhcp.h dhcpv6.c dhcpv6.h ndp.c ndp.h s
$(CC) $(CFLAGS) passt.c arp.c dhcp.c dhcpv6.c ndp.c siphash.c tap.c icmp.c tcp.c udp.c util.c -o passt
qrap: qrap.c passt.h
- $(CC) $(CFLAGS) qrap.c -o qrap
+ $(CC) $(CFLAGS) -DARCH=\"$(shell uname -m)\" qrap.c -o qrap
.PHONY: clean
clean:
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;