The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6037
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Fixes issue when using IP filtering with a statically assigned IP and a parent device that has no DHCP or IP address assigned.
From 05e2b336f05fdb8b058bd43667322a56de227164 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 1 Aug 2019 21:43:25 +0100 Subject: [PATCH 1/2] device/nic/bridged: Fixes issue with non-dhcp, non-addressed parent device IP filtering wasn't working on a parent bridge that did not have managed DHCP or any IP addresses on host. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/device/nic_bridged.go | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go index d2f08a3dc7..15deced6a0 100644 --- a/lxd/device/nic_bridged.go +++ b/lxd/device/nic_bridged.go @@ -74,15 +74,6 @@ func (d *nicBridged) validateConfig() error { return err } - // If parent isn't a managed network, check that no managed-only features are enabled. - if !shared.PathExists(shared.VarPath("networks", d.config["parent"], "dnsmasq.pid")) { - for _, k := range []string{"ipv4.address", "ipv6.address", "security.mac_filtering", "security.ipv4_filtering", "security.ipv6_filtering"} { - if d.config[k] != "" || shared.IsTrue(d.config[k]) { - return fmt.Errorf("%s can only be used with managed networks", k) - } - } - } - return nil } @@ -620,14 +611,17 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) { netConfig := dbInfo.Config + canIPv4Allocate := netConfig["ipv4.address"] != "" && netConfig["ipv4.address"] != "none" && (netConfig["ipv4.dhcp"] == "" || shared.IsTrue(netConfig["ipv4.dhcp"])) + canIPv6Allocate := netConfig["ipv6.address"] != "" && netConfig["ipv6.address"] != "none" && (netConfig["ipv4.dhcp"] == "" || shared.IsTrue(netConfig["ipv4.dhcp"])) + // Check DHCPv4 is enabled on parent if dynamic IPv4 allocation is needed. - if shared.IsTrue(d.config["security.ipv4_filtering"]) && IPv4 == nil && netConfig["ipv4.dhcp"] != "" && !shared.IsTrue(netConfig["ipv4.dhcp"]) { - return nil, nil, fmt.Errorf("Cannot use security.ipv4_filtering as DHCPv4 is disabled on parent %s and no static IPv4 address set", d.config["parent"]) + if shared.IsTrue(d.config["security.ipv4_filtering"]) && IPv4 == nil && !canIPv4Allocate { + return nil, nil, fmt.Errorf("Cannot use security.ipv4_filtering as DHCPv4 is disabled or no IPv4 on parent %s and no static IPv4 address set", d.config["parent"]) } // Check DHCPv6 is enabled on parent if dynamic IPv6 allocation is needed. - if shared.IsTrue(d.config["security.ipv6_filtering"]) && IPv6 == nil && netConfig["ipv6.dhcp"] != "" && !shared.IsTrue(netConfig["ipv6.dhcp"]) { - return nil, nil, fmt.Errorf("Cannot use security.ipv6_filtering as DHCPv6 is disabled on parent %s and no static IPv6 address set", d.config["parent"]) + if shared.IsTrue(d.config["security.ipv6_filtering"]) && IPv6 == nil && !canIPv6Allocate { + return nil, nil, fmt.Errorf("Cannot use security.ipv6_filtering as DHCPv6 is disabled or no IPv6 on parent %s and no static IPv6 address set", d.config["parent"]) } dnsmasq.ConfigMutex.Lock() @@ -640,7 +634,7 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) { } // If no static IPv4, then check if there is a valid static DHCP IPv4 address defined. - if IPv4 == nil && curIPv4.IP != nil { + if IPv4 == nil && curIPv4.IP != nil && canIPv4Allocate { _, subnet, err := net.ParseCIDR(netConfig["ipv4.address"]) if err != nil { return nil, nil, err @@ -655,7 +649,7 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) { } // If no static IPv6, then check if there is a valid static DHCP IPv6 address defined. - if IPv6 == nil && curIPv6.IP != nil { + if IPv6 == nil && curIPv6.IP != nil && canIPv6Allocate { _, subnet, err := net.ParseCIDR(netConfig["ipv6.address"]) if err != nil { return IPv4, IPv6, err @@ -670,23 +664,23 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) { } // If we need to generate either a new IPv4 or IPv6, load existing IPs used in network. - if IPv4 == nil || IPv6 == nil { + if (IPv4 == nil && canIPv4Allocate) || (IPv6 == nil && canIPv6Allocate) { // Get existing allocations in network. IPv4Allocs, IPv6Allocs, err := d.getDHCPAllocatedIPs(d.config["parent"]) if err != nil { return nil, nil, err } - // Allocate a new IPv4 address is IPv4 filtering enabled. - if IPv4 == nil && shared.IsTrue(d.config["security.ipv4_filtering"]) { + // Allocate a new IPv4 address if IPv4 filtering enabled. + if IPv4 == nil && canIPv4Allocate && shared.IsTrue(d.config["security.ipv4_filtering"]) { IPv4, err = d.getDHCPFreeIPv4(IPv4Allocs, netConfig, d.instance.Name(), d.config["hwaddr"]) if err != nil { return nil, nil, err } } - // Allocate a new IPv6 address is IPv6 filtering enabled. - if IPv6 == nil && shared.IsTrue(d.config["security.ipv6_filtering"]) { + // Allocate a new IPv6 address if IPv6 filtering enabled. + if IPv6 == nil && canIPv6Allocate && shared.IsTrue(d.config["security.ipv6_filtering"]) { IPv6, err = d.getDHCPFreeIPv6(IPv6Allocs, netConfig, d.instance.Name(), d.config["hwaddr"]) if err != nil { return nil, nil, err @@ -694,8 +688,9 @@ func (d *nicBridged) allocateFilterIPs() (net.IP, net.IP, error) { } } - // If either IPv4 or IPv6 assigned is different than what is in dnsmasq config, rebuild config. - if (IPv4 != nil && bytes.Compare(curIPv4.IP, IPv4.To4()) != 0) || (IPv6 != nil && bytes.Compare(curIPv6.IP, IPv6.To16()) != 0) { + // If parent is a DHCP enabled managed network and either IPv4 or IPv6 assigned is different than what is in dnsmasq config, rebuild config. + if shared.PathExists(shared.VarPath("networks", d.config["parent"], "dnsmasq.pid")) && + ((IPv4 != nil && bytes.Compare(curIPv4.IP, IPv4.To4()) != 0) || (IPv6 != nil && bytes.Compare(curIPv6.IP, IPv6.To16()) != 0)) { var IPv4Str, IPv6Str string if IPv4 != nil { From cc7b85330c59088f8de720c480450de14a6a0807 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Thu, 1 Aug 2019 21:44:19 +0100 Subject: [PATCH 2/2] test: Updates nic bridged filtering tests for non-IP addressed parent Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- .../container_devices_nic_bridged_filtering.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/suites/container_devices_nic_bridged_filtering.sh b/test/suites/container_devices_nic_bridged_filtering.sh index a94c43b009..23ace8c2b7 100644 --- a/test/suites/container_devices_nic_bridged_filtering.sh +++ b/test/suites/container_devices_nic_bridged_filtering.sh @@ -315,12 +315,24 @@ test_container_devices_nic_bridged_filtering() { lxc delete -f "${ctPrefix}A" lxc delete -f "${ctPrefix}B" - # Check filtering works with non-DHCP statically defined IPs. + # Check filtering works with non-DHCP statically defined IPs and a bridge with no IP address and DHCP disabled. lxc network set "${brName}" ipv4.dhcp false + lxc network set "${brName}" ipv4.address none + lxc network set "${brName}" ipv6.dhcp false + lxc network set "${brName}" ipv6.address none + lxc network set "${brName}" ipv6.dhcp.stateful false lxc init testimage "${ctPrefix}A" -p "${ctPrefix}" - lxc config device add "${ctPrefix}A" eth0 nic nictype=nic name=eth0 nictype=bridged parent="${brName}" ipv4.address=192.0.2.2 ipv6.address=2001:db8::2 security.ipv4_filtering=true security.ipv6_filtering=true + lxc config device add "${ctPrefix}A" eth0 nic \ + nictype=nic \ + name=eth0 \ + nictype=bridged \ + parent="${brName}" \ + ipv4.address=192.0.2.2 \ + ipv6.address=2001:db8::2 \ + security.ipv4_filtering=true \ + security.ipv6_filtering=true lxc start "${ctPrefix}A" # Check MAC filter is present in ebtables.
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel