summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/dhcpv6_relay.py94
-rwxr-xr-xsrc/conf_mode/dhcpv6_server.py2
-rwxr-xr-xsrc/conf_mode/nat.py2
-rwxr-xr-xsrc/conf_mode/protocols_igmp.py5
-rwxr-xr-xsrc/conf_mode/protocols_isis.py39
-rwxr-xr-xsrc/conf_mode/protocols_mpls.py36
-rwxr-xr-xsrc/conf_mode/protocols_pim.py5
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py67
8 files changed, 158 insertions, 92 deletions
diff --git a/src/conf_mode/dhcpv6_relay.py b/src/conf_mode/dhcpv6_relay.py
index d4212b8be..cf8a26674 100755
--- a/src/conf_mode/dhcpv6_relay.py
+++ b/src/conf_mode/dhcpv6_relay.py
@@ -17,90 +17,84 @@
import os
from sys import exit
-from copy import deepcopy
from vyos.config import Config
-from vyos import ConfigError
-from vyos.util import call
+from vyos.configdict import dict_merge
+from vyos.ifconfig import Interface
from vyos.template import render
-
+from vyos.util import call
+from vyos.util import dict_search
+from vyos.validate import is_ipv6_link_local
+from vyos.xml import defaults
+from vyos import ConfigError
from vyos import airbag
airbag.enable()
-config_file = r'/run/dhcp-relay/dhcpv6.conf'
-
-default_config_data = {
- 'listen_addr': [],
- 'upstream_addr': [],
- 'options': [],
-}
+config_file = '/run/dhcp-relay/dhcrelay6.conf'
def get_config(config=None):
- relay = deepcopy(default_config_data)
if config:
conf = config
else:
conf = Config()
- if not conf.exists('service dhcpv6-relay'):
+ base = ['service', 'dhcpv6-relay']
+ if not conf.exists(base):
return None
- else:
- conf.set_level('service dhcpv6-relay')
-
- # Network interfaces/address to listen on for DHCPv6 query(s)
- if conf.exists('listen-interface'):
- interfaces = conf.list_nodes('listen-interface')
- for intf in interfaces:
- if conf.exists('listen-interface {0} address'.format(intf)):
- addr = conf.return_value('listen-interface {0} address'.format(intf))
- listen = addr + '%' + intf
- relay['listen_addr'].append(listen)
-
- # Upstream interface/address for remote DHCPv6 server
- if conf.exists('upstream-interface'):
- interfaces = conf.list_nodes('upstream-interface')
- for intf in interfaces:
- addresses = conf.return_values('upstream-interface {0} address'.format(intf))
- for addr in addresses:
- server = addr + '%' + intf
- relay['upstream_addr'].append(server)
-
- # Maximum hop count. When forwarding packets, dhcrelay discards packets
- # which have reached a hop count of COUNT. Default is 10. Maximum is 255.
- if conf.exists('max-hop-count'):
- count = '-c ' + conf.return_value('max-hop-count')
- relay['options'].append(count)
-
- if conf.exists('use-interface-id-option'):
- relay['options'].append('-I')
+
+ relay = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+ # We have gathered the dict representation of the CLI, but there are default
+ # options which we need to update into the dictionary retrived.
+ default_values = defaults(base)
+ relay = dict_merge(default_values, relay)
return relay
def verify(relay):
# bail out early - looks like removal from running config
- if relay is None:
+ if not relay:
return None
- if len(relay['listen_addr']) == 0 or len(relay['upstream_addr']) == 0:
- raise ConfigError('Must set at least one listen and upstream interface addresses.')
+ if 'upstream_interface' not in relay:
+ raise ConfigError('At least one upstream interface required!')
+ for interface, config in relay['upstream_interface'].items():
+ if 'address' not in config:
+ raise ConfigError('DHCPv6 server required for upstream ' \
+ f'interface {interface}!')
+
+ if 'listen_interface' not in relay:
+ raise ConfigError('At least one listen interface required!')
+
+ # DHCPv6 relay requires at least one global unicat address assigned to the
+ # interface
+ for interface in relay['listen_interface']:
+ has_global = False
+ for addr in Interface(interface).get_addr():
+ if not is_ipv6_link_local(addr.split('/')[0]):
+ has_global = True
+ if not has_global:
+ raise ConfigError(f'Interface {interface} does not have global '\
+ 'IPv6 address assigned!')
return None
def generate(relay):
# bail out early - looks like removal from running config
- if relay is None:
+ if not relay:
return None
- render(config_file, 'dhcpv6-relay/config.tmpl', relay)
+ render(config_file, 'dhcp-relay/dhcrelay6.conf.tmpl', relay)
return None
def apply(relay):
- if relay is not None:
- call('systemctl restart isc-dhcp-relay6.service')
- else:
+ # bail out early - looks like removal from running config
+ if not relay:
# DHCPv6 relay support is removed in the commit
call('systemctl stop isc-dhcp-relay6.service')
if os.path.exists(config_file):
os.unlink(config_file)
+ return None
+
+ call('systemctl restart isc-dhcp-relay6.service')
return None
diff --git a/src/conf_mode/dhcpv6_server.py b/src/conf_mode/dhcpv6_server.py
index c2868e078..db248de50 100755
--- a/src/conf_mode/dhcpv6_server.py
+++ b/src/conf_mode/dhcpv6_server.py
@@ -390,7 +390,7 @@ def generate(dhcpv6):
if not dhcpv6 or dhcpv6['disabled']:
return None
- render(config_file, 'dhcpv6-server/dhcpdv6.conf.tmpl', dhcpv6)
+ render(config_file, 'dhcp-server/dhcpdv6.conf.tmpl', dhcpv6)
return None
def apply(dhcpv6):
diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py
index f5c023b81..1ccec3d2e 100755
--- a/src/conf_mode/nat.py
+++ b/src/conf_mode/nat.py
@@ -130,7 +130,7 @@ def verify(nat):
# no need to verify the CLI as NAT is going to be deactivated
return None
- if nat['helper_functions']:
+ if 'helper_functions' in nat:
if not (nat['pre_ct_ignore'] or nat['pre_ct_conntrack'] or nat['out_ct_ignore'] or nat['out_ct_conntrack']):
raise Exception('could not determine nftable ruleset handlers')
diff --git a/src/conf_mode/protocols_igmp.py b/src/conf_mode/protocols_igmp.py
index 8606e7364..28d560d03 100755
--- a/src/conf_mode/protocols_igmp.py
+++ b/src/conf_mode/protocols_igmp.py
@@ -28,6 +28,9 @@ from signal import SIGTERM
from vyos import airbag
airbag.enable()
+# Required to use the full path to pimd, in another case daemon will not be started
+pimd_cmd = f'/usr/lib/frr/pimd -d -F traditional --daemon -A 127.0.0.1'
+
config_file = r'/tmp/igmp.frr'
def get_config(config=None):
@@ -115,7 +118,7 @@ def apply(igmp):
pim_pid = process_named_running('pimd')
if igmp['igmp_conf'] or igmp['pim_conf']:
if not pim_pid:
- call(f'pimd -d -F traditional --daemon -A 127.0.0.1')
+ call(pimd_cmd)
if os.path.exists(config_file):
call(f'vtysh -d pimd -f {config_file}')
diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py
index df03fd990..97ab79583 100755
--- a/src/conf_mode/protocols_isis.py
+++ b/src/conf_mode/protocols_isis.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2017-2020 VyOS maintainers and contributors
+# Copyright (C) 2020 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -28,8 +28,6 @@ from vyos import frr
from vyos import airbag
airbag.enable()
-config_file = r'/tmp/isis.frr'
-
def get_config(config=None):
if config:
conf = config
@@ -39,13 +37,6 @@ def get_config(config=None):
isis = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
- # determine which members have been removed
- for instance in isis:
- conf.set_level(base + [instance])
- tmp = node_changed(conf, ['interface'])
- if tmp:
- isis[instance].update({'interface_remove': tmp})
-
return isis
def verify(isis):
@@ -106,9 +97,6 @@ def generate(isis):
process = list(isis.keys())[0]
isis[process]['process'] = process
- # render(config) not needed, its only for debug
- render(config_file, 'frr/isis.frr.tmpl', isis[process])
-
isis['new_frr_config'] = render_to_string('frr/isis.frr.tmpl',
isis[process])
@@ -116,24 +104,27 @@ def generate(isis):
def apply(isis):
# Save original configuration prior to starting any commit actions
- frr_cfg = {}
- frr_cfg['original_config'] = frr.get_configuration(daemon='isisd')
- frr_cfg['modified_config'] = frr.replace_section(frr_cfg['original_config'], isis['new_frr_config'], from_re='router isis .*')
+ frr_cfg = frr.FRRConfig()
+ frr_cfg.load_configuration(daemon='isisd')
+ frr_cfg.modify_section(r'interface \S+', '')
+ frr_cfg.modify_section(f'router isis \S+', '')
+ frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', isis['new_frr_config'])
+ frr_cfg.commit_configuration(daemon='isisd')
+
+ # If FRR config is blank, rerun the blank commit x times due to frr-reload
+ # behavior/bug not properly clearing out on one commit.
+ if isis['new_frr_config'] == '':
+ for a in range(5):
+ frr_cfg.commit_configuration(daemon='isisd')
# Debugging
+ '''
print('')
print('--------- DEBUGGING ----------')
print(f'Existing config:\n{frr_cfg["original_config"]}\n\n')
print(f'Replacement config:\n{isis["new_frr_config"]}\n\n')
print(f'Modified config:\n{frr_cfg["modified_config"]}\n\n')
-
- # FRR mark configuration will test for syntax errors and throws an
- # exception if any syntax errors is detected
- frr.mark_configuration(frr_cfg['modified_config'])
-
- # Commit resulting configuration to FRR, this will throw CommitError
- # on failure
- frr.reload_configuration(frr_cfg['modified_config'], daemon='isisd')
+ '''
return None
diff --git a/src/conf_mode/protocols_mpls.py b/src/conf_mode/protocols_mpls.py
index 791b18110..3b27608da 100755
--- a/src/conf_mode/protocols_mpls.py
+++ b/src/conf_mode/protocols_mpls.py
@@ -18,11 +18,13 @@ import os
from sys import exit
+from glob import glob
from vyos.config import Config
from vyos.configdict import node_changed
from vyos.template import render_to_string
from vyos.util import call
from vyos.util import dict_search
+from vyos.util import read_file
from vyos import ConfigError
from vyos import frr
from vyos import airbag
@@ -118,22 +120,28 @@ def apply(mpls):
# Enable and disable MPLS processing on interfaces per configuration
if 'interface' in mpls:
system_interfaces = []
- system_interfaces.append(((os.popen('sysctl net.mpls.conf').read()).split('\n')))
- del system_interfaces[0][-1]
- for configured_interface in mpls['interface']:
- for system_interface in system_interfaces[0]:
- if configured_interface in system_interface:
- call(f'sysctl -wq net.mpls.conf.{configured_interface}.input=1')
- elif system_interface.endswith(' = 1'):
- system_interface = system_interface.replace(' = 1', '=0')
- call(f'sysctl -wq {system_interface}')
+ # Populate system interfaces list with local MPLS capable interfaces
+ for interface in glob('/proc/sys/net/mpls/conf/*'):
+ system_interfaces.append(os.path.basename(interface))
+ # This is where the comparison is done on if an interface needs to be enabled/disabled.
+ for system_interface in system_interfaces:
+ interface_state = read_file(f'/proc/sys/net/mpls/conf/{system_interface}/input')
+ if '1' in interface_state:
+ if system_interface not in mpls['interface']:
+ system_interface = system_interface.replace('.', '/')
+ call(f'sysctl -wq net.mpls.conf.{system_interface}.input=0')
+ elif '0' in interface_state:
+ if system_interface in mpls['interface']:
+ system_interface = system_interface.replace('.', '/')
+ call(f'sysctl -wq net.mpls.conf.{system_interface}.input=1')
else:
- # If MPLS interfaces are not configured, set MPLS processing disabled
system_interfaces = []
- system_interfaces.append(((os.popen('sysctl net.mpls.conf').read()).replace(" = 1", "=0")).split('\n'))
- del system_interfaces[0][-1]
- for interface in (system_interfaces[0]):
- call(f'sysctl -wq {interface}')
+ # If MPLS interfaces are not configured, set MPLS processing disabled
+ for interface in glob('/proc/sys/net/mpls/conf/*'):
+ system_interfaces.append(os.path.basename(interface))
+ for system_interface in system_interfaces:
+ system_interface = system_interface.replace('.', '/')
+ call(f'sysctl -wq net.mpls.conf.{system_interface}.input=0')
return None
diff --git a/src/conf_mode/protocols_pim.py b/src/conf_mode/protocols_pim.py
index 8a9f034d5..df2e6f941 100755
--- a/src/conf_mode/protocols_pim.py
+++ b/src/conf_mode/protocols_pim.py
@@ -28,6 +28,9 @@ from signal import SIGTERM
from vyos import airbag
airbag.enable()
+# Required to use the full path to pimd, in another case daemon will not be started
+pimd_cmd = f'/usr/lib/frr/pimd -d -F traditional --daemon -A 127.0.0.1'
+
config_file = r'/tmp/pimd.frr'
def get_config(config=None):
@@ -142,7 +145,7 @@ def apply(pim):
pim_pid = process_named_running('pimd')
if pim['igmp_conf'] or pim['pim_conf']:
if not pim_pid:
- call(f'pimd -d -F traditional --daemon -A 127.0.0.1')
+ call(pimd_cmd)
if os.path.exists(config_file):
call("vtysh -d pimd -f " + config_file)
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
new file mode 100755
index 000000000..969266c30
--- /dev/null
+++ b/src/conf_mode/vpn_ipsec.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+
+from sys import exit
+
+from vyos.config import Config
+from vyos.template import render
+from vyos.util import call
+from vyos.util import dict_search
+from vyos import ConfigError
+from vyos import airbag
+from pprint import pprint
+airbag.enable()
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+ base = ['vpn', 'nipsec']
+ if not conf.exists(base):
+ return None
+
+ # retrieve common dictionary keys
+ ipsec = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+ return ipsec
+
+def verify(ipsec):
+ if not ipsec:
+ return None
+
+def generate(ipsec):
+ if not ipsec:
+ return None
+
+ return ipsec
+
+def apply(ipsec):
+ if not ipsec:
+ return None
+
+ pprint(ipsec)
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)