mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 17:35:17 +00:00
Tue Feb 14 16:08:55 IST 2007 Mark McLoughlin <markmc@redhat.com>
* qemud/conf.c: add support for connecting a qemu guest to a bridge using a tap device in order to connect it to a virtual network. * qemud/internal.h: add <interface type="network"> config and track tapfds so as to not close them on exec. * qemud/qemud.c: don't close tapfds on exec and disconnect the iface when the guest shuts down.
This commit is contained in:
parent
3fbd82faa0
commit
0c15bd8b87
124
ChangeLog
124
ChangeLog
@ -1,26 +1,128 @@
|
||||
Tue Feb 14 15:07:26 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 16:08:55 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/conf.c: add support for connecting a qemu
|
||||
guest to a bridge using a tap device in order to
|
||||
connect it to a virtual network.
|
||||
|
||||
* qemud/internal.h: add <interface type="network">
|
||||
config and track tapfds so as to not close them
|
||||
on exec.
|
||||
|
||||
* qemud/qemud.c: don't close tapfds on exec and
|
||||
disconnect the iface when the guest shuts down.
|
||||
|
||||
Tue Feb 14 16:04:48 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/conf.c, qemud/internal.h: add dhcp config
|
||||
|
||||
* qemud/qemud.c: start dnsmasq to provide dns/dhcp
|
||||
for virtual networks.
|
||||
|
||||
Tue Feb 14 16:02:23 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* configure.in: add --disable-bridge-params, check
|
||||
for libsysfs and various kernel headers
|
||||
|
||||
* bridge.[ch]: add code for managing bridges
|
||||
|
||||
* qemud/Makefile.am: add bridge.[ch] and link against
|
||||
libsysfs if enabled.
|
||||
|
||||
* qemud/conf.c: add support for bridge config.
|
||||
|
||||
* qemud/internal.h: add various bridging bits
|
||||
|
||||
* qemud/qemud.c: implement qemudStartNetworkDaemon()
|
||||
and qemudShutdownNetworkDaemon().
|
||||
|
||||
Tue Feb 14 15:55:02 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/conf.[ch]: implement parsing and saving network
|
||||
configs.
|
||||
|
||||
* qemud/driver.c: flesh out the stubs
|
||||
|
||||
* qemud/internal.h: add networks list etc. to
|
||||
struct qemud_server
|
||||
|
||||
* qemud/qemud.c: add qemudStartNetworkDaemon() and
|
||||
qemudShutdownNetworkDaemon() stubs.
|
||||
|
||||
Tue Feb 14 15:52:34 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/protocol.h: add the protocol for virtual networks
|
||||
|
||||
* qemud/dispatch.c: implement the protocol
|
||||
|
||||
* qemud/driver.[ch]: add stubs for the driver
|
||||
|
||||
* qemud/internal.h: add struct qemud_network
|
||||
|
||||
* src/qemu_internal.c: add a virtual networks driver
|
||||
|
||||
Tue Feb 14 15:43:28 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* src/virsh.c: add the net-* commands.
|
||||
|
||||
Tue Feb 14 15:37:17 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
Note: potential ABI break here, but people should
|
||||
only really be using virError structs returned from
|
||||
libvirt itself.
|
||||
|
||||
* include/libvirt/virterror.h: add virNetwork
|
||||
to virError
|
||||
|
||||
* src/internal.h, src/virterror.c: add network param
|
||||
to __virRaiseError()
|
||||
|
||||
* src/conf.c, src/hash.c, src/libvirt.c, src/proxy_internal.c,
|
||||
src/qemu_internal.c, src/sexpr.c, src/test.c, src/xen_internal.c,
|
||||
src/xend_internal.c, src/xm_internal.c, src/xml.c, src/xmlrpc.c,
|
||||
src/xs_internal.c: update.
|
||||
|
||||
Tue Feb 14 15:33:05 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* include/libvirt/libvirt.h.in: add the networks APIs
|
||||
|
||||
* include/libvirt/virterror.h: add some error codes
|
||||
|
||||
* src/driver.h: add network driver vtable
|
||||
|
||||
* src/hash.c: add networks hash
|
||||
|
||||
* src/internal.h: add virNetwork
|
||||
|
||||
* src/libvirt.c: hook up the APIs to the network
|
||||
driver
|
||||
|
||||
* src/libvirt_sym.version: add the new APIs
|
||||
|
||||
* src/virterror.c: handle the new error codes
|
||||
|
||||
Tue Feb 14 15:07:26 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* src/conf.h: fix merge error - remove the argc argument
|
||||
from qemudBuildCommandLine()
|
||||
|
||||
Tue Feb 14 15:03:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 15:03:22 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* src/virsh.c: Re-name some of the VSH_DOMBYFOO stuff
|
||||
to VSH_BYFOO in order to re-use it for the network stuff.
|
||||
|
||||
Tue Feb 14 14:58:35 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:58:35 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* src/hash.c, src/internal.h: Re-name virConnect->domains_mux
|
||||
to virConnect->hashes_mux since it will also be used to
|
||||
protect the networks hash.
|
||||
|
||||
Tue Feb 14 14:57:52 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:57:52 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/conf.c: qemudSaveConfig() will always report a
|
||||
more specific error, so we should avoid overwriting
|
||||
this error.
|
||||
|
||||
Tue Feb 14 14:54:25 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:54:25 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/qemud.c: Re-factor out qemudExec() so that it can
|
||||
be used to launch dnsmasq.
|
||||
@ -28,7 +130,7 @@ Tue Feb 14 14:54:25 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
* qemud/conf.c: don't return argc from qemudBuildCommandLine()
|
||||
as exec() doesn't need it.
|
||||
|
||||
Tue Feb 14 14:52:12 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:52:12 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/conf.c: Re-factor bits of conf.c so that:
|
||||
|
||||
@ -38,25 +140,25 @@ Tue Feb 14 14:52:12 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
- split qemudScanConfigDir() out so that qemudScanConfigs()
|
||||
can scan multiple configDirs
|
||||
|
||||
Tue Feb 14 14:50:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:50:22 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/conf.c: handle an unspecified MAC address,
|
||||
fix the argv freeing code in qemudBuildCommandLine()
|
||||
and fix copy and paste error in qemudGenerateXML()
|
||||
|
||||
Tue Feb 14 14:42:38 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:42:38 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* src/internal.h: add virConnect->qemud_fd so that
|
||||
xen and qemu don't share the handle member.
|
||||
|
||||
* src/hash.c, src/qemu_internal.c: update
|
||||
|
||||
Tue Feb 14 14:40:52 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:40:52 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* qemud/conf.c, qemud/dispatch.c, qemud/driver.c,
|
||||
qemud/qemud.c: include autoconf's config.h
|
||||
|
||||
Tue Feb 14 14:39:18 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:39:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* conf.[ch]: rename from config.[ch] so we can use
|
||||
autoconf's config.h
|
||||
@ -65,7 +167,7 @@ Tue Feb 14 14:39:18 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* driver.c, qemud.c: upd.
|
||||
|
||||
Tue Feb 14 14:33:22 EST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
Tue Feb 14 14:33:22 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||
|
||||
* autogen.sh: run autoheader
|
||||
|
||||
|
148
qemud/conf.c
148
qemud/conf.c
@ -366,6 +366,8 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||
xmlNodePtr cur;
|
||||
xmlChar *macaddr = NULL;
|
||||
xmlChar *type = NULL;
|
||||
xmlChar *network = NULL;
|
||||
xmlChar *tapifname = NULL;
|
||||
|
||||
if (!net) {
|
||||
qemudReportError(server, VIR_ERR_NO_MEMORY, "net");
|
||||
@ -386,6 +388,8 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||
net->type = QEMUD_NET_CLIENT;
|
||||
else if (xmlStrEqual(type, BAD_CAST "mcast"))
|
||||
net->type = QEMUD_NET_MCAST;
|
||||
else if (xmlStrEqual(type, BAD_CAST "network"))
|
||||
net->type = QEMUD_NET_NETWORK;
|
||||
/*
|
||||
else if (xmlStrEqual(type, BAD_CAST "vde"))
|
||||
typ = QEMUD_NET_VDE;
|
||||
@ -402,6 +406,14 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||
if ((macaddr == NULL) &&
|
||||
(xmlStrEqual(cur->name, BAD_CAST "mac"))) {
|
||||
macaddr = xmlGetProp(cur, BAD_CAST "address");
|
||||
} else if ((network == NULL) &&
|
||||
(net->type == QEMUD_NET_NETWORK) &&
|
||||
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
||||
network = xmlGetProp(cur, BAD_CAST "network");
|
||||
} else if ((tapifname == NULL) &&
|
||||
(net->type == QEMUD_NET_NETWORK) &&
|
||||
xmlStrEqual(cur->name, BAD_CAST "tap")) {
|
||||
tapifname = xmlGetProp(cur, BAD_CAST "ifname");
|
||||
}
|
||||
}
|
||||
cur = cur->next;
|
||||
@ -421,7 +433,47 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||
xmlFree(macaddr);
|
||||
}
|
||||
|
||||
if (net->type == QEMUD_NET_NETWORK) {
|
||||
int len;
|
||||
|
||||
if (network == NULL) {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"No <source> 'network' attribute specified with <interface type='network'/>");
|
||||
goto error;
|
||||
} else if ((len = xmlStrlen(network)) >= QEMUD_MAX_NAME_LEN) {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"Network name '%s' too long", network);
|
||||
goto error;
|
||||
} else {
|
||||
strncpy(net->dst.network.name, (char *)network, len);
|
||||
net->dst.network.name[len] = '\0';
|
||||
}
|
||||
|
||||
if (network)
|
||||
xmlFree(network);
|
||||
|
||||
if (tapifname != NULL) {
|
||||
if ((len == xmlStrlen(tapifname)) >= BR_IFNAME_MAXLEN) {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"TAP interface name '%s' is too long", tapifname);
|
||||
goto error;
|
||||
} else {
|
||||
strncpy(net->dst.network.tapifname, (char *)tapifname, len);
|
||||
net->dst.network.tapifname[len] = '\0';
|
||||
}
|
||||
xmlFree(tapifname);
|
||||
}
|
||||
}
|
||||
|
||||
return net;
|
||||
|
||||
error:
|
||||
if (network)
|
||||
xmlFree(network);
|
||||
if (tapifname)
|
||||
xmlFree(tapifname);
|
||||
free(net);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -770,6 +822,68 @@ static int qemudParseXML(struct qemud_server *server,
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qemudNetworkIfaceConnect(struct qemud_server *server,
|
||||
struct qemud_vm *vm,
|
||||
struct qemud_vm_net_def *net)
|
||||
{
|
||||
struct qemud_network *network;
|
||||
const char *tapifname;
|
||||
char tapfdstr[4+3+32+7];
|
||||
char *retval = NULL;
|
||||
int err;
|
||||
int tapfd = -1;
|
||||
int *tapfds;
|
||||
|
||||
if (!(network = qemudFindNetworkByName(server, net->dst.network.name))) {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"Network '%s' not found", net->dst.network.name);
|
||||
goto error;
|
||||
} else if (network->bridge[0] == '\0') {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"Network '%s' not active", net->dst.network.name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (net->dst.network.tapifname[0] == '\0' ||
|
||||
strchr(net->dst.network.tapifname, '%')) {
|
||||
tapifname = "vnet%d";
|
||||
} else {
|
||||
tapifname = net->dst.network.tapifname;
|
||||
}
|
||||
|
||||
if ((err = brAddTap(server->brctl, network->bridge, tapifname,
|
||||
&net->dst.network.tapifname[0], BR_IFNAME_MAXLEN, &tapfd))) {
|
||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||
"Failed to add tap interface '%s' to bridge '%s' : %s",
|
||||
tapifname, network->bridge, strerror(err));
|
||||
goto error;
|
||||
}
|
||||
|
||||
snprintf(tapfdstr, sizeof(tapfdstr), "tap,fd=%d,script=", tapfd);
|
||||
|
||||
if (!(retval = strdup(tapfdstr)))
|
||||
goto no_memory;
|
||||
|
||||
if (!(tapfds = realloc(vm->tapfds, sizeof(int) * (vm->ntapfds+2))))
|
||||
goto no_memory;
|
||||
|
||||
vm->tapfds = tapfds;
|
||||
vm->tapfds[vm->ntapfds++] = tapfd;
|
||||
vm->tapfds[vm->ntapfds] = -1;
|
||||
|
||||
return retval;
|
||||
|
||||
no_memory:
|
||||
qemudReportError(server, VIR_ERR_NO_MEMORY, "tapfds");
|
||||
error:
|
||||
if (retval)
|
||||
free(retval);
|
||||
if (tapfd != -1)
|
||||
close(tapfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructs a argv suitable for launching qemu with config defined
|
||||
* for a given virtual machine.
|
||||
@ -921,9 +1035,15 @@ int qemudBuildCommandLine(struct qemud_server *server,
|
||||
goto no_memory;
|
||||
if (!((*argv)[++n] = strdup("-net")))
|
||||
goto no_memory;
|
||||
/* XXX don't hardcode user */
|
||||
if (!((*argv)[++n] = strdup("user")))
|
||||
goto no_memory;
|
||||
|
||||
if (net->type != QEMUD_NET_NETWORK) {
|
||||
/* XXX don't hardcode user */
|
||||
if (!((*argv)[++n] = strdup("user")))
|
||||
goto no_memory;
|
||||
} else {
|
||||
if (!((*argv)[++n] = qemudNetworkIfaceConnect(server, vm, net)))
|
||||
goto error;
|
||||
}
|
||||
|
||||
net = net->next;
|
||||
}
|
||||
@ -948,12 +1068,20 @@ int qemudBuildCommandLine(struct qemud_server *server,
|
||||
return 0;
|
||||
|
||||
no_memory:
|
||||
qemudReportError(server, VIR_ERR_NO_MEMORY, "argv");
|
||||
error:
|
||||
if (vm->tapfds) {
|
||||
for (i = 0; vm->tapfds[i] != -1; i++)
|
||||
close(vm->tapfds[i]);
|
||||
free(vm->tapfds);
|
||||
vm->tapfds = NULL;
|
||||
vm->ntapfds = 0;
|
||||
}
|
||||
if (argv) {
|
||||
for (i = 0 ; i < n ; i++)
|
||||
free((*argv)[i]);
|
||||
free(*argv);
|
||||
}
|
||||
qemudReportError(server, VIR_ERR_NO_MEMORY, "argv");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1716,6 +1844,18 @@ char *qemudGenerateXML(struct qemud_server *server, struct qemud_vm *vm) {
|
||||
net->mac[3], net->mac[4], net->mac[5]) < 0)
|
||||
goto no_memory;
|
||||
|
||||
if (net->type == QEMUD_NET_NETWORK) {
|
||||
if (qemudBufferPrintf(&buf, " <network name='%s", net->dst.network.name) < 0)
|
||||
goto no_memory;
|
||||
|
||||
if (net->dst.network.tapifname[0] != '\0' &&
|
||||
qemudBufferPrintf(&buf, " tapifname='%s'", net->dst.network.tapifname) < 0)
|
||||
goto no_memory;
|
||||
|
||||
if (qemudBufferPrintf(&buf, "/>\n") < 0)
|
||||
goto no_memory;
|
||||
}
|
||||
|
||||
if (qemudBufferPrintf(&buf, " </interface>\n") < 0)
|
||||
goto no_memory;
|
||||
|
||||
|
@ -95,6 +95,7 @@ enum qemud_vm_net_type {
|
||||
QEMUD_NET_SERVER,
|
||||
QEMUD_NET_CLIENT,
|
||||
QEMUD_NET_MCAST,
|
||||
QEMUD_NET_NETWORK,
|
||||
/* QEMUD_NET_VDE*/
|
||||
};
|
||||
|
||||
@ -123,6 +124,10 @@ struct qemud_vm_net_def {
|
||||
struct {
|
||||
char vlan[PATH_MAX];
|
||||
} vde;
|
||||
struct {
|
||||
char name[QEMUD_MAX_NAME_LEN];
|
||||
char tapifname[BR_IFNAME_MAXLEN];
|
||||
} network;
|
||||
} dst;
|
||||
|
||||
struct qemud_vm_net_def *next;
|
||||
@ -193,6 +198,9 @@ struct qemud_vm {
|
||||
int monitor;
|
||||
int pid;
|
||||
|
||||
int *tapfds;
|
||||
int ntapfds;
|
||||
|
||||
char configFile[PATH_MAX];
|
||||
|
||||
struct qemud_vm_def def;
|
||||
|
@ -332,9 +332,24 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemudLeaveFdOpen(int *openfds, int fd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!openfds)
|
||||
return 0;
|
||||
|
||||
for (i = 0; openfds[i] != -1; i++)
|
||||
if (fd == openfds[i])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qemudExec(struct qemud_server *server, char **argv,
|
||||
int *retpid, int *outfd, int *errfd) {
|
||||
int *retpid, int *outfd, int *errfd, int *openfds) {
|
||||
int pid, null;
|
||||
int pipeout[2] = {-1,-1};
|
||||
int pipeerr[2] = {-1,-1};
|
||||
@ -392,7 +407,8 @@ qemudExec(struct qemud_server *server, char **argv,
|
||||
for (i = 0; i < open_max; i++)
|
||||
if (i != STDOUT_FILENO &&
|
||||
i != STDERR_FILENO &&
|
||||
i != STDIN_FILENO)
|
||||
i != STDIN_FILENO &&
|
||||
!qemudLeaveFdOpen(openfds, i))
|
||||
close(i);
|
||||
|
||||
execvp(argv[0], argv);
|
||||
@ -429,10 +445,20 @@ int qemudStartVMDaemon(struct qemud_server *server,
|
||||
if (qemudBuildCommandLine(server, vm, &argv) < 0)
|
||||
return -1;
|
||||
|
||||
if (qemudExec(server, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) {
|
||||
if (qemudExec(server, argv, &vm->pid, &vm->stdout, &vm->stderr, vm->tapfds) == 0) {
|
||||
vm->def.id = server->nextvmid++;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (vm->tapfds) {
|
||||
for (i = 0; vm->tapfds[i] != -1; i++) {
|
||||
close(vm->tapfds[i]);
|
||||
vm->tapfds[i] = -1;
|
||||
}
|
||||
free(vm->tapfds);
|
||||
vm->tapfds = NULL;
|
||||
vm->ntapfds = 0;
|
||||
}
|
||||
|
||||
for (i = 0 ; argv[i] ; i++)
|
||||
free(argv[i]);
|
||||
@ -632,8 +658,17 @@ static int qemudVMData(struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
qemudNetworkIfaceDisconnect(struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||
struct qemud_vm *vm ATTRIBUTE_UNUSED,
|
||||
struct qemud_vm_net_def *net) {
|
||||
/* FIXME: will be needed to remove iptables rules */
|
||||
net = NULL;
|
||||
}
|
||||
|
||||
int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
|
||||
struct qemud_vm *prev = NULL, *curr = server->activevms;
|
||||
struct qemud_vm_net_def *net;
|
||||
|
||||
/* Already cleaned-up */
|
||||
if (vm->pid < 0)
|
||||
@ -676,6 +711,13 @@ int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
|
||||
curr->monitor = -1;
|
||||
server->nvmfds -= 2;
|
||||
|
||||
net = vm->def.nets;
|
||||
while (net) {
|
||||
if (net->type == QEMUD_NET_NETWORK)
|
||||
qemudNetworkIfaceDisconnect(server, vm, net);
|
||||
net = net->next;
|
||||
}
|
||||
|
||||
if (waitpid(vm->pid, NULL, WNOHANG) != vm->pid) {
|
||||
kill(vm->pid, SIGKILL);
|
||||
if (waitpid(vm->pid, NULL, 0) != vm->pid) {
|
||||
@ -794,7 +836,7 @@ dhcpStartDhcpDaemon(struct qemud_server *server,
|
||||
if (qemudBuildDnsmasqArgv(server, network, &argv) < 0)
|
||||
return -1;
|
||||
|
||||
ret = qemudExec(server, argv, &network->dnsmasqPid, NULL, NULL);
|
||||
ret = qemudExec(server, argv, &network->dnsmasqPid, NULL, NULL, NULL);
|
||||
|
||||
for (i = 0; argv[i]; i++)
|
||||
free(argv[i]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user