network: split setup of ipv4 and ipv6 top level chains

During startup libvirtd creates top level chains for both ipv4
and ipv6 protocols. If this fails for any reason then startup
of virtual networks is blocked.

The default virtual network, however, only requires use of ipv4
and some servers have ipv6 disabled so it is expected that ipv6
chain creation will fail. There could equally be servers with
no ipv4, only ipv6.

This patch thus makes error reporting a little more fine grained
so that it works more sensibly when either ipv4 or ipv6 is
disabled on the server. Only the protocols that are actually
used by the virtual network have errors reported.

Reviewed-by: Andrea Bolognani <abologna@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 686803a1a2e1e0641916b1c9e2c7e3910fe598d4)
This commit is contained in:
Daniel P. Berrangé 2019-03-18 16:49:32 +00:00
parent b990740b12
commit 095c450366
3 changed files with 33 additions and 17 deletions

View File

@ -35,10 +35,12 @@ VIR_LOG_INIT("network.bridge_driver_linux");
#define PROC_NET_ROUTE "/proc/net/route" #define PROC_NET_ROUTE "/proc/net/route"
static virErrorPtr errInit; static virErrorPtr errInitV4;
static virErrorPtr errInitV6;
void networkPreReloadFirewallRules(bool startup) void networkPreReloadFirewallRules(bool startup)
{ {
bool created = false;
int rc; int rc;
/* We create global rules upfront as we don't want /* We create global rules upfront as we don't want
@ -49,11 +51,21 @@ void networkPreReloadFirewallRules(bool startup)
* of starting the network though as that makes them * of starting the network though as that makes them
* more likely to be seen by a human * more likely to be seen by a human
*/ */
rc = iptablesSetupPrivateChains(); rc = iptablesSetupPrivateChains(VIR_FIREWALL_LAYER_IPV4);
if (rc < 0) { if (rc < 0) {
errInit = virSaveLastError(); errInitV4 = virSaveLastError();
virResetLastError(); virResetLastError();
} }
if (rc)
created = true;
rc = iptablesSetupPrivateChains(VIR_FIREWALL_LAYER_IPV6);
if (rc < 0) {
errInitV6 = virSaveLastError();
virResetLastError();
}
if (rc)
created = true;
/* /*
* If this is initial startup, and we just created the * If this is initial startup, and we just created the
@ -68,7 +80,7 @@ void networkPreReloadFirewallRules(bool startup)
* rules will be present. Thus we can safely just tell it * rules will be present. Thus we can safely just tell it
* to always delete from the builin chain * to always delete from the builin chain
*/ */
if (startup && rc == 1) if (startup && created)
iptablesSetDeletePrivate(false); iptablesSetDeletePrivate(false);
} }
@ -683,8 +695,18 @@ int networkAddFirewallRules(virNetworkDefPtr def)
virFirewallPtr fw = NULL; virFirewallPtr fw = NULL;
int ret = -1; int ret = -1;
if (errInit) { if (errInitV4 &&
virSetError(errInit); (virNetworkDefGetIPByIndex(def, AF_INET, 0) ||
virNetworkDefGetRouteByIndex(def, AF_INET, 0))) {
virSetError(errInitV4);
return -1;
}
if (errInitV6 &&
(virNetworkDefGetIPByIndex(def, AF_INET6, 0) ||
virNetworkDefGetRouteByIndex(def, AF_INET6, 0) ||
def->ipv6nogw)) {
virSetError(errInitV6);
return -1; return -1;
} }

View File

@ -127,7 +127,7 @@ iptablesPrivateChainCreate(virFirewallPtr fw,
int int
iptablesSetupPrivateChains(void) iptablesSetupPrivateChains(virFirewallLayer layer)
{ {
virFirewallPtr fw = NULL; virFirewallPtr fw = NULL;
int ret = -1; int ret = -1;
@ -143,17 +143,11 @@ iptablesSetupPrivateChains(void)
}; };
bool changed = false; bool changed = false;
iptablesGlobalChainData data[] = { iptablesGlobalChainData data[] = {
{ VIR_FIREWALL_LAYER_IPV4, "filter", { layer, "filter",
filter_chains, ARRAY_CARDINALITY(filter_chains), &changed }, filter_chains, ARRAY_CARDINALITY(filter_chains), &changed },
{ VIR_FIREWALL_LAYER_IPV4, "nat", { layer, "nat",
natmangle_chains, ARRAY_CARDINALITY(natmangle_chains), &changed }, natmangle_chains, ARRAY_CARDINALITY(natmangle_chains), &changed },
{ VIR_FIREWALL_LAYER_IPV4, "mangle", { layer, "mangle",
natmangle_chains, ARRAY_CARDINALITY(natmangle_chains), &changed },
{ VIR_FIREWALL_LAYER_IPV6, "filter",
filter_chains, ARRAY_CARDINALITY(filter_chains), &changed },
{ VIR_FIREWALL_LAYER_IPV6, "nat",
natmangle_chains, ARRAY_CARDINALITY(natmangle_chains), &changed },
{ VIR_FIREWALL_LAYER_IPV6, "mangle",
natmangle_chains, ARRAY_CARDINALITY(natmangle_chains), &changed }, natmangle_chains, ARRAY_CARDINALITY(natmangle_chains), &changed },
}; };
size_t i; size_t i;

View File

@ -24,7 +24,7 @@
# include "virsocketaddr.h" # include "virsocketaddr.h"
# include "virfirewall.h" # include "virfirewall.h"
int iptablesSetupPrivateChains (void); int iptablesSetupPrivateChains (virFirewallLayer layer);
void iptablesSetDeletePrivate (bool pvt); void iptablesSetDeletePrivate (bool pvt);