summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/router-advert/radvd.conf.tmpl72
-rw-r--r--interface-definitions/service_router-advert.xml.in11
-rwxr-xr-xsrc/conf_mode/service_router-advert.py163
3 files changed, 98 insertions, 148 deletions
diff --git a/data/templates/router-advert/radvd.conf.tmpl b/data/templates/router-advert/radvd.conf.tmpl
index 073623eac..cebfc54b5 100644
--- a/data/templates/router-advert/radvd.conf.tmpl
+++ b/data/templates/router-advert/radvd.conf.tmpl
@@ -1,37 +1,47 @@
### Autogenerated by service_router-advert.py ###
-{% for i in interfaces -%}
-interface {{ i.name }} {
+{% if interface is defined and interface is not none %}
+{% for iface in interface %}
+interface {{ iface }} {
IgnoreIfMissing on;
- AdvDefaultPreference {{ i.default_preference }};
- AdvManagedFlag {{ i.managed_flag }};
- MaxRtrAdvInterval {{ i.interval_max }};
-{% if i.interval_min %}
- MinRtrAdvInterval {{ i.interval_min }};
-{% endif %}
- AdvReachableTime {{ i.reachable_time }};
- AdvIntervalOpt {{ i.send_advert }};
- AdvSendAdvert {{ i.send_advert }};
-{% if i.default_lifetime %}
- AdvDefaultLifetime {{ i.default_lifetime }};
-{% endif %}
-{% if i.link_mtu %}
- AdvLinkMTU {{ i.link_mtu }};
-{% endif %}
- AdvOtherConfigFlag {{ i.other_config_flag }};
- AdvRetransTimer {{ i.retrans_timer }};
- AdvCurHopLimit {{ i.hop_limit }};
-{% for p in i.prefixes %}
- prefix {{ p.prefix }} {
- AdvAutonomous {{ p.autonomous_flag }};
- AdvValidLifetime {{ p.valid_lifetime }};
- AdvOnLink {{ p.on_link }};
- AdvPreferredLifetime {{ p.preferred_lifetime }};
+{% if interface[iface].default_preference is defined and interface[iface].default_preference is not none %}
+ AdvDefaultPreference {{ interface[iface].default_preference }};
+{% endif %}
+{% if interface[iface].managed_flag is defined and interface[iface].managed_flag is not none %}
+ AdvManagedFlag {{ 'on' if interface[iface].managed_flag is defined else 'off' }};
+{% endif %}
+{% if interface[iface].interval.max is defined and interface[iface].interval.max is not none %}
+ MaxRtrAdvInterval {{ interface[iface].interval.max }};
+{% endif %}
+{% if interface[iface].interval.min is defined and interface[iface].interval.min is not none %}
+ MinRtrAdvInterval {{ interface[iface].interval.min }};
+{% endif %}
+{% if interface[iface].reachable_time is defined and interface[iface].reachable_time is not none %}
+ AdvReachableTime {{ interface[iface].reachable_time }};
+{% endif %}
+ AdvIntervalOpt {{ 'off' if interface[iface].no_send_advert is defined else 'on' }};
+ AdvSendAdvert {{ 'off' if interface[iface].no_send_advert is defined else 'on' }};
+{% if interface[iface].default_lifetime is defined %}
+ AdvDefaultLifetime {{ interface[iface].default_lifetime }};
+{% endif %}
+{% if interface[iface].link_mtu is defined %}
+ AdvLinkMTU {{ interface[iface].link_mtu }};
+{% endif %}
+ AdvOtherConfigFlag {{ 'on' if interface[iface].other_config_flag is defined else 'off' }};
+ AdvRetransTimer {{ interface[iface].retrans_timer }};
+ AdvCurHopLimit {{ interface[iface].hop_limit }};
+{% for prefix in interface[iface].prefix %}
+ prefix {{ prefix }} {
+ AdvAutonomous {{ 'off' if interface[iface].prefix[prefix].no_autonomous_flag is defined else 'on' }};
+ AdvValidLifetime {{ interface[iface].prefix[prefix].valid_lifetime }};
+ AdvOnLink {{ 'off' if interface[iface].prefix[prefix].no_on_link_flag is defined else 'on' }};
+ AdvPreferredLifetime {{ interface[iface].prefix[prefix].preferred_lifetime }};
};
-{% endfor %}
-{% if i.name_server %}
- RDNSS {{ i.name_server | join(" ") }} {
+{% endfor %}
+{% if interface[iface].name_server is defined %}
+ RDNSS {{ interface[iface].name_server | join(" ") }} {
};
-{% endif %}
+{% endif %}
};
-{% endfor -%}
+{% endfor -%}
+{% endif %}
diff --git a/interface-definitions/service_router-advert.xml.in b/interface-definitions/service_router-advert.xml.in
index 6a4706ab7..5a472fc9a 100644
--- a/interface-definitions/service_router-advert.xml.in
+++ b/interface-definitions/service_router-advert.xml.in
@@ -32,6 +32,7 @@
</constraint>
<constraintErrorMessage>Hop count must be between 0 and 255</constraintErrorMessage>
</properties>
+ <defaultValue>64</defaultValue>
</leafNode>
<leafNode name="default-lifetime">
<properties>
@@ -69,10 +70,11 @@
<description>Default router has high preference</description>
</valueHelp>
<constraint>
- <regex>(low|medium|high)</regex>
+ <regex>^(low|medium|high)$</regex>
</constraint>
<constraintErrorMessage>Default preference must be low, medium or high</constraintErrorMessage>
</properties>
+ <defaultValue>medium</defaultValue>
</leafNode>
<leafNode name="dnssl">
<properties>
@@ -116,6 +118,7 @@
</constraint>
<constraintErrorMessage>Maximum interval must be between 4 and 1800 seconds</constraintErrorMessage>
</properties>
+ <defaultValue>600</defaultValue>
</leafNode>
<leafNode name="min">
<properties>
@@ -191,9 +194,10 @@
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
- <regex>(infinity)</regex>
+ <regex>^(infinity)$</regex>
</constraint>
</properties>
+ <defaultValue>14400</defaultValue>
</leafNode>
<leafNode name="valid-lifetime">
<properties>
@@ -214,6 +218,7 @@
<regex>(infinity)</regex>
</constraint>
</properties>
+ <defaultValue>2592000</defaultValue>
</leafNode>
</children>
</tagNode>
@@ -233,6 +238,7 @@
</constraint>
<constraintErrorMessage>Reachable time must be 0 or between 1 and 3600000 milliseconds</constraintErrorMessage>
</properties>
+ <defaultValue>0</defaultValue>
</leafNode>
<leafNode name="retrans-timer">
<properties>
@@ -250,6 +256,7 @@
</constraint>
<constraintErrorMessage>Retransmit interval must be 0 or between 1 and 4294967295 milliseconds</constraintErrorMessage>
</properties>
+ <defaultValue>0</defaultValue>
</leafNode>
<leafNode name="no-send-advert">
<properties>
diff --git a/src/conf_mode/service_router-advert.py b/src/conf_mode/service_router-advert.py
index ef6148ebd..1b333e1a5 100755
--- a/src/conf_mode/service_router-advert.py
+++ b/src/conf_mode/service_router-advert.py
@@ -16,145 +16,77 @@
import os
-from stat import S_IRUSR, S_IWUSR, S_IRGRP
from sys import exit
from vyos.config import Config
-from vyos import ConfigError
-from vyos.util import call
+from vyos.configdict import dict_merge
from vyos.template import render
-
+from vyos.util import call
+from vyos.xml import defaults
+from vyos import ConfigError
from vyos import airbag
airbag.enable()
config_file = r'/run/radvd/radvd.conf'
-default_config_data = {
- 'interfaces': []
-}
-
def get_config():
- rtradv = default_config_data
conf = Config()
- base_level = ['service', 'router-advert']
-
- if not conf.exists(base_level):
- return rtradv
-
- for interface in conf.list_nodes(base_level + ['interface']):
- intf = {
- 'name': interface,
- 'hop_limit' : '64',
- 'default_lifetime': '',
- 'default_preference': 'medium',
- 'dnssl': [],
- 'link_mtu': '',
- 'managed_flag': 'off',
- 'interval_max': '600',
- 'interval_min': '',
- 'name_server': [],
- 'other_config_flag': 'off',
- 'prefixes' : [],
- 'reachable_time': '0',
- 'retrans_timer': '0',
- 'send_advert': 'on'
- }
-
- # set config level first to reduce boilerplate code
- conf.set_level(base_level + ['interface', interface])
-
- if conf.exists(['hop-limit']):
- intf['hop_limit'] = conf.return_value(['hop-limit'])
-
- if conf.exists(['default-lifetime']):
- intf['default_lifetime'] = conf.return_value(['default-lifetime'])
-
- if conf.exists(['default-preference']):
- intf['default_preference'] = conf.return_value(['default-preference'])
-
- if conf.exists(['dnssl']):
- intf['dnssl'] = conf.return_values(['dnssl'])
-
- if conf.exists(['link-mtu']):
- intf['link_mtu'] = conf.return_value(['link-mtu'])
-
- if conf.exists(['managed-flag']):
- intf['managed_flag'] = 'on'
-
- if conf.exists(['interval', 'max']):
- intf['interval_max'] = conf.return_value(['interval', 'max'])
-
- if conf.exists(['interval', 'min']):
- intf['interval_min'] = conf.return_value(['interval', 'min'])
-
- if conf.exists(['name-server']):
- intf['name_server'] = conf.return_values(['name-server'])
-
- if conf.exists(['other-config-flag']):
- intf['other_config_flag'] = 'on'
-
- if conf.exists(['reachable-time']):
- intf['reachable_time'] = conf.return_value(['reachable-time'])
-
- if conf.exists(['retrans-timer']):
- intf['retrans_timer'] = conf.return_value(['retrans-timer'])
-
- if conf.exists(['no-send-advert']):
- intf['send_advert'] = 'off'
-
- for prefix in conf.list_nodes(['prefix']):
- tmp = {
- 'prefix' : prefix,
- 'autonomous_flag' : 'on',
- 'on_link' : 'on',
- 'preferred_lifetime': 14400,
- 'valid_lifetime' : 2592000
-
- }
-
- # set config level first to reduce boilerplate code
- conf.set_level(base_level + ['interface', interface, 'prefix', prefix])
-
- if conf.exists(['no-autonomous-flag']):
- tmp['autonomous_flag'] = 'off'
-
- if conf.exists(['no-on-link-flag']):
- tmp['on_link'] = 'off'
-
- if conf.exists(['preferred-lifetime']):
- tmp['preferred_lifetime'] = int(conf.return_value(['preferred-lifetime']))
-
- if conf.exists(['valid-lifetime']):
- tmp['valid_lifetime'] = int(conf.return_value(['valid-lifetime']))
-
- intf['prefixes'].append(tmp)
-
- rtradv['interfaces'].append(intf)
+ base = ['service', 'router-advert']
+ rtradv = 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_interface_values = defaults(base + ['interface'])
+ # we deal with prefix defaults later on
+ if 'prefix' in default_interface_values:
+ del default_interface_values['prefix']
+
+ default_prefix_values = defaults(base + ['interface', 'prefix'])
+
+ if 'interface' in rtradv:
+ for interface in rtradv['interface']:
+ rtradv['interface'][interface] = dict_merge(
+ default_interface_values, rtradv['interface'][interface])
+
+ if 'prefix' in rtradv['interface'][interface]:
+ for prefix in rtradv['interface'][interface]['prefix']:
+ rtradv['interface'][interface]['prefix'][prefix] = dict_merge(
+ default_prefix_values, rtradv['interface'][interface]['prefix'][prefix])
+
+ if 'name_server' in rtradv['interface'][interface]:
+ # always use a list when dealing with nameservers - eases the template generation
+ if isinstance(rtradv['interface'][interface]['name_server'], str):
+ rtradv['interface'][interface]['name_server'] = [
+ rtradv['interface'][interface]['name_server']]
return rtradv
def verify(rtradv):
- for interface in rtradv['interfaces']:
- for prefix in interface['prefixes']:
- if not (prefix['valid_lifetime'] > prefix['preferred_lifetime']):
- raise ConfigError('Prefix valid-lifetime must be greater then preferred-lifetime')
+ if not rtradv:
+ return None
+
+ if 'interface' not in rtradv:
+ return None
+
+ for interface in rtradv['interface']:
+ interface = rtradv['interface'][interface]
+ if 'prefix' in interface:
+ for prefix in interface['prefix']:
+ prefix = interface['prefix'][prefix]
+ if not (int(prefix['valid_lifetime']) > int(prefix['preferred_lifetime'])):
+ raise ConfigError('Prefix valid-lifetime must be greater then preferred-lifetime')
return None
def generate(rtradv):
- if not rtradv['interfaces']:
+ if not rtradv:
return None
- render(config_file, 'router-advert/radvd.conf.tmpl', rtradv, trim_blocks=True)
-
- # adjust file permissions of new configuration file
- if os.path.exists(config_file):
- os.chmod(config_file, S_IRUSR | S_IWUSR | S_IRGRP)
-
+ render(config_file, 'router-advert/radvd.conf.tmpl', rtradv, trim_blocks=True, permission=0o644)
return None
def apply(rtradv):
- if not rtradv['interfaces']:
+ if not rtradv:
# bail out early - looks like removal from running config
call('systemctl stop radvd.service')
if os.path.exists(config_file):
@@ -163,6 +95,7 @@ def apply(rtradv):
return None
call('systemctl restart radvd.service')
+
return None
if __name__ == '__main__':