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

Reply via email to