From 93b4dab57e2e13bd804cbee999241be65a443e2e Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Fri, 1 Jun 2018 15:04:49 +0530 Subject: [PATCH 1/2] networkd: Allow to retain configs even if carrier is lost When there is bad link in the network the carrier goes up/down. This makes networkd stops all the clients and drop config. But if the remote router/dhcpserver running a prevention of DHCP Starvation attack or DHCP Flood attack it does not allow networkd to take a DHCP lease resulting failure in configuration. This patch allows to keep the client running and keep the conf also for this scenario. Closes #9111 --- man/systemd.network.xml | 9 +++++++++ src/network/networkd-link.c | 3 +++ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.h | 1 + test/fuzz/fuzz-network-parser/directives.network | 1 + 5 files changed, 15 insertions(+) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index ee464ffff4..25a6bc1467 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -800,6 +800,15 @@ + + IgnoreCarrierLoss= + + A boolean. Allows networkd to retain both the static and dynamic configuration of the + interface even if its carrier is lost. Defaults to false. + + + + diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 736373ae34..463c20774e 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3500,6 +3500,9 @@ static int link_carrier_lost(Link *link) { assert(link); + if (link->network->ignore_carrier_loss) + return 0; + /* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop. * setting_mtu keep track whether the device got reset because of setting MTU and does not drop the * configuration and stop the clients as well. */ diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 5d8aede593..0a0c24c69a 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -81,6 +81,7 @@ Network.ProxyARP, config_parse_tristate, Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0 Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier) Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier) +Network.IgnoreCarrierLoss, config_parse_bool, 0, offsetof(Network, ignore_carrier_loss) Address.Address, config_parse_address, 0, 0 Address.Peer, config_parse_address, 0, 0 Address.Broadcast, config_parse_broadcast, 0, 0 diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index f6e62cdd79..d1cdba55a6 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -224,6 +224,7 @@ struct Network { int allmulticast; bool unmanaged; bool configure_without_carrier; + bool ignore_carrier_loss; uint32_t iaid; DUID duid; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 209132f239..3fb785baa9 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -116,6 +116,7 @@ VLAN= DHCPServer= BindCarrier= VRF= +IgnoreCarrierLoss= [IPv6Prefix] Prefix= OnLink= From 804b6cd26b60dfb0b4a919111823a8d105fde761 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 6 Feb 2019 12:45:56 +0100 Subject: [PATCH 2/2] test-network: add testcases for IgnoreCarrierLoss= --- .../conf/bridge99-ignore-carrier-loss.network | 7 ++++ test/test-network/systemd-networkd-tests.py | 37 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 test/test-network/conf/bridge99-ignore-carrier-loss.network diff --git a/test/test-network/conf/bridge99-ignore-carrier-loss.network b/test/test-network/conf/bridge99-ignore-carrier-loss.network new file mode 100644 index 0000000000..922d57091e --- /dev/null +++ b/test/test-network/conf/bridge99-ignore-carrier-loss.network @@ -0,0 +1,7 @@ +[Match] +Name=bridge99 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 +IgnoreCarrierLoss=true diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 29bd08906c..29a6c44ee1 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -914,6 +914,7 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities): '26-bridge.netdev', '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', + 'bridge99-ignore-carrier-loss.network', 'bridge99.network'] def setUp(self): @@ -959,6 +960,42 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities): if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')): self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1') + self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0) + time.sleep(1) + + self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0) + self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0) + time.sleep(3) + + output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'NO-CARRIER') + self.assertNotRegex(output, '192.168.0.15/24') + self.assertNotRegex(output, '192.168.0.16/24') + + def test_bridge_ignore_carrier_loss(self): + self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', + '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', + 'bridge99-ignore-carrier-loss.network') + self.start_networkd() + + self.assertTrue(self.link_exits('dummy98')) + self.assertTrue(self.link_exits('test1')) + self.assertTrue(self.link_exits('bridge99')) + + self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0) + time.sleep(1) + + self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0) + self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0) + time.sleep(3) + + output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'NO-CARRIER') + self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99') + self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99') + class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities): links = ['veth99']