implemented mconsole notification to check if guest came up
slightly modified menu commands
This commit is contained in:
+5
-11
@@ -26,22 +26,16 @@ struct private_dumm_t {
|
||||
linked_list_t *guests;
|
||||
};
|
||||
|
||||
static guest_t* start_guest(private_dumm_t *this, char *name, char *kernel,
|
||||
char *master, int mem)
|
||||
static guest_t* create_guest(private_dumm_t *this, char *name, char *master, int mem)
|
||||
{
|
||||
guest_t *guest;
|
||||
|
||||
guest = guest_create(name, kernel, master, mem);
|
||||
guest = guest_create(name, master, mem);
|
||||
if (guest)
|
||||
{
|
||||
if (guest->start(guest))
|
||||
{
|
||||
this->guests->insert_last(this->guests, guest);
|
||||
return guest;
|
||||
}
|
||||
guest->destroy(guest);
|
||||
this->guests->insert_last(this->guests, guest);
|
||||
}
|
||||
return NULL;
|
||||
return guest;
|
||||
}
|
||||
|
||||
static iterator_t* create_guest_iterator(private_dumm_t *this)
|
||||
@@ -73,7 +67,7 @@ dumm_t *dumm_create()
|
||||
{
|
||||
private_dumm_t *this = malloc_thing(private_dumm_t);
|
||||
|
||||
this->public.start_guest = (void*)start_guest;
|
||||
this->public.create_guest = (void*)create_guest;
|
||||
this->public.create_guest_iterator = (void*)create_guest_iterator;
|
||||
this->public.destroy = (void*)destroy;
|
||||
|
||||
|
||||
+1
-3
@@ -39,13 +39,11 @@ struct dumm_t {
|
||||
* @brief Starts a new UML guest
|
||||
*
|
||||
* @param name name of the guest
|
||||
* @param kernel kernel to boot
|
||||
* @param master mounted read only master filesystem
|
||||
* @param mem amount of memory for guest, in MB
|
||||
* @return guest if started, NULL if failed
|
||||
*/
|
||||
guest_t* (*start_guest) (dumm_t *this, char *name, char *kernel,
|
||||
char *master, int mem);
|
||||
guest_t* (*create_guest) (dumm_t *this, char *name, char *master, int mem);
|
||||
|
||||
/**
|
||||
* @brief Create an iterator over all guests.
|
||||
|
||||
+48
-11
@@ -38,14 +38,14 @@ struct private_guest_t {
|
||||
guest_t public;
|
||||
/** name of the guest */
|
||||
char *name;
|
||||
/** kernel to boot for guest */
|
||||
char *kernel;
|
||||
/** read only master filesystem guest uses */
|
||||
char *master;
|
||||
/** amount of memory for guest, in MB */
|
||||
int mem;
|
||||
/** pid of guest child process */
|
||||
int pid;
|
||||
/** state of guest */
|
||||
guest_state_t state;
|
||||
/** log file for console 0 */
|
||||
int bootlog;
|
||||
/** mconsole to control running UML */
|
||||
@@ -54,6 +54,14 @@ struct private_guest_t {
|
||||
linked_list_t *ifaces;
|
||||
};
|
||||
|
||||
ENUM(guest_state_names, GUEST_STOPPED, GUEST_STOPPING,
|
||||
"STOPPED",
|
||||
"STARTING",
|
||||
"RUNNING",
|
||||
"PAUSED",
|
||||
"STOPPING",
|
||||
);
|
||||
|
||||
/**
|
||||
* Implementation of guest_t.get_name.
|
||||
*/
|
||||
@@ -103,6 +111,22 @@ static iterator_t* create_iface_iterator(private_guest_t *this)
|
||||
{
|
||||
return this->ifaces->create_iterator(this->ifaces, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of guest_t.get_state.
|
||||
*/
|
||||
static guest_state_t get_state(private_guest_t *this)
|
||||
{
|
||||
return this->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of guest_t.get_pid.
|
||||
*/
|
||||
static pid_t get_pid(private_guest_t *this)
|
||||
{
|
||||
return this->pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* write format string to a buffer, and advance buffer position
|
||||
@@ -129,16 +153,26 @@ static char* write_arg(char **pos, size_t *left, char *format, ...)
|
||||
/**
|
||||
* Implementation of guest_t.start.
|
||||
*/
|
||||
static bool start(private_guest_t *this)
|
||||
static bool start(private_guest_t *this, char *kernel)
|
||||
{
|
||||
char buf[1024];
|
||||
char cwd[512];
|
||||
char *notify;
|
||||
char *pos = buf;
|
||||
char *args[16];
|
||||
int i = 0;
|
||||
size_t left = sizeof(buf);
|
||||
|
||||
args[i++] = this->kernel;
|
||||
|
||||
if (this->state != GUEST_STOPPED)
|
||||
{
|
||||
DBG1("unable to start guest in state %N", guest_state_names, this->state);
|
||||
return FALSE;
|
||||
}
|
||||
this->state = GUEST_STARTING;
|
||||
|
||||
notify = write_arg(&pos, &left, "%s/%s/notify", RUN_DIR, this->name);
|
||||
|
||||
args[i++] = kernel;
|
||||
args[i++] = write_arg(&pos, &left, "root=/dev/root");
|
||||
args[i++] = write_arg(&pos, &left, "rootfstype=hostfs");
|
||||
args[i++] = write_arg(&pos, &left, "rootflags=%s/%s/%s",
|
||||
@@ -146,9 +180,11 @@ static bool start(private_guest_t *this)
|
||||
args[i++] = write_arg(&pos, &left, "uml_dir=%s/%s", RUN_DIR, this->name);
|
||||
args[i++] = write_arg(&pos, &left, "umid=%s", this->name);
|
||||
args[i++] = write_arg(&pos, &left, "mem=%dM", this->mem);
|
||||
args[i++] = write_arg(&pos, &left, "mconsole=notify:%s", notify);
|
||||
/*args[i++] = write_arg(&pos, &left, "con=pts");*/
|
||||
args[i++] = write_arg(&pos, &left, "con0=null,fd:%d", this->bootlog);
|
||||
args[i++] = write_arg(&pos, &left, "con1=fd:0,fd:1");
|
||||
/*args[i++] = write_arg(&pos, &left, "con1=fd:0,fd:1");*/
|
||||
args[i++] = write_arg(&pos, &left, "con2=null,null");
|
||||
args[i++] = write_arg(&pos, &left, "con3=null,null");
|
||||
args[i++] = write_arg(&pos, &left, "con4=null,null");
|
||||
args[i++] = write_arg(&pos, &left, "con5=null,null");
|
||||
@@ -172,8 +208,7 @@ static bool start(private_guest_t *this)
|
||||
break;
|
||||
}
|
||||
/* open mconsole */
|
||||
snprintf(buf, sizeof(buf), "%s/%s/%s/mconsole", RUN_DIR, this->name, this->name);
|
||||
this->mconsole = mconsole_create(buf);
|
||||
this->mconsole = mconsole_create(notify);
|
||||
if (this->mconsole == NULL)
|
||||
{
|
||||
DBG1("opening mconsole at '%s' failed, stopping guest", buf);
|
||||
@@ -181,6 +216,7 @@ static bool start(private_guest_t *this)
|
||||
this->pid = 0;
|
||||
return FALSE;
|
||||
}
|
||||
this->state = GUEST_RUNNING;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -293,7 +329,6 @@ static void destroy(private_guest_t *this)
|
||||
this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
|
||||
DESTROY_IF(this->mconsole);
|
||||
free(this->name);
|
||||
free(this->kernel);
|
||||
free(this->master);
|
||||
free(this);
|
||||
}
|
||||
@@ -301,11 +336,13 @@ static void destroy(private_guest_t *this)
|
||||
/**
|
||||
* create the guest instance, including required dirs and mounts
|
||||
*/
|
||||
guest_t *guest_create(char *name, char *kernel, char *master, int mem)
|
||||
guest_t *guest_create(char *name, char *master, int mem)
|
||||
{
|
||||
private_guest_t *this = malloc_thing(private_guest_t);
|
||||
|
||||
this->public.get_name = (void*)get_name;
|
||||
this->public.get_pid = (pid_t(*)(guest_t*))get_pid;
|
||||
this->public.get_state = (guest_state_t(*)(guest_t*))get_state;
|
||||
this->public.create_iface = (iface_t*(*)(guest_t*,char*))create_iface;
|
||||
this->public.create_iface_iterator = (iterator_t*(*)(guest_t*))create_iface_iterator;
|
||||
this->public.start = (void*)start;
|
||||
@@ -320,10 +357,10 @@ guest_t *guest_create(char *name, char *kernel, char *master, int mem)
|
||||
}
|
||||
|
||||
this->name = strdup(name);
|
||||
this->kernel = strdup(kernel);
|
||||
this->master = strdup(master);
|
||||
this->mem = mem;
|
||||
this->pid = 0;
|
||||
this->state = GUEST_STOPPED;
|
||||
this->bootlog = open_bootlog(name);
|
||||
this->mconsole = NULL;
|
||||
this->ifaces = linked_list_create();
|
||||
|
||||
+39
-3
@@ -21,6 +21,29 @@
|
||||
|
||||
#include "iface.h"
|
||||
|
||||
typedef enum guest_state_t guest_state_t;
|
||||
|
||||
/**
|
||||
* @brief State of a guest (started, stopped, ...)
|
||||
*/
|
||||
enum guest_state_t {
|
||||
/** guest kernel not running at all */
|
||||
GUEST_STOPPED,
|
||||
/** kernel started, but not yet available */
|
||||
GUEST_STARTING,
|
||||
/** guest is up and running */
|
||||
GUEST_RUNNING,
|
||||
/** guest has been paused */
|
||||
GUEST_PAUSED,
|
||||
/** guest is stopping (shutting down) */
|
||||
GUEST_STOPPING,
|
||||
};
|
||||
|
||||
/**
|
||||
* string mappings for guest_state_t
|
||||
*/
|
||||
extern enum_name_t *guest_state_names;
|
||||
|
||||
typedef struct guest_t guest_t;
|
||||
|
||||
/**
|
||||
@@ -35,12 +58,26 @@ struct guest_t {
|
||||
*/
|
||||
char* (*get_name) (guest_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the process ID of the guest child process.
|
||||
*
|
||||
* @return name of the guest
|
||||
*/
|
||||
pid_t (*get_pid) (guest_t *this);
|
||||
/**
|
||||
* @brief Get the state of the guest (stopped, started, etc.).
|
||||
*
|
||||
* @return guests state
|
||||
*/
|
||||
guest_state_t (*get_state)(guest_t *this);
|
||||
|
||||
/**
|
||||
* @brief Start the guest.
|
||||
*
|
||||
* @param kernel kernel to boot for this guest
|
||||
* @return TRUE if guest successfully started
|
||||
*/
|
||||
bool (*start) (guest_t *this);
|
||||
bool (*start) (guest_t *this, char *kernel);
|
||||
|
||||
/**
|
||||
* @brief Kill the guest.
|
||||
@@ -74,11 +111,10 @@ struct guest_t {
|
||||
* @brief Create a new, unstarted guest.
|
||||
*
|
||||
* @param name name of the guest
|
||||
* @param kernel kernel to boot for this guest
|
||||
* @param master read-only master filesystem for guest
|
||||
* @param mem amount of memory to give the guest
|
||||
*/
|
||||
guest_t *guest_create(char *name, char *kernel, char *master, int mem);
|
||||
guest_t *guest_create(char *name, char *master, int mem);
|
||||
|
||||
#endif /* GUEST_H */
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* Copyright (C) 2002 Jeff Dike
|
||||
*
|
||||
* Based on the "tunctl" utlity from Jeff Dike.
|
||||
* Based on the "tunctl" utility from Jeff Dike.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
||||
+123
-87
@@ -39,23 +39,21 @@ static void usage()
|
||||
*/
|
||||
static void help()
|
||||
{
|
||||
printf("start name=<name> [options] start a guest named <name>\n");
|
||||
printf(" additional options:\n");
|
||||
printf(" kernel=<uml-kernel>\n");
|
||||
printf(" master=<read-only root files>\n");
|
||||
printf(" memory=<guest memory in MB>\n");
|
||||
printf("create name=<name> start a guest named <name>\n");
|
||||
printf(" [master=<dir>] read only master root filesystem\n");
|
||||
printf(" [memory=<MB>] guest main memory in megabyte\n");
|
||||
printf("list list running guests\n");
|
||||
printf("guest <name> open guest menu for <name>\n");
|
||||
printf("help show this help\n");
|
||||
printf("quit kill quests and exit\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* help for guest shell
|
||||
*/
|
||||
static void help_guest()
|
||||
{
|
||||
printf("start [kernel=<uml-kernel>] start the guest\n");
|
||||
printf("addif <name> add an interface to the guest\n");
|
||||
printf("delif <name> remove the interface\n");
|
||||
printf("listif list guests interfaces\n");
|
||||
@@ -63,83 +61,6 @@ static void help_guest()
|
||||
printf("quit quit the guest menu\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* start an UML guest
|
||||
*/
|
||||
static void start(dumm_t *dumm, char *line)
|
||||
{
|
||||
enum {
|
||||
NAME = 0,
|
||||
MASTER,
|
||||
KERNEL,
|
||||
MEMORY,
|
||||
};
|
||||
char *const opts[] = {
|
||||
[NAME] = "name",
|
||||
[MASTER] = "master",
|
||||
[KERNEL] = "kernel",
|
||||
[MEMORY] = "memory",
|
||||
NULL
|
||||
};
|
||||
char *value;
|
||||
char *name = NULL;
|
||||
char *kernel = NULL;
|
||||
char *master = NULL;
|
||||
int mem = 0;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (getsubopt(&line, opts, &value))
|
||||
{
|
||||
case NAME:
|
||||
name = value;
|
||||
continue;
|
||||
case MASTER:
|
||||
master = value;
|
||||
continue;
|
||||
case KERNEL:
|
||||
kernel = value;
|
||||
continue;
|
||||
case MEMORY:
|
||||
if (value)
|
||||
{
|
||||
mem = atoi(value);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (name == NULL)
|
||||
{
|
||||
printf("option 'name' is required.\n");
|
||||
help();
|
||||
return;
|
||||
}
|
||||
if (kernel == NULL)
|
||||
{
|
||||
kernel = "./linux";
|
||||
}
|
||||
if (master == NULL)
|
||||
{
|
||||
master = "master";
|
||||
}
|
||||
if (mem == 0)
|
||||
{
|
||||
mem = 128;
|
||||
}
|
||||
|
||||
if (dumm->start_guest(dumm, name, kernel, master, mem))
|
||||
{
|
||||
printf("starting guest '%s'\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("starting guest '%s' failed\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add an iface to a guest
|
||||
*/
|
||||
@@ -207,6 +128,49 @@ static void list_if(guest_t *guest)
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* start an UML guest
|
||||
*/
|
||||
static void start_guest(guest_t *guest, char *line)
|
||||
{
|
||||
enum {
|
||||
KERNEL = 0,
|
||||
};
|
||||
char *const opts[] = {
|
||||
[KERNEL] = "kernel",
|
||||
NULL
|
||||
};
|
||||
char *value;
|
||||
char *kernel = NULL;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (getsubopt(&line, opts, &value))
|
||||
{
|
||||
case KERNEL:
|
||||
kernel = value;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (kernel == NULL)
|
||||
{
|
||||
kernel = "./linux";
|
||||
}
|
||||
|
||||
printf("starting guest '%s'... \n", guest->get_name(guest));
|
||||
if (guest->start(guest, kernel))
|
||||
{
|
||||
printf("guest '%s' is up\n", guest->get_name(guest));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("failed to start guest '%s'!\n", guest->get_name(guest));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* subshell for guests
|
||||
*/
|
||||
@@ -246,6 +210,7 @@ static void guest(dumm_t *dumm, char *name)
|
||||
enum {
|
||||
QUIT = 0,
|
||||
HELP,
|
||||
START,
|
||||
ADDIF,
|
||||
DELIF,
|
||||
LISTIF,
|
||||
@@ -253,6 +218,7 @@ static void guest(dumm_t *dumm, char *name)
|
||||
char *const opts[] = {
|
||||
[QUIT] = "quit",
|
||||
[HELP] = "help",
|
||||
[START] = "start",
|
||||
[ADDIF] = "addif",
|
||||
[DELIF] = "delif",
|
||||
[LISTIF] = "listif",
|
||||
@@ -285,6 +251,9 @@ static void guest(dumm_t *dumm, char *name)
|
||||
case HELP:
|
||||
help_guest();
|
||||
continue;
|
||||
case START:
|
||||
start_guest(guest, pos);
|
||||
continue;
|
||||
case ADDIF:
|
||||
add_if(guest, pos);
|
||||
continue;
|
||||
@@ -302,6 +271,73 @@ static void guest(dumm_t *dumm, char *name)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create an UML guest
|
||||
*/
|
||||
static void create_guest(dumm_t *dumm, char *line)
|
||||
{
|
||||
enum {
|
||||
NAME = 0,
|
||||
MASTER,
|
||||
MEMORY,
|
||||
};
|
||||
char *const opts[] = {
|
||||
[NAME] = "name",
|
||||
[MASTER] = "master",
|
||||
[MEMORY] = "memory",
|
||||
NULL
|
||||
};
|
||||
char *value;
|
||||
char *name = NULL;
|
||||
char *master = NULL;
|
||||
int mem = 0;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (getsubopt(&line, opts, &value))
|
||||
{
|
||||
case NAME:
|
||||
name = value;
|
||||
continue;
|
||||
case MASTER:
|
||||
master = value;
|
||||
continue;
|
||||
case MEMORY:
|
||||
if (value)
|
||||
{
|
||||
mem = atoi(value);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (name == NULL)
|
||||
{
|
||||
printf("option 'name' is required.\n");
|
||||
help();
|
||||
return;
|
||||
}
|
||||
if (master == NULL)
|
||||
{
|
||||
master = "master";
|
||||
}
|
||||
if (mem == 0)
|
||||
{
|
||||
mem = 128;
|
||||
}
|
||||
if (dumm->create_guest(dumm, name, master, mem))
|
||||
{
|
||||
printf("guest '%s' created\n", name);
|
||||
guest(dumm, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("failed to create guest '%s'!\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list running UML guests
|
||||
*/
|
||||
@@ -370,14 +406,14 @@ int main(int argc, char *argv[])
|
||||
enum {
|
||||
QUIT = 0,
|
||||
HELP,
|
||||
START,
|
||||
CREATE,
|
||||
LIST,
|
||||
GUEST,
|
||||
};
|
||||
char *const opts[] = {
|
||||
[QUIT] = "quit",
|
||||
[HELP] = "help",
|
||||
[START] = "start",
|
||||
[CREATE] = "create",
|
||||
[LIST] = "list",
|
||||
[GUEST] = "guest",
|
||||
NULL
|
||||
@@ -410,8 +446,8 @@ int main(int argc, char *argv[])
|
||||
case HELP:
|
||||
help();
|
||||
continue;
|
||||
case START:
|
||||
start(dumm, pos);
|
||||
case CREATE:
|
||||
create_guest(dumm, pos);
|
||||
continue;
|
||||
case LIST:
|
||||
list(dumm);
|
||||
|
||||
+129
-31
@@ -3,7 +3,7 @@
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* Copyright (C) 2001-2004 Jeff Dike
|
||||
*
|
||||
* Based on the "uml_mconsole" utilty from Jeff Dike.
|
||||
* Based on the "uml_mconsole" utility from Jeff Dike.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -36,28 +36,57 @@ struct private_mconsole_t {
|
||||
/** public interface */
|
||||
mconsole_t public;
|
||||
/** mconsole socket */
|
||||
int socket;
|
||||
int console;
|
||||
/** notify socket */
|
||||
int notify;
|
||||
/** address of uml socket */
|
||||
struct sockaddr_un uml;
|
||||
};
|
||||
|
||||
/**
|
||||
* mconsole message format from "arch/um/include/mconsole.h"
|
||||
*/
|
||||
typedef struct mconsole_request mconsole_request;
|
||||
/** mconsole request message */
|
||||
struct mconsole_request {
|
||||
u_int32_t magic;
|
||||
u_int32_t version;
|
||||
u_int32_t len;
|
||||
char data[MCONSOLE_MAX_DATA];
|
||||
};
|
||||
|
||||
|
||||
typedef struct mconsole_reply mconsole_reply;
|
||||
/** mconsole reply message */
|
||||
struct mconsole_reply {
|
||||
u_int32_t err;
|
||||
u_int32_t more;
|
||||
u_int32_t len;
|
||||
char data[MCONSOLE_MAX_DATA];
|
||||
};
|
||||
|
||||
typedef struct mconsole_notify mconsole_notify;
|
||||
/** mconsole notify message */
|
||||
struct mconsole_notify {
|
||||
u_int32_t magic;
|
||||
u_int32_t version;
|
||||
enum {
|
||||
MCONSOLE_SOCKET,
|
||||
MCONSOLE_PANIC,
|
||||
MCONSOLE_HANG,
|
||||
MCONSOLE_USER_NOTIFY,
|
||||
} type;
|
||||
u_int32_t len;
|
||||
char data[MCONSOLE_MAX_DATA];
|
||||
};
|
||||
|
||||
/**
|
||||
* send a request to UML using mconsole
|
||||
*/
|
||||
static bool request(private_mconsole_t *this, char *command)
|
||||
{
|
||||
struct {
|
||||
u_int32_t magic;
|
||||
u_int32_t version;
|
||||
u_int32_t len;
|
||||
char data[MCONSOLE_MAX_DATA];
|
||||
} request;
|
||||
struct {
|
||||
u_int32_t err;
|
||||
u_int32_t more;
|
||||
u_int32_t len;
|
||||
char data[MCONSOLE_MAX_DATA];
|
||||
} reply;
|
||||
mconsole_request request;
|
||||
mconsole_reply reply;
|
||||
bool first = TRUE, good = TRUE;
|
||||
int len;
|
||||
|
||||
@@ -67,7 +96,7 @@ static bool request(private_mconsole_t *this, char *command)
|
||||
request.len = min(strlen(command), sizeof(reply.data) - 1);
|
||||
strncpy(request.data, command, request.len);
|
||||
|
||||
if (sendto(this->socket, &request, sizeof(request), 0,
|
||||
if (sendto(this->console, &request, sizeof(request), 0,
|
||||
(struct sockaddr*)&this->uml, sizeof(this->uml)) < 0)
|
||||
{
|
||||
DBG1("sending mconsole command to UML failed: %m");
|
||||
@@ -75,7 +104,7 @@ static bool request(private_mconsole_t *this, char *command)
|
||||
}
|
||||
do
|
||||
{
|
||||
len = recvfrom(this->socket, &reply, sizeof(reply), 0, NULL, 0);
|
||||
len = recvfrom(this->console, &reply, sizeof(reply), 0, NULL, 0);
|
||||
if (len < 0)
|
||||
{
|
||||
DBG1("receiving from mconsole failed: %m");
|
||||
@@ -129,41 +158,110 @@ static bool del_iface(private_mconsole_t *this, char *guest)
|
||||
*/
|
||||
static void destroy(private_mconsole_t *this)
|
||||
{
|
||||
close(this->socket);
|
||||
close(this->console);
|
||||
close(this->notify);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* setup the mconsole notify connection and wait for its readyness
|
||||
*/
|
||||
static bool wait_for_notify(private_mconsole_t *this, char *nsock)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
mconsole_notify notify;
|
||||
int len;
|
||||
|
||||
this->notify = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (this->notify < 0)
|
||||
{
|
||||
DBG1("opening mconsole notify socket failed: %m");
|
||||
return FALSE;
|
||||
}
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, nsock, sizeof(addr));
|
||||
if (bind(this->notify, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
DBG1("binding mconsole notify socket to '%s' failed: %m", nsock);
|
||||
close(this->notify);
|
||||
return FALSE;
|
||||
}
|
||||
len = recvfrom(this->notify, ¬ify, sizeof(notify), 0, NULL, 0);
|
||||
if (len < 0 || len >= sizeof(notify))
|
||||
{
|
||||
DBG1("reading from mconsole notify socket failed: %m");
|
||||
close(this->notify);
|
||||
unlink(nsock);
|
||||
return FALSE;
|
||||
}
|
||||
if (notify.magic != MCONSOLE_MAGIC ||
|
||||
notify.version != MCONSOLE_VERSION ||
|
||||
notify.type != MCONSOLE_SOCKET)
|
||||
{
|
||||
DBG1("received unexpected message from mconsole notify socket: %b",
|
||||
¬ify, sizeof(notify));
|
||||
close(this->notify);
|
||||
unlink(nsock);
|
||||
return FALSE;
|
||||
}
|
||||
memset(&this->uml, 0, sizeof(this->uml));
|
||||
this->uml.sun_family = AF_UNIX;
|
||||
strncpy(this->uml.sun_path, (char*)¬ify.data, sizeof(this->uml.sun_path));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup the mconsole console connection
|
||||
*/
|
||||
static bool setup_console(private_mconsole_t *this)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
|
||||
this->console = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (this->console < 0)
|
||||
{
|
||||
DBG1("opening mconsole socket failed: %m");
|
||||
return FALSE;
|
||||
}
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
snprintf(&addr.sun_path[1], sizeof(addr.sun_path), "%5d-%d",
|
||||
getpid(), this->console);
|
||||
if (bind(this->console, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
DBG1("binding mconsole socket to '%s' failed: %m", &addr.sun_path[1]);
|
||||
close(this->console);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* create the mconsole instance
|
||||
*/
|
||||
mconsole_t *mconsole_create(char *sock)
|
||||
mconsole_t *mconsole_create(char *notify)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
private_mconsole_t *this = malloc_thing(private_mconsole_t);
|
||||
|
||||
this->public.add_iface = (bool(*)(mconsole_t*, char *guest, char *host))add_iface;
|
||||
this->public.del_iface = (bool(*)(mconsole_t*, char *guest))del_iface;
|
||||
this->public.destroy = (void*)destroy;
|
||||
|
||||
this->socket = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (this->socket < 0)
|
||||
if (!wait_for_notify(this, notify))
|
||||
{
|
||||
DBG1("opening mconsole socket failed: %m");
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
snprintf(&addr.sun_path[1], sizeof(addr.sun_path), "%5d-%s", getpid(), sock);
|
||||
if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||
|
||||
if (!setup_console(this))
|
||||
{
|
||||
DBG1("binding mconsole socket failed: %m");
|
||||
destroy(this);
|
||||
close(this->notify);
|
||||
unlink(notify);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
memset(&this->uml, 0, sizeof(this->uml));
|
||||
this->uml.sun_family = AF_UNIX;
|
||||
strncpy(this->uml.sun_path, sock, sizeof(this->uml.sun_path));
|
||||
unlink(notify);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
+5
-2
@@ -51,10 +51,13 @@ struct mconsole_t {
|
||||
/**
|
||||
* @brief Create a new mconsole connection to a guest.
|
||||
*
|
||||
* @param socket guests mconsole socket
|
||||
* Waits for a notification from the guest through the notify socket and tries
|
||||
* to connect to the mconsole socket supplied in the received notification.
|
||||
*
|
||||
* @param notify unix notify socket path
|
||||
* @return mconsole instance, or NULL if failed
|
||||
*/
|
||||
mconsole_t *mconsole_create(char *socket);
|
||||
mconsole_t *mconsole_create(char *notify);
|
||||
|
||||
#endif /* MCONSOLE_H */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user