summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-04-07 22:02:49 +0200
committerChristian Poessinger <christian@poessinger.com>2020-04-07 22:02:49 +0200
commitfcce4714146a39f608ddd141338547a5a952c63f (patch)
tree3b521908928e0cae15c2e8f8979088b5f7d2c0a5 /src/conf_mode
parent681576fff6a268ed04ae1a73ad7771882672cdb6 (diff)
downloadvyos-1x-fcce4714146a39f608ddd141338547a5a952c63f.tar.gz
vyos-1x-fcce4714146a39f608ddd141338547a5a952c63f.zip
bridge: T2232: prevent deletion of enslaved interfaces
Interfaces enslaved to a bridge are not allowed to be deleted. If an interface is deleted from the config but it is still enslaved to a bridge will cause a configuration error on the subsequent boot.
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/interfaces-bonding.py19
-rwxr-xr-xsrc/conf_mode/interfaces-bridge.py3
-rwxr-xr-xsrc/conf_mode/interfaces-dummy.py11
-rwxr-xr-xsrc/conf_mode/interfaces-geneve.py13
-rwxr-xr-xsrc/conf_mode/interfaces-l2tpv3.py11
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py10
-rwxr-xr-xsrc/conf_mode/interfaces-pseudo-ethernet.py8
-rwxr-xr-xsrc/conf_mode/interfaces-vxlan.py11
-rwxr-xr-xsrc/conf_mode/interfaces-wireguard.py12
-rwxr-xr-xsrc/conf_mode/interfaces-wireless.py10
-rwxr-xr-xsrc/conf_mode/interfaces-wirelessmodem.py9
11 files changed, 99 insertions, 18 deletions
diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py
index 19f43f725..6a002bc06 100755
--- a/src/conf_mode/interfaces-bonding.py
+++ b/src/conf_mode/interfaces-bonding.py
@@ -24,9 +24,8 @@ from vyos.ifconfig import BondIf
from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config
from vyos.configdict import list_diff, vlan_to_dict
from vyos.config import Config
+from vyos.util import run, is_bridge_member
from vyos import ConfigError
-from vyos.util import run
-
default_config_data = {
'address': [],
@@ -278,17 +277,23 @@ def get_config():
def verify(bond):
+ if bond['deleted']:
+ interface = bond['intf']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
+ return None
+
if len (bond['arp_mon_tgt']) > 16:
raise ConfigError('The maximum number of targets that can be specified is 16')
if bond['primary']:
if bond['mode'] not in ['active-backup', 'balance-tlb', 'balance-alb']:
raise ConfigError('Mode dependency failed, primary not supported ' \
- 'in this mode.'.format())
-
- if bond['primary'] not in bond['member']:
- raise ConfigError('Interface "{}" is not part of the bond' \
- .format(bond['primary']))
+ 'in mode "{}"!'.format(bond['mode']))
vrf_name = bond['vrf']
if vrf_name and vrf_name not in interfaces():
diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py
index 28e5957e4..79247ee51 100755
--- a/src/conf_mode/interfaces-bridge.py
+++ b/src/conf_mode/interfaces-bridge.py
@@ -243,6 +243,9 @@ def verify(bridge):
if intf['name'] not in interfaces():
raise ConfigError('Can not add non existing interface "{}" to bridge "{}"'.format(intf['name'], bridge['intf']))
+ if intf['name'] == 'lo':
+ raise ConfigError('Loopback interface "lo" can not be added to a bridge')
+
# bridge members are not allowed to be bond members, too
for intf in bridge['member']:
for bond in conf.list_nodes('interfaces bonding'):
diff --git a/src/conf_mode/interfaces-dummy.py b/src/conf_mode/interfaces-dummy.py
index b7b75517d..a256103af 100755
--- a/src/conf_mode/interfaces-dummy.py
+++ b/src/conf_mode/interfaces-dummy.py
@@ -23,6 +23,7 @@ from netifaces import interfaces
from vyos.ifconfig import DummyIf
from vyos.configdict import list_diff
from vyos.config import Config
+from vyos.util import is_bridge_member
from vyos import ConfigError
default_config_data = {
@@ -78,6 +79,16 @@ def get_config():
return dummy
def verify(dummy):
+ if dummy['deleted']:
+ interface = dummy['intf']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
+ return None
+
vrf_name = dummy['vrf']
if vrf_name and vrf_name not in interfaces():
raise ConfigError(f'VRF "{vrf_name}" does not exist')
diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py
index eaa678d3e..e47473d76 100755
--- a/src/conf_mode/interfaces-geneve.py
+++ b/src/conf_mode/interfaces-geneve.py
@@ -18,11 +18,12 @@ import os
from sys import exit
from copy import deepcopy
+from netifaces import interfaces
from vyos.config import Config
-from vyos.ifconfig import GeneveIf, Interface
+from vyos.ifconfig import GeneveIf
+from vyos.util import is_bridge_member
from vyos import ConfigError
-from netifaces import interfaces
default_config_data = {
'address': [],
@@ -92,7 +93,13 @@ def get_config():
def verify(geneve):
if geneve['deleted']:
- # bail out early
+ interface = geneve['intf']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
return None
if not geneve['remote']:
diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py
index d71e3908c..0400cb849 100755
--- a/src/conf_mode/interfaces-l2tpv3.py
+++ b/src/conf_mode/interfaces-l2tpv3.py
@@ -22,7 +22,7 @@ from copy import deepcopy
from vyos.config import Config
from vyos.ifconfig import L2TPv3If, Interface
from vyos import ConfigError
-from vyos.util import run
+from vyos.util import run, is_bridge_member
from netifaces import interfaces
default_config_data = {
@@ -154,8 +154,15 @@ def get_config():
def verify(l2tpv3):
+ interface = l2tpv3['intf']
+
if l2tpv3['deleted']:
- # bail out early
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
return None
if not l2tpv3['local_address']:
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 1fe1143cd..e9b40bb38 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -31,7 +31,7 @@ from shutil import rmtree
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos.ifconfig import VTunIf
-from vyos.util import process_running, cmd
+from vyos.util import process_running, cmd, is_bridge_member
from vyos.validate import is_addr_assigned
from vyos import ConfigError
@@ -444,8 +444,16 @@ def get_config():
def verify(openvpn):
if openvpn['deleted']:
+ interface = openvpn['intf']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
return None
+
if not openvpn['mode']:
raise ConfigError('Must specify OpenVPN operation mode')
diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py
index 56d4fdfc3..50b5a12a0 100755
--- a/src/conf_mode/interfaces-pseudo-ethernet.py
+++ b/src/conf_mode/interfaces-pseudo-ethernet.py
@@ -24,6 +24,7 @@ from vyos.ifconfig import MACVLANIf
from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config
from vyos.configdict import list_diff, vlan_to_dict
from vyos.config import Config
+from vyos.util import is_bridge_member
from vyos import ConfigError
default_config_data = {
@@ -217,6 +218,13 @@ def get_config():
def verify(peth):
if peth['deleted']:
+ interface = peth['intf']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
return None
if not peth['link']:
diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py
index 1f9636729..b9bfb242a 100755
--- a/src/conf_mode/interfaces-vxlan.py
+++ b/src/conf_mode/interfaces-vxlan.py
@@ -18,11 +18,12 @@ import os
from sys import exit
from copy import deepcopy
+from netifaces import interfaces
from vyos.config import Config
from vyos.ifconfig import VXLANIf, Interface
+from vyos.util import is_bridge_member
from vyos import ConfigError
-from netifaces import interfaces
default_config_data = {
'address': [],
@@ -148,7 +149,13 @@ def get_config():
def verify(vxlan):
if vxlan['deleted']:
- # bail out early
+ interface = vxlan['intf']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
return None
if vxlan['mtu'] < 1500:
diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py
index 4fa0dd8c0..54121a6c1 100755
--- a/src/conf_mode/interfaces-wireguard.py
+++ b/src/conf_mode/interfaces-wireguard.py
@@ -24,7 +24,7 @@ from netifaces import interfaces
from vyos import ConfigError
from vyos.config import Config
from vyos.configdict import list_diff
-from vyos.util import run
+from vyos.util import run, is_bridge_member
from vyos.ifconfig import WireGuardIf
kdir = r'/config/auth/wireguard'
@@ -179,6 +179,16 @@ def verify(c):
if not c:
return None
+ if c['delete']:
+ interface = c['intfc']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
+ return None
+
if not os.path.exists(c['pk']):
raise ConfigError(
"No keys found, generate them by executing: \'run generate wireguard [keypair|named-keypairs]\'")
diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py
index 188d0ee22..4c70b1478 100755
--- a/src/conf_mode/interfaces-wireless.py
+++ b/src/conf_mode/interfaces-wireless.py
@@ -29,7 +29,7 @@ from vyos.configdict import list_diff, vlan_to_dict
from vyos.defaults import directories as vyos_data_dir
from vyos.ifconfig import WiFiIf
from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config
-from vyos.util import process_running, chmod_x, chown_file, run
+from vyos.util import process_running, chmod_x, chown_file, run, is_bridge_member
from vyos import ConfigError
user = 'root'
@@ -554,8 +554,16 @@ def get_config():
def verify(wifi):
if wifi['deleted']:
+ interface = wifi['intfc']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
return None
+
if wifi['op_mode'] != 'monitor' and not wifi['ssid']:
raise ConfigError('SSID must be set for {}'.format(wifi['intf']))
diff --git a/src/conf_mode/interfaces-wirelessmodem.py b/src/conf_mode/interfaces-wirelessmodem.py
index 5e10cfce7..a93b20d27 100755
--- a/src/conf_mode/interfaces-wirelessmodem.py
+++ b/src/conf_mode/interfaces-wirelessmodem.py
@@ -23,7 +23,7 @@ from netifaces import interfaces
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
-from vyos.util import chown_file, chmod_x, cmd, run
+from vyos.util import chown_file, chmod_x, cmd, run, is_bridge_member
from vyos import ConfigError
default_config_data = {
@@ -115,6 +115,13 @@ def get_config():
def verify(wwan):
if wwan['deleted']:
+ interface = wwan['intfc']
+ is_member, bridge = is_bridge_member(interface)
+ if is_member:
+ # can not use a f'' formatted-string here as bridge would not get
+ # expanded in the print statement
+ raise ConfigError('Can not delete interface "{0}" as it ' \
+ 'is a member of bridge "{1}"!'.format(interface, bridge))
return None
if not wwan['apn']: