summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/babeld.frr.j285
-rw-r--r--data/templates/frr/daemons.frr.tmpl3
-rw-r--r--data/templates/frr/distribute_list_macro.j230
-rw-r--r--data/templates/frr/ipv6_distribute_list_macro.j230
-rw-r--r--data/templates/frr/ripd.frr.j230
-rw-r--r--data/templates/frr/ripngd.frr.j230
-rw-r--r--interface-definitions/container.xml.in27
-rw-r--r--interface-definitions/include/babel/interface.xml.i187
-rw-r--r--interface-definitions/include/bgp/protocol-common-config.xml.i16
-rw-r--r--interface-definitions/include/eigrp/protocol-common-config.xml.i6
-rw-r--r--interface-definitions/include/isis/protocol-common-config.xml.i18
-rw-r--r--interface-definitions/include/ospf/protocol-common-config.xml.i10
-rw-r--r--interface-definitions/include/ospfv3/protocol-common-config.xml.i8
-rw-r--r--interface-definitions/protocols-babel.xml.in254
-rw-r--r--interface-definitions/protocols-rip.xml.in9
-rw-r--r--interface-definitions/protocols-ripng.xml.in8
-rw-r--r--op-mode-definitions/dhcp.xml.in4
-rw-r--r--op-mode-definitions/flow-accounting-op.xml.in2
-rw-r--r--op-mode-definitions/force-arp.xml.in6
-rw-r--r--op-mode-definitions/force-ipv6-nd.xml.in2
-rw-r--r--op-mode-definitions/force-ipv6-rd.xml.in2
-rw-r--r--op-mode-definitions/force-mtu-host.xml.in2
-rw-r--r--op-mode-definitions/generate-openvpn-config-client.xml.in2
-rw-r--r--op-mode-definitions/generate-wireguard.xml.in2
-rw-r--r--op-mode-definitions/include/isis-common.xml.i6
-rw-r--r--op-mode-definitions/include/ospf-common.xml.i4
-rw-r--r--op-mode-definitions/include/ospfv3/interface.xml.i2
-rw-r--r--op-mode-definitions/ipv4-route.xml.in2
-rw-r--r--op-mode-definitions/ipv6-route.xml.in4
-rw-r--r--op-mode-definitions/lldp.xml.in2
-rw-r--r--op-mode-definitions/monitor-bandwidth.xml.in2
-rw-r--r--op-mode-definitions/monitor-log.xml.in4
-rw-r--r--op-mode-definitions/monitor-ndp.xml.in2
-rw-r--r--op-mode-definitions/openvpn.xml.in4
-rw-r--r--op-mode-definitions/restart-frr.xml.in6
-rw-r--r--op-mode-definitions/show-arp.xml.in2
-rw-r--r--op-mode-definitions/show-babel.xml.in41
-rw-r--r--op-mode-definitions/show-bridge.xml.in2
-rw-r--r--op-mode-definitions/show-interfaces-wireguard.xml.in2
-rw-r--r--op-mode-definitions/show-interfaces-wireless.xml.in2
-rw-r--r--op-mode-definitions/show-ip.xml.in2
-rw-r--r--op-mode-definitions/show-log.xml.in4
-rw-r--r--op-mode-definitions/show-protocols.xml.in2
-rw-r--r--op-mode-definitions/snmp.xml.in6
-rw-r--r--op-mode-definitions/wake-on-lan.xml.in2
-rw-r--r--op-mode-definitions/wireless.xml.in2
-rw-r--r--python/vyos/frr.py2
-rwxr-xr-xsrc/conf_mode/container.py21
-rwxr-xr-xsrc/conf_mode/protocols_babel.py163
-rwxr-xr-xsrc/conf_mode/system-login.py22
-rwxr-xr-xsrc/conf_mode/vpn_openconnect.py12
-rw-r--r--src/etc/dhcp/dhclient-enter-hooks.d/99-run-user-hooks5
-rwxr-xr-xsrc/etc/dhcp/dhclient-exit-hooks.d/99-run-user-hooks5
-rwxr-xr-xsrc/op_mode/generate_public_key_command.py59
-rwxr-xr-xsrc/op_mode/openvpn.py6
-rwxr-xr-xsrc/op_mode/restart_frr.py2
-rw-r--r--src/services/api/graphql/graphql/auth_token_mutation.py14
-rw-r--r--src/services/api/graphql/libs/token_auth.py7
-rw-r--r--src/services/api/graphql/session/session.py38
59 files changed, 1078 insertions, 156 deletions
diff --git a/data/templates/frr/babeld.frr.j2 b/data/templates/frr/babeld.frr.j2
new file mode 100644
index 000000000..344a5f988
--- /dev/null
+++ b/data/templates/frr/babeld.frr.j2
@@ -0,0 +1,85 @@
+{% from 'frr/distribute_list_macro.j2' import render_distribute_list %}
+{% from 'frr/ipv6_distribute_list_macro.j2' import render_ipv6_distribute_list %}
+!
+{# Interface specific configuration #}
+{% if interface is vyos_defined %}
+{% for iface, iface_config in interface.items() %}
+interface {{ iface }}
+{% if iface_config.type is vyos_defined('wired') or iface_config.type is vyos_defined('wireless') %}
+ babel {{ iface_config.type }}
+{% endif %}
+{% if iface_config.split_horizon is vyos_defined("enable") %}
+ babel split-horizon
+{% elif iface_config.split_horizon is vyos_defined("disable") %}
+ no babel split-horizon
+{% endif %}
+{% if iface_config.hello_interval is vyos_defined %}
+ babel hello-interval {{ iface_config.hello_interval }}
+{% endif %}
+{% if iface_config.update_interval is vyos_defined %}
+ babel update-interval {{ iface_config.update_interval }}
+{% endif %}
+{% if iface_config.rxcost is vyos_defined %}
+ babel rxcost {{ iface_config.rxcost }}
+{% endif %}
+{% if iface_config.rtt_decay is vyos_defined %}
+ babel rtt-decay {{ iface_config.rtt_decay }}
+{% endif %}
+{% if iface_config.rtt_min is vyos_defined %}
+ babel rtt-min {{ iface_config.rtt_min }}
+{% endif %}
+{% if iface_config.rtt_max is vyos_defined %}
+ babel rtt-max {{ iface_config.rtt_max }}
+{% endif %}
+{% if iface_config.max_rtt_penalty is vyos_defined %}
+ babel max-rtt-penalty {{ iface_config.max_rtt_penalty }}
+{% endif %}
+{% if iface_config.enable_timestamps is vyos_defined %}
+ babel enable-timestamps
+{% endif %}
+{% if iface_config.channel is vyos_defined %}
+ babel channel {{ iface_config.channel | replace("non-interfering", "noninterfering") }}
+{% endif %}
+exit
+!
+{% endfor %}
+{% endif %}
+!
+{# Babel configuration #}
+router babel
+{% if parameters.diversity is vyos_defined %}
+ babel diversity
+{% endif %}
+{% if parameters.diversity_factor is vyos_defined %}
+ babel diversity-factor {{ parameters.diversity_factor }}
+{% endif %}
+{% if parameters.resend_delay is vyos_defined %}
+ babel resend-delay {{ parameters.resend_delay }}
+{% endif %}
+{% if parameters.smoothing_half_life is vyos_defined %}
+ babel smoothing-half-life {{ parameters.smoothing_half_life }}
+{% endif %}
+{% if interface is vyos_defined %}
+{% for iface, iface_config in interface.items() %}
+ network {{ iface }}
+{% endfor %}
+{% endif %}
+{% if redistribute is vyos_defined %}
+{% for address_family in redistribute %}
+{% for protocol, protocol_config in redistribute[address_family].items() %}
+{% if protocol is vyos_defined('ospfv3') %}
+{% set protocol = 'ospf6' %}
+{% endif %}
+ redistribute {{ address_family }} {{ protocol }}
+{% endfor %}
+{% endfor %}
+{% endif %}
+{% if distribute_list.ipv4 is vyos_defined %}
+{{ render_distribute_list(distribute_list.ipv4) }}
+{% endif %}
+{% if distribute_list.ipv6 is vyos_defined %}
+{{ render_ipv6_distribute_list(distribute_list.ipv6) }}
+{% endif %}
+exit
+!
+end
diff --git a/data/templates/frr/daemons.frr.tmpl b/data/templates/frr/daemons.frr.tmpl
index df98e74d6..fdff9772a 100644
--- a/data/templates/frr/daemons.frr.tmpl
+++ b/data/templates/frr/daemons.frr.tmpl
@@ -9,7 +9,7 @@ pimd=no
ldpd=yes
nhrpd=no
eigrpd=yes
-babeld=no
+babeld=yes
sharpd=no
pbrd=no
bfdd=yes
@@ -51,4 +51,3 @@ bfdd_options=" --daemon -A 127.0.0.1"
watchfrr_enable=no
valgrind_enable=no
-
diff --git a/data/templates/frr/distribute_list_macro.j2 b/data/templates/frr/distribute_list_macro.j2
new file mode 100644
index 000000000..c10bf732d
--- /dev/null
+++ b/data/templates/frr/distribute_list_macro.j2
@@ -0,0 +1,30 @@
+{% macro render_distribute_list(distribute_list) %}
+{% if distribute_list.access_list.in is vyos_defined %}
+ distribute-list {{ distribute_list.access_list.in }} in
+{% endif %}
+{% if distribute_list.access_list.out is vyos_defined %}
+ distribute-list {{ distribute_list.access_list.out }} out
+{% endif %}
+{% if distribute_list.interface is vyos_defined %}
+{% for interface, interface_config in distribute_list.interface.items() %}
+{% if interface_config.access_list.in is vyos_defined %}
+ distribute-list {{ interface_config.access_list.in }} in {{ interface }}
+{% endif %}
+{% if interface_config.access_list.out is vyos_defined %}
+ distribute-list {{ interface_config.access_list.out }} out {{ interface }}
+{% endif %}
+{% if interface_config.prefix_list.in is vyos_defined %}
+ distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }}
+{% endif %}
+{% if interface_config.prefix_list.out is vyos_defined %}
+ distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if distribute_list.prefix_list.in is vyos_defined %}
+ distribute-list prefix {{ distribute_list.prefix_list.in }} in
+{% endif %}
+{% if distribute_list.prefix_list.out is vyos_defined %}
+ distribute-list prefix {{ distribute_list.prefix_list.out }} out
+{% endif %}
+{% endmacro %}
diff --git a/data/templates/frr/ipv6_distribute_list_macro.j2 b/data/templates/frr/ipv6_distribute_list_macro.j2
new file mode 100644
index 000000000..c365fbdae
--- /dev/null
+++ b/data/templates/frr/ipv6_distribute_list_macro.j2
@@ -0,0 +1,30 @@
+{% macro render_ipv6_distribute_list(distribute_list) %}
+{% if distribute_list.access_list.in is vyos_defined %}
+ ipv6 distribute-list {{ distribute_list.access_list.in }} in
+{% endif %}
+{% if distribute_list.access_list.out is vyos_defined %}
+ ipv6 distribute-list {{ distribute_list.access_list.out }} out
+{% endif %}
+{% if distribute_list.interface is vyos_defined %}
+{% for interface, interface_config in distribute_list.interface.items() %}
+{% if interface_config.access_list.in is vyos_defined %}
+ ipv6 distribute-list {{ interface_config.access_list.in }} in {{ interface }}
+{% endif %}
+{% if interface_config.access_list.out is vyos_defined %}
+ ipv6 distribute-list {{ interface_config.access_list.out }} out {{ interface }}
+{% endif %}
+{% if interface_config.prefix_list.in is vyos_defined %}
+ ipv6 distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }}
+{% endif %}
+{% if interface_config.prefix_list.out is vyos_defined %}
+ ipv6 distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if distribute_list.prefix_list.in is vyos_defined %}
+ ipv6 distribute-list prefix {{ distribute_list.prefix_list.in }} in
+{% endif %}
+{% if distribute_list.prefix_list.out is vyos_defined %}
+ ipv6 distribute-list prefix {{ distribute_list.prefix_list.out }} out
+{% endif %}
+{% endmacro %}
diff --git a/data/templates/frr/ripd.frr.j2 b/data/templates/frr/ripd.frr.j2
index e9e484cc2..1445bf97f 100644
--- a/data/templates/frr/ripd.frr.j2
+++ b/data/templates/frr/ripd.frr.j2
@@ -1,3 +1,4 @@
+{% from 'frr/distribute_list_macro.j2' import render_distribute_list %}
{# RIP key-chain definition #}
{% if interface is vyos_defined %}
{% for iface, iface_config in interface.items() %}
@@ -60,34 +61,7 @@ router rip
{% endfor %}
{% endif %}
{% if distribute_list is vyos_defined %}
-{% if distribute_list.access_list.in is vyos_defined %}
- distribute-list {{ distribute_list.access_list.in }} in
-{% endif %}
-{% if distribute_list.access_list.out is vyos_defined %}
- distribute-list {{ distribute_list.access_list.out }} out
-{% endif %}
-{% if distribute_list.interface is vyos_defined %}
-{% for interface, interface_config in distribute_list.interface.items() %}
-{% if interface_config.access_list.in is vyos_defined %}
- distribute-list {{ interface_config.access_list.in }} in {{ interface }}
-{% endif %}
-{% if interface_config.access_list.out is vyos_defined %}
- distribute-list {{ interface_config.access_list.out }} out {{ interface }}
-{% endif %}
-{% if interface_config.prefix_list.in is vyos_defined %}
- distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }}
-{% endif %}
-{% if interface_config.prefix_list.out is vyos_defined %}
- distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }}
-{% endif %}
-{% endfor %}
-{% endif %}
-{% if distribute_list.prefix_list.in is vyos_defined %}
- distribute-list prefix {{ distribute_list.prefix_list.in }} in
-{% endif %}
-{% if distribute_list.prefix_list.out is vyos_defined %}
- distribute-list prefix {{ distribute_list.prefix_list.out }} out
-{% endif %}
+{{ render_distribute_list(distribute_list) }}
{% endif %}
{% include 'frr/rip_ripng.frr.j2' %}
{% if version is vyos_defined %}
diff --git a/data/templates/frr/ripngd.frr.j2 b/data/templates/frr/ripngd.frr.j2
index 7919b1bad..e857e9481 100644
--- a/data/templates/frr/ripngd.frr.j2
+++ b/data/templates/frr/ripngd.frr.j2
@@ -1,3 +1,4 @@
+{% from 'frr/ipv6_distribute_list_macro.j2' import render_ipv6_distribute_list %}
{# Interface specific configuration #}
{% if interface is vyos_defined %}
{% for iface, iface_config in interface.items() %}
@@ -19,34 +20,7 @@ router ripng
{% endfor %}
{% endif %}
{% if distribute_list is vyos_defined %}
-{% if distribute_list.access_list.in is vyos_defined %}
- ipv6 distribute-list {{ distribute_list.access_list.in }} in
-{% endif %}
-{% if distribute_list.access_list.out is vyos_defined %}
- ipv6 distribute-list {{ distribute_list.access_list.out }} out
-{% endif %}
-{% if distribute_list.interface is vyos_defined %}
-{% for interface, interface_config in distribute_list.interface.items() %}
-{% if interface_config.access_list.in is vyos_defined %}
- ipv6 distribute-list {{ interface_config.access_list.in }} in {{ interface }}
-{% endif %}
-{% if interface_config.access_list.out is vyos_defined %}
- ipv6 distribute-list {{ interface_config.access_list.out }} out {{ interface }}
-{% endif %}
-{% if interface_config.prefix_list.in is vyos_defined %}
- ipv6 distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }}
-{% endif %}
-{% if interface_config.prefix_list.out is vyos_defined %}
- ipv6 distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }}
-{% endif %}
-{% endfor %}
-{% endif %}
-{% if distribute_list.prefix_list.in is vyos_defined %}
- ipv6 distribute-list prefix {{ distribute_list.prefix_list.in }} in
-{% endif %}
-{% if distribute_list.prefix_list.out is vyos_defined %}
- ipv6 distribute-list prefix {{ distribute_list.prefix_list.out }} out
-{% endif %}
+{{ render_ipv6_distribute_list(distribute_list) }}
{% endif %}
{% include 'frr/rip_ripng.frr.j2' %}
exit
diff --git a/interface-definitions/container.xml.in b/interface-definitions/container.xml.in
index b61664125..2ea1e6ab2 100644
--- a/interface-definitions/container.xml.in
+++ b/interface-definitions/container.xml.in
@@ -104,11 +104,38 @@
</leafNode>
</children>
</tagNode>
+ <leafNode name="entrypoint">
+ <properties>
+ <help>Override the default ENTRYPOINT from the image</help>
+ <constraint>
+ <regex>[ !#-%&amp;(-~]+</regex>
+ </constraint>
+ <constraintErrorMessage>Entrypoint must be ascii characters, use &amp;quot; and &amp;apos for double and single quotes respectively</constraintErrorMessage>
+ </properties>
+ </leafNode>
<leafNode name="image">
<properties>
<help>Image name in the hub-registry</help>
</properties>
</leafNode>
+ <leafNode name="command">
+ <properties>
+ <help>Override the default CMD from the image</help>
+ <constraint>
+ <regex>[ !#-%&amp;(-~]+</regex>
+ </constraint>
+ <constraintErrorMessage>Command must be ascii characters, use &amp;quot; and &amp;apos for double and single quotes respectively</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ <leafNode name="arguments">
+ <properties>
+ <help>The command's arguments for this container</help>
+ <constraint>
+ <regex>[ !#-%&amp;(-~]+</regex>
+ </constraint>
+ <constraintErrorMessage>The command's arguments must be ascii characters, use &amp;quot; and &amp;apos for double and single quotes respectively</constraintErrorMessage>
+ </properties>
+ </leafNode>
<leafNode name="memory">
<properties>
<help>Memory (RAM) available to this container</help>
diff --git a/interface-definitions/include/babel/interface.xml.i b/interface-definitions/include/babel/interface.xml.i
new file mode 100644
index 000000000..549e4909d
--- /dev/null
+++ b/interface-definitions/include/babel/interface.xml.i
@@ -0,0 +1,187 @@
+<!-- include start from babel/interface.xml.i -->
+<tagNode name="interface">
+ <properties>
+ <help>Interface name</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface name</description>
+ </valueHelp>
+ <constraint>
+ #include <include/constraint/interface-name.xml.in>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="type">
+ <properties>
+ <help>Interface type</help>
+ <completionHelp>
+ <list>auto wired wireless</list>
+ </completionHelp>
+ <valueHelp>
+ <format>auto</format>
+ <description>Automatically detect interface type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>wired</format>
+ <description>Wired interface</description>
+ </valueHelp>
+ <valueHelp>
+ <format>wireless</format>
+ <description>Wireless interface</description>
+ </valueHelp>
+ <constraint>
+ <regex>(auto|wired|wireless)</regex>
+ </constraint>
+ </properties>
+ <defaultValue>auto</defaultValue>
+ </leafNode>
+ <leafNode name="split-horizon">
+ <properties>
+ <help>Split horizon parameters</help>
+ <completionHelp>
+ <list>default enable disable</list>
+ </completionHelp>
+ <valueHelp>
+ <format>default</format>
+ <description>Enable on wired interfaces, and disable on wireless interfaces</description>
+ </valueHelp>
+ <valueHelp>
+ <format>enable</format>
+ <description>Enable split horizon processing</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disable</format>
+ <description>Disable split horizon processing</description>
+ </valueHelp>
+ <constraint>
+ <regex>(default|enable|disable)</regex>
+ </constraint>
+ </properties>
+ <defaultValue>default</defaultValue>
+ </leafNode>
+ <leafNode name="hello-interval">
+ <properties>
+ <help>Time between scheduled hellos</help>
+ <valueHelp>
+ <format>u32:20-655340</format>
+ <description>Milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 20-655340"/>
+ </constraint>
+ </properties>
+ <defaultValue>4000</defaultValue>
+ </leafNode>
+ <leafNode name="update-interval">
+ <properties>
+ <help>Time between scheduled updates</help>
+ <valueHelp>
+ <format>u32:20-655340</format>
+ <description>Milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 20-655340"/>
+ </constraint>
+ </properties>
+ <defaultValue>20000</defaultValue>
+ </leafNode>
+ <leafNode name="rxcost">
+ <properties>
+ <help>Base receive cost for this interface</help>
+ <valueHelp>
+ <format>u32:1-65534</format>
+ <description>Base receive cost</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65534"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="rtt-decay">
+ <properties>
+ <help>Decay factor for exponential moving average of RTT samples</help>
+ <valueHelp>
+ <format>u32:1-256</format>
+ <description>Decay factor, in units of 1/256</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-256"/>
+ </constraint>
+ </properties>
+ <defaultValue>42</defaultValue>
+ </leafNode>
+ <leafNode name="rtt-min">
+ <properties>
+ <help>Minimum RTT</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>10</defaultValue>
+ </leafNode>
+ <leafNode name="rtt-max">
+ <properties>
+ <help>Maximum RTT</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>120</defaultValue>
+ </leafNode>
+ <leafNode name="max-rtt-penalty">
+ <properties>
+ <help>Maximum additional cost due to RTT</help>
+ <valueHelp>
+ <format>u32:0-65535</format>
+ <description>Milliseconds (0 to disable the use of RTT-based cost)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>150</defaultValue>
+ </leafNode>
+ <leafNode name="enable-timestamps">
+ <properties>
+ <help>Enable timestamps with each Hello and IHU message in order to compute RTT values</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="channel">
+ <properties>
+ <help>Channel number for diversity routing</help>
+ <completionHelp>
+ <list>interfering non-interfering</list>
+ </completionHelp>
+ <valueHelp>
+ <format>u32:1-254</format>
+ <description>Interfaces with a channel number interfere with interfering interfaces and interfaces with the same channel number</description>
+ </valueHelp>
+ <valueHelp>
+ <format>interfering</format>
+ <description>Interfering interfaces are assumed to interfere with all other channels except non-interfering channels</description>
+ </valueHelp>
+ <valueHelp>
+ <format>non-interfering</format>
+ <description>Non-interfering interfaces only interfere with themselves</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-254"/>
+ <regex>(interfering|non-interfering)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</tagNode>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i
index ec065347c..0d88c7b25 100644
--- a/interface-definitions/include/bgp/protocol-common-config.xml.i
+++ b/interface-definitions/include/bgp/protocol-common-config.xml.i
@@ -165,6 +165,14 @@
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
+ <node name="babel">
+ <properties>
+ <help>Redistribute Babel routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
<node name="static">
<properties>
<help>Redistribute static routes into BGP</help>
@@ -542,6 +550,14 @@
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
+ <node name="babel">
+ <properties>
+ <help>Redistribute Babel routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
<node name="static">
<properties>
<help>Redistribute static routes into BGP</help>
diff --git a/interface-definitions/include/eigrp/protocol-common-config.xml.i b/interface-definitions/include/eigrp/protocol-common-config.xml.i
index 147277102..30ddc5d11 100644
--- a/interface-definitions/include/eigrp/protocol-common-config.xml.i
+++ b/interface-definitions/include/eigrp/protocol-common-config.xml.i
@@ -87,6 +87,10 @@
<description>Routing Information Protocol (RIP)</description>
</valueHelp>
<valueHelp>
+ <format>babel</format>
+ <description>Babel routing protocol (Babel)</description>
+ </valueHelp>
+ <valueHelp>
<format>static</format>
<description>Statically configured routes</description>
</valueHelp>
@@ -98,7 +102,7 @@
<list>bgp connected nhrp ospf rip static vnc</list>
</completionHelp>
<constraint>
- <regex>(bgp|connected|nhrp|ospf|rip|static|vnc)</regex>
+ <regex>(bgp|connected|nhrp|ospf|rip|babel|static|vnc)</regex>
</constraint>
<multi/>
</properties>
diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i
index 42bda7a80..c44939528 100644
--- a/interface-definitions/include/isis/protocol-common-config.xml.i
+++ b/interface-definitions/include/isis/protocol-common-config.xml.i
@@ -394,6 +394,14 @@
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
+ <node name="babel">
+ <properties>
+ <help>Redistribute Babel routes into IS-IS</help>
+ </properties>
+ <children>
+ #include <include/isis/redistribute-level-1-2.xml.i>
+ </children>
+ </node>
<node name="static">
<properties>
<help>Redistribute static routes into IS-IS</help>
@@ -449,6 +457,14 @@
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
+ <node name="babel">
+ <properties>
+ <help>Redistribute Babel routes into IS-IS</help>
+ </properties>
+ <children>
+ #include <include/isis/redistribute-level-1-2.xml.i>
+ </children>
+ </node>
<node name="static">
<properties>
<help>Redistribute static routes into IS-IS</help>
@@ -670,4 +686,4 @@
</children>
</tagNode>
#include <include/route-map.xml.i>
-<!-- include end --> \ No newline at end of file
+<!-- include end -->
diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i
index 06609c10e..16b346131 100644
--- a/interface-definitions/include/ospf/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospf/protocol-common-config.xml.i
@@ -756,6 +756,16 @@
#include <include/route-map.xml.i>
</children>
</node>
+ <node name="babel">
+ <properties>
+ <help>Redistribute Babel routes</help>
+ </properties>
+ <children>
+ #include <include/ospf/metric.xml.i>
+ #include <include/ospf/metric-type.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
<node name="static">
<properties>
<help>Redistribute statically configured routes</help>
diff --git a/interface-definitions/include/ospfv3/protocol-common-config.xml.i b/interface-definitions/include/ospfv3/protocol-common-config.xml.i
index c0aab912d..fd00af95e 100644
--- a/interface-definitions/include/ospfv3/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospfv3/protocol-common-config.xml.i
@@ -238,6 +238,14 @@
#include <include/route-map.xml.i>
</children>
</node>
+ <node name="babel">
+ <properties>
+ <help>Redistribute Babel routes</help>
+ </properties>
+ <children>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
<node name="static">
<properties>
<help>Redistribute static routes</help>
diff --git a/interface-definitions/protocols-babel.xml.in b/interface-definitions/protocols-babel.xml.in
new file mode 100644
index 000000000..0ef833077
--- /dev/null
+++ b/interface-definitions/protocols-babel.xml.in
@@ -0,0 +1,254 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="protocols">
+ <children>
+ <node name="babel" owner="${vyos_conf_scripts_dir}/protocols_babel.py">
+ <properties>
+ <help>Babel Routing Protocol</help>
+ <priority>650</priority>
+ </properties>
+ <children>
+ <node name="parameters">
+ <properties>
+ <help>Babel-specific parameters</help>
+ </properties>
+ <children>
+ <leafNode name="diversity">
+ <properties>
+ <help>Enable diversity-aware routing</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="diversity-factor">
+ <properties>
+ <help>Multiplicative factor used for diversity routing</help>
+ <valueHelp>
+ <format>u32:1-256</format>
+ <description>Multiplicative factor, in units of 1/256</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-256"/>
+ </constraint>
+ </properties>
+ <defaultValue>256</defaultValue>
+ </leafNode>
+ <leafNode name="resend-delay">
+ <properties>
+ <help>Time before resending a message</help>
+ <valueHelp>
+ <format>u32:20-655340</format>
+ <description>Milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 20-655340"/>
+ </constraint>
+ </properties>
+ <defaultValue>2000</defaultValue>
+ </leafNode>
+ <leafNode name="smoothing-half-life">
+ <properties>
+ <help>Smoothing half-life</help>
+ <valueHelp>
+ <format>u32:0-65534</format>
+ <description>Seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-65534"/>
+ </constraint>
+ </properties>
+ <defaultValue>4</defaultValue>
+ </leafNode>
+ </children>
+ </node>
+ #include <include/babel/interface.xml.i>
+ <node name="redistribute">
+ <properties>
+ <help>Redistribute information from another routing protocol</help>
+ </properties>
+ <children>
+ <node name="ipv4">
+ <properties>
+ <help>Redistribute IPv4 routes</help>
+ </properties>
+ <children>
+ <leafNode name="bgp">
+ <properties>
+ <help>Redistribute BGP routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="connected">
+ <properties>
+ <help>Redistribute connected routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="eigrp">
+ <properties>
+ <help>Redistribute EIGRP routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="isis">
+ <properties>
+ <help>Redistribute IS-IS routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="kernel">
+ <properties>
+ <help>Redistribute kernel routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="nhrp">
+ <properties>
+ <help>Redistribute NHRP routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ospf">
+ <properties>
+ <help>Redistribute OSPF routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="rip">
+ <properties>
+ <help>Redistribute RIP routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="static">
+ <properties>
+ <help>Redistribute static routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <node name="ipv6">
+ <properties>
+ <help>Redistribute IPv6 routes</help>
+ </properties>
+ <children>
+ <leafNode name="bgp">
+ <properties>
+ <help>Redistribute BGP routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="connected">
+ <properties>
+ <help>Redistribute connected routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="isis">
+ <properties>
+ <help>Redistribute IS-IS routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="kernel">
+ <properties>
+ <help>Redistribute kernel routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="nhrp">
+ <properties>
+ <help>Redistribute NHRP routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ospfv3">
+ <properties>
+ <help>Redistribute OSPFv3 routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ripng">
+ <properties>
+ <help>Redistribute RIPng routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="static">
+ <properties>
+ <help>Redistribute static routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <node name="distribute-list">
+ <properties>
+ <help>Filter networks in routing updates</help>
+ </properties>
+ <children>
+ <node name="ipv4">
+ <properties>
+ <help>Filter IPv4 routes</help>
+ </properties>
+ <children>
+ #include <include/rip/access-list.xml.i>
+ <tagNode name="interface">
+ <properties>
+ <help>Apply filtering to an interface</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Apply filtering to an interface</description>
+ </valueHelp>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <constraint>
+ #include <include/constraint/interface-name.xml.in>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/rip/access-list.xml.i>
+ #include <include/rip/prefix-list.xml.i>
+ </children>
+ </tagNode>
+ #include <include/rip/prefix-list.xml.i>
+ </children>
+ </node>
+ <node name="ipv6">
+ <properties>
+ <help>Filter IPv6 routes</help>
+ </properties>
+ <children>
+ #include <include/rip/access-list6.xml.i>
+ <tagNode name="interface">
+ <properties>
+ <help>Apply filtering to an interface</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Apply filtering to an interface</description>
+ </valueHelp>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <constraint>
+ #include <include/constraint/interface-name.xml.in>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/rip/access-list6.xml.i>
+ #include <include/rip/prefix-list6.xml.i>
+ </children>
+ </tagNode>
+ #include <include/rip/prefix-list6.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/interface-definitions/protocols-rip.xml.in b/interface-definitions/protocols-rip.xml.in
index 33aae5015..b5d48090a 100644
--- a/interface-definitions/protocols-rip.xml.in
+++ b/interface-definitions/protocols-rip.xml.in
@@ -225,6 +225,14 @@
#include <include/rip/redistribute.xml.i>
</children>
</node>
+ <node name="babel">
+ <properties>
+ <help>Redistribute Babel routes</help>
+ </properties>
+ <children>
+ #include <include/rip/redistribute.xml.i>
+ </children>
+ </node>
</children>
</node>
<leafNode name="route">
@@ -248,4 +256,3 @@
</children>
</node>
</interfaceDefinition>
-
diff --git a/interface-definitions/protocols-ripng.xml.in b/interface-definitions/protocols-ripng.xml.in
index cd35dbf53..cf000b824 100644
--- a/interface-definitions/protocols-ripng.xml.in
+++ b/interface-definitions/protocols-ripng.xml.in
@@ -123,6 +123,14 @@
#include <include/rip/redistribute.xml.i>
</children>
</node>
+ <node name="babel">
+ <properties>
+ <help>Redistribute Babel routes</help>
+ </properties>
+ <children>
+ #include <include/rip/redistribute.xml.i>
+ </children>
+ </node>
</children>
</node>
<leafNode name="route">
diff --git a/op-mode-definitions/dhcp.xml.in b/op-mode-definitions/dhcp.xml.in
index 419abe7ad..66584efc3 100644
--- a/op-mode-definitions/dhcp.xml.in
+++ b/op-mode-definitions/dhcp.xml.in
@@ -175,7 +175,7 @@
<properties>
<help>Renew DHCP client lease for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>sudo systemctl restart "dhclient@$4.service"</command>
@@ -191,7 +191,7 @@
<properties>
<help>Renew DHCPv6 client lease for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>sudo systemctl restart "dhcp6c@$4.service"</command>
diff --git a/op-mode-definitions/flow-accounting-op.xml.in b/op-mode-definitions/flow-accounting-op.xml.in
index 7aaae5974..46dc77d05 100644
--- a/op-mode-definitions/flow-accounting-op.xml.in
+++ b/op-mode-definitions/flow-accounting-op.xml.in
@@ -13,7 +13,7 @@
<properties>
<help>Show flow accounting statistics for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/flow_accounting_op.py --action show --interface $4</command>
diff --git a/op-mode-definitions/force-arp.xml.in b/op-mode-definitions/force-arp.xml.in
index f9f7c7643..05aa04e6b 100644
--- a/op-mode-definitions/force-arp.xml.in
+++ b/op-mode-definitions/force-arp.xml.in
@@ -19,7 +19,7 @@
<properties>
<help>Send gratuitous ARP reply on specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<children>
@@ -50,7 +50,7 @@
<properties>
<help>Send gratuitous ARP request on specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<children>
@@ -81,7 +81,7 @@
<properties>
<help>Send ARP for DAD detection on specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<children>
diff --git a/op-mode-definitions/force-ipv6-nd.xml.in b/op-mode-definitions/force-ipv6-nd.xml.in
index 49de097f6..664fee4fb 100644
--- a/op-mode-definitions/force-ipv6-nd.xml.in
+++ b/op-mode-definitions/force-ipv6-nd.xml.in
@@ -11,7 +11,7 @@
<properties>
<help>IPv6 Neighbor Discovery on specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<children>
diff --git a/op-mode-definitions/force-ipv6-rd.xml.in b/op-mode-definitions/force-ipv6-rd.xml.in
index 8c901af25..c81b81a49 100644
--- a/op-mode-definitions/force-ipv6-rd.xml.in
+++ b/op-mode-definitions/force-ipv6-rd.xml.in
@@ -11,7 +11,7 @@
<properties>
<help>IPv6 Router Discovery on specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>/usr/bin/rdisc6 "$4"</command>
diff --git a/op-mode-definitions/force-mtu-host.xml.in b/op-mode-definitions/force-mtu-host.xml.in
index b92179f11..56241678a 100644
--- a/op-mode-definitions/force-mtu-host.xml.in
+++ b/op-mode-definitions/force-mtu-host.xml.in
@@ -20,7 +20,7 @@
<properties>
<help>Source interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/force_mtu_host.sh $4 $6</command>
diff --git a/op-mode-definitions/generate-openvpn-config-client.xml.in b/op-mode-definitions/generate-openvpn-config-client.xml.in
index baec0842b..fc8bfa346 100644
--- a/op-mode-definitions/generate-openvpn-config-client.xml.in
+++ b/op-mode-definitions/generate-openvpn-config-client.xml.in
@@ -16,7 +16,7 @@
<properties>
<help>Local interface used for connection</help>
<completionHelp>
- <path>interfaces openvpn</path>
+ <script>${vyos_completion_dir}/list_interfaces --type openvpn</script>
</completionHelp>
</properties>
<children>
diff --git a/op-mode-definitions/generate-wireguard.xml.in b/op-mode-definitions/generate-wireguard.xml.in
index 6c01619be..1dcafcd8b 100644
--- a/op-mode-definitions/generate-wireguard.xml.in
+++ b/op-mode-definitions/generate-wireguard.xml.in
@@ -19,7 +19,7 @@
<properties>
<help>Local interface used for connection</help>
<completionHelp>
- <path>interfaces wireguard</path>
+ <script>${vyos_completion_dir}/list_interfaces --type wireguard</script>
</completionHelp>
</properties>
<children>
diff --git a/op-mode-definitions/include/isis-common.xml.i b/op-mode-definitions/include/isis-common.xml.i
index 5674bc22f..95a171515 100644
--- a/op-mode-definitions/include/isis-common.xml.i
+++ b/op-mode-definitions/include/isis-common.xml.i
@@ -32,7 +32,7 @@
<properties>
<help>Show IS-IS interfaces</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<children>
@@ -49,7 +49,7 @@
<properties>
<help>Show specific IS-IS interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
@@ -75,7 +75,7 @@
<properties>
<help>Show specific IS-IS interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
diff --git a/op-mode-definitions/include/ospf-common.xml.i b/op-mode-definitions/include/ospf-common.xml.i
index 23769c8ba..098254f4e 100644
--- a/op-mode-definitions/include/ospf-common.xml.i
+++ b/op-mode-definitions/include/ospf-common.xml.i
@@ -512,7 +512,7 @@
<properties>
<help>Show IPv4 OSPF information for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
@@ -536,7 +536,7 @@
<help>Show IPv4 OSPF neighbor information for specified IP address or interface</help>
<completionHelp>
<list>&lt;x.x.x.x&gt;</list>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
diff --git a/op-mode-definitions/include/ospfv3/interface.xml.i b/op-mode-definitions/include/ospfv3/interface.xml.i
index 0fb66257d..7a0b8ea48 100644
--- a/op-mode-definitions/include/ospfv3/interface.xml.i
+++ b/op-mode-definitions/include/ospfv3/interface.xml.i
@@ -38,7 +38,7 @@
<properties>
<help>Specific insterface to examine</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
diff --git a/op-mode-definitions/ipv4-route.xml.in b/op-mode-definitions/ipv4-route.xml.in
index 660b34496..17a0a4ad9 100644
--- a/op-mode-definitions/ipv4-route.xml.in
+++ b/op-mode-definitions/ipv4-route.xml.in
@@ -45,7 +45,7 @@
<properties>
<help>Reset ARP cache for interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>sudo ${vyos_op_scripts_dir}/neighbor.py reset --family inet --interface "$5"</command>
diff --git a/op-mode-definitions/ipv6-route.xml.in b/op-mode-definitions/ipv6-route.xml.in
index 46e416a8a..5ed0b9dba 100644
--- a/op-mode-definitions/ipv6-route.xml.in
+++ b/op-mode-definitions/ipv6-route.xml.in
@@ -26,7 +26,7 @@
<properties>
<help>Show IPv6 neighbor table for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/neighbor.py show --family inet6 --interface "$5"</command>
@@ -71,7 +71,7 @@
<properties>
<help>Reset IPv6 ND cache for interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>sudo ip -f inet6 neigh flush dev "$5"</command>
diff --git a/op-mode-definitions/lldp.xml.in b/op-mode-definitions/lldp.xml.in
index 07cafa77f..985262a89 100644
--- a/op-mode-definitions/lldp.xml.in
+++ b/op-mode-definitions/lldp.xml.in
@@ -17,7 +17,7 @@
<properties>
<help>Show LLDP for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/lldp.py show_neighbors --interface $5</command>
diff --git a/op-mode-definitions/monitor-bandwidth.xml.in b/op-mode-definitions/monitor-bandwidth.xml.in
index 9af0a9e70..2da9d34f4 100644
--- a/op-mode-definitions/monitor-bandwidth.xml.in
+++ b/op-mode-definitions/monitor-bandwidth.xml.in
@@ -12,7 +12,7 @@
<properties>
<help>Monitor bandwidth usage on specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
</tagNode>
diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in
index d5892398b..06b1cf129 100644
--- a/op-mode-definitions/monitor-log.xml.in
+++ b/op-mode-definitions/monitor-log.xml.in
@@ -48,7 +48,7 @@
<properties>
<help>Show DHCP client log on specific interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<command>journalctl --no-hostname --follow --boot --unit "dhclient@$6.service"</command>
@@ -78,7 +78,7 @@
<properties>
<help>Show DHCPv6 client log on specific interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>journalctl --no-hostname --follow --boot --unit "dhcp6c@$6.service"</command>
diff --git a/op-mode-definitions/monitor-ndp.xml.in b/op-mode-definitions/monitor-ndp.xml.in
index 1ac6ce39b..26d881f1a 100644
--- a/op-mode-definitions/monitor-ndp.xml.in
+++ b/op-mode-definitions/monitor-ndp.xml.in
@@ -13,7 +13,7 @@
<properties>
<help>Monitor ndp protocol on specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<children>
diff --git a/op-mode-definitions/openvpn.xml.in b/op-mode-definitions/openvpn.xml.in
index 0a2657398..0aa9c3209 100644
--- a/op-mode-definitions/openvpn.xml.in
+++ b/op-mode-definitions/openvpn.xml.in
@@ -20,7 +20,7 @@
<properties>
<help>Reset OpenVPN process on interface</help>
<completionHelp>
- <path>interfaces openvpn</path>
+ <script>sudo ${vyos_completion_dir}/list_interfaces --type openvpn</script>
</completionHelp>
</properties>
<command>sudo ${vyos_op_scripts_dir}/openvpn.py reset --interface $4</command>
@@ -51,7 +51,7 @@
<properties>
<help>Show OpenVPN interface information</help>
<completionHelp>
- <path>interfaces openvpn</path>
+ <script>sudo ${vyos_completion_dir}/list_interfaces --type openvpn</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/interfaces.py show --intf_name=$4</command>
diff --git a/op-mode-definitions/restart-frr.xml.in b/op-mode-definitions/restart-frr.xml.in
index 4e2be1bf2..4572858b5 100644
--- a/op-mode-definitions/restart-frr.xml.in
+++ b/op-mode-definitions/restart-frr.xml.in
@@ -68,6 +68,12 @@
</properties>
<command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon zebra</command>
</leafNode>
+ <leafNode name="babel">
+ <properties>
+ <help>Restart Babel routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon babeld</command>
+ </leafNode>
</children>
</node>
</interfaceDefinition>
diff --git a/op-mode-definitions/show-arp.xml.in b/op-mode-definitions/show-arp.xml.in
index 3680c20c6..84170f070 100644
--- a/op-mode-definitions/show-arp.xml.in
+++ b/op-mode-definitions/show-arp.xml.in
@@ -12,7 +12,7 @@
<properties>
<help>Show Address Resolution Protocol (ARP) cache for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/neighbor.py show --family inet --interface "$4"</command>
diff --git a/op-mode-definitions/show-babel.xml.in b/op-mode-definitions/show-babel.xml.in
new file mode 100644
index 000000000..3aac3764e
--- /dev/null
+++ b/op-mode-definitions/show-babel.xml.in
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="show">
+ <children>
+ <node name="babel">
+ <properties>
+ <help>Show Babel routing protocol information</help>
+ </properties>
+ <children>
+ <leafNode name="interface">
+ <properties>
+ <help>Show Babel Interface information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="neighbor">
+ <properties>
+ <help>Show Babel neighbor information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <tagNode name="neighbor">
+ <properties>
+ <help>Show Babel neighbor information for specified interface</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </tagNode>
+ <leafNode name="route">
+ <properties>
+ <help>Show Babel route information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/op-mode-definitions/show-bridge.xml.in b/op-mode-definitions/show-bridge.xml.in
index e7a646fdc..acf3a00c7 100644
--- a/op-mode-definitions/show-bridge.xml.in
+++ b/op-mode-definitions/show-bridge.xml.in
@@ -25,7 +25,7 @@
<properties>
<help>Show bridge information for a given bridge interface</help>
<completionHelp>
- <path>interfaces bridge</path>
+ <script>${vyos_completion_dir}/list_interfaces --type bridge</script>
</completionHelp>
</properties>
<command>bridge -c link show | grep "master $3"</command>
diff --git a/op-mode-definitions/show-interfaces-wireguard.xml.in b/op-mode-definitions/show-interfaces-wireguard.xml.in
index 75b0cc88e..d045beafc 100644
--- a/op-mode-definitions/show-interfaces-wireguard.xml.in
+++ b/op-mode-definitions/show-interfaces-wireguard.xml.in
@@ -8,7 +8,7 @@
<properties>
<help>Show specified WireGuard interface information</help>
<completionHelp>
- <path>interfaces wireguard</path>
+ <script>${vyos_completion_dir}/list_interfaces --type wireguard</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wireguard</command>
diff --git a/op-mode-definitions/show-interfaces-wireless.xml.in b/op-mode-definitions/show-interfaces-wireless.xml.in
index cdd591f82..f39d402f1 100644
--- a/op-mode-definitions/show-interfaces-wireless.xml.in
+++ b/op-mode-definitions/show-interfaces-wireless.xml.in
@@ -28,7 +28,7 @@
<properties>
<help>Show specified wireless interface information</help>
<completionHelp>
- <path>interfaces wireless</path>
+ <script>${vyos_completion_dir}/list_interfaces --type wireless</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wireless</command>
diff --git a/op-mode-definitions/show-ip.xml.in b/op-mode-definitions/show-ip.xml.in
index a710e33d2..d5dbb7850 100644
--- a/op-mode-definitions/show-ip.xml.in
+++ b/op-mode-definitions/show-ip.xml.in
@@ -17,7 +17,7 @@
<properties>
<help>Show IPv4 neighbor table for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/neighbor.py show --family inet --interface "$5"</command>
diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in
index c626e45fb..7f6469ca9 100644
--- a/op-mode-definitions/show-log.xml.in
+++ b/op-mode-definitions/show-log.xml.in
@@ -66,7 +66,7 @@
<properties>
<help>Show DHCP client log on specific interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<command>journalctl --no-hostname --boot --unit "dhclient@$6.service"</command>
@@ -96,7 +96,7 @@
<properties>
<help>Show DHCPv6 client log on specific interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>journalctl --no-hostname --boot --unit "dhcp6c@$6.service"</command>
diff --git a/op-mode-definitions/show-protocols.xml.in b/op-mode-definitions/show-protocols.xml.in
index 27146f90d..8f98f3a4c 100644
--- a/op-mode-definitions/show-protocols.xml.in
+++ b/op-mode-definitions/show-protocols.xml.in
@@ -22,7 +22,7 @@
<properties>
<help>Show Address Resolution Protocol (ARP) cache for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
+ <script>${vyos_completion_dir}/list_interfaces --broadcast</script>
</completionHelp>
</properties>
<command>/usr/sbin/arp -e -n -i "$6"</command>
diff --git a/op-mode-definitions/snmp.xml.in b/op-mode-definitions/snmp.xml.in
index a0a47da40..894005e7b 100644
--- a/op-mode-definitions/snmp.xml.in
+++ b/op-mode-definitions/snmp.xml.in
@@ -39,7 +39,7 @@
<properties>
<help>Show SNMP ifAlias for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/snmp_ifmib.py --ifalias="$6"</command>
@@ -48,7 +48,7 @@
<properties>
<help>Show SNMP ifDescr for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/snmp_ifmib.py --ifdescr="$6"</command>
@@ -57,7 +57,7 @@
<properties>
<help>Show SNMP ifDescr for specified interface</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/snmp_ifmib.py --ifindex="$6"</command>
diff --git a/op-mode-definitions/wake-on-lan.xml.in b/op-mode-definitions/wake-on-lan.xml.in
index 1a9b88596..7119eeb65 100644
--- a/op-mode-definitions/wake-on-lan.xml.in
+++ b/op-mode-definitions/wake-on-lan.xml.in
@@ -9,7 +9,7 @@
<properties>
<help>Interface where the station is connected</help>
<completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
+ <script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<children>
diff --git a/op-mode-definitions/wireless.xml.in b/op-mode-definitions/wireless.xml.in
index f8e53ad21..25809e0b8 100644
--- a/op-mode-definitions/wireless.xml.in
+++ b/op-mode-definitions/wireless.xml.in
@@ -21,7 +21,7 @@
<properties>
<help>Clear interface information for a given wireless interface</help>
<completionHelp>
- <path>interfaces wireless</path>
+ <script>${vyos_completion_dir}/list_interfaces --type wireless</script>
</completionHelp>
</properties>
<children>
diff --git a/python/vyos/frr.py b/python/vyos/frr.py
index ccb132dd5..a84f183ef 100644
--- a/python/vyos/frr.py
+++ b/python/vyos/frr.py
@@ -85,7 +85,7 @@ LOG.addHandler(ch2)
_frr_daemons = ['zebra', 'bgpd', 'fabricd', 'isisd', 'ospf6d', 'ospfd', 'pbrd',
'pimd', 'ripd', 'ripngd', 'sharpd', 'staticd', 'vrrpd', 'ldpd',
- 'bfdd', 'eigrpd']
+ 'bfdd', 'eigrpd', 'babeld']
path_vtysh = '/usr/bin/vtysh'
path_frr_reload = '/usr/lib/frr/frr-reload.py'
diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py
index 90e5f84f2..4f93c93a1 100755
--- a/src/conf_mode/container.py
+++ b/src/conf_mode/container.py
@@ -279,8 +279,22 @@ def generate_run_arguments(name, container_config):
f'--memory {memory}m --shm-size {shared_memory}m --memory-swap 0 --restart {restart} ' \
f'--name {name} {device} {port} {volume} {env_opt}'
+ entrypoint = ''
+ if 'entrypoint' in container_config:
+ # it needs to be json-formatted with single quote on the outside
+ entrypoint = json_write(container_config['entrypoint'].split()).replace('"', "&quot;")
+ entrypoint = f'--entrypoint &apos;{entrypoint}&apos;'
+
+ command = ''
+ if 'command' in container_config:
+ command = container_config['command'].strip()
+
+ command_arguments = ''
+ if 'arguments' in container_config:
+ command_arguments = container_config['arguments'].strip()
+
if 'allow_host_networks' in container_config:
- return f'{container_base_cmd} --net host {image}'
+ return f'{container_base_cmd} --net host {entrypoint} {image} {command} {command_arguments}'.strip()
ip_param = ''
networks = ",".join(container_config['network'])
@@ -289,7 +303,7 @@ def generate_run_arguments(name, container_config):
address = container_config['network'][network]['address']
ip_param = f'--ip {address}'
- return f'{container_base_cmd} --net {networks} {ip_param} {image}'
+ return f'{container_base_cmd} --net {networks} {ip_param} {entrypoint} {image} {command} {command_arguments}'.strip()
def generate(container):
# bail out early - looks like removal from running config
@@ -341,7 +355,8 @@ def generate(container):
file_path = os.path.join(systemd_unit_path, f'vyos-container-{name}.service')
run_args = generate_run_arguments(name, container_config)
- render(file_path, 'container/systemd-unit.j2', {'name': name, 'run_args': run_args})
+ render(file_path, 'container/systemd-unit.j2', {'name': name, 'run_args': run_args,},
+ formater=lambda _: _.replace("&quot;", '"').replace("&apos;", "'"))
return None
diff --git a/src/conf_mode/protocols_babel.py b/src/conf_mode/protocols_babel.py
new file mode 100755
index 000000000..20821c7f2
--- /dev/null
+++ b/src/conf_mode/protocols_babel.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021-2023 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.configdict import dict_merge
+from vyos.configdict import node_changed
+from vyos.configverify import verify_common_route_maps
+from vyos.configverify import verify_access_list
+from vyos.configverify import verify_prefix_list
+from vyos.util import dict_search
+from vyos.xml import defaults
+from vyos.template import render_to_string
+from vyos import ConfigError
+from vyos import frr
+from vyos import airbag
+airbag.enable()
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+ base = ['protocols', 'babel']
+ babel = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+
+ # FRR has VRF support for different routing daemons. As interfaces belong
+ # to VRFs - or the global VRF, we need to check for changed interfaces so
+ # that they will be properly rendered for the FRR config. Also this eases
+ # removal of interfaces from the running configuration.
+ interfaces_removed = node_changed(conf, base + ['interface'])
+ if interfaces_removed:
+ babel['interface_removed'] = list(interfaces_removed)
+
+ # Bail out early if configuration tree does not exist
+ if not conf.exists(base):
+ babel.update({'deleted' : ''})
+ return babel
+
+ # 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)
+
+ # XXX: T2665: we currently have no nice way for defaults under tag nodes,
+ # clean them out and add them manually :(
+ del default_values['interface']
+
+ # merge in remaining default values
+ babel = dict_merge(default_values, babel)
+
+ # We also need some additional information from the config, prefix-lists
+ # and route-maps for instance. They will be used in verify().
+ #
+ # XXX: one MUST always call this without the key_mangling() option! See
+ # vyos.configverify.verify_common_route_maps() for more information.
+ tmp = conf.get_config_dict(['policy'])
+ # Merge policy dict into "regular" config dict
+ babel = dict_merge(tmp, babel)
+ return babel
+
+def verify(babel):
+ if not babel:
+ return None
+
+ # verify distribute_list
+ if "distribute_list" in babel:
+ acl_keys = {
+ "ipv4": [
+ "distribute_list.ipv4.access_list.in",
+ "distribute_list.ipv4.access_list.out",
+ ],
+ "ipv6": [
+ "distribute_list.ipv6.access_list.in",
+ "distribute_list.ipv6.access_list.out",
+ ]
+ }
+ prefix_list_keys = {
+ "ipv4": [
+ "distribute_list.ipv4.prefix_list.in",
+ "distribute_list.ipv4.prefix_list.out",
+ ],
+ "ipv6":[
+ "distribute_list.ipv6.prefix_list.in",
+ "distribute_list.ipv6.prefix_list.out",
+ ]
+ }
+ for address_family in ["ipv4", "ipv6"]:
+ for iface_key in babel["distribute_list"].get(address_family, {}).get("interface", {}).keys():
+ acl_keys[address_family].extend([
+ f"distribute_list.{address_family}.interface.{iface_key}.access_list.in",
+ f"distribute_list.{address_family}.interface.{iface_key}.access_list.out"
+ ])
+ prefix_list_keys[address_family].extend([
+ f"distribute_list.{address_family}.interface.{iface_key}.prefix_list.in",
+ f"distribute_list.{address_family}.interface.{iface_key}.prefix_list.out"
+ ])
+
+ for address_family, keys in acl_keys.items():
+ for key in keys:
+ acl = dict_search(key, babel)
+ if acl:
+ verify_access_list(acl, babel, version='6' if address_family == 'ipv6' else '')
+
+ for address_family, keys in prefix_list_keys.items():
+ for key in keys:
+ prefix_list = dict_search(key, babel)
+ if prefix_list:
+ verify_prefix_list(prefix_list, babel, version='6' if address_family == 'ipv6' else '')
+
+
+def generate(babel):
+ if not babel or 'deleted' in babel:
+ return None
+
+ babel['new_frr_config'] = render_to_string('frr/babeld.frr.j2', babel)
+ return None
+
+def apply(babel):
+ babel_daemon = 'babeld'
+
+ # Save original configuration prior to starting any commit actions
+ frr_cfg = frr.FRRConfig()
+
+ frr_cfg.load_configuration(babel_daemon)
+ frr_cfg.modify_section('^router babel', stop_pattern='^exit', remove_stop_mark=True)
+
+ for key in ['interface', 'interface_removed']:
+ if key not in babel:
+ continue
+ for interface in babel[key]:
+ frr_cfg.modify_section(f'^interface {interface}', stop_pattern='^exit', remove_stop_mark=True)
+
+ if 'new_frr_config' in babel:
+ frr_cfg.add_before(frr.default_add_before, babel['new_frr_config'])
+ frr_cfg.commit_configuration(babel_daemon)
+
+ return None
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)
diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py
index 74e8827ef..0a4a88bf8 100755
--- a/src/conf_mode/system-login.py
+++ b/src/conf_mode/system-login.py
@@ -42,6 +42,11 @@ airbag.enable()
autologout_file = "/etc/profile.d/autologout.sh"
radius_config_file = "/etc/pam_radius_auth.conf"
+# LOGIN_TIMEOUT from /etc/loign.defs minus 10 sec
+MAX_RADIUS_TIMEOUT: int = 50
+# MAX_RADIUS_TIMEOUT divided by 2 sec (minimum recomended timeout)
+MAX_RADIUS_COUNT: int = 25
+
def get_local_users():
"""Return list of dynamically allocated users (see Debian Policy Manual)"""
local_users = []
@@ -124,18 +129,27 @@ def verify(login):
if 'radius' in login:
if 'server' not in login['radius']:
raise ConfigError('No RADIUS server defined!')
-
+ sum_timeout: int = 0
+ radius_servers_count: int = 0
fail = True
for server, server_config in dict_search('radius.server', login).items():
if 'key' not in server_config:
raise ConfigError(f'RADIUS server "{server}" requires key!')
-
- if 'disabled' not in server_config:
+ if 'disable' not in server_config:
+ sum_timeout += int(server_config['timeout'])
+ radius_servers_count += 1
fail = False
- continue
+
if fail:
raise ConfigError('All RADIUS servers are disabled')
+ if radius_servers_count > MAX_RADIUS_COUNT:
+ raise ConfigError('Number of RADIUS servers more than 25 ')
+
+ if sum_timeout > MAX_RADIUS_TIMEOUT:
+ raise ConfigError('Sum of RADIUS servers timeouts '
+ 'has to be less or eq 50 sec')
+
verify_vrf(login['radius'])
if 'source_address' in login['radius']:
diff --git a/src/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py
index bf5d3ac84..68da70d7d 100755
--- a/src/conf_mode/vpn_openconnect.py
+++ b/src/conf_mode/vpn_openconnect.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2022 VyOS maintainers and contributors
+# Copyright (C) 2018-2023 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
@@ -47,7 +47,7 @@ def get_hash(password):
return crypt(password, mksalt(METHOD_SHA512))
-def T2665_default_dict_cleanup(origin: dict, default_values: dict) -> dict:
+def _default_dict_cleanup(origin: dict, default_values: dict) -> dict:
"""
https://vyos.dev/T2665
Clear unnecessary key values in merged config by dict_merge function
@@ -63,7 +63,7 @@ def T2665_default_dict_cleanup(origin: dict, default_values: dict) -> dict:
del origin['authentication']['local_users']['username']['otp']
if not origin["authentication"]["local_users"]["username"]:
raise ConfigError(
- 'Openconnect mode local required at least one user')
+ 'Openconnect authentication mode local requires at least one user')
default_ocserv_usr_values = \
default_values['authentication']['local_users']['username']['otp']
for user, params in origin['authentication']['local_users'][
@@ -82,7 +82,7 @@ def T2665_default_dict_cleanup(origin: dict, default_values: dict) -> dict:
del origin['authentication']['radius']['server']['port']
if not origin["authentication"]['radius']['server']:
raise ConfigError(
- 'Openconnect authentication mode radius required at least one radius server')
+ 'Openconnect authentication mode radius requires at least one RADIUS server')
default_values_radius_port = \
default_values['authentication']['radius']['server']['port']
for server, params in origin['authentication']['radius'][
@@ -95,7 +95,7 @@ def T2665_default_dict_cleanup(origin: dict, default_values: dict) -> dict:
del origin['accounting']['radius']['server']['port']
if not origin["accounting"]['radius']['server']:
raise ConfigError(
- 'Openconnect accounting mode radius required at least one radius server')
+ 'Openconnect accounting mode radius requires at least one RADIUS server')
default_values_radius_port = \
default_values['accounting']['radius']['server']['port']
for server, params in origin['accounting']['radius'][
@@ -120,7 +120,7 @@ def get_config(config=None):
default_values = defaults(base)
ocserv = dict_merge(default_values, ocserv)
# workaround a "know limitation" - https://vyos.dev/T2665
- ocserv = T2665_default_dict_cleanup(ocserv, default_values)
+ ocserv = _default_dict_cleanup(ocserv, default_values)
if ocserv:
ocserv['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
get_first_key=True, no_tag_node_value_mangle=True)
diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/99-run-user-hooks b/src/etc/dhcp/dhclient-enter-hooks.d/99-run-user-hooks
new file mode 100644
index 000000000..b4b4d516d
--- /dev/null
+++ b/src/etc/dhcp/dhclient-enter-hooks.d/99-run-user-hooks
@@ -0,0 +1,5 @@
+#!/bin/bash
+DHCP_PRE_HOOKS="/config/scripts/dhcp-client/pre-hooks.d/"
+if [ -d "${DHCP_PRE_HOOKS}" ] ; then
+ run-parts "${DHCP_PRE_HOOKS}"
+fi
diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/99-run-user-hooks b/src/etc/dhcp/dhclient-exit-hooks.d/99-run-user-hooks
new file mode 100755
index 000000000..442419d79
--- /dev/null
+++ b/src/etc/dhcp/dhclient-exit-hooks.d/99-run-user-hooks
@@ -0,0 +1,5 @@
+#!/bin/bash
+DHCP_POST_HOOKS="/config/scripts/dhcp-client/post-hooks.d/"
+if [ -d "${DHCP_POST_HOOKS}" ] ; then
+ run-parts "${DHCP_POST_HOOKS}"
+fi
diff --git a/src/op_mode/generate_public_key_command.py b/src/op_mode/generate_public_key_command.py
index f071ae350..8ba55c901 100755
--- a/src/op_mode/generate_public_key_command.py
+++ b/src/op_mode/generate_public_key_command.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2022 VyOS maintainers and contributors
+# Copyright (C) 2022-2023 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
@@ -19,28 +19,51 @@ import sys
import urllib.parse
import vyos.remote
+from vyos.template import generate_uuid4
-def get_key(path):
+
+def get_key(path) -> list:
+ """Get public keys from a local file or remote URL
+
+ Args:
+ path: Path to the public keys file
+
+ Returns: list of public keys split by new line
+
+ """
url = urllib.parse.urlparse(path)
if url.scheme == 'file' or url.scheme == '':
with open(os.path.expanduser(path), 'r') as f:
key_string = f.read()
else:
key_string = vyos.remote.get_remote_config(path)
- return key_string.split()
-
-try:
- username = sys.argv[1]
- algorithm, key, identifier = get_key(sys.argv[2])
-except Exception as e:
- print("Failed to retrieve the public key: {}".format(e))
- sys.exit(1)
-
-print('# To add this key as an embedded key, run the following commands:')
-print('configure')
-print(f'set system login user {username} authentication public-keys {identifier} key {key}')
-print(f'set system login user {username} authentication public-keys {identifier} type {algorithm}')
-print('commit')
-print('save')
-print('exit')
+ return key_string.split('\n')
+
+
+if __name__ == "__main__":
+ first_loop = True
+
+ for k in get_key(sys.argv[2]):
+ k = k.split()
+ # Skip empty list entry
+ if k == []:
+ continue
+
+ try:
+ username = sys.argv[1]
+ # Github keys don't have identifier for example 'vyos@localhost'
+ # 'ssh-rsa AAAA... vyos@localhost'
+ # Generate uuid4 identifier
+ identifier = f'github@{generate_uuid4("")}' if sys.argv[2].startswith('https://github.com') else k[2]
+ algorithm, key = k[0], k[1]
+ except Exception as e:
+ print("Failed to retrieve the public key: {}".format(e))
+ sys.exit(1)
+
+ if first_loop:
+ print('# To add this key as an embedded key, run the following commands:')
+ print('configure')
+ print(f'set system login user {username} authentication public-keys {identifier} key {key}')
+ print(f'set system login user {username} authentication public-keys {identifier} type {algorithm}')
+ first_loop = False
diff --git a/src/op_mode/openvpn.py b/src/op_mode/openvpn.py
index d957a1d01..79130c7c0 100755
--- a/src/op_mode/openvpn.py
+++ b/src/op_mode/openvpn.py
@@ -173,8 +173,8 @@ def _format_openvpn(data: dict) -> str:
'TX bytes', 'RX bytes', 'Connected Since']
out = ''
- data_out = []
for intf in list(data):
+ data_out = []
l_host = data[intf]['local_host']
l_port = data[intf]['local_port']
for client in list(data[intf]['clients']):
@@ -192,7 +192,9 @@ def _format_openvpn(data: dict) -> str:
data_out.append([name, remote, tunnel, local, tx_bytes,
rx_bytes, online_since])
- out += tabulate(data_out, headers)
+ if data_out:
+ out += tabulate(data_out, headers)
+ out += "\n"
return out
diff --git a/src/op_mode/restart_frr.py b/src/op_mode/restart_frr.py
index 91b25567a..680d9f8cc 100755
--- a/src/op_mode/restart_frr.py
+++ b/src/op_mode/restart_frr.py
@@ -139,7 +139,7 @@ def _reload_config(daemon):
# define program arguments
cmd_args_parser = argparse.ArgumentParser(description='restart frr daemons')
cmd_args_parser.add_argument('--action', choices=['restart'], required=True, help='action to frr daemons')
-cmd_args_parser.add_argument('--daemon', choices=['bfdd', 'bgpd', 'ldpd', 'ospfd', 'ospf6d', 'isisd', 'ripd', 'ripngd', 'staticd', 'zebra'], required=False, nargs='*', help='select single or multiple daemons')
+cmd_args_parser.add_argument('--daemon', choices=['bfdd', 'bgpd', 'ldpd', 'ospfd', 'ospf6d', 'isisd', 'ripd', 'ripngd', 'staticd', 'zebra', 'babeld'], required=False, nargs='*', help='select single or multiple daemons')
# parse arguments
cmd_args = cmd_args_parser.parse_args()
diff --git a/src/services/api/graphql/graphql/auth_token_mutation.py b/src/services/api/graphql/graphql/auth_token_mutation.py
index 21ac40094..603a13758 100644
--- a/src/services/api/graphql/graphql/auth_token_mutation.py
+++ b/src/services/api/graphql/graphql/auth_token_mutation.py
@@ -20,6 +20,7 @@ from ariadne import ObjectType, UnionType
from graphql import GraphQLResolveInfo
from .. libs.token_auth import generate_token
+from .. session.session import get_user_info
from .. import state
auth_token_mutation = ObjectType("Mutation")
@@ -36,13 +37,24 @@ def auth_token_resolver(obj: Any, info: GraphQLResolveInfo, data: Dict):
datetime.timedelta(seconds=exp_interval))
res = generate_token(user, passwd, secret, expiration)
- if res:
+ try:
+ res |= get_user_info(user)
+ except ValueError:
+ # non-existent user already caught
+ pass
+ if 'token' in res:
data['result'] = res
return {
"success": True,
"data": data
}
+ if 'errors' in res:
+ return {
+ "success": False,
+ "errors": res['errors']
+ }
+
return {
"success": False,
"errors": ['token generation failed']
diff --git a/src/services/api/graphql/libs/token_auth.py b/src/services/api/graphql/libs/token_auth.py
index 2100eba7f..8585485c9 100644
--- a/src/services/api/graphql/libs/token_auth.py
+++ b/src/services/api/graphql/libs/token_auth.py
@@ -29,14 +29,13 @@ def generate_token(user: str, passwd: str, secret: str, exp: int) -> dict:
payload_data = {'iss': user, 'sub': user_id, 'exp': exp}
secret = state.settings.get('secret')
if secret is None:
- return {
- "success": False,
- "errors": ['failed secret generation']
- }
+ return {"errors": ['missing secret']}
token = jwt.encode(payload=payload_data, key=secret, algorithm="HS256")
users |= {user_id: user}
return {'token': token}
+ else:
+ return {"errors": ['failed pam authentication']}
def get_user_context(request):
context = {}
diff --git a/src/services/api/graphql/session/session.py b/src/services/api/graphql/session/session.py
index b2aef9bd9..3c5a062b6 100644
--- a/src/services/api/graphql/session/session.py
+++ b/src/services/api/graphql/session/session.py
@@ -29,6 +29,28 @@ from api.graphql.libs.op_mode import normalize_output
op_mode_include_file = os.path.join(directories['data'], 'op-mode-standardized.json')
+def get_config_dict(path=[], effective=False, key_mangling=None,
+ get_first_key=False, no_multi_convert=False,
+ no_tag_node_value_mangle=False):
+ config = Config()
+ return config.get_config_dict(path=path, effective=effective,
+ key_mangling=key_mangling,
+ get_first_key=get_first_key,
+ no_multi_convert=no_multi_convert,
+ no_tag_node_value_mangle=no_tag_node_value_mangle)
+
+def get_user_info(user):
+ user_info = {}
+ info = get_config_dict(['system', 'login', 'user', user],
+ get_first_key=True)
+ if not info:
+ raise ValueError("No such user")
+
+ user_info['user'] = user
+ user_info['full_name'] = info.get('full-name', '')
+
+ return user_info
+
class Session:
"""
Wrapper for calling configsession functions based on GraphQL requests.
@@ -46,17 +68,6 @@ class Session:
except Exception:
self._op_mode_list = None
- @staticmethod
- def _get_config_dict(path=[], effective=False, key_mangling=None,
- get_first_key=False, no_multi_convert=False,
- no_tag_node_value_mangle=False):
- config = Config()
- return config.get_config_dict(path=path, effective=effective,
- key_mangling=key_mangling,
- get_first_key=get_first_key,
- no_multi_convert=no_multi_convert,
- no_tag_node_value_mangle=no_tag_node_value_mangle)
-
def show_config(self):
session = self._session
data = self._data
@@ -134,10 +145,7 @@ class Session:
user_info = {}
user = data['user']
try:
- info = self._get_config_dict(['system', 'login', 'user', user,
- 'full-name'])
- user_info['user'] = user
- user_info['full_name'] = info.get('full-name', '')
+ user_info = get_user_info(user)
except Exception as error:
raise error