mirror of https://gitee.com/openkylin/libvirt.git
Improve support for virtual networking
This commit is contained in:
parent
06b3f3ced3
commit
a534de5281
36
ChangeLog
36
ChangeLog
|
@ -1,3 +1,39 @@
|
||||||
|
Tue Mar 13 18:04:14 EST 2007 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
* qemud/qemud.c: Use the --dhcp-leasefile arg to dnsmasq to
|
||||||
|
ensure multiple instances of dnsmasq can co-exist without
|
||||||
|
splaterring each other's leases.
|
||||||
|
|
||||||
|
* qemud/bridge.c: Use a single ifname arg instead of two separate
|
||||||
|
ifnameOrFmt & ifname args to simply use by callers
|
||||||
|
|
||||||
|
* qemud/conf.c: Autogenerate a MAC address if none is provided.
|
||||||
|
Added support for ethernet, bridge, mcast, client and server
|
||||||
|
networking config types in XML parser, generator and command
|
||||||
|
line args. Use the 'vlan' attribute for all QEMU nics to ensure
|
||||||
|
they don't all appear on same virtual LAN. Ensure order of
|
||||||
|
QEMU NICs matches order they are declared in the XML. Tweak
|
||||||
|
existing XML generation of 'network' type to match syntax
|
||||||
|
used by Xen for specifying tap device name. Add support for
|
||||||
|
creating isolated networks, or networks forwarding to an
|
||||||
|
explicit named physical device.
|
||||||
|
|
||||||
|
* qemud/default-network.xml: Add <forward/> to make default network
|
||||||
|
automatically forward to any active physical device.
|
||||||
|
|
||||||
|
* qemud/internal.h: Added struct fields for new types of network
|
||||||
|
config, and for tracking network forward device.
|
||||||
|
|
||||||
|
* qemud/iptables.h, qemud/iptables.c: Allow an optional target
|
||||||
|
device name to be passed in to restrict IP tables forwarding
|
||||||
|
rules.
|
||||||
|
|
||||||
|
* qemud/Makefile.am: Create $sysconfdir/lib/libvirt for DHCP
|
||||||
|
leases file
|
||||||
|
|
||||||
|
* libvirt.spec.in: Include %{_sysconfdir}/lib/libvirt for DHCP
|
||||||
|
leases file
|
||||||
|
|
||||||
Mon Mar 12 23:17:11 EST 2007 Daniel P. Berrange <berrange@redhat.com>
|
Mon Mar 12 23:17:11 EST 2007 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
* libvirt.spec.in: Don't run UUID generation on first install,
|
* libvirt.spec.in: Don't run UUID generation on first install,
|
||||||
|
|
|
@ -113,6 +113,7 @@ fi
|
||||||
%config %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/networks/autostart/default.xml
|
%config %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/networks/autostart/default.xml
|
||||||
%{_sysconfdir}/rc.d/init.d/libvirtd
|
%{_sysconfdir}/rc.d/init.d/libvirtd
|
||||||
%dir %{_localstatedir}/run/libvirt/
|
%dir %{_localstatedir}/run/libvirt/
|
||||||
|
%dir %{_localstatedir}/lib/libvirt/
|
||||||
%attr(4755, root, root) %{_libexecdir}/libvirt_proxy
|
%attr(4755, root, root) %{_libexecdir}/libvirt_proxy
|
||||||
%attr(0755, root, root) %{_sbindir}/libvirt_qemud
|
%attr(0755, root, root) %{_sbindir}/libvirt_qemud
|
||||||
%doc docs/libvirt.rng
|
%doc docs/libvirt.rng
|
||||||
|
|
|
@ -28,12 +28,14 @@ install-data-local:
|
||||||
test -e $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml || \
|
test -e $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml || \
|
||||||
ln -s ../default.xml $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
|
ln -s ../default.xml $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
|
||||||
mkdir -p $(DESTDIR)$(localstatedir)/run/libvirt
|
mkdir -p $(DESTDIR)$(localstatedir)/run/libvirt
|
||||||
|
mkdir -p $(DESTDIR)$(localstatedir)/lib/libvirt
|
||||||
|
|
||||||
uninstall-local:
|
uninstall-local:
|
||||||
rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
|
rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
|
||||||
rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml
|
rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/default.xml
|
||||||
rmdir $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart || :
|
rmdir $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart || :
|
||||||
rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
|
rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
|
||||||
|
rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || :
|
||||||
|
|
||||||
EXTRA_DIST = libvirtd.in default-network.xml
|
EXTRA_DIST = libvirtd.in default-network.xml
|
||||||
|
|
||||||
|
|
|
@ -190,27 +190,22 @@ brDeleteInterface(brControl *ctl,
|
||||||
return brAddDelInterface(ctl, SIOCBRDELIF, bridge, iface);
|
return brAddDelInterface(ctl, SIOCBRDELIF, bridge, iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
brAddTap(brControl *ctl,
|
brAddTap(brControl *ctl,
|
||||||
const char *bridge,
|
const char *bridge,
|
||||||
const char *ifnameOrFmt,
|
|
||||||
char *ifname,
|
char *ifname,
|
||||||
int maxlen,
|
int maxlen,
|
||||||
int *tapfd)
|
int *tapfd)
|
||||||
{
|
{
|
||||||
int id, subst, fd;
|
int id, subst, fd;
|
||||||
|
|
||||||
if (!ctl || !ctl->fd || !bridge || !ifnameOrFmt || !tapfd)
|
if (!ctl || !ctl->fd || !bridge || !ifname || !tapfd)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if (!ifname)
|
|
||||||
maxlen = BR_IFNAME_MAXLEN;
|
|
||||||
else if (maxlen >= BR_IFNAME_MAXLEN)
|
|
||||||
maxlen = BR_IFNAME_MAXLEN;
|
|
||||||
|
|
||||||
subst = id = 0;
|
subst = id = 0;
|
||||||
|
|
||||||
if (strstr(ifnameOrFmt, "%d"))
|
if (strstr(ifname, "%d"))
|
||||||
subst = 1;
|
subst = 1;
|
||||||
|
|
||||||
if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
|
if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
|
||||||
|
@ -225,19 +220,19 @@ brAddTap(brControl *ctl,
|
||||||
try.ifr_flags = IFF_TAP|IFF_NO_PI;
|
try.ifr_flags = IFF_TAP|IFF_NO_PI;
|
||||||
|
|
||||||
if (subst) {
|
if (subst) {
|
||||||
len = snprintf(try.ifr_name, maxlen, ifnameOrFmt, id);
|
len = snprintf(try.ifr_name, maxlen, ifname, id);
|
||||||
if (len >= maxlen) {
|
if (len >= maxlen) {
|
||||||
errno = EADDRINUSE;
|
errno = EADDRINUSE;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
len = strlen(ifnameOrFmt);
|
len = strlen(ifname);
|
||||||
if (len >= maxlen - 1) {
|
if (len >= maxlen - 1) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(try.ifr_name, ifnameOrFmt, len);
|
strncpy(try.ifr_name, ifname, len);
|
||||||
try.ifr_name[len] = '\0';
|
try.ifr_name[len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,6 @@ int brDeleteInterface (brControl *ctl,
|
||||||
|
|
||||||
int brAddTap (brControl *ctl,
|
int brAddTap (brControl *ctl,
|
||||||
const char *bridge,
|
const char *bridge,
|
||||||
const char *ifnameOrFmt,
|
|
||||||
char *ifname,
|
char *ifname,
|
||||||
int maxlen,
|
int maxlen,
|
||||||
int *tapfd);
|
int *tapfd);
|
||||||
|
|
411
qemud/conf.c
411
qemud/conf.c
|
@ -444,6 +444,15 @@ static struct qemud_vm_disk_def *qemudParseDiskXML(struct qemud_server *server,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qemudRandomMAC(struct qemud_vm_net_def *net) {
|
||||||
|
net->mac[0] = 0x52;
|
||||||
|
net->mac[1] = 0x54;
|
||||||
|
net->mac[2] = 0x00;
|
||||||
|
net->mac[3] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
|
||||||
|
net->mac[4] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
|
||||||
|
net->mac[5] = 1 + (int)(256*(rand()/(RAND_MAX+1.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parse the XML definition for a network interface */
|
/* Parse the XML definition for a network interface */
|
||||||
static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *server,
|
static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *server,
|
||||||
|
@ -453,7 +462,11 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||||
xmlChar *macaddr = NULL;
|
xmlChar *macaddr = NULL;
|
||||||
xmlChar *type = NULL;
|
xmlChar *type = NULL;
|
||||||
xmlChar *network = NULL;
|
xmlChar *network = NULL;
|
||||||
xmlChar *tapifname = NULL;
|
xmlChar *bridge = NULL;
|
||||||
|
xmlChar *ifname = NULL;
|
||||||
|
xmlChar *script = NULL;
|
||||||
|
xmlChar *address = NULL;
|
||||||
|
xmlChar *port = NULL;
|
||||||
|
|
||||||
if (!net) {
|
if (!net) {
|
||||||
qemudReportError(server, VIR_ERR_NO_MEMORY, "net");
|
qemudReportError(server, VIR_ERR_NO_MEMORY, "net");
|
||||||
|
@ -466,8 +479,8 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||||
if (type != NULL) {
|
if (type != NULL) {
|
||||||
if (xmlStrEqual(type, BAD_CAST "user"))
|
if (xmlStrEqual(type, BAD_CAST "user"))
|
||||||
net->type = QEMUD_NET_USER;
|
net->type = QEMUD_NET_USER;
|
||||||
else if (xmlStrEqual(type, BAD_CAST "tap"))
|
else if (xmlStrEqual(type, BAD_CAST "ethernet"))
|
||||||
net->type = QEMUD_NET_TAP;
|
net->type = QEMUD_NET_ETHERNET;
|
||||||
else if (xmlStrEqual(type, BAD_CAST "server"))
|
else if (xmlStrEqual(type, BAD_CAST "server"))
|
||||||
net->type = QEMUD_NET_SERVER;
|
net->type = QEMUD_NET_SERVER;
|
||||||
else if (xmlStrEqual(type, BAD_CAST "client"))
|
else if (xmlStrEqual(type, BAD_CAST "client"))
|
||||||
|
@ -476,10 +489,8 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||||
net->type = QEMUD_NET_MCAST;
|
net->type = QEMUD_NET_MCAST;
|
||||||
else if (xmlStrEqual(type, BAD_CAST "network"))
|
else if (xmlStrEqual(type, BAD_CAST "network"))
|
||||||
net->type = QEMUD_NET_NETWORK;
|
net->type = QEMUD_NET_NETWORK;
|
||||||
/*
|
else if (xmlStrEqual(type, BAD_CAST "bridge"))
|
||||||
else if (xmlStrEqual(type, BAD_CAST "vde"))
|
net->type = QEMUD_NET_BRIDGE;
|
||||||
typ = QEMUD_NET_VDE;
|
|
||||||
*/
|
|
||||||
else
|
else
|
||||||
net->type = QEMUD_NET_USER;
|
net->type = QEMUD_NET_USER;
|
||||||
xmlFree(type);
|
xmlFree(type);
|
||||||
|
@ -496,17 +507,32 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||||
(net->type == QEMUD_NET_NETWORK) &&
|
(net->type == QEMUD_NET_NETWORK) &&
|
||||||
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
||||||
network = xmlGetProp(cur, BAD_CAST "network");
|
network = xmlGetProp(cur, BAD_CAST "network");
|
||||||
} else if ((tapifname == NULL) &&
|
} else if ((network == NULL) &&
|
||||||
(net->type == QEMUD_NET_NETWORK) &&
|
(net->type == QEMUD_NET_BRIDGE) &&
|
||||||
xmlStrEqual(cur->name, BAD_CAST "tap")) {
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
||||||
tapifname = xmlGetProp(cur, BAD_CAST "ifname");
|
bridge = xmlGetProp(cur, BAD_CAST "dev");
|
||||||
|
} else if ((network == NULL) &&
|
||||||
|
((net->type == QEMUD_NET_SERVER) ||
|
||||||
|
(net->type == QEMUD_NET_CLIENT) ||
|
||||||
|
(net->type == QEMUD_NET_MCAST)) &&
|
||||||
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
||||||
|
address = xmlGetProp(cur, BAD_CAST "address");
|
||||||
|
port = xmlGetProp(cur, BAD_CAST "port");
|
||||||
|
} else if ((ifname == NULL) &&
|
||||||
|
((net->type == QEMUD_NET_NETWORK) ||
|
||||||
|
(net->type == QEMUD_NET_ETHERNET) ||
|
||||||
|
(net->type == QEMUD_NET_BRIDGE)) &&
|
||||||
|
xmlStrEqual(cur->name, BAD_CAST "target")) {
|
||||||
|
ifname = xmlGetProp(cur, BAD_CAST "dev");
|
||||||
|
} else if ((script == NULL) &&
|
||||||
|
(net->type == QEMUD_NET_ETHERNET) &&
|
||||||
|
xmlStrEqual(cur->name, BAD_CAST "script")) {
|
||||||
|
script = xmlGetProp(cur, BAD_CAST "path");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
net->vlan = 0;
|
|
||||||
|
|
||||||
if (macaddr) {
|
if (macaddr) {
|
||||||
unsigned int mac[6];
|
unsigned int mac[6];
|
||||||
sscanf((const char *)macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
sscanf((const char *)macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
@ -524,6 +550,9 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||||
net->mac[5] = mac[5];
|
net->mac[5] = mac[5];
|
||||||
|
|
||||||
xmlFree(macaddr);
|
xmlFree(macaddr);
|
||||||
|
macaddr = NULL;
|
||||||
|
} else {
|
||||||
|
qemudRandomMAC(net);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (net->type == QEMUD_NET_NETWORK) {
|
if (net->type == QEMUD_NET_NETWORK) {
|
||||||
|
@ -533,7 +562,7 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"No <source> 'network' attribute specified with <interface type='network'/>");
|
"No <source> 'network' attribute specified with <interface type='network'/>");
|
||||||
goto error;
|
goto error;
|
||||||
} else if ((len = xmlStrlen(network)) >= QEMUD_MAX_NAME_LEN) {
|
} else if ((len = xmlStrlen(network)) >= (QEMUD_MAX_NAME_LEN-1)) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"Network name '%s' too long", network);
|
"Network name '%s' too long", network);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -542,20 +571,118 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||||
net->dst.network.name[len] = '\0';
|
net->dst.network.name[len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network)
|
if (network) {
|
||||||
xmlFree(network);
|
xmlFree(network);
|
||||||
|
network = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (tapifname != NULL) {
|
if (ifname != NULL) {
|
||||||
if ((len == xmlStrlen(tapifname)) >= BR_IFNAME_MAXLEN) {
|
if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"TAP interface name '%s' is too long", tapifname);
|
"TAP interface name '%s' is too long", ifname);
|
||||||
goto error;
|
goto error;
|
||||||
} else {
|
} else {
|
||||||
strncpy(net->dst.network.tapifname, (char *)tapifname, len);
|
strncpy(net->dst.network.ifname, (char *)ifname, len);
|
||||||
net->dst.network.tapifname[len] = '\0';
|
net->dst.network.ifname[len] = '\0';
|
||||||
}
|
}
|
||||||
xmlFree(tapifname);
|
xmlFree(ifname);
|
||||||
|
ifname = NULL;
|
||||||
}
|
}
|
||||||
|
} else if (net->type == QEMUD_NET_ETHERNET) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (script != NULL) {
|
||||||
|
if ((len = xmlStrlen(script)) >= (PATH_MAX-1)) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"TAP script path '%s' is too long", script);
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
strncpy(net->dst.ethernet.script, (char *)script, len);
|
||||||
|
net->dst.ethernet.script[len] = '\0';
|
||||||
|
}
|
||||||
|
xmlFree(script);
|
||||||
|
script = NULL;
|
||||||
|
}
|
||||||
|
if (ifname != NULL) {
|
||||||
|
if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"TAP interface name '%s' is too long", ifname);
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
strncpy(net->dst.ethernet.ifname, (char *)ifname, len);
|
||||||
|
net->dst.ethernet.ifname[len] = '\0';
|
||||||
|
}
|
||||||
|
xmlFree(ifname);
|
||||||
|
}
|
||||||
|
} else if (net->type == QEMUD_NET_BRIDGE) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (bridge == NULL) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"No <source> 'dev' attribute specified with <interface type='bridge'/>");
|
||||||
|
goto error;
|
||||||
|
} else if ((len = xmlStrlen(bridge)) >= (BR_IFNAME_MAXLEN-1)) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"TAP bridge path '%s' is too long", bridge);
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
strncpy(net->dst.bridge.brname, (char *)bridge, len);
|
||||||
|
net->dst.bridge.brname[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFree(bridge);
|
||||||
|
bridge = NULL;
|
||||||
|
|
||||||
|
if (ifname != NULL) {
|
||||||
|
if ((len = xmlStrlen(ifname)) >= (BR_IFNAME_MAXLEN-1)) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"TAP interface name '%s' is too long", ifname);
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
strncpy(net->dst.bridge.ifname, (char *)ifname, len);
|
||||||
|
net->dst.bridge.ifname[len] = '\0';
|
||||||
|
}
|
||||||
|
xmlFree(ifname);
|
||||||
|
}
|
||||||
|
} else if (net->type == QEMUD_NET_CLIENT ||
|
||||||
|
net->type == QEMUD_NET_SERVER ||
|
||||||
|
net->type == QEMUD_NET_MCAST) {
|
||||||
|
int len;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
if (port == NULL) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"No <source> 'port' attribute specified with socket interface");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (!(net->dst.socket.port = strtol((char*)port, &ret, 10)) &&
|
||||||
|
ret == (char*)port) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Cannot parse <source> 'port' attribute with socket interface");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
xmlFree(port);
|
||||||
|
port = NULL;
|
||||||
|
|
||||||
|
if (address == NULL) {
|
||||||
|
if (net->type == QEMUD_NET_CLIENT ||
|
||||||
|
net->type == QEMUD_NET_MCAST) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"No <source> 'address' attribute specified with socket interface");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if ((len = xmlStrlen(address)) >= (BR_INET_ADDR_MAXLEN)) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"IP address '%s' is too long", address);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (address == NULL) {
|
||||||
|
net->dst.socket.address[0] = '\0';
|
||||||
|
} else {
|
||||||
|
strncpy(net->dst.socket.address, (char*)address,len);
|
||||||
|
net->dst.socket.address[len] = '\0';
|
||||||
|
}
|
||||||
|
xmlFree(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
return net;
|
return net;
|
||||||
|
@ -563,8 +690,16 @@ static struct qemud_vm_net_def *qemudParseInterfaceXML(struct qemud_server *serv
|
||||||
error:
|
error:
|
||||||
if (network)
|
if (network)
|
||||||
xmlFree(network);
|
xmlFree(network);
|
||||||
if (tapifname)
|
if (address)
|
||||||
xmlFree(tapifname);
|
xmlFree(address);
|
||||||
|
if (port)
|
||||||
|
xmlFree(port);
|
||||||
|
if (ifname)
|
||||||
|
xmlFree(ifname);
|
||||||
|
if (script)
|
||||||
|
xmlFree(script);
|
||||||
|
if (bridge)
|
||||||
|
xmlFree(bridge);
|
||||||
free(net);
|
free(net);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -886,14 +1021,20 @@ static struct qemud_vm_def *qemudParseXML(struct qemud_server *server,
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
|
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
||||||
|
struct qemud_vm_disk_def *prev = NULL;
|
||||||
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
||||||
struct qemud_vm_disk_def *disk;
|
struct qemud_vm_disk_def *disk;
|
||||||
if (!(disk = qemudParseDiskXML(server, obj->nodesetval->nodeTab[i]))) {
|
if (!(disk = qemudParseDiskXML(server, obj->nodesetval->nodeTab[i]))) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
def->ndisks++;
|
def->ndisks++;
|
||||||
disk->next = def->disks;
|
disk->next = NULL;
|
||||||
|
if (i == 0) {
|
||||||
def->disks = disk;
|
def->disks = disk;
|
||||||
|
} else {
|
||||||
|
prev->next = disk;
|
||||||
|
}
|
||||||
|
prev = disk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
|
@ -903,14 +1044,20 @@ static struct qemud_vm_def *qemudParseXML(struct qemud_server *server,
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
|
obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
||||||
|
struct qemud_vm_net_def *prev = NULL;
|
||||||
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
||||||
struct qemud_vm_net_def *net;
|
struct qemud_vm_net_def *net;
|
||||||
if (!(net = qemudParseInterfaceXML(server, obj->nodesetval->nodeTab[i]))) {
|
if (!(net = qemudParseInterfaceXML(server, obj->nodesetval->nodeTab[i]))) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
def->nnets++;
|
def->nnets++;
|
||||||
net->next = def->nets;
|
net->next = NULL;
|
||||||
|
if (i == 0) {
|
||||||
def->nets = net;
|
def->nets = net;
|
||||||
|
} else {
|
||||||
|
prev->next = net;
|
||||||
|
}
|
||||||
|
prev = net;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
|
@ -933,16 +1080,19 @@ static struct qemud_vm_def *qemudParseXML(struct qemud_server *server,
|
||||||
static char *
|
static char *
|
||||||
qemudNetworkIfaceConnect(struct qemud_server *server,
|
qemudNetworkIfaceConnect(struct qemud_server *server,
|
||||||
struct qemud_vm *vm,
|
struct qemud_vm *vm,
|
||||||
struct qemud_vm_net_def *net)
|
struct qemud_vm_net_def *net,
|
||||||
|
int vlan)
|
||||||
{
|
{
|
||||||
struct qemud_network *network;
|
struct qemud_network *network = NULL;
|
||||||
const char *tapifname;
|
char *brname;
|
||||||
|
char *ifname;
|
||||||
char tapfdstr[4+3+32+7];
|
char tapfdstr[4+3+32+7];
|
||||||
char *retval = NULL;
|
char *retval = NULL;
|
||||||
int err;
|
int err;
|
||||||
int tapfd = -1;
|
int tapfd = -1;
|
||||||
int *tapfds;
|
int *tapfds;
|
||||||
|
|
||||||
|
if (net->type == QEMUD_NET_NETWORK) {
|
||||||
if (!(network = qemudFindNetworkByName(server, net->dst.network.name))) {
|
if (!(network = qemudFindNetworkByName(server, net->dst.network.name))) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"Network '%s' not found", net->dst.network.name);
|
"Network '%s' not found", net->dst.network.name);
|
||||||
|
@ -952,30 +1102,43 @@ qemudNetworkIfaceConnect(struct qemud_server *server,
|
||||||
"Network '%s' not active", net->dst.network.name);
|
"Network '%s' not active", net->dst.network.name);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
brname = network->bridge;
|
||||||
if (net->dst.network.tapifname[0] == '\0' ||
|
if (net->dst.network.ifname[0] == '\0' ||
|
||||||
strchr(net->dst.network.tapifname, '%')) {
|
strchr(net->dst.network.ifname, '%')) {
|
||||||
tapifname = "vnet%d";
|
strcpy(net->dst.network.ifname, "vnet%d");
|
||||||
|
}
|
||||||
|
ifname = net->dst.network.ifname;
|
||||||
|
} else if (net->type == QEMUD_NET_BRIDGE) {
|
||||||
|
brname = net->dst.bridge.brname;
|
||||||
|
if (net->dst.bridge.ifname[0] == '\0' ||
|
||||||
|
strchr(net->dst.bridge.ifname, '%')) {
|
||||||
|
strcpy(net->dst.bridge.ifname, "vnet%d");
|
||||||
|
}
|
||||||
|
ifname = net->dst.bridge.ifname;
|
||||||
} else {
|
} else {
|
||||||
tapifname = net->dst.network.tapifname;
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Network type %d is not supported", net->type);
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = brAddTap(server->brctl, network->bridge, tapifname,
|
if ((err = brAddTap(server->brctl, brname,
|
||||||
&net->dst.network.tapifname[0], BR_IFNAME_MAXLEN, &tapfd))) {
|
ifname, BR_IFNAME_MAXLEN, &tapfd))) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"Failed to add tap interface '%s' to bridge '%s' : %s",
|
"Failed to add tap interface '%s' to bridge '%s' : %s",
|
||||||
tapifname, network->bridge, strerror(err));
|
ifname, brname, strerror(err));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = iptablesAddPhysdevForward(server->iptables, net->dst.network.tapifname))) {
|
if (net->type == QEMUD_NET_NETWORK && network->def->forward) {
|
||||||
|
if ((err = iptablesAddPhysdevForward(server->iptables, ifname, network->def->forwardDev))) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"Failed to add iptables rule to allow bridging from '%s' :%s",
|
"Failed to add iptables rule to allow bridging from '%s' :%s",
|
||||||
net->dst.network.tapifname, strerror(err));
|
ifname, strerror(err));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(tapfdstr, sizeof(tapfdstr), "tap,fd=%d,script=", tapfd);
|
snprintf(tapfdstr, sizeof(tapfdstr), "tap,fd=%d,script=,vlan=%d", tapfd, vlan);
|
||||||
|
|
||||||
if (!(retval = strdup(tapfdstr)))
|
if (!(retval = strdup(tapfdstr)))
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
@ -990,7 +1153,8 @@ qemudNetworkIfaceConnect(struct qemud_server *server,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
no_memory:
|
no_memory:
|
||||||
iptablesRemovePhysdevForward(server->iptables, net->dst.network.tapifname);
|
if (net->type == QEMUD_NET_NETWORK && network->def->forward)
|
||||||
|
iptablesRemovePhysdevForward(server->iptables, ifname, network->def->forwardDev);
|
||||||
qemudReportError(server, VIR_ERR_NO_MEMORY, "tapfds");
|
qemudReportError(server, VIR_ERR_NO_MEMORY, "tapfds");
|
||||||
error:
|
error:
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -1137,36 +1301,88 @@ int qemudBuildCommandLine(struct qemud_server *server,
|
||||||
if (!((*argv)[++n] = strdup("none")))
|
if (!((*argv)[++n] = strdup("none")))
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
} else {
|
} else {
|
||||||
|
int vlan = 0;
|
||||||
while (net) {
|
while (net) {
|
||||||
char nic[3+1+7+1+17+1];
|
char nic[3+1+7+1+17+1];
|
||||||
|
|
||||||
if (!net->mac[0] && !net->mac[1] && !net->mac[2] &&
|
sprintf(nic, "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d",
|
||||||
!net->mac[3] && !net->mac[4] && !net->mac[5]) {
|
|
||||||
strncpy(nic, "nic", 4);
|
|
||||||
} else {
|
|
||||||
sprintf(nic, "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
|
||||||
net->mac[0], net->mac[1],
|
net->mac[0], net->mac[1],
|
||||||
net->mac[2], net->mac[3],
|
net->mac[2], net->mac[3],
|
||||||
net->mac[4], net->mac[5]);
|
net->mac[4], net->mac[5],
|
||||||
}
|
vlan);
|
||||||
|
|
||||||
if (!((*argv)[++n] = strdup("-net")))
|
if (!((*argv)[++n] = strdup("-net")))
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
if (!((*argv)[++n] = strdup(nic)))
|
if (!((*argv)[++n] = strdup(nic)))
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
if (!((*argv)[++n] = strdup("-net")))
|
if (!((*argv)[++n] = strdup("-net")))
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
if (net->type != QEMUD_NET_NETWORK) {
|
switch (net->type) {
|
||||||
/* XXX don't hardcode user */
|
case QEMUD_NET_NETWORK:
|
||||||
if (!((*argv)[++n] = strdup("user")))
|
case QEMUD_NET_BRIDGE:
|
||||||
goto no_memory;
|
if (!((*argv)[++n] = qemudNetworkIfaceConnect(server, vm, net, vlan)))
|
||||||
} else {
|
|
||||||
if (!((*argv)[++n] = qemudNetworkIfaceConnect(server, vm, net)))
|
|
||||||
goto error;
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMUD_NET_ETHERNET:
|
||||||
|
{
|
||||||
|
char arg[PATH_MAX];
|
||||||
|
if (snprintf(arg, PATH_MAX-1, "tap,ifname=%s,script=%s,vlan=%d",
|
||||||
|
net->dst.ethernet.ifname,
|
||||||
|
net->dst.ethernet.script,
|
||||||
|
vlan) >= (PATH_MAX-1))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!((*argv)[++n] = strdup(arg)))
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMUD_NET_CLIENT:
|
||||||
|
case QEMUD_NET_SERVER:
|
||||||
|
case QEMUD_NET_MCAST:
|
||||||
|
{
|
||||||
|
char arg[PATH_MAX];
|
||||||
|
const char *mode = NULL;
|
||||||
|
switch (net->type) {
|
||||||
|
case QEMUD_NET_CLIENT:
|
||||||
|
mode = "connect";
|
||||||
|
break;
|
||||||
|
case QEMUD_NET_SERVER:
|
||||||
|
mode = "listen";
|
||||||
|
break;
|
||||||
|
case QEMUD_NET_MCAST:
|
||||||
|
mode = "mcast";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (snprintf(arg, PATH_MAX-1, "socket,%s=%s:%d,vlan=%d",
|
||||||
|
mode,
|
||||||
|
net->dst.socket.address,
|
||||||
|
net->dst.socket.port,
|
||||||
|
vlan) >= (PATH_MAX-1))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!((*argv)[++n] = strdup(arg)))
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMUD_NET_USER:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
char arg[PATH_MAX];
|
||||||
|
if (snprintf(arg, PATH_MAX-1, "user,vlan=%d", vlan) >= (PATH_MAX-1))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!((*argv)[++n] = strdup(arg)))
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
net = net->next;
|
net = net->next;
|
||||||
|
vlan++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1567,7 +1783,7 @@ static struct qemud_network_def *qemudParseNetworkXML(struct qemud_server *serve
|
||||||
xmlDocPtr xml) {
|
xmlDocPtr xml) {
|
||||||
xmlNodePtr root = NULL;
|
xmlNodePtr root = NULL;
|
||||||
xmlXPathContextPtr ctxt = NULL;
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
xmlXPathObjectPtr obj = NULL;
|
xmlXPathObjectPtr obj = NULL, tmp = NULL;
|
||||||
struct qemud_network_def *def;
|
struct qemud_network_def *def;
|
||||||
|
|
||||||
if (!(def = calloc(1, sizeof(struct qemud_network_def)))) {
|
if (!(def = calloc(1, sizeof(struct qemud_network_def)))) {
|
||||||
|
@ -1620,6 +1836,31 @@ static struct qemud_network_def *qemudParseNetworkXML(struct qemud_server *serve
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
|
|
||||||
|
obj = xmlXPathEval(BAD_CAST "count(/network/forward) > 0", ctxt);
|
||||||
|
if ((obj != NULL) && (obj->type == XPATH_BOOLEAN) &&
|
||||||
|
obj->boolval) {
|
||||||
|
def->forward = 1;
|
||||||
|
tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@dev)", ctxt);
|
||||||
|
if ((tmp != NULL) && (tmp->type == XPATH_STRING) &&
|
||||||
|
(tmp->stringval != NULL) && (tmp->stringval[0] != 0)) {
|
||||||
|
int len;
|
||||||
|
if ((len = xmlStrlen(tmp->stringval)) >= (BR_IFNAME_MAXLEN-1)) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"forward device name '%s' is too long",
|
||||||
|
(char*)tmp->stringval);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
strcpy(def->forwardDev, (char*)tmp->stringval);
|
||||||
|
} else {
|
||||||
|
def->forwardDev[0] = '\0';
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(tmp);
|
||||||
|
tmp = NULL;
|
||||||
|
} else {
|
||||||
|
def->forward = 0;
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
|
||||||
/* Parse bridge information */
|
/* Parse bridge information */
|
||||||
obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt);
|
obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
||||||
|
@ -1649,6 +1890,8 @@ static struct qemud_network_def *qemudParseNetworkXML(struct qemud_server *serve
|
||||||
the caller ? */
|
the caller ? */
|
||||||
if (obj)
|
if (obj)
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
|
if (tmp)
|
||||||
|
xmlXPathFreeObject(tmp);
|
||||||
if (ctxt)
|
if (ctxt)
|
||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
qemudFreeNetworkDef(def);
|
qemudFreeNetworkDef(def);
|
||||||
|
@ -2320,35 +2563,66 @@ char *qemudGenerateXML(struct qemud_server *server,
|
||||||
while (net) {
|
while (net) {
|
||||||
const char *types[] = {
|
const char *types[] = {
|
||||||
"user",
|
"user",
|
||||||
"tap",
|
"ethernet",
|
||||||
"server",
|
"server",
|
||||||
"client",
|
"client",
|
||||||
"mcast",
|
"mcast",
|
||||||
"network",
|
"network",
|
||||||
"vde",
|
"bridge",
|
||||||
};
|
};
|
||||||
if (qemudBufferPrintf(&buf, " <interface type='%s'>\n",
|
if (qemudBufferPrintf(&buf, " <interface type='%s'>\n",
|
||||||
types[net->type]) < 0)
|
types[net->type]) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
if (net->mac[0] && net->mac[1] && net->mac[2] &&
|
if (qemudBufferPrintf(&buf, " <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
|
||||||
net->mac[3] && net->mac[4] && net->mac[5] &&
|
|
||||||
qemudBufferPrintf(&buf, " <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
|
|
||||||
net->mac[0], net->mac[1], net->mac[2],
|
net->mac[0], net->mac[1], net->mac[2],
|
||||||
net->mac[3], net->mac[4], net->mac[5]) < 0)
|
net->mac[3], net->mac[4], net->mac[5]) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
if (net->type == QEMUD_NET_NETWORK) {
|
switch (net->type) {
|
||||||
if (qemudBufferPrintf(&buf, " <source network='%s'", net->dst.network.name) < 0)
|
case QEMUD_NET_NETWORK:
|
||||||
|
if (qemudBufferPrintf(&buf, " <source network='%s'/>\n", net->dst.network.name) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
if (net->dst.network.tapifname[0] != '\0' &&
|
if (net->dst.network.ifname[0] != '\0') {
|
||||||
qemudBufferPrintf(&buf, " tapifname='%s'", net->dst.network.tapifname) < 0)
|
if (qemudBufferPrintf(&buf, " <target dev='%s'/>\n", net->dst.network.ifname) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if (qemudBufferPrintf(&buf, "/>\n") < 0)
|
case QEMUD_NET_ETHERNET:
|
||||||
|
if (net->dst.ethernet.ifname[0] != '\0') {
|
||||||
|
if (qemudBufferPrintf(&buf, " <target dev='%s'/>\n", net->dst.ethernet.ifname) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
}
|
}
|
||||||
|
if (net->dst.ethernet.script[0] != '\0') {
|
||||||
|
if (qemudBufferPrintf(&buf, " <script path='%s'/>\n", net->dst.ethernet.script) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMUD_NET_BRIDGE:
|
||||||
|
if (qemudBufferPrintf(&buf, " <source dev='%s'/>\n", net->dst.bridge.brname) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
if (net->dst.bridge.ifname[0] != '\0') {
|
||||||
|
if (qemudBufferPrintf(&buf, " <target dev='%s'/>\n", net->dst.bridge.ifname) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEMUD_NET_SERVER:
|
||||||
|
case QEMUD_NET_CLIENT:
|
||||||
|
case QEMUD_NET_MCAST:
|
||||||
|
if (net->dst.socket.address[0] != '\0') {
|
||||||
|
if (qemudBufferPrintf(&buf, " <source address='%s' port='%d'/>\n",
|
||||||
|
net->dst.socket.address, net->dst.socket.port) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
} else {
|
||||||
|
if (qemudBufferPrintf(&buf, " <source port='%d'/>\n",
|
||||||
|
net->dst.socket.port) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (qemudBufferPrintf(&buf, " </interface>\n") < 0)
|
if (qemudBufferPrintf(&buf, " </interface>\n") < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
@ -2428,6 +2702,15 @@ char *qemudGenerateNetworkXML(struct qemud_server *server,
|
||||||
uuid[12], uuid[13], uuid[14], uuid[15]) < 0)
|
uuid[12], uuid[13], uuid[14], uuid[15]) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
|
if (def->forward) {
|
||||||
|
if (def->forwardDev[0]) {
|
||||||
|
qemudBufferPrintf(&buf, " <forward dev='%s'/>\n",
|
||||||
|
def->forwardDev);
|
||||||
|
} else {
|
||||||
|
qemudBufferAdd(&buf, " <forward/>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((def->bridge != '\0' || def->disableSTP || def->forwardDelay) &&
|
if ((def->bridge != '\0' || def->disableSTP || def->forwardDelay) &&
|
||||||
qemudBufferPrintf(&buf, " <bridge name='%s' stp='%s' delay='%d' />\n",
|
qemudBufferPrintf(&buf, " <bridge name='%s' stp='%s' delay='%d' />\n",
|
||||||
def->bridge,
|
def->bridge,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<network>
|
<network>
|
||||||
<name>default</name>
|
<name>default</name>
|
||||||
<bridge name="virbr0" />
|
<bridge name="virbr0" />
|
||||||
|
<forward/>
|
||||||
<ip address="192.168.122.1" netmask="255.255.255.0">
|
<ip address="192.168.122.1" netmask="255.255.255.0">
|
||||||
<dhcp>
|
<dhcp>
|
||||||
<range start="192.168.122.2" end="192.168.122.254" />
|
<range start="192.168.122.2" end="192.168.122.254" />
|
||||||
|
|
|
@ -103,43 +103,35 @@ struct qemud_vm_disk_def {
|
||||||
/* 5 different types of networking config */
|
/* 5 different types of networking config */
|
||||||
enum qemud_vm_net_type {
|
enum qemud_vm_net_type {
|
||||||
QEMUD_NET_USER,
|
QEMUD_NET_USER,
|
||||||
QEMUD_NET_TAP,
|
QEMUD_NET_ETHERNET,
|
||||||
QEMUD_NET_SERVER,
|
QEMUD_NET_SERVER,
|
||||||
QEMUD_NET_CLIENT,
|
QEMUD_NET_CLIENT,
|
||||||
QEMUD_NET_MCAST,
|
QEMUD_NET_MCAST,
|
||||||
QEMUD_NET_NETWORK,
|
QEMUD_NET_NETWORK,
|
||||||
/* QEMUD_NET_VDE*/
|
QEMUD_NET_BRIDGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stores the virtual network interface configuration */
|
/* Stores the virtual network interface configuration */
|
||||||
struct qemud_vm_net_def {
|
struct qemud_vm_net_def {
|
||||||
int type;
|
int type;
|
||||||
int vlan;
|
|
||||||
unsigned char mac[QEMUD_MAC_ADDRESS_LEN];
|
unsigned char mac[QEMUD_MAC_ADDRESS_LEN];
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
char ifname[NAME_MAX];
|
char ifname[BR_IFNAME_MAXLEN];
|
||||||
char script[PATH_MAX];
|
char script[PATH_MAX];
|
||||||
} tap;
|
} ethernet;
|
||||||
struct {
|
struct {
|
||||||
struct sockaddr_in listen;
|
char address[BR_INET_ADDR_MAXLEN];
|
||||||
int port;
|
int port;
|
||||||
} server;
|
} socket; /* any of NET_CLIENT or NET_SERVER or NET_MCAST */
|
||||||
struct {
|
|
||||||
struct sockaddr_in connect;
|
|
||||||
int port;
|
|
||||||
} client;
|
|
||||||
struct {
|
|
||||||
struct sockaddr_in group;
|
|
||||||
int port;
|
|
||||||
} mcast;
|
|
||||||
struct {
|
|
||||||
char vlan[PATH_MAX];
|
|
||||||
} vde;
|
|
||||||
struct {
|
struct {
|
||||||
char name[QEMUD_MAX_NAME_LEN];
|
char name[QEMUD_MAX_NAME_LEN];
|
||||||
char tapifname[BR_IFNAME_MAXLEN];
|
char ifname[BR_IFNAME_MAXLEN];
|
||||||
} network;
|
} network;
|
||||||
|
struct {
|
||||||
|
char brname[BR_IFNAME_MAXLEN];
|
||||||
|
char ifname[BR_IFNAME_MAXLEN];
|
||||||
|
} bridge;
|
||||||
} dst;
|
} dst;
|
||||||
|
|
||||||
struct qemud_vm_net_def *next;
|
struct qemud_vm_net_def *next;
|
||||||
|
@ -249,6 +241,9 @@ struct qemud_network_def {
|
||||||
int disableSTP;
|
int disableSTP;
|
||||||
int forwardDelay;
|
int forwardDelay;
|
||||||
|
|
||||||
|
int forward;
|
||||||
|
char forwardDev[BR_IFNAME_MAXLEN];
|
||||||
|
|
||||||
char ipAddress[BR_INET_ADDR_MAXLEN];
|
char ipAddress[BR_INET_ADDR_MAXLEN];
|
||||||
char netmask[BR_INET_ADDR_MAXLEN];
|
char netmask[BR_INET_ADDR_MAXLEN];
|
||||||
|
|
||||||
|
|
|
@ -532,20 +532,17 @@ iptablesInput(iptablesContext *ctx,
|
||||||
int tcp)
|
int tcp)
|
||||||
{
|
{
|
||||||
char portstr[32];
|
char portstr[32];
|
||||||
int ret;
|
|
||||||
|
|
||||||
snprintf(portstr, sizeof(portstr), "%d", port);
|
snprintf(portstr, sizeof(portstr), "%d", port);
|
||||||
portstr[sizeof(portstr) - 1] = '\0';
|
portstr[sizeof(portstr) - 1] = '\0';
|
||||||
|
|
||||||
ret = iptablesAddRemoveRule(ctx->input_filter,
|
return iptablesAddRemoveRule(ctx->input_filter,
|
||||||
action,
|
action,
|
||||||
"--in-interface", iface,
|
"--in-interface", iface,
|
||||||
"--protocol", tcp ? "tcp" : "udp",
|
"--protocol", tcp ? "tcp" : "udp",
|
||||||
"--destination-port", portstr,
|
"--destination-port", portstr,
|
||||||
"--jump", "ACCEPT",
|
"--jump", "ACCEPT",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -583,61 +580,97 @@ iptablesRemoveUdpInput(iptablesContext *ctx,
|
||||||
static int
|
static int
|
||||||
iptablesPhysdevForward(iptablesContext *ctx,
|
iptablesPhysdevForward(iptablesContext *ctx,
|
||||||
const char *iface,
|
const char *iface,
|
||||||
|
const char *target,
|
||||||
int action)
|
int action)
|
||||||
{
|
{
|
||||||
|
if (target && target[0]) {
|
||||||
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
|
action,
|
||||||
|
"--match", "physdev",
|
||||||
|
"--physdev-in", iface,
|
||||||
|
"--out", target,
|
||||||
|
"--jump", "ACCEPT",
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
return iptablesAddRemoveRule(ctx->forward_filter,
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
action,
|
action,
|
||||||
"--match", "physdev",
|
"--match", "physdev",
|
||||||
"--physdev-in", iface,
|
"--physdev-in", iface,
|
||||||
"--jump", "ACCEPT",
|
"--jump", "ACCEPT",
|
||||||
NULL);
|
NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iptablesAddPhysdevForward(iptablesContext *ctx,
|
iptablesAddPhysdevForward(iptablesContext *ctx,
|
||||||
const char *iface)
|
const char *iface,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
return iptablesPhysdevForward(ctx, iface, ADD);
|
return iptablesPhysdevForward(ctx, iface, target, ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iptablesRemovePhysdevForward(iptablesContext *ctx,
|
iptablesRemovePhysdevForward(iptablesContext *ctx,
|
||||||
const char *iface)
|
const char *iface,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
return iptablesPhysdevForward(ctx, iface, REMOVE);
|
return iptablesPhysdevForward(ctx, iface, target, REMOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iptablesInterfaceForward(iptablesContext *ctx,
|
iptablesInterfaceForward(iptablesContext *ctx,
|
||||||
const char *iface,
|
const char *iface,
|
||||||
|
const char *target,
|
||||||
int action)
|
int action)
|
||||||
{
|
{
|
||||||
|
if (target && target[0]) {
|
||||||
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
|
action,
|
||||||
|
"--in-interface", iface,
|
||||||
|
"--out-interface", target,
|
||||||
|
"--jump", "ACCEPT",
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
return iptablesAddRemoveRule(ctx->forward_filter,
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
action,
|
action,
|
||||||
"--in-interface", iface,
|
"--in-interface", iface,
|
||||||
"--jump", "ACCEPT",
|
"--jump", "ACCEPT",
|
||||||
NULL);
|
NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iptablesAddInterfaceForward(iptablesContext *ctx,
|
iptablesAddInterfaceForward(iptablesContext *ctx,
|
||||||
const char *iface)
|
const char *iface,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
return iptablesInterfaceForward(ctx, iface, ADD);
|
return iptablesInterfaceForward(ctx, iface, target, ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iptablesRemoveInterfaceForward(iptablesContext *ctx,
|
iptablesRemoveInterfaceForward(iptablesContext *ctx,
|
||||||
const char *iface)
|
const char *iface,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
return iptablesInterfaceForward(ctx, iface, REMOVE);
|
return iptablesInterfaceForward(ctx, iface, target, REMOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iptablesStateForward(iptablesContext *ctx,
|
iptablesStateForward(iptablesContext *ctx,
|
||||||
const char *iface,
|
const char *iface,
|
||||||
|
const char *target,
|
||||||
int action)
|
int action)
|
||||||
{
|
{
|
||||||
|
if (target && target[0]) {
|
||||||
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
|
action,
|
||||||
|
"--in-interface", target,
|
||||||
|
"--out-interface", iface,
|
||||||
|
"--match", "state",
|
||||||
|
"--state", "ESTABLISHED,RELATED",
|
||||||
|
"--jump", "ACCEPT",
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
return iptablesAddRemoveRule(ctx->forward_filter,
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
action,
|
action,
|
||||||
"--out-interface", iface,
|
"--out-interface", iface,
|
||||||
|
@ -645,44 +678,60 @@ iptablesStateForward(iptablesContext *ctx,
|
||||||
"--state", "ESTABLISHED,RELATED",
|
"--state", "ESTABLISHED,RELATED",
|
||||||
"--jump", "ACCEPT",
|
"--jump", "ACCEPT",
|
||||||
NULL);
|
NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iptablesAddStateForward(iptablesContext *ctx,
|
iptablesAddStateForward(iptablesContext *ctx,
|
||||||
const char *iface)
|
const char *iface,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
return iptablesStateForward(ctx, iface, ADD);
|
return iptablesStateForward(ctx, iface, target, ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iptablesRemoveStateForward(iptablesContext *ctx,
|
iptablesRemoveStateForward(iptablesContext *ctx,
|
||||||
const char *iface)
|
const char *iface,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
return iptablesStateForward(ctx, iface, REMOVE);
|
return iptablesStateForward(ctx, iface, target, REMOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iptablesNonBridgedMasq(iptablesContext *ctx,
|
iptablesNonBridgedMasq(iptablesContext *ctx,
|
||||||
|
const char *target,
|
||||||
int action)
|
int action)
|
||||||
{
|
{
|
||||||
|
if (target && target[0]) {
|
||||||
|
return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||||
|
action,
|
||||||
|
"--out-interface", target,
|
||||||
|
"--match", "physdev",
|
||||||
|
"!", "--physdev-is-bridged",
|
||||||
|
"--jump", "MASQUERADE",
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
return iptablesAddRemoveRule(ctx->nat_postrouting,
|
return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||||
action,
|
action,
|
||||||
"--match", "physdev",
|
"--match", "physdev",
|
||||||
"!", "--physdev-is-bridged",
|
"!", "--physdev-is-bridged",
|
||||||
"--jump", "MASQUERADE",
|
"--jump", "MASQUERADE",
|
||||||
NULL);
|
NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iptablesAddNonBridgedMasq(iptablesContext *ctx)
|
iptablesAddNonBridgedMasq(iptablesContext *ctx,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
return iptablesNonBridgedMasq(ctx, ADD);
|
return iptablesNonBridgedMasq(ctx, target, ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iptablesRemoveNonBridgedMasq(iptablesContext *ctx)
|
iptablesRemoveNonBridgedMasq(iptablesContext *ctx,
|
||||||
|
const char *target)
|
||||||
{
|
{
|
||||||
return iptablesNonBridgedMasq(ctx, REMOVE);
|
return iptablesNonBridgedMasq(ctx, target, REMOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -42,22 +42,30 @@ int iptablesRemoveUdpInput (iptablesContext *ctx,
|
||||||
int port);
|
int port);
|
||||||
|
|
||||||
int iptablesAddPhysdevForward (iptablesContext *ctx,
|
int iptablesAddPhysdevForward (iptablesContext *ctx,
|
||||||
const char *iface);
|
const char *iface,
|
||||||
|
const char *target);
|
||||||
int iptablesRemovePhysdevForward (iptablesContext *ctx,
|
int iptablesRemovePhysdevForward (iptablesContext *ctx,
|
||||||
const char *iface);
|
const char *iface,
|
||||||
|
const char *target);
|
||||||
|
|
||||||
int iptablesAddInterfaceForward (iptablesContext *ctx,
|
int iptablesAddInterfaceForward (iptablesContext *ctx,
|
||||||
const char *iface);
|
const char *iface,
|
||||||
|
const char *target);
|
||||||
int iptablesRemoveInterfaceForward (iptablesContext *ctx,
|
int iptablesRemoveInterfaceForward (iptablesContext *ctx,
|
||||||
const char *iface);
|
const char *iface,
|
||||||
|
const char *target);
|
||||||
|
|
||||||
int iptablesAddStateForward (iptablesContext *ctx,
|
int iptablesAddStateForward (iptablesContext *ctx,
|
||||||
const char *iface);
|
const char *iface,
|
||||||
|
const char *target);
|
||||||
int iptablesRemoveStateForward (iptablesContext *ctx,
|
int iptablesRemoveStateForward (iptablesContext *ctx,
|
||||||
const char *iface);
|
const char *iface,
|
||||||
|
const char *target);
|
||||||
|
|
||||||
int iptablesAddNonBridgedMasq (iptablesContext *ctx);
|
int iptablesAddNonBridgedMasq (iptablesContext *ctx,
|
||||||
int iptablesRemoveNonBridgedMasq (iptablesContext *ctx);
|
const char *target);
|
||||||
|
int iptablesRemoveNonBridgedMasq (iptablesContext *ctx,
|
||||||
|
const char *target);
|
||||||
|
|
||||||
#endif /* __QEMUD_IPTABLES_H__ */
|
#endif /* __QEMUD_IPTABLES_H__ */
|
||||||
|
|
||||||
|
|
|
@ -1032,7 +1032,18 @@ static void
|
||||||
qemudNetworkIfaceDisconnect(struct qemud_server *server,
|
qemudNetworkIfaceDisconnect(struct qemud_server *server,
|
||||||
struct qemud_vm *vm ATTRIBUTE_UNUSED,
|
struct qemud_vm *vm ATTRIBUTE_UNUSED,
|
||||||
struct qemud_vm_net_def *net) {
|
struct qemud_vm_net_def *net) {
|
||||||
iptablesRemovePhysdevForward(server->iptables, net->dst.network.tapifname);
|
struct qemud_network *network;
|
||||||
|
if (net->type != QEMUD_NET_NETWORK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(network = qemudFindNetworkByName(server, net->dst.network.name))) {
|
||||||
|
return;
|
||||||
|
} else if (network->bridge[0] == '\0') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (network->def->forward)
|
||||||
|
iptablesRemovePhysdevForward(server->iptables, net->dst.network.ifname, network->def->forwardDev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
|
int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
|
||||||
|
@ -1105,7 +1116,7 @@ qemudBuildDnsmasqArgv(struct qemud_server *server,
|
||||||
struct qemud_network *network,
|
struct qemud_network *network,
|
||||||
char ***argv) {
|
char ***argv) {
|
||||||
int i, len;
|
int i, len;
|
||||||
char buf[BR_INET_ADDR_MAXLEN * 2];
|
char buf[PATH_MAX];
|
||||||
struct qemud_dhcp_range_def *range;
|
struct qemud_dhcp_range_def *range;
|
||||||
|
|
||||||
len =
|
len =
|
||||||
|
@ -1114,8 +1125,10 @@ qemudBuildDnsmasqArgv(struct qemud_server *server,
|
||||||
1 + /* --bind-interfaces */
|
1 + /* --bind-interfaces */
|
||||||
2 + /* --pid-file "" */
|
2 + /* --pid-file "" */
|
||||||
2 + /* --conf-file "" */
|
2 + /* --conf-file "" */
|
||||||
|
/*2 + *//* --interface virbr0 */
|
||||||
2 + /* --except-interface lo */
|
2 + /* --except-interface lo */
|
||||||
2 + /* --listen-address 10.0.0.1 */
|
2 + /* --listen-address 10.0.0.1 */
|
||||||
|
1 + /* --dhcp-leasefile=path */
|
||||||
(2 * network->def->nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
|
(2 * network->def->nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
|
||||||
1; /* NULL */
|
1; /* NULL */
|
||||||
|
|
||||||
|
@ -1142,11 +1155,29 @@ qemudBuildDnsmasqArgv(struct qemud_server *server,
|
||||||
APPEND_ARG(*argv, i++, "--conf-file");
|
APPEND_ARG(*argv, i++, "--conf-file");
|
||||||
APPEND_ARG(*argv, i++, "");
|
APPEND_ARG(*argv, i++, "");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX does not actually work, due to some kind of
|
||||||
|
* race condition setting up ipv6 addresses on the
|
||||||
|
* interface. A sleep(10) makes it work, but that's
|
||||||
|
* clearly not practical
|
||||||
|
*
|
||||||
|
* APPEND_ARG(*argv, i++, "--interface");
|
||||||
|
* APPEND_ARG(*argv, i++, network->def->bridge);
|
||||||
|
*/
|
||||||
|
APPEND_ARG(*argv, i++, "--listen-address");
|
||||||
|
APPEND_ARG(*argv, i++, network->def->ipAddress);
|
||||||
|
|
||||||
APPEND_ARG(*argv, i++, "--except-interface");
|
APPEND_ARG(*argv, i++, "--except-interface");
|
||||||
APPEND_ARG(*argv, i++, "lo");
|
APPEND_ARG(*argv, i++, "lo");
|
||||||
|
|
||||||
APPEND_ARG(*argv, i++, "--listen-address");
|
/*
|
||||||
APPEND_ARG(*argv, i++, network->def->ipAddress);
|
* NB, dnsmasq command line arg bug means we need to
|
||||||
|
* use a single arg '--dhcp-leasefile=path' rather than
|
||||||
|
* two separate args in '--dhcp-leasefile path' style
|
||||||
|
*/
|
||||||
|
snprintf(buf, sizeof(buf), "--dhcp-leasefile=%s/lib/libvirt/dhcp-%s.leases",
|
||||||
|
LOCAL_STATE_DIR, network->def->name);
|
||||||
|
APPEND_ARG(*argv, i++, buf);
|
||||||
|
|
||||||
range = network->def->ranges;
|
range = network->def->ranges;
|
||||||
while (range) {
|
while (range) {
|
||||||
|
@ -1211,7 +1242,7 @@ qemudAddIptablesRules(struct qemud_server *server,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allow bridging from the bridge interface itself */
|
/* allow bridging from the bridge interface itself */
|
||||||
if ((err = iptablesAddPhysdevForward(server->iptables, network->bridge))) {
|
if ((err = iptablesAddPhysdevForward(server->iptables, network->bridge, network->def->forwardDev))) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"failed to add iptables rule to allow bridging from '%s' : %s\n",
|
"failed to add iptables rule to allow bridging from '%s' : %s\n",
|
||||||
network->bridge, strerror(err));
|
network->bridge, strerror(err));
|
||||||
|
@ -1219,7 +1250,7 @@ qemudAddIptablesRules(struct qemud_server *server,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allow forwarding packets from the bridge interface */
|
/* allow forwarding packets from the bridge interface */
|
||||||
if ((err = iptablesAddInterfaceForward(server->iptables, network->bridge))) {
|
if ((err = iptablesAddInterfaceForward(server->iptables, network->bridge, network->def->forwardDev))) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"failed to add iptables rule to allow forwarding from '%s' : %s\n",
|
"failed to add iptables rule to allow forwarding from '%s' : %s\n",
|
||||||
network->bridge, strerror(err));
|
network->bridge, strerror(err));
|
||||||
|
@ -1227,7 +1258,7 @@ qemudAddIptablesRules(struct qemud_server *server,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allow forwarding packets to the bridge interface if they are part of an existing connection */
|
/* allow forwarding packets to the bridge interface if they are part of an existing connection */
|
||||||
if ((err = iptablesAddStateForward(server->iptables, network->bridge))) {
|
if ((err = iptablesAddStateForward(server->iptables, network->bridge, network->def->forwardDev))) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"failed to add iptables rule to allow forwarding to '%s' : %s\n",
|
"failed to add iptables rule to allow forwarding to '%s' : %s\n",
|
||||||
network->bridge, strerror(err));
|
network->bridge, strerror(err));
|
||||||
|
@ -1235,7 +1266,7 @@ qemudAddIptablesRules(struct qemud_server *server,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable masquerading */
|
/* enable masquerading */
|
||||||
if ((err = iptablesAddNonBridgedMasq(server->iptables))) {
|
if ((err = iptablesAddNonBridgedMasq(server->iptables, network->def->forwardDev))) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"failed to add iptables rule to enable masquerading : %s\n",
|
"failed to add iptables rule to enable masquerading : %s\n",
|
||||||
strerror(err));
|
strerror(err));
|
||||||
|
@ -1281,13 +1312,13 @@ qemudAddIptablesRules(struct qemud_server *server,
|
||||||
err6:
|
err6:
|
||||||
iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
|
iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
|
||||||
err5:
|
err5:
|
||||||
iptablesRemoveNonBridgedMasq(server->iptables);
|
iptablesRemoveNonBridgedMasq(server->iptables, network->def->forwardDev);
|
||||||
err4:
|
err4:
|
||||||
iptablesRemoveStateForward(server->iptables, network->bridge);
|
iptablesRemoveStateForward(server->iptables, network->bridge, network->def->forwardDev);
|
||||||
err3:
|
err3:
|
||||||
iptablesRemoveInterfaceForward(server->iptables, network->bridge);
|
iptablesRemoveInterfaceForward(server->iptables, network->bridge, network->def->forwardDev);
|
||||||
err2:
|
err2:
|
||||||
iptablesRemovePhysdevForward(server->iptables, network->bridge);
|
iptablesRemovePhysdevForward(server->iptables, network->bridge, network->def->forwardDev);
|
||||||
err1:
|
err1:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1295,14 +1326,16 @@ qemudAddIptablesRules(struct qemud_server *server,
|
||||||
static void
|
static void
|
||||||
qemudRemoveIptablesRules(struct qemud_server *server,
|
qemudRemoveIptablesRules(struct qemud_server *server,
|
||||||
struct qemud_network *network) {
|
struct qemud_network *network) {
|
||||||
|
if (network->def->forward) {
|
||||||
iptablesRemoveUdpInput(server->iptables, network->bridge, 53);
|
iptablesRemoveUdpInput(server->iptables, network->bridge, 53);
|
||||||
iptablesRemoveTcpInput(server->iptables, network->bridge, 53);
|
iptablesRemoveTcpInput(server->iptables, network->bridge, 53);
|
||||||
iptablesRemoveUdpInput(server->iptables, network->bridge, 67);
|
iptablesRemoveUdpInput(server->iptables, network->bridge, 67);
|
||||||
iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
|
iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
|
||||||
iptablesRemoveNonBridgedMasq(server->iptables);
|
iptablesRemoveNonBridgedMasq(server->iptables, network->def->forwardDev);
|
||||||
iptablesRemoveStateForward(server->iptables, network->bridge);
|
iptablesRemoveStateForward(server->iptables, network->bridge, network->def->forwardDev);
|
||||||
iptablesRemoveInterfaceForward(server->iptables, network->bridge);
|
iptablesRemoveInterfaceForward(server->iptables, network->bridge, network->def->forwardDev);
|
||||||
iptablesRemovePhysdevForward(server->iptables, network->bridge);
|
iptablesRemovePhysdevForward(server->iptables, network->bridge, network->def->forwardDev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1379,10 +1412,12 @@ int qemudStartNetworkDaemon(struct qemud_server *server,
|
||||||
goto err_delbr;
|
goto err_delbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qemudAddIptablesRules(server, network))
|
if (network->def->forward &&
|
||||||
|
!qemudAddIptablesRules(server, network))
|
||||||
goto err_delbr1;
|
goto err_delbr1;
|
||||||
|
|
||||||
if (!qemudEnableIpForwarding()) {
|
if (network->def->forward &&
|
||||||
|
!qemudEnableIpForwarding()) {
|
||||||
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
"failed to enable IP forwarding : %s\n", strerror(err));
|
"failed to enable IP forwarding : %s\n", strerror(err));
|
||||||
goto err_delbr2;
|
goto err_delbr2;
|
||||||
|
|
Loading…
Reference in New Issue