mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-25 22:15:20 +00:00
Support multiple IP addresses on one network in bridge_driver.c
This patch reorganizes the code in bridge_driver.c to account for the concept of a single network with multiple IP addresses, without adding in the extra variable of IPv6. A small bit of code has been temporarily added that checks all given addresses to verify they are IPv4 - this will be removed when full IPv6 support is turned on.
This commit is contained in:
parent
a950dd2a31
commit
ad48dfa15c
@ -521,20 +521,25 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dhcpStartDhcpDaemon(virNetworkObjPtr network,
|
networkStartDhcpDaemon(virNetworkObjPtr network)
|
||||||
virNetworkIpDefPtr ipdef)
|
|
||||||
{
|
{
|
||||||
virCommandPtr cmd = NULL;
|
virCommandPtr cmd = NULL;
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
int ret = -1, err;
|
int ret = -1, err, ii;
|
||||||
|
virNetworkIpDefPtr ipdef;
|
||||||
|
|
||||||
network->dnsmasqPid = -1;
|
network->dnsmasqPid = -1;
|
||||||
|
|
||||||
if (!VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
|
/* Look for first IPv4 address that has dhcp defined. */
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
/* We support dhcp config on 1 IPv4 interface only. */
|
||||||
"%s", _("cannot start dhcp daemon without IPv4 address for server"));
|
for (ii = 0;
|
||||||
goto cleanup;
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
||||||
|
ii++) {
|
||||||
|
if (ipdef->nranges || ipdef->nhosts)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (!ipdef)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if ((err = virFileMakePath(NETWORK_PID_DIR)) != 0) {
|
if ((err = virFileMakePath(NETWORK_PID_DIR)) != 0) {
|
||||||
virReportSystemError(err,
|
virReportSystemError(err,
|
||||||
@ -583,8 +588,8 @@ cleanup:
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
||||||
virNetworkObjPtr network,
|
virNetworkObjPtr network,
|
||||||
virNetworkIpDefPtr ipdef)
|
virNetworkIpDefPtr ipdef)
|
||||||
{
|
{
|
||||||
int prefix = virNetworkIpDefPrefix(ipdef);
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
|
||||||
@ -607,7 +612,9 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
goto masqerr1;
|
goto masqerr1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 (iptablesAddForwardAllowRelatedIn(driver->iptables,
|
if (iptablesAddForwardAllowRelatedIn(driver->iptables,
|
||||||
&ipdef->address,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
@ -708,10 +715,48 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
networkRemoveMasqueradingIptablesRules(struct network_driver *driver,
|
||||||
|
virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
|
||||||
|
if (prefix >= 0) {
|
||||||
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||||
|
&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->forwardDev,
|
||||||
|
"tcp");
|
||||||
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||||
|
&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->forwardDev,
|
||||||
|
"udp");
|
||||||
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||||
|
&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->forwardDev,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
||||||
|
&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
network->def->forwardDev);
|
||||||
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
||||||
|
&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
network->def->forwardDev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
networkAddRoutingIptablesRules(struct network_driver *driver,
|
networkAddRoutingIptablesRules(struct network_driver *driver,
|
||||||
virNetworkObjPtr network,
|
virNetworkObjPtr network,
|
||||||
virNetworkIpDefPtr ipdef) {
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
int prefix = virNetworkIpDefPrefix(ipdef);
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
|
||||||
if (prefix < 0) {
|
if (prefix < 0) {
|
||||||
@ -747,23 +792,56 @@ networkAddRoutingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
routeerr2:
|
||||||
routeerr2:
|
|
||||||
iptablesRemoveForwardAllowOut(driver->iptables,
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
||||||
&ipdef->address,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev);
|
network->def->forwardDev);
|
||||||
routeerr1:
|
routeerr1:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
networkRemoveRoutingIptablesRules(struct network_driver *driver,
|
||||||
|
virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
|
||||||
|
if (prefix >= 0) {
|
||||||
|
iptablesRemoveForwardAllowIn(driver->iptables,
|
||||||
|
&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
network->def->forwardDev);
|
||||||
|
|
||||||
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
||||||
|
&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
network->def->forwardDev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
networkAddIptablesRules(struct network_driver *driver,
|
networkAddGeneralIptablesRules(struct network_driver *driver,
|
||||||
virNetworkObjPtr network,
|
virNetworkObjPtr network)
|
||||||
virNetworkIpDefPtr ipdef) {
|
{
|
||||||
|
int ii;
|
||||||
|
virNetworkIpDefPtr ipv4def;
|
||||||
|
|
||||||
|
/* First look for first IPv4 address that has dhcp or tftpboot defined. */
|
||||||
|
/* We support dhcp config on 1 IPv4 interface only. */
|
||||||
|
for (ii = 0;
|
||||||
|
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
||||||
|
ii++) {
|
||||||
|
if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* allow DHCP requests through to dnsmasq */
|
/* allow DHCP requests through to dnsmasq */
|
||||||
|
|
||||||
if (iptablesAddTcpInput(driver->iptables, network->def->bridge, 67) < 0) {
|
if (iptablesAddTcpInput(driver->iptables, network->def->bridge, 67) < 0) {
|
||||||
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
||||||
@ -778,6 +856,20 @@ networkAddIptablesRules(struct network_driver *driver,
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we are doing local DHCP service on this network, attempt to
|
||||||
|
* add a rule that will fixup the checksum of DHCP response
|
||||||
|
* packets back to the guests (but report failure without
|
||||||
|
* aborting, since not all iptables implementations support it).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ipv4def && (ipv4def->nranges || ipv4def->nhosts) &&
|
||||||
|
(iptablesAddOutputFixUdpChecksum(driver->iptables,
|
||||||
|
network->def->bridge, 68) < 0)) {
|
||||||
|
VIR_WARN("Could not add rule to fixup DHCP response checksums "
|
||||||
|
"on network '%s'.", network->def->name);
|
||||||
|
VIR_WARN0("May need to update iptables package & kernel to support CHECKSUM rule.");
|
||||||
|
}
|
||||||
|
|
||||||
/* allow DNS requests through to dnsmasq */
|
/* allow DNS requests through to dnsmasq */
|
||||||
if (iptablesAddTcpInput(driver->iptables, network->def->bridge, 53) < 0) {
|
if (iptablesAddTcpInput(driver->iptables, network->def->bridge, 53) < 0) {
|
||||||
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
@ -793,30 +885,29 @@ networkAddIptablesRules(struct network_driver *driver,
|
|||||||
goto err4;
|
goto err4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allow TFTP requests through to dnsmasq */
|
/* allow TFTP requests through to dnsmasq if necessary */
|
||||||
if (ipdef && ipdef->tftproot &&
|
if (ipv4def && ipv4def->tftproot &&
|
||||||
iptablesAddUdpInput(driver->iptables, network->def->bridge, 69) < 0) {
|
iptablesAddUdpInput(driver->iptables, network->def->bridge, 69) < 0) {
|
||||||
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("failed to add iptables rule to allow TFTP requests from '%s'"),
|
_("failed to add iptables rule to allow TFTP requests from '%s'"),
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
goto err4tftp;
|
goto err5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Catch all rules to block forwarding to/from bridges */
|
/* Catch all rules to block forwarding to/from bridges */
|
||||||
|
|
||||||
if (iptablesAddForwardRejectOut(driver->iptables, network->def->bridge) < 0) {
|
if (iptablesAddForwardRejectOut(driver->iptables, network->def->bridge) < 0) {
|
||||||
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("failed to add iptables rule to block outbound traffic from '%s'"),
|
_("failed to add iptables rule to block outbound traffic from '%s'"),
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
goto err5;
|
goto err6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iptablesAddForwardRejectIn(driver->iptables, network->def->bridge) < 0) {
|
if (iptablesAddForwardRejectIn(driver->iptables, network->def->bridge) < 0) {
|
||||||
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("failed to add iptables rule to block inbound traffic to '%s'"),
|
_("failed to add iptables rule to block inbound traffic to '%s'"),
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
goto err6;
|
goto err7;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow traffic between guests on the same bridge */
|
/* Allow traffic between guests on the same bridge */
|
||||||
@ -824,129 +915,139 @@ networkAddIptablesRules(struct network_driver *driver,
|
|||||||
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("failed to add iptables rule to allow cross bridge traffic on '%s'"),
|
_("failed to add iptables rule to allow cross bridge traffic on '%s'"),
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
goto err7;
|
goto err8;
|
||||||
}
|
|
||||||
|
|
||||||
if (ipdef) {
|
|
||||||
/* If masquerading is enabled, set up the rules*/
|
|
||||||
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT &&
|
|
||||||
networkAddMasqueradingIptablesRules(driver, network, ipdef) < 0)
|
|
||||||
goto err8;
|
|
||||||
/* else if routing is enabled, set up the rules*/
|
|
||||||
else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE &&
|
|
||||||
networkAddRoutingIptablesRules(driver, network, ipdef) < 0)
|
|
||||||
goto err8;
|
|
||||||
|
|
||||||
/* If we are doing local DHCP service on this network, attempt to
|
|
||||||
* add a rule that will fixup the checksum of DHCP response
|
|
||||||
* packets back to the guests (but report failure without
|
|
||||||
* aborting, since not all iptables implementations support it).
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (ipdef && (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET) ||
|
|
||||||
ipdef->nranges) &&
|
|
||||||
(iptablesAddOutputFixUdpChecksum(driver->iptables,
|
|
||||||
network->def->bridge, 68) < 0)) {
|
|
||||||
VIR_WARN("Could not add rule to fixup DHCP response checksums "
|
|
||||||
"on network '%s'.", network->def->name);
|
|
||||||
VIR_WARN0("May need to update iptables package & kernel to support CHECKSUM rule.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err8:
|
/* unwind in reverse order from the point of failure */
|
||||||
iptablesRemoveForwardAllowCross(driver->iptables,
|
err8:
|
||||||
network->def->bridge);
|
iptablesRemoveForwardRejectIn(driver->iptables, network->def->bridge);
|
||||||
err7:
|
err7:
|
||||||
iptablesRemoveForwardRejectIn(driver->iptables,
|
iptablesRemoveForwardRejectOut(driver->iptables, network->def->bridge);
|
||||||
network->def->bridge);
|
err6:
|
||||||
err6:
|
if (ipv4def && ipv4def->tftproot) {
|
||||||
iptablesRemoveForwardRejectOut(driver->iptables,
|
|
||||||
network->def->bridge);
|
|
||||||
err5:
|
|
||||||
if (ipdef && ipdef->tftproot) {
|
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
||||||
}
|
}
|
||||||
err4tftp:
|
err5:
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
|
||||||
err4:
|
err4:
|
||||||
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
|
||||||
err3:
|
err3:
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67);
|
||||||
err2:
|
err2:
|
||||||
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67);
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67);
|
||||||
err1:
|
err1:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
networkRemoveIptablesRules(struct network_driver *driver,
|
networkRemoveGeneralIptablesRules(struct network_driver *driver,
|
||||||
virNetworkObjPtr network,
|
virNetworkObjPtr network)
|
||||||
virNetworkIpDefPtr ipdef) {
|
{
|
||||||
|
int ii;
|
||||||
|
virNetworkIpDefPtr ipv4def;
|
||||||
|
|
||||||
if (ipdef && (VIR_SOCKET_HAS_ADDR(&ipdef->address) ||
|
for (ii = 0;
|
||||||
ipdef->nranges)) {
|
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
||||||
iptablesRemoveOutputFixUdpChecksum(driver->iptables,
|
ii++) {
|
||||||
network->def->bridge, 68);
|
if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (ipdef && network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
|
|
||||||
int prefix = virNetworkIpDefPrefix(ipdef);
|
|
||||||
|
|
||||||
if (prefix < 0) {
|
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Invalid prefix or netmask for '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
|
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
||||||
&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->forwardDev,
|
|
||||||
"tcp");
|
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
||||||
&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->forwardDev,
|
|
||||||
"udp");
|
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
||||||
&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->forwardDev,
|
|
||||||
NULL);
|
|
||||||
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
|
||||||
&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
network->def->forwardDev);
|
|
||||||
} else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
|
|
||||||
iptablesRemoveForwardAllowIn(driver->iptables,
|
|
||||||
&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
network->def->forwardDev);
|
|
||||||
}
|
|
||||||
|
|
||||||
iptablesRemoveForwardAllowOut(driver->iptables,
|
|
||||||
&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
network->def->forwardDev);
|
|
||||||
}
|
|
||||||
error:
|
|
||||||
iptablesRemoveForwardAllowCross(driver->iptables, network->def->bridge);
|
iptablesRemoveForwardAllowCross(driver->iptables, network->def->bridge);
|
||||||
iptablesRemoveForwardRejectIn(driver->iptables, network->def->bridge);
|
iptablesRemoveForwardRejectIn(driver->iptables, network->def->bridge);
|
||||||
iptablesRemoveForwardRejectOut(driver->iptables, network->def->bridge);
|
iptablesRemoveForwardRejectOut(driver->iptables, network->def->bridge);
|
||||||
if (ipdef && ipdef->tftproot)
|
if (ipv4def && ipv4def->tftproot) {
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
||||||
|
}
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
|
||||||
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
|
||||||
|
if (ipv4def && (ipv4def->nranges || ipv4def->nhosts)) {
|
||||||
|
iptablesRemoveOutputFixUdpChecksum(driver->iptables,
|
||||||
|
network->def->bridge, 68);
|
||||||
|
}
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67);
|
||||||
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67);
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
networkAddIpSpecificIptablesRules(struct network_driver *driver,
|
||||||
|
virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT &&
|
||||||
|
networkAddMasqueradingIptablesRules(driver, network, ipdef) < 0)
|
||||||
|
return -1;
|
||||||
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE &&
|
||||||
|
networkAddRoutingIptablesRules(driver, network, ipdef) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
networkRemoveIpSpecificIptablesRules(struct network_driver *driver,
|
||||||
|
virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT)
|
||||||
|
networkRemoveMasqueradingIptablesRules(driver, network, ipdef);
|
||||||
|
else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE)
|
||||||
|
networkRemoveRoutingIptablesRules(driver, network, ipdef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add all rules for all ip addresses (and general rules) on a network */
|
||||||
|
static int
|
||||||
|
networkAddIptablesRules(struct network_driver *driver,
|
||||||
|
virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
int ii;
|
||||||
|
virNetworkIpDefPtr ipdef;
|
||||||
|
|
||||||
|
/* Add "once per network" rules */
|
||||||
|
if (networkAddGeneralIptablesRules(driver, network) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (ii = 0;
|
||||||
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
||||||
|
ii++) {
|
||||||
|
/* Add address-specific iptables rules */
|
||||||
|
if (networkAddIpSpecificIptablesRules(driver, network, ipdef) < 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* The final failed call to networkAddIpSpecificIptablesRules will
|
||||||
|
* have removed any rules it created, but we need to remove those
|
||||||
|
* added for previous IP addresses.
|
||||||
|
*/
|
||||||
|
while ((--ii >= 0) &&
|
||||||
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii))) {
|
||||||
|
networkRemoveIpSpecificIptablesRules(driver, network, ipdef);
|
||||||
|
}
|
||||||
|
networkRemoveGeneralIptablesRules(driver, network);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove all rules for all ip addresses (and general rules) on a network */
|
||||||
|
static void
|
||||||
|
networkRemoveIptablesRules(struct network_driver *driver,
|
||||||
|
virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
int ii;
|
||||||
|
virNetworkIpDefPtr ipdef;
|
||||||
|
|
||||||
|
for (ii = 0;
|
||||||
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
||||||
|
ii++) {
|
||||||
|
networkRemoveIpSpecificIptablesRules(driver, network, ipdef);
|
||||||
|
}
|
||||||
|
networkRemoveGeneralIptablesRules(driver, network);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
networkReloadIptablesRules(struct network_driver *driver)
|
networkReloadIptablesRules(struct network_driver *driver)
|
||||||
{
|
{
|
||||||
@ -956,22 +1057,12 @@ networkReloadIptablesRules(struct network_driver *driver)
|
|||||||
|
|
||||||
for (i = 0 ; i < driver->networks.count ; i++) {
|
for (i = 0 ; i < driver->networks.count ; i++) {
|
||||||
virNetworkObjLock(driver->networks.objs[i]);
|
virNetworkObjLock(driver->networks.objs[i]);
|
||||||
|
|
||||||
if (virNetworkObjIsActive(driver->networks.objs[i])) {
|
if (virNetworkObjIsActive(driver->networks.objs[i])) {
|
||||||
virNetworkIpDefPtr ipv4def;
|
networkRemoveIptablesRules(driver, driver->networks.objs[i]);
|
||||||
|
if (networkAddIptablesRules(driver, driver->networks.objs[i]) < 0) {
|
||||||
/* Find the one allowed IPv4 ip address in the definition */
|
/* failed to add but already logged */
|
||||||
/* Even if none is found, we still call the functions below */
|
}
|
||||||
ipv4def = virNetworkDefGetIpByIndex(driver->networks.objs[i]->def,
|
|
||||||
AF_INET, 0);
|
|
||||||
networkRemoveIptablesRules(driver, driver->networks.objs[i],
|
|
||||||
ipv4def);
|
|
||||||
if (networkAddIptablesRules(driver, driver->networks.objs[i],
|
|
||||||
ipv4def) < 0) {
|
|
||||||
/* failed to add but already logged */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virNetworkObjUnlock(driver->networks.objs[i]);
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1043,32 +1134,16 @@ cleanup:
|
|||||||
* other scenarios where we can ruin host network connectivity.
|
* other scenarios where we can ruin host network connectivity.
|
||||||
* XXX: Using a proper library is preferred over parsing /proc
|
* XXX: Using a proper library is preferred over parsing /proc
|
||||||
*/
|
*/
|
||||||
static int networkCheckRouteCollision(virNetworkObjPtr network,
|
static int
|
||||||
virNetworkIpDefPtr ipdef)
|
networkCheckRouteCollision(virNetworkObjPtr network)
|
||||||
{
|
{
|
||||||
int ret = -1, len;
|
int ret = 0, len;
|
||||||
unsigned int net_dest;
|
|
||||||
virSocketAddr netmask;
|
|
||||||
char *cur, *buf = NULL;
|
char *cur, *buf = NULL;
|
||||||
enum {MAX_ROUTE_SIZE = 1024*64};
|
enum {MAX_ROUTE_SIZE = 1024*64};
|
||||||
|
|
||||||
if (!VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
|
|
||||||
/* Only support collision check for IPv4 */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
|
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Failed to get netmask of '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
}
|
|
||||||
|
|
||||||
net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
|
|
||||||
netmask.data.inet4.sin_addr.s_addr);
|
|
||||||
|
|
||||||
/* Read whole routing table into memory */
|
/* Read whole routing table into memory */
|
||||||
if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
|
if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
|
||||||
goto error;
|
goto out;
|
||||||
|
|
||||||
/* Dropping the last character shouldn't hurt */
|
/* Dropping the last character shouldn't hurt */
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
@ -1087,7 +1162,8 @@ static int networkCheckRouteCollision(virNetworkObjPtr network,
|
|||||||
while (cur) {
|
while (cur) {
|
||||||
char iface[17], dest[128], mask[128];
|
char iface[17], dest[128], mask[128];
|
||||||
unsigned int addr_val, mask_val;
|
unsigned int addr_val, mask_val;
|
||||||
int num;
|
virNetworkIpDefPtr ipdef;
|
||||||
|
int num, ii;
|
||||||
|
|
||||||
/* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
|
/* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
|
||||||
char *nl = strchr(cur, '\n');
|
char *nl = strchr(cur, '\n');
|
||||||
@ -1116,28 +1192,71 @@ static int networkCheckRouteCollision(virNetworkObjPtr network,
|
|||||||
|
|
||||||
addr_val &= mask_val;
|
addr_val &= mask_val;
|
||||||
|
|
||||||
if ((net_dest == addr_val) &&
|
for (ii = 0;
|
||||||
(netmask.data.inet4.sin_addr.s_addr == mask_val)) {
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
ii++) {
|
||||||
_("Network is already in use by interface %s"),
|
|
||||||
iface);
|
unsigned int net_dest;
|
||||||
goto error;
|
virSocketAddr netmask;
|
||||||
|
|
||||||
|
if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
|
||||||
|
VIR_WARN("Failed to get netmask of '%s'",
|
||||||
|
network->def->bridge);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
|
||||||
|
netmask.data.inet4.sin_addr.s_addr);
|
||||||
|
|
||||||
|
if ((net_dest == addr_val) &&
|
||||||
|
(netmask.data.inet4.sin_addr.s_addr == mask_val)) {
|
||||||
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Network is already in use by interface %s"),
|
||||||
|
iface);
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ret = 0;
|
|
||||||
error:
|
|
||||||
VIR_FREE(buf);
|
VIR_FREE(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int networkStartNetworkDaemon(struct network_driver *driver,
|
static int
|
||||||
virNetworkObjPtr network)
|
networkAddAddrToBridge(struct network_driver *driver,
|
||||||
|
virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
{
|
{
|
||||||
int err;
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
virErrorPtr save_err;
|
|
||||||
virNetworkIpDefPtr ipv4def;
|
if (prefix < 0) {
|
||||||
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("bridge '%s' has an invalid netmask or IP address"),
|
||||||
|
network->def->bridge);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (brAddInetAddress(driver->brctl, network->def->bridge,
|
||||||
|
&ipdef->address, prefix) < 0) {
|
||||||
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot set IP address on bridge '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
networkStartNetworkDaemon(struct network_driver *driver,
|
||||||
|
virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
int ii, err;
|
||||||
|
bool v4present = false;
|
||||||
|
virErrorPtr save_err = NULL;
|
||||||
|
virNetworkIpDefPtr ipdef;
|
||||||
|
|
||||||
if (virNetworkObjIsActive(network)) {
|
if (virNetworkObjIsActive(network)) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -1145,13 +1264,11 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find the one allowed IPv4 ip address in the definition */
|
/* Check to see if any network IP collides with an existing route */
|
||||||
ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, 0);
|
if (networkCheckRouteCollision(network) < 0)
|
||||||
|
|
||||||
/* Check to see if network collides with an existing route */
|
|
||||||
if (ipv4def && networkCheckRouteCollision(network, ipv4def) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* Create and configure the bridge device */
|
||||||
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
|
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
|
||||||
virReportSystemError(err,
|
virReportSystemError(err,
|
||||||
_("cannot create bridge '%s'"),
|
_("cannot create bridge '%s'"),
|
||||||
@ -1159,15 +1276,13 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkDisableIPV6(network) < 0)
|
/* Set bridge options */
|
||||||
goto err_delbr;
|
|
||||||
|
|
||||||
if ((err = brSetForwardDelay(driver->brctl, network->def->bridge,
|
if ((err = brSetForwardDelay(driver->brctl, network->def->bridge,
|
||||||
network->def->delay))) {
|
network->def->delay))) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot set forward delay on bridge '%s'"),
|
_("cannot set forward delay on bridge '%s'"),
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
goto err_delbr;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = brSetEnableSTP(driver->brctl, network->def->bridge,
|
if ((err = brSetEnableSTP(driver->brctl, network->def->bridge,
|
||||||
@ -1175,90 +1290,95 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot set STP '%s' on bridge '%s'"),
|
_("cannot set STP '%s' on bridge '%s'"),
|
||||||
network->def->stp ? "on" : "off", network->def->bridge);
|
network->def->stp ? "on" : "off", network->def->bridge);
|
||||||
goto err_delbr;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ipv4def) {
|
/* Disable IPv6 on the bridge */
|
||||||
int prefix = virNetworkIpDefPrefix(ipv4def);
|
if (networkDisableIPV6(network) < 0)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
if (prefix < 0) {
|
/* Add "once per network" rules */
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
if (networkAddIptablesRules(driver, network) < 0)
|
||||||
_("bridge '%s' has an invalid netmask or IP address"),
|
goto err1;
|
||||||
network->def->bridge);
|
|
||||||
goto err_delbr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = brAddInetAddress(driver->brctl, network->def->bridge,
|
for (ii = 0;
|
||||||
&ipv4def->address, prefix))) {
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
ii++) {
|
||||||
_("cannot set IP address on bridge '%s'"),
|
if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET))
|
||||||
network->def->bridge);
|
v4present = true;
|
||||||
goto err_delbr;
|
|
||||||
|
/* Add the IP address/netmask to the bridge */
|
||||||
|
if (networkAddAddrToBridge(driver, network, ipdef) < 0) {
|
||||||
|
goto err2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bring up the bridge interface */
|
||||||
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
|
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
|
||||||
virReportSystemError(err,
|
virReportSystemError(err,
|
||||||
_("failed to bring the bridge '%s' up"),
|
_("failed to bring the bridge '%s' up"),
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
goto err_delbr;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ipv4def && networkAddIptablesRules(driver, network, ipv4def) < 0)
|
/* If forwardType != NONE, turn on global IP forwarding */
|
||||||
goto err_delbr1;
|
|
||||||
|
|
||||||
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
|
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
|
||||||
networkEnableIpForwarding() < 0) {
|
networkEnableIpForwarding() < 0) {
|
||||||
virReportSystemError(errno, "%s",
|
virReportSystemError(errno, "%s",
|
||||||
_("failed to enable IP forwarding"));
|
_("failed to enable IP forwarding"));
|
||||||
goto err_delbr2;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Start the dhcp daemon for the 1st (and only supported) ipv4
|
/* start dnsmasq if there are any IPv4 addresses */
|
||||||
* address.
|
if (v4present && networkStartDhcpDaemon(network) < 0)
|
||||||
*/
|
goto err3;
|
||||||
if (ipv4def && dhcpStartDhcpDaemon(network, ipv4def) < 0)
|
|
||||||
goto err_delbr2;
|
|
||||||
|
|
||||||
/* Persist the live configuration now we have bridge info */
|
/* Persist the live configuration now we have bridge info */
|
||||||
if (virNetworkSaveConfig(NETWORK_STATE_DIR, network->def) < 0) {
|
if (virNetworkSaveConfig(NETWORK_STATE_DIR, network->def) < 0) {
|
||||||
goto err_kill;
|
goto err4;
|
||||||
}
|
}
|
||||||
|
|
||||||
network->active = 1;
|
network->active = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_kill:
|
err4:
|
||||||
|
if (!save_err)
|
||||||
|
save_err = virSaveLastError();
|
||||||
|
|
||||||
if (network->dnsmasqPid > 0) {
|
if (network->dnsmasqPid > 0) {
|
||||||
kill(network->dnsmasqPid, SIGTERM);
|
kill(network->dnsmasqPid, SIGTERM);
|
||||||
network->dnsmasqPid = -1;
|
network->dnsmasqPid = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
err_delbr2:
|
err3:
|
||||||
save_err = virSaveLastError();
|
if (!save_err)
|
||||||
if (ipv4def)
|
save_err = virSaveLastError();
|
||||||
networkRemoveIptablesRules(driver, network, ipv4def);
|
|
||||||
if (save_err) {
|
|
||||||
virSetError(save_err);
|
|
||||||
virFreeError(save_err);
|
|
||||||
}
|
|
||||||
|
|
||||||
err_delbr1:
|
|
||||||
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
|
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
|
||||||
char ebuf[1024];
|
char ebuf[1024];
|
||||||
VIR_WARN("Failed to bring down bridge '%s' : %s",
|
VIR_WARN("Failed to bring down bridge '%s' : %s",
|
||||||
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
err_delbr:
|
err2:
|
||||||
|
if (!save_err)
|
||||||
|
save_err = virSaveLastError();
|
||||||
|
networkRemoveIptablesRules(driver, network);
|
||||||
|
|
||||||
|
err1:
|
||||||
|
if (!save_err)
|
||||||
|
save_err = virSaveLastError();
|
||||||
if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
|
if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
|
||||||
char ebuf[1024];
|
char ebuf[1024];
|
||||||
VIR_WARN("Failed to delete bridge '%s' : %s",
|
VIR_WARN("Failed to delete bridge '%s' : %s",
|
||||||
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (save_err) {
|
||||||
|
virSetError(save_err);
|
||||||
|
virFreeError(save_err);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1268,7 +1388,6 @@ static int networkShutdownNetworkDaemon(struct network_driver *driver,
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
char *stateFile;
|
char *stateFile;
|
||||||
virNetworkIpDefPtr ipv4def;
|
|
||||||
|
|
||||||
VIR_INFO(_("Shutting down network '%s'"), network->def->name);
|
VIR_INFO(_("Shutting down network '%s'"), network->def->name);
|
||||||
|
|
||||||
@ -1285,17 +1404,14 @@ static int networkShutdownNetworkDaemon(struct network_driver *driver,
|
|||||||
if (network->dnsmasqPid > 0)
|
if (network->dnsmasqPid > 0)
|
||||||
kill(network->dnsmasqPid, SIGTERM);
|
kill(network->dnsmasqPid, SIGTERM);
|
||||||
|
|
||||||
/* find the one allowed IPv4 ip address in the definition */
|
|
||||||
ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, 0);
|
|
||||||
if (ipv4def)
|
|
||||||
networkRemoveIptablesRules(driver, network, ipv4def);
|
|
||||||
|
|
||||||
char ebuf[1024];
|
char ebuf[1024];
|
||||||
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
|
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
|
||||||
VIR_WARN("Failed to bring down bridge '%s' : %s",
|
VIR_WARN("Failed to bring down bridge '%s' : %s",
|
||||||
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
networkRemoveIptablesRules(driver, network);
|
||||||
|
|
||||||
if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
|
if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
|
||||||
VIR_WARN("Failed to delete bridge '%s' : %s",
|
VIR_WARN("Failed to delete bridge '%s' : %s",
|
||||||
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
||||||
@ -1552,10 +1668,11 @@ cleanup:
|
|||||||
|
|
||||||
static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
|
static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
|
||||||
struct network_driver *driver = conn->networkPrivateData;
|
struct network_driver *driver = conn->networkPrivateData;
|
||||||
virNetworkIpDefPtr ipv4def;
|
virNetworkIpDefPtr ipdef, ipv4def = NULL;
|
||||||
virNetworkDefPtr def;
|
virNetworkDefPtr def;
|
||||||
virNetworkObjPtr network = NULL;
|
virNetworkObjPtr network = NULL;
|
||||||
virNetworkPtr ret = NULL;
|
virNetworkPtr ret = NULL;
|
||||||
|
int ii;
|
||||||
|
|
||||||
networkDriverLock(driver);
|
networkDriverLock(driver);
|
||||||
|
|
||||||
@ -1583,10 +1700,33 @@ static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we only support dhcp on one IPv4 address per defined network */
|
/* we only support dhcp on one IPv4 address per defined network, and currently
|
||||||
ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, 0);
|
* don't support IPv6.
|
||||||
|
*/
|
||||||
|
for (ii = 0;
|
||||||
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
||||||
|
ii++) {
|
||||||
|
if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
|
||||||
|
if (ipdef->nranges || ipdef->nhosts) {
|
||||||
|
if (ipv4def) {
|
||||||
|
networkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
"%s", _("Multiple dhcp sections found. dhcp is supported only for a single IPv4 address on each network"));
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
ipv4def = ipdef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* we currently only support IPv4 */
|
||||||
|
networkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unsupported address family '%s' (%d) in network definition"),
|
||||||
|
ipdef->family ? ipdef->family : "unspecified",
|
||||||
|
VIR_SOCKET_FAMILY(&ipdef->address));
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (ipv4def && ipv4def->nhosts > 0) {
|
}
|
||||||
|
}
|
||||||
|
if (ipv4def) {
|
||||||
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
||||||
if (dctx == NULL)
|
if (dctx == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -1609,7 +1749,7 @@ static int networkUndefine(virNetworkPtr net) {
|
|||||||
struct network_driver *driver = net->conn->networkPrivateData;
|
struct network_driver *driver = net->conn->networkPrivateData;
|
||||||
virNetworkObjPtr network;
|
virNetworkObjPtr network;
|
||||||
virNetworkIpDefPtr ipv4def;
|
virNetworkIpDefPtr ipv4def;
|
||||||
int ret = -1;
|
int ret = -1, ii;
|
||||||
|
|
||||||
networkDriverLock(driver);
|
networkDriverLock(driver);
|
||||||
|
|
||||||
@ -1631,10 +1771,14 @@ static int networkUndefine(virNetworkPtr net) {
|
|||||||
network) < 0)
|
network) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* find the one allowed IPv4 ip address in the definition */
|
/* we only support dhcp on one IPv4 address per defined network */
|
||||||
ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, 0);
|
for (ii = 0;
|
||||||
|
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
||||||
if (ipv4def && ipv4def->nhosts > 0) {
|
ii++) {
|
||||||
|
if (ipv4def->nranges || ipv4def->nhosts)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ipv4def) {
|
||||||
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
||||||
if (dctx == NULL)
|
if (dctx == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user