diff options
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>[ !#-%&(-~]+</regex> +              </constraint> +              <constraintErrorMessage>Entrypoint must be ascii characters, use &quot; and &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>[ !#-%&(-~]+</regex> +              </constraint> +              <constraintErrorMessage>Command must be ascii characters, use &quot; and &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>[ !#-%&(-~]+</regex> +              </constraint> +              <constraintErrorMessage>The command's arguments must be ascii characters, use &quot; and &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><x.x.x.x></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('"', """) +        entrypoint = f'--entrypoint '{entrypoint}'' + +    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(""", '"').replace("'", "'"))      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 | 
