2015-10-03 10:56:08 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015, Stefan Lankes, RWTH Aachen University
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* * Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this
|
|
|
|
* software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2016-08-28 08:50:25 +02:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
2016-10-19 12:49:37 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
2016-08-28 10:43:41 +02:00
|
|
|
#include <arpa/inet.h>
|
2016-03-25 14:42:42 +01:00
|
|
|
#include <errno.h>
|
2016-08-28 10:43:41 +02:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <linux/tcp.h>
|
|
|
|
#include <netinet/in.h>
|
2016-08-22 16:04:49 +02:00
|
|
|
#include <sched.h>
|
2016-08-28 10:43:41 +02:00
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/inotify.h>
|
2015-10-03 10:56:08 +02:00
|
|
|
#include <sys/socket.h>
|
2016-08-28 08:50:25 +02:00
|
|
|
#include <sys/types.h>
|
2016-08-28 10:43:41 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
2016-10-19 12:49:37 +02:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <net/if.h>
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-01-16 18:47:13 +01:00
|
|
|
#include "proxy.h"
|
|
|
|
|
2015-12-31 01:22:54 +01:00
|
|
|
#define MAX_PATH 255
|
2016-08-22 06:38:06 +02:00
|
|
|
#define MAX_ARGS 1024
|
2016-03-30 16:11:19 +02:00
|
|
|
#define INADDR(a, b, c, d) (struct in_addr) { .s_addr = ((((((d) << 8) | (c)) << 8) | (b)) << 8) | (a) }
|
2016-03-30 13:08:55 +02:00
|
|
|
|
|
|
|
#define HERMIT_PORT 0x494E
|
|
|
|
#define HERMIT_IP(isle) INADDR(192, 168, 28, isle + 2)
|
|
|
|
#define HERMIT_MAGIC 0x7E317
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2016-08-28 08:50:25 +02:00
|
|
|
#define EVENT_SIZE (sizeof (struct inotify_event))
|
|
|
|
#define BUF_LEN (1024 * (EVENT_SIZE + 16))
|
|
|
|
|
2017-02-20 22:25:28 +01:00
|
|
|
#if 0
|
2017-02-18 21:58:33 +01:00
|
|
|
#define PROXY_DEBUG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__);
|
|
|
|
#else
|
|
|
|
#define PROXY_DEBUG(fmt, ...) {}
|
|
|
|
#endif
|
|
|
|
|
2017-02-25 17:21:14 +01:00
|
|
|
typedef enum {
|
|
|
|
BAREMETAL = 0,
|
|
|
|
QEMU,
|
|
|
|
UHYVE
|
|
|
|
} monitor_t;
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
static monitor_t monitor = BAREMETAL;
|
2015-10-03 10:56:08 +02:00
|
|
|
static int sobufsize = 131072;
|
2015-10-17 14:55:54 +02:00
|
|
|
static unsigned int isle_nr = 0;
|
2016-08-22 06:38:06 +02:00
|
|
|
static unsigned int port = HERMIT_PORT;
|
2017-02-20 22:14:21 +01:00
|
|
|
static char pidname[] = "/tmp/hpid-XXXXXX";
|
2016-08-22 06:38:06 +02:00
|
|
|
static char tmpname[] = "/tmp/hermit-XXXXXX";
|
2016-10-08 23:24:55 +02:00
|
|
|
static char cmdline[MAX_PATH] = "";
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2016-01-04 19:31:54 +01:00
|
|
|
extern char **environ;
|
|
|
|
|
2016-03-15 22:03:06 +01:00
|
|
|
static void stop_hermit(void);
|
|
|
|
static void dump_log(void);
|
2017-02-21 14:08:49 +01:00
|
|
|
static int multi_init(char *path);
|
|
|
|
static int qemu_init(char *path);
|
2016-03-15 22:03:06 +01:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
static void qemu_fini(void)
|
2015-10-17 14:55:54 +02:00
|
|
|
{
|
2017-02-21 09:18:07 +01:00
|
|
|
FILE* fp = NULL;
|
|
|
|
|
2017-02-20 22:14:21 +01:00
|
|
|
// try to kill qemu
|
2017-02-21 14:08:49 +01:00
|
|
|
if (monitor == QEMU)
|
2017-02-21 09:18:07 +01:00
|
|
|
fp = fopen(pidname, "r");
|
2017-02-20 22:14:21 +01:00
|
|
|
if (fp) {
|
|
|
|
pid_t id = -1;
|
|
|
|
|
|
|
|
int ret = fscanf(fp, "%d", &id);
|
|
|
|
if (ret <= 0)
|
|
|
|
fprintf(stderr, "Unable to read Qemu's pid\n");
|
|
|
|
fclose(fp);
|
2017-02-20 22:25:28 +01:00
|
|
|
unlink(pidname);
|
2017-02-20 22:14:21 +01:00
|
|
|
|
|
|
|
if (id >= 0) {
|
|
|
|
int status = 0;
|
2016-08-22 06:38:06 +02:00
|
|
|
|
2017-02-20 22:14:21 +01:00
|
|
|
kill(id, SIGINT);
|
|
|
|
wait(&status);
|
|
|
|
}
|
2017-01-16 18:47:13 +01:00
|
|
|
}
|
2016-08-22 06:38:06 +02:00
|
|
|
|
2017-01-16 18:47:13 +01:00
|
|
|
dump_log();
|
2017-02-20 22:25:28 +01:00
|
|
|
unlink(tmpname);
|
2017-01-16 18:47:13 +01:00
|
|
|
}
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
static void multi_fini(void)
|
2017-01-16 18:47:13 +01:00
|
|
|
{
|
|
|
|
dump_log();
|
|
|
|
stop_hermit();
|
|
|
|
}
|
2015-12-29 02:22:41 +01:00
|
|
|
|
2016-03-25 09:21:54 +01:00
|
|
|
static void exit_handler(int sig)
|
|
|
|
{
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2017-04-03 09:16:54 +02:00
|
|
|
static char* get_append_string(void)
|
2016-10-08 00:59:52 +02:00
|
|
|
{
|
|
|
|
char line[2048];
|
2016-10-09 23:14:31 +02:00
|
|
|
char* match;
|
|
|
|
char* point;
|
2016-10-08 00:59:52 +02:00
|
|
|
|
|
|
|
FILE* fp = fopen("/proc/cpuinfo", "r");
|
|
|
|
if (!fp)
|
2016-10-09 08:55:10 +02:00
|
|
|
return "-freq0";
|
2016-10-08 00:59:52 +02:00
|
|
|
|
|
|
|
while(fgets(line, 2048, fp)) {
|
2016-10-09 08:55:10 +02:00
|
|
|
if ((match = strstr(line, "cpu MHz")) == NULL)
|
2016-10-08 00:59:52 +02:00
|
|
|
continue;
|
|
|
|
|
2016-10-09 08:55:10 +02:00
|
|
|
// scan strinf for the next number
|
|
|
|
for(; (*match < 0x30) || (*match > 0x39); match++)
|
|
|
|
;
|
|
|
|
|
2016-10-09 23:14:31 +02:00
|
|
|
for(point = match; ((*point != '.') && (*point != '\0')); point++)
|
|
|
|
;
|
|
|
|
*point = '\0';
|
|
|
|
|
2017-04-03 09:16:54 +02:00
|
|
|
snprintf(cmdline, MAX_PATH, "\"-freq%s -proxy\"", match);
|
2016-10-08 00:59:52 +02:00
|
|
|
fclose(fp);
|
|
|
|
|
2016-10-08 23:24:55 +02:00
|
|
|
return cmdline;
|
2016-10-08 00:59:52 +02:00
|
|
|
}
|
|
|
|
|
2016-10-09 08:55:10 +02:00
|
|
|
return "-freq0";
|
2016-10-08 00:59:52 +02:00
|
|
|
}
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
static int env_init(char *path)
|
2015-12-29 02:22:41 +01:00
|
|
|
{
|
2015-10-17 14:55:54 +02:00
|
|
|
char* str;
|
2016-03-25 09:21:54 +01:00
|
|
|
struct sigaction sINT, sTERM;
|
|
|
|
|
2016-03-30 13:11:45 +02:00
|
|
|
// define action for SIGINT
|
2016-03-25 09:21:54 +01:00
|
|
|
sINT.sa_handler = exit_handler;
|
|
|
|
sINT.sa_flags = 0;
|
|
|
|
if (sigaction(SIGINT, &sINT, NULL) < 0)
|
|
|
|
{
|
|
|
|
perror("sigaction");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2016-03-30 13:11:45 +02:00
|
|
|
// define action for SIGTERM
|
2016-03-25 09:21:54 +01:00
|
|
|
sTERM.sa_handler = exit_handler;
|
|
|
|
sTERM.sa_flags = 0;
|
|
|
|
if (sigaction(SIGTERM, &sTERM, NULL) < 0)
|
|
|
|
{
|
|
|
|
perror("sigaction");
|
|
|
|
exit(1);
|
|
|
|
}
|
2015-10-17 14:55:54 +02:00
|
|
|
|
|
|
|
str = getenv("HERMIT_ISLE");
|
|
|
|
if (str)
|
|
|
|
{
|
2016-08-22 06:38:06 +02:00
|
|
|
if (strncmp(str, "qemu", 4) == 0) {
|
2017-02-21 14:08:49 +01:00
|
|
|
monitor = QEMU;
|
2017-01-16 18:47:13 +01:00
|
|
|
isle_nr = 0;
|
|
|
|
} else if (strncmp(str, "uhyve", 5) == 0) {
|
2017-02-21 14:08:49 +01:00
|
|
|
monitor = UHYVE;
|
2015-10-17 14:55:54 +02:00
|
|
|
isle_nr = 0;
|
2016-08-22 06:38:06 +02:00
|
|
|
} else {
|
|
|
|
isle_nr = atoi(str);
|
|
|
|
if (isle_nr > 254)
|
|
|
|
isle_nr = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
str = getenv("HERMIT_PORT");
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
port = atoi(str);
|
|
|
|
if ((port == 0) || (port >= UINT16_MAX))
|
|
|
|
port = HERMIT_PORT;
|
2015-10-17 14:55:54 +02:00
|
|
|
}
|
2016-03-30 21:41:56 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
if (monitor == QEMU) {
|
|
|
|
atexit(qemu_fini);
|
|
|
|
return qemu_init(path);
|
|
|
|
} else if (monitor == UHYVE) {
|
|
|
|
return uhyve_init(path);
|
2017-01-16 18:47:13 +01:00
|
|
|
} else {
|
2017-02-21 14:08:49 +01:00
|
|
|
atexit(multi_fini);
|
|
|
|
return multi_init(path);
|
2017-01-16 18:47:13 +01:00
|
|
|
}
|
2016-08-22 06:38:06 +02:00
|
|
|
}
|
|
|
|
|
2016-10-19 12:49:37 +02:00
|
|
|
static int is_hermit_available(void)
|
2016-08-28 08:50:25 +02:00
|
|
|
{
|
2016-08-28 09:34:14 +02:00
|
|
|
char* line = (char*) malloc(2048);
|
2016-08-28 08:50:25 +02:00
|
|
|
size_t n = 2048;
|
2016-08-28 09:46:59 +02:00
|
|
|
int ret = 0;
|
2016-10-19 12:49:37 +02:00
|
|
|
FILE* file;
|
2016-08-28 08:50:25 +02:00
|
|
|
|
2016-08-28 09:34:14 +02:00
|
|
|
if (!line) {
|
|
|
|
fprintf(stderr, "Not enough memory\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
if (monitor == QEMU) {
|
2016-10-19 12:49:37 +02:00
|
|
|
file = fopen(tmpname, "r");
|
2017-02-19 22:25:11 +01:00
|
|
|
if (!file) {
|
|
|
|
PROXY_DEBUG("%s isn't available\n", tmpname);
|
|
|
|
}
|
2017-02-19 22:11:47 +01:00
|
|
|
} else {
|
2016-10-19 12:49:37 +02:00
|
|
|
char logname[MAX_PATH];
|
|
|
|
|
|
|
|
snprintf(logname, MAX_PATH, "/sys/hermit/isle%d/log", isle_nr);
|
|
|
|
file = fopen(logname, "r");
|
|
|
|
}
|
|
|
|
|
2016-08-28 08:50:25 +02:00
|
|
|
if (!file)
|
|
|
|
return 0;
|
|
|
|
|
2017-02-18 22:21:53 +01:00
|
|
|
//PROXY_DEBUG("Open log file\n");
|
2017-02-18 22:12:01 +01:00
|
|
|
|
2016-08-28 09:34:14 +02:00
|
|
|
while(getline(&line, &n, file) > 0) {
|
2016-11-13 23:13:23 +01:00
|
|
|
if (strstr(line, "TCP server is listening.") != NULL) {
|
2016-08-28 09:46:59 +02:00
|
|
|
ret = 1;
|
|
|
|
break;
|
2016-08-28 08:50:25 +02:00
|
|
|
}
|
2017-02-18 23:15:16 +01:00
|
|
|
//PROXY_DEBUG("%s\n", line);
|
2016-08-28 08:50:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fclose(file);
|
2016-08-28 09:34:14 +02:00
|
|
|
free(line);
|
2016-08-28 08:50:25 +02:00
|
|
|
|
2016-08-28 09:46:59 +02:00
|
|
|
return ret;
|
2016-08-28 08:50:25 +02:00
|
|
|
}
|
|
|
|
|
2016-08-28 10:43:41 +02:00
|
|
|
// wait until HermitCore is sucessfully booted
|
2016-10-19 12:49:37 +02:00
|
|
|
static void wait_hermit_available(void)
|
2016-08-28 10:43:41 +02:00
|
|
|
{
|
2016-08-28 10:54:57 +02:00
|
|
|
char buffer[BUF_LEN];
|
2016-10-19 12:49:37 +02:00
|
|
|
int wd;
|
2016-08-28 10:54:57 +02:00
|
|
|
|
2016-10-19 12:49:37 +02:00
|
|
|
if (is_hermit_available())
|
2016-08-28 10:43:41 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
int fd = inotify_init();
|
|
|
|
if ( fd < 0 ) {
|
|
|
|
perror( "inotify_init" );
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
if (monitor == QEMU)
|
2016-10-19 12:49:37 +02:00
|
|
|
wd = inotify_add_watch(fd, "/tmp", IN_MODIFY|IN_CREATE);
|
|
|
|
else
|
|
|
|
wd = inotify_add_watch(fd, "/sys/hermit", IN_MODIFY|IN_CREATE);
|
2016-08-28 10:43:41 +02:00
|
|
|
|
2017-02-18 13:20:43 +01:00
|
|
|
if (wd < 0) {
|
|
|
|
perror("inotify_add_watch");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2016-08-28 10:43:41 +02:00
|
|
|
while(1) {
|
|
|
|
int length = read(fd, buffer, BUF_LEN);
|
|
|
|
|
|
|
|
if (length < 0) {
|
|
|
|
perror("read");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-10-19 12:49:37 +02:00
|
|
|
if (length != 0 && is_hermit_available())
|
2016-08-28 10:43:41 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//printf("HermitCore is available\n");
|
2017-02-18 13:23:43 +01:00
|
|
|
if (inotify_rm_watch(fd, wd) < 0) {
|
|
|
|
perror("inotify_rm_watch");
|
|
|
|
exit(1);
|
|
|
|
}
|
2016-08-28 10:43:41 +02:00
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
static int qemu_init(char *path)
|
2016-08-22 06:38:06 +02:00
|
|
|
{
|
2016-08-28 08:50:25 +02:00
|
|
|
int kvm, i = 0;
|
2016-08-22 06:38:06 +02:00
|
|
|
char* str;
|
|
|
|
char loader_path[MAX_PATH];
|
|
|
|
char hostfwd[MAX_PATH];
|
|
|
|
char monitor_str[MAX_PATH];
|
|
|
|
char chardev_file[MAX_PATH];
|
2016-09-20 00:32:48 +02:00
|
|
|
char port_str[MAX_PATH];
|
2017-02-20 22:14:21 +01:00
|
|
|
pid_t qemu_pid;
|
2016-08-22 06:38:06 +02:00
|
|
|
char* qemu_str = "qemu-system-x86_64";
|
2017-04-03 09:16:54 +02:00
|
|
|
char* qemu_argv[] = {qemu_str, "-daemonize", "-display", "none", "-smp", "1", "-m", "2G", "-pidfile", pidname, "-net", "nic,model=rtl8139", "-net", hostfwd, "-chardev", chardev_file, "-device", "pci-serial,chardev=gnc0", "-kernel", loader_path, "-initrd", path, "-append", get_append_string(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
2016-08-22 06:38:06 +02:00
|
|
|
|
|
|
|
str = getenv("HERMIT_CPUS");
|
|
|
|
if (str)
|
2017-02-20 22:14:21 +01:00
|
|
|
qemu_argv[5] = str;
|
2016-08-22 06:38:06 +02:00
|
|
|
|
|
|
|
str = getenv("HERMIT_MEM");
|
|
|
|
if (str)
|
2017-02-20 22:14:21 +01:00
|
|
|
qemu_argv[7] = str;
|
2016-08-22 06:38:06 +02:00
|
|
|
|
|
|
|
str = getenv("HERMIT_QEMU");
|
|
|
|
if (str)
|
|
|
|
qemu_argv[0] = qemu_str = str;
|
|
|
|
|
2016-08-25 17:52:37 +02:00
|
|
|
snprintf(hostfwd, MAX_PATH, "user,hostfwd=tcp:127.0.0.1:%u-:%u", port, port);
|
2016-08-22 06:38:06 +02:00
|
|
|
snprintf(monitor_str, MAX_PATH, "telnet:127.0.0.1:%d,server,nowait", port+1);
|
|
|
|
|
2017-02-20 22:14:21 +01:00
|
|
|
if (mkstemp(pidname) < 0)
|
|
|
|
{
|
|
|
|
perror("mkstemp");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2016-11-26 20:44:30 +01:00
|
|
|
if (mkstemp(tmpname) < 0)
|
|
|
|
{
|
|
|
|
perror("mkstemp");
|
|
|
|
exit(1);
|
|
|
|
}
|
2016-08-22 06:38:06 +02:00
|
|
|
snprintf(chardev_file, MAX_PATH, "file,id=gnc0,path=%s", tmpname);
|
|
|
|
|
2016-11-26 20:44:30 +01:00
|
|
|
if (readlink("/proc/self/exe", loader_path, MAX_PATH) < 0)
|
|
|
|
{
|
|
|
|
perror("readlink");
|
|
|
|
exit(1);
|
|
|
|
}
|
2016-08-22 06:38:06 +02:00
|
|
|
str = strstr(loader_path, "proxy");
|
2017-01-17 22:55:42 +01:00
|
|
|
strncpy(str, "ldhermit.elf", MAX_PATH-strlen(loader_path)+5);
|
2016-08-22 06:38:06 +02:00
|
|
|
|
2016-09-20 00:32:48 +02:00
|
|
|
str = getenv("HERMIT_APP_PORT");
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
int app_port = atoi(str);
|
|
|
|
|
|
|
|
if (app_port > 0) {
|
2017-02-19 11:10:14 +01:00
|
|
|
for(; qemu_argv[i] != NULL; i++)
|
2016-09-20 00:32:48 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
snprintf(port_str, MAX_PATH, "tcp:%u::%u", app_port, app_port);
|
|
|
|
|
|
|
|
qemu_argv[i] = "-redir";
|
|
|
|
qemu_argv[i+1] = port_str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-27 19:12:08 +02:00
|
|
|
str = getenv("HERMIT_KVM");
|
|
|
|
if (str && (strcmp(str, "0") == 0))
|
|
|
|
kvm = 0;
|
|
|
|
else
|
|
|
|
kvm = 1;
|
|
|
|
|
|
|
|
if (kvm)
|
|
|
|
{
|
2017-02-19 11:10:14 +01:00
|
|
|
for(; qemu_argv[i] != NULL; i++)
|
2016-08-27 19:12:08 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
qemu_argv[i] = "-machine";
|
|
|
|
qemu_argv[i+1] = "accel=kvm";
|
|
|
|
qemu_argv[i+2] = "-cpu";
|
|
|
|
qemu_argv[i+3] = "host";
|
|
|
|
} /*else {
|
2017-02-19 11:10:14 +01:00
|
|
|
for(; qemu_argv[i] != NULL; i++)
|
2016-08-27 19:12:08 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
qemu_argv[i] = "-cpu";
|
|
|
|
qemu_argv[i+1] = "SandyBridge";
|
|
|
|
}*/
|
|
|
|
|
2017-02-19 11:58:44 +01:00
|
|
|
str = getenv("HERMIT_MONITOR");
|
2017-02-19 11:54:31 +01:00
|
|
|
if (str && (strcmp(str, "0") != 0))
|
|
|
|
{
|
|
|
|
for(; qemu_argv[i] != NULL; i++)
|
|
|
|
;
|
|
|
|
|
|
|
|
qemu_argv[i] = "-monitor";
|
|
|
|
qemu_argv[i+1] = monitor_str;
|
|
|
|
}
|
|
|
|
|
2016-11-20 14:38:43 +01:00
|
|
|
str = getenv("HERMIT_DEBUG");
|
|
|
|
if (str && (strcmp(str, "0") != 0))
|
|
|
|
{
|
2017-02-19 11:10:14 +01:00
|
|
|
for(; qemu_argv[i] != NULL; i++)
|
2016-11-20 14:38:43 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
// add flag to start gdbserver on TCP port 1234
|
|
|
|
qemu_argv[i] = "-s";
|
|
|
|
}
|
|
|
|
|
2017-02-19 10:56:24 +01:00
|
|
|
str = getenv("HERMIT_CAPTURE_NET");
|
|
|
|
if (str && (strcmp(str, "0") != 0))
|
|
|
|
{
|
2017-02-19 11:10:14 +01:00
|
|
|
for(; qemu_argv[i] != NULL; i++)
|
2017-02-19 10:56:24 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
// add flags to capture the network traffic
|
|
|
|
qemu_argv[i] = "-net";
|
|
|
|
qemu_argv[i+1] = "dump";
|
|
|
|
}
|
|
|
|
|
2016-08-23 10:12:25 +02:00
|
|
|
str = getenv("HERMIT_VERBOSE");
|
2016-09-22 19:39:52 +02:00
|
|
|
if (str && (strcmp(str, "0") != 0))
|
2016-08-23 10:12:25 +02:00
|
|
|
{
|
2016-08-28 18:12:31 +02:00
|
|
|
printf("qemu startup command: ");
|
2016-08-23 10:12:25 +02:00
|
|
|
|
2016-08-25 17:52:37 +02:00
|
|
|
for(i=0; qemu_argv[i] != NULL; i++)
|
2016-08-23 10:12:25 +02:00
|
|
|
printf("%s ", qemu_argv[i]);
|
2017-02-19 11:58:44 +01:00
|
|
|
printf("\n");
|
2016-08-23 10:12:25 +02:00
|
|
|
fflush(stdout);
|
|
|
|
}
|
2016-08-22 06:38:06 +02:00
|
|
|
|
2017-02-20 22:14:21 +01:00
|
|
|
qemu_pid = fork();
|
|
|
|
if (qemu_pid == 0)
|
2016-08-22 06:38:06 +02:00
|
|
|
{
|
|
|
|
execvp(qemu_str, qemu_argv);
|
|
|
|
|
|
|
|
fprintf(stderr, "Didn't find qemu\n");
|
|
|
|
exit(1);
|
2017-02-20 22:14:21 +01:00
|
|
|
} else if (qemu_pid < 0) {
|
2017-02-18 12:32:29 +01:00
|
|
|
perror("fork");
|
|
|
|
exit(1);
|
2016-08-22 06:38:06 +02:00
|
|
|
}
|
|
|
|
|
2017-02-20 22:14:21 +01:00
|
|
|
PROXY_DEBUG("Create VM with pid %d\n", qemu_pid);
|
2017-02-18 21:58:33 +01:00
|
|
|
|
2016-08-22 09:01:59 +02:00
|
|
|
// move the parent process to the end of the queue
|
|
|
|
// => child would be scheduled next
|
|
|
|
sched_yield();
|
|
|
|
|
2016-08-28 08:50:25 +02:00
|
|
|
// wait until HermitCore is sucessfully booted
|
2016-10-19 12:49:37 +02:00
|
|
|
wait_hermit_available();
|
2016-08-28 08:50:25 +02:00
|
|
|
|
2017-02-18 21:58:33 +01:00
|
|
|
PROXY_DEBUG("VM is available\n");
|
|
|
|
|
2016-08-22 06:38:06 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
static int multi_init(char *path)
|
2016-08-22 06:38:06 +02:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
char* str;
|
|
|
|
FILE* file;
|
|
|
|
char isle_path[MAX_PATH];
|
|
|
|
char* result;
|
|
|
|
|
2016-04-02 09:39:06 +02:00
|
|
|
// set path to temporary file
|
2016-04-12 10:13:10 +02:00
|
|
|
snprintf(isle_path, MAX_PATH, "/sys/hermit/isle%d/path", isle_nr);
|
|
|
|
file = fopen(isle_path, "w");
|
2016-04-02 09:39:06 +02:00
|
|
|
if (!file) {
|
|
|
|
perror("fopen");
|
2015-12-29 02:22:41 +01:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2016-04-02 09:39:06 +02:00
|
|
|
fprintf(file, "%s", path);
|
|
|
|
fclose(file);
|
|
|
|
|
2015-12-29 02:22:41 +01:00
|
|
|
// start application
|
2015-12-31 01:22:54 +01:00
|
|
|
snprintf(isle_path, MAX_PATH, "/sys/hermit/isle%d/cpus", isle_nr);
|
|
|
|
file = fopen(isle_path, "w");
|
2015-12-29 02:22:41 +01:00
|
|
|
if (!file) {
|
|
|
|
perror("fopen");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2015-12-31 01:22:54 +01:00
|
|
|
str = getenv("HERMIT_CPUS");
|
|
|
|
if (str)
|
2016-03-14 21:08:57 +01:00
|
|
|
fprintf(file, "%s", str);
|
2015-12-31 01:22:54 +01:00
|
|
|
else
|
2016-03-14 21:08:57 +01:00
|
|
|
fprintf(file, "%s", "1");
|
2015-12-29 02:22:41 +01:00
|
|
|
|
|
|
|
fclose(file);
|
|
|
|
|
2016-03-13 10:01:46 +01:00
|
|
|
// check result
|
|
|
|
file = fopen(isle_path, "r");
|
|
|
|
if (!file) {
|
|
|
|
perror("fopen");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2016-03-13 10:28:25 +01:00
|
|
|
result = NULL;
|
|
|
|
ret = fscanf(file, "%ms", &result);
|
2016-03-14 21:08:57 +01:00
|
|
|
|
2016-03-13 10:28:25 +01:00
|
|
|
fclose(file);
|
2016-03-13 10:01:46 +01:00
|
|
|
|
2016-03-13 10:28:25 +01:00
|
|
|
if (ret <= 0) {
|
|
|
|
fprintf(stderr, "Unable to check the boot process!\n");
|
2016-03-13 10:01:46 +01:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2016-03-13 10:28:25 +01:00
|
|
|
if (strcmp(result, "-1") == 0) {
|
|
|
|
free(result);
|
|
|
|
fprintf(stderr, "Unable to boot cores %s\n", str ? str : "1");
|
|
|
|
exit(1);
|
2016-03-13 10:01:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
free(result);
|
2015-12-29 02:22:41 +01:00
|
|
|
|
2016-10-19 12:49:37 +02:00
|
|
|
// wait until HermitCore is sucessfully booted
|
2016-10-20 20:47:31 +02:00
|
|
|
//wait_hermit_available();
|
2016-10-19 12:49:37 +02:00
|
|
|
|
2015-10-17 14:55:54 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-05 23:18:56 +01:00
|
|
|
static void dump_log(void)
|
|
|
|
{
|
|
|
|
char* str = getenv("HERMIT_VERBOSE");
|
|
|
|
FILE* file;
|
|
|
|
char line[2048];
|
|
|
|
|
2016-09-22 19:39:52 +02:00
|
|
|
if (!(str && (strcmp(str, "0") != 0)))
|
2016-01-05 23:18:56 +01:00
|
|
|
return;
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
if (monitor == BAREMETAL)
|
2016-08-22 06:38:06 +02:00
|
|
|
{
|
|
|
|
char isle_path[MAX_PATH];
|
|
|
|
|
|
|
|
snprintf(isle_path, MAX_PATH, "/sys/hermit/isle%d/log", isle_nr);
|
|
|
|
file = fopen(isle_path, "r");
|
|
|
|
} else file = fopen(tmpname, "r");
|
|
|
|
|
2016-01-05 23:18:56 +01:00
|
|
|
if (!file) {
|
|
|
|
perror("fopen");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
puts("\nDump kernel log:");
|
|
|
|
puts("================\n");
|
|
|
|
|
|
|
|
while(fgets(line, 2048, file)) {
|
|
|
|
printf("%s", line);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
|
2016-03-15 22:03:06 +01:00
|
|
|
static void stop_hermit(void)
|
2016-01-05 23:18:56 +01:00
|
|
|
{
|
|
|
|
FILE* file;
|
|
|
|
char isle_path[MAX_PATH];
|
|
|
|
|
2016-02-14 15:18:29 +01:00
|
|
|
fflush(stdout);
|
|
|
|
fflush(stderr);
|
|
|
|
|
2016-01-05 23:18:56 +01:00
|
|
|
snprintf(isle_path, MAX_PATH, "/sys/hermit/isle%d/cpus", isle_nr);
|
|
|
|
|
|
|
|
file = fopen(isle_path, "w");
|
|
|
|
if (!file) {
|
|
|
|
perror("fopen");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(file, "-1");
|
|
|
|
|
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
|
2015-10-03 10:56:08 +02:00
|
|
|
/*
|
|
|
|
* in principle, HermitCore forwards basic system calls to
|
|
|
|
* this proxy, which mapped these call to Linux system calls.
|
|
|
|
*/
|
|
|
|
int handle_syscalls(int s)
|
|
|
|
{
|
|
|
|
int sysnr;
|
2016-05-16 23:58:41 +02:00
|
|
|
ssize_t sret;
|
2016-08-25 17:52:37 +02:00
|
|
|
size_t j;
|
2015-10-03 10:56:08 +02:00
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
2016-08-25 17:52:37 +02:00
|
|
|
j = 0;
|
|
|
|
while(j < sizeof(sysnr)) {
|
|
|
|
sret = read(s, ((char*)&sysnr)+j, sizeof(sysnr)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
|
|
|
|
switch(sysnr)
|
|
|
|
{
|
|
|
|
case __HERMIT_exit: {
|
2015-10-05 10:12:34 +02:00
|
|
|
int arg = 0;
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while(j < sizeof(arg)) {
|
|
|
|
sret = read(s, ((char*)&arg)+j, sizeof(arg)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
close(s);
|
2016-01-05 23:18:56 +01:00
|
|
|
|
2016-03-15 22:03:06 +01:00
|
|
|
// already called by fini_env
|
|
|
|
//dump_log();
|
|
|
|
//stop_hermit();
|
2016-01-05 23:18:56 +01:00
|
|
|
|
2016-05-14 08:32:21 +02:00
|
|
|
if (arg == -14)
|
2016-09-11 14:06:48 +02:00
|
|
|
fprintf(stderr, "Did HermitCore receive an exception?\n");
|
2015-10-03 10:56:08 +02:00
|
|
|
exit(arg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case __HERMIT_write: {
|
|
|
|
int fd;
|
2015-10-05 10:12:34 +02:00
|
|
|
size_t len;
|
2015-10-03 10:56:08 +02:00
|
|
|
char* buff;
|
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(fd)) {
|
|
|
|
sret = read(s, ((char*)&fd)+j, sizeof(fd)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(len)) {
|
|
|
|
sret = read(s, ((char*)&len)+j, sizeof(len)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
|
|
|
|
buff = malloc(len);
|
|
|
|
if (!buff) {
|
|
|
|
fprintf(stderr,"Proxy: not enough memory");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
j=0;
|
|
|
|
while(j < len)
|
|
|
|
{
|
2016-05-16 23:58:41 +02:00
|
|
|
sret = read(s, buff+j, len-j);
|
|
|
|
if (sret < 0)
|
2015-10-03 10:56:08 +02:00
|
|
|
goto out;
|
2016-05-16 23:58:41 +02:00
|
|
|
j += sret;
|
2015-10-03 10:56:08 +02:00
|
|
|
}
|
|
|
|
|
2016-05-16 23:58:41 +02:00
|
|
|
if (fd > 2) {
|
|
|
|
sret = write(fd, buff, len);
|
2016-11-26 20:44:30 +01:00
|
|
|
j = 0;
|
|
|
|
while(j < sizeof(sret))
|
|
|
|
{
|
|
|
|
int l = write(s, ((char*)&sret)+j, sizeof(sret)-j);
|
|
|
|
if (l < 0)
|
|
|
|
goto out;
|
|
|
|
j += l;
|
|
|
|
}
|
2016-05-16 23:58:41 +02:00
|
|
|
} else {
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
2016-05-16 23:58:41 +02:00
|
|
|
while(j < len)
|
|
|
|
{
|
|
|
|
sret = write(fd, buff+j, len-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
|
|
|
free(buff);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case __HERMIT_open: {
|
2016-08-25 17:52:37 +02:00
|
|
|
size_t len;
|
2015-10-05 10:12:34 +02:00
|
|
|
char* fname;
|
2016-05-16 23:58:41 +02:00
|
|
|
int flags, mode, ret;
|
2015-10-05 10:12:34 +02:00
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(len))
|
|
|
|
{
|
|
|
|
sret = read(s, ((char*)&len)+j, sizeof(len)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
|
|
|
fname = malloc(len);
|
|
|
|
if (!fname)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
j = 0;
|
2016-07-05 12:35:36 +02:00
|
|
|
while (j < len)
|
2015-10-03 10:56:08 +02:00
|
|
|
{
|
2016-05-16 23:58:41 +02:00
|
|
|
sret = read(s, fname+j, len-j);
|
|
|
|
if (sret < 0)
|
2015-10-03 10:56:08 +02:00
|
|
|
goto out;
|
2016-05-16 23:58:41 +02:00
|
|
|
j += sret;
|
2015-10-03 10:56:08 +02:00
|
|
|
}
|
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(flags))
|
|
|
|
{
|
|
|
|
sret = read(s, ((char*)&flags)+j, sizeof(flags)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(mode))
|
|
|
|
{
|
|
|
|
sret = read(s, ((char*)&mode)+j, sizeof(mode)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
|
|
|
//printf("flags 0x%x, mode 0x%x\n", flags, mode);
|
|
|
|
|
|
|
|
ret = open(fname, flags, mode);
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while(j < sizeof(ret))
|
|
|
|
{
|
|
|
|
sret = write(s, ((char*)&ret)+j, sizeof(ret)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
|
|
|
free(fname);
|
2015-10-03 10:56:08 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case __HERMIT_close: {
|
2016-05-16 23:58:41 +02:00
|
|
|
int fd, ret;
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while(j < sizeof(fd))
|
|
|
|
{
|
2016-08-25 17:52:37 +02:00
|
|
|
sret = read(s, ((char*)&fd)+j, sizeof(fd)-j);
|
2016-07-05 12:35:36 +02:00
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
|
|
|
|
if (fd > 2)
|
|
|
|
ret = close(fd);
|
|
|
|
else
|
|
|
|
ret = 0;
|
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(ret))
|
|
|
|
{
|
|
|
|
sret = write(s, ((char*)&ret)+j, sizeof(ret)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
break;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
case __HERMIT_read: {
|
|
|
|
int fd, flag;
|
2016-08-25 17:52:37 +02:00
|
|
|
size_t len;
|
2016-07-05 12:35:36 +02:00
|
|
|
ssize_t sj;
|
2015-10-05 10:12:34 +02:00
|
|
|
char* buff;
|
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while(j < sizeof(fd))
|
|
|
|
{
|
|
|
|
sret = read(s, ((char*)&fd)+j, sizeof(fd)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while(j < sizeof(len))
|
|
|
|
{
|
|
|
|
sret = read(s, ((char*)&len)+j, sizeof(len)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
|
|
|
buff = malloc(len);
|
|
|
|
if (!buff)
|
|
|
|
goto out;
|
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
sj = read(fd, buff, len);
|
2015-10-05 10:12:34 +02:00
|
|
|
|
|
|
|
flag = 0;
|
|
|
|
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
|
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(sj))
|
|
|
|
{
|
2016-08-25 17:52:37 +02:00
|
|
|
sret = write(s, ((char*)&sj)+j, sizeof(sj)-j);
|
2016-07-05 12:35:36 +02:00
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
if (sj > 0)
|
2015-10-05 10:12:34 +02:00
|
|
|
{
|
2016-08-25 17:52:37 +02:00
|
|
|
size_t i = 0;
|
2015-10-05 10:12:34 +02:00
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
while (i < sj)
|
2015-10-05 10:12:34 +02:00
|
|
|
{
|
2016-07-05 12:35:36 +02:00
|
|
|
sret = write(s, buff+i, sj-i);
|
2016-05-16 23:58:41 +02:00
|
|
|
if (sret < 0)
|
2016-07-05 12:35:36 +02:00
|
|
|
goto out;
|
2015-10-05 10:12:34 +02:00
|
|
|
|
2016-05-16 23:58:41 +02:00
|
|
|
i += sret;
|
2015-10-05 10:12:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
flag = 1;
|
|
|
|
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
|
|
|
|
|
|
|
|
free(buff);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case __HERMIT_lseek: {
|
|
|
|
int fd, whence;
|
|
|
|
off_t offset;
|
2016-07-05 12:35:36 +02:00
|
|
|
|
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(fd))
|
|
|
|
{
|
|
|
|
sret = read(s, ((char*)&fd)+j, sizeof(fd)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(offset))
|
|
|
|
{
|
|
|
|
sret = read(s, ((char*)&offset)+j, sizeof(offset)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
2016-07-05 12:35:36 +02:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(whence))
|
|
|
|
{
|
|
|
|
sret = read(s, ((char*)&whence)+j, sizeof(whence)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
|
|
|
|
offset = lseek(fd, offset, whence);
|
2016-07-05 12:35:36 +02:00
|
|
|
|
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(offset))
|
|
|
|
{
|
|
|
|
sret = write(s, ((char*)&offset)+j, sizeof(offset)-j);
|
|
|
|
if (sret < 0)
|
|
|
|
goto out;
|
|
|
|
j += sret;
|
|
|
|
}
|
2015-10-05 10:12:34 +02:00
|
|
|
break;
|
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
default:
|
2016-05-16 23:58:41 +02:00
|
|
|
fprintf(stderr, "Proxy: invalid syscall number %d, errno %d, ret %zd\n", sysnr, errno, sret);
|
2016-04-13 22:54:55 +02:00
|
|
|
close(s);
|
2016-03-16 09:35:27 +01:00
|
|
|
exit(1);
|
2015-10-03 10:56:08 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2015-10-05 10:12:34 +02:00
|
|
|
perror("Proxy -- communication error");
|
2015-10-03 10:56:08 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
int socket_loop(int argc, char **argv)
|
2015-10-03 10:56:08 +02:00
|
|
|
{
|
|
|
|
int i, j, ret, s;
|
|
|
|
int32_t magic = HERMIT_MAGIC;
|
|
|
|
struct sockaddr_in serv_name;
|
|
|
|
|
2016-10-19 12:49:37 +02:00
|
|
|
#if 0
|
2017-02-21 14:08:49 +01:00
|
|
|
// check if mmnif interface is available
|
|
|
|
if (!qemu) {
|
|
|
|
struct ifreq ethreq;
|
|
|
|
|
|
|
|
memset(ðreq, 0, sizeof(ethreq));
|
|
|
|
strncpy(ethreq.ifr_name, "mmnif", IFNAMSIZ);
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
/* this socket doesn't really matter, we just need a descriptor
|
|
|
|
* to perform the ioctl on */
|
|
|
|
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
|
|
ioctl(s, SIOCGIFFLAGS, ðreq);
|
|
|
|
close(s);
|
|
|
|
|
|
|
|
if (ethreq.ifr_flags & (IFF_UP|IFF_RUNNING))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sched_yield();
|
2016-10-19 12:49:37 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
/* create a socket */
|
|
|
|
s = socket(PF_INET, SOCK_STREAM, 0);
|
|
|
|
if (s < 0)
|
|
|
|
{
|
|
|
|
perror("Proxy: socket creation error");
|
|
|
|
exit(1);
|
2016-02-17 21:22:49 +01:00
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
|
|
|
|
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
|
|
|
|
i = 1;
|
|
|
|
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &i, sizeof(i));
|
|
|
|
i = 0;
|
|
|
|
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &i, sizeof(i));
|
|
|
|
|
|
|
|
/* server address */
|
|
|
|
memset((char *) &serv_name, 0x00, sizeof(serv_name));
|
|
|
|
serv_name.sin_family = AF_INET;
|
|
|
|
if (monitor == QEMU)
|
|
|
|
serv_name.sin_addr = INADDR(127, 0, 0, 1);
|
|
|
|
else
|
|
|
|
serv_name.sin_addr = HERMIT_IP(isle_nr);
|
|
|
|
serv_name.sin_port = htons(port);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
retry:
|
|
|
|
ret = connect(s, (struct sockaddr*)&serv_name, sizeof(serv_name));
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
if (i <= 10) {
|
|
|
|
usleep(10000);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
perror("Proxy -- connection error");
|
|
|
|
close(s);
|
|
|
|
exit(1);
|
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
ret = write(s, &magic, sizeof(magic));
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
2016-03-30 16:11:19 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
// forward program arguments to HermitCore
|
|
|
|
// argv[0] is path of this proxy so we strip it
|
2016-03-30 16:11:19 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
argv++;
|
|
|
|
argc--;
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
ret = write(s, &argc, sizeof(argc));
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
for(i=0; i<argc; i++)
|
2016-07-05 12:35:36 +02:00
|
|
|
{
|
2017-02-21 14:08:49 +01:00
|
|
|
int len = strlen(argv[i])+1;
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(len))
|
|
|
|
{
|
|
|
|
ret = write(s, ((char*)&len)+j, sizeof(len)-j);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
j += ret;
|
|
|
|
}
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
j = 0;
|
|
|
|
while (j < len)
|
|
|
|
{
|
|
|
|
ret = write(s, argv[i]+j, len-j);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
j += ret;
|
|
|
|
}
|
|
|
|
}
|
2016-01-04 19:31:54 +01:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
// send environment
|
|
|
|
i = 0;
|
|
|
|
while(environ[i])
|
|
|
|
i++;
|
2016-01-04 19:31:54 +01:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
ret = write(s, &i, sizeof(i));
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
2016-01-04 19:31:54 +01:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
for(i=0; environ[i] ;i++)
|
2016-07-05 12:35:36 +02:00
|
|
|
{
|
2017-02-21 14:08:49 +01:00
|
|
|
int len = strlen(environ[i])+1;
|
2016-01-04 19:31:54 +01:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
j = 0;
|
|
|
|
while (j < sizeof(len))
|
|
|
|
{
|
|
|
|
ret = write(s, ((char*)&len)+j, sizeof(len)-j);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
j += ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
while (j < len)
|
|
|
|
{
|
|
|
|
ret = write(s, environ[i]+j, len-j);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
j += ret;
|
|
|
|
}
|
2016-01-04 19:31:54 +01:00
|
|
|
}
|
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
ret = handle_syscalls(s);
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
close(s);
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
return ret;
|
2015-10-03 10:56:08 +02:00
|
|
|
|
2017-02-21 14:08:49 +01:00
|
|
|
out:
|
|
|
|
perror("Proxy -- communication error");
|
|
|
|
close(s);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = env_init(argv[1]);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2017-03-01 18:49:23 +01:00
|
|
|
|
|
|
|
switch(monitor) {
|
|
|
|
case UHYVE:
|
|
|
|
return uhyve_loop();
|
|
|
|
|
|
|
|
case BAREMETAL:
|
|
|
|
case QEMU:
|
2017-02-21 14:08:49 +01:00
|
|
|
return socket_loop(argc, argv);
|
2017-03-01 18:49:23 +01:00
|
|
|
|
|
|
|
default:
|
|
|
|
perror("Unknown monitor");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2015-10-03 10:56:08 +02:00
|
|
|
}
|