diff options
138 files changed, 2400 insertions, 822 deletions
| diff --git a/data/op-mode-standardized.json b/data/op-mode-standardized.json index f0d896dd0..3205c7d20 100644 --- a/data/op-mode-standardized.json +++ b/data/op-mode-standardized.json @@ -8,6 +8,7 @@  "dhcp.py",  "dns.py",  "interfaces.py", +"lldp.py",  "log.py",  "memory.py",  "nat.py", diff --git a/data/templates/chrony/chrony.conf.j2 b/data/templates/chrony/chrony.conf.j2 new file mode 100644 index 000000000..b3bfc8c0c --- /dev/null +++ b/data/templates/chrony/chrony.conf.j2 @@ -0,0 +1,58 @@ +### Autogenerated by ntp.py ### + +# This would step the system clock if the adjustment is larger than 0.1 seconds, +# but only in the first three clock updates. +makestep 1.0 3 + +# The rtcsync directive enables a mode where the system time is periodically +# copied to the RTC and chronyd does not try to track its drift. This directive +# cannot be used with the rtcfile directive. On Linux, the RTC copy is performed +# by the kernel every 11 minutes. +rtcsync + +# This directive specifies the maximum amount of memory that chronyd is allowed +# to allocate for logging of client accesses and the state that chronyd as an +# NTP server needs to support the interleaved mode for its clients. +clientloglimit 1048576 + +driftfile /run/chrony/drift +dumpdir /run/chrony +pidfile {{ config_file | replace('.conf', '.pid') }} + +# Determine when will the next leap second occur and what is the current offset +leapsectz right/UTC + +user {{ user }} + +# NTP servers to reach out to +{% if server is vyos_defined %} +{%     for server, config in server.items() %} +{%         set association = 'server' %} +{%         if config.pool is vyos_defined %} +{%             set association = 'pool' %} +{%         endif %} +{{ association }} {{ server | replace('_', '-') }} iburst {{ 'noselect' if config.noselect is vyos_defined }} {{ 'prefer' if config.prefer is vyos_defined }} +{%     endfor %} +{% endif %} + +# Allowed clients configuration +{% if allow_client.address is vyos_defined %} +{%     for address in allow_client.address %} +allow {{ address }} +{%     endfor %} +{% endif %} +deny all + +{% if listen_address is vyos_defined or interface is vyos_defined %} +# NTP should listen on configured addresses only +{%     if listen_address is vyos_defined %} +{%         for address in listen_address %} +bindaddress {{ address }} +{%         endfor %} +{%     endif %} +{%     if interface is vyos_defined %} +{%         for ifname in interface %} +binddevice {{ ifname }} +{%         endfor %} +{%     endif %} +{% endif %} diff --git a/data/templates/ntp/override.conf.j2 b/data/templates/chrony/override.conf.j2 index 6fed9d7d2..9eaea7608 100644 --- a/data/templates/ntp/override.conf.j2 +++ b/data/templates/chrony/override.conf.j2 @@ -5,10 +5,13 @@ ConditionPathExists={{ config_file }}  After=vyos-router.service  [Service] +EnvironmentFile=  ExecStart= -ExecStart={{ vrf_command }}/usr/sbin/ntpd -g -p {{ config_file | replace('.conf', '.pid') }} -c {{ config_file }} -u ntp:ntp +ExecStart={{ vrf_command }}/usr/sbin/chronyd -F 1 -f {{ config_file }}  PIDFile=  PIDFile={{ config_file | replace('.conf', '.pid') }}  Restart=always  RestartSec=10 +# Required for VRF support +ProtectControlGroups=No diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2 index 882ec8f97..8c4a81c57 100644 --- a/data/templates/frr/ospfd.frr.j2 +++ b/data/templates/frr/ospfd.frr.j2 @@ -84,11 +84,13 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}  {%         endfor %}  {%         if area_config.range is vyos_defined %}  {%             for range, range_config in area_config.range.items() %} -{%                 if range_config.cost is vyos_defined %} - area {{ area_id }} range {{ range }} cost {{ range_config.cost }} -{%                 endif %}  {%                 if range_config.not_advertise is vyos_defined %}   area {{ area_id }} range {{ range }} not-advertise +{%                 else %} + area {{ area_id }} range {{ range }} +{%                 endif %} +{%                 if range_config.cost is vyos_defined %} + area {{ area_id }} range {{ range }} cost {{ range_config.cost }}  {%                 endif %}  {%                 if range_config.substitute is vyos_defined %}   area {{ area_id }} range {{ range }} substitute {{ range_config.substitute }} @@ -170,7 +172,7 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}  {% if parameters.router_id is vyos_defined %}   ospf router-id {{ parameters.router_id }}  {% endif %} -{% if passive_interface.default is vyos_defined %} +{% if passive_interface is vyos_defined('default') %}   passive-interface default  {% endif %}  {% if redistribute is vyos_defined %} diff --git a/data/templates/high-availability/keepalived.conf.j2 b/data/templates/high-availability/keepalived.conf.j2 index 706e1c5ae..ebff52e1f 100644 --- a/data/templates/high-availability/keepalived.conf.j2 +++ b/data/templates/high-availability/keepalived.conf.j2 @@ -126,7 +126,12 @@ vrrp_sync_group {{ name }} {  {% if virtual_server is vyos_defined %}  # Virtual-server configuration  {%     for vserver, vserver_config in virtual_server.items() %} +# Vserver {{ vserver }} +{%         if vserver_config.port is vyos_defined %}  virtual_server {{ vserver }} {{ vserver_config.port }} { +{%         else %} +virtual_server fwmark {{ vserver_config.fwmark }} { +{%         endif %}      delay_loop {{ vserver_config.delay_loop }}  {%         if vserver_config.algorithm is vyos_defined('round-robin') %}      lb_algo rr @@ -156,9 +161,14 @@ virtual_server {{ vserver }} {{ vserver_config.port }} {  {%             for rserver, rserver_config in vserver_config.real_server.items() %}      real_server {{ rserver }} {{ rserver_config.port }} {          weight 1 +{%                 if rserver_config.health_check.script is vyos_defined %} +        MISC_CHECK { +            misc_path {{ rserver_config.health_check.script }} +{%                 else %}          {{ vserver_config.protocol | upper }}_CHECK { -{%                 if rserver_config.connection_timeout is vyos_defined %} +{%                     if rserver_config.connection_timeout is vyos_defined %}              connect_timeout {{ rserver_config.connection_timeout }} +{%                     endif %}  {%                 endif %}          }      } diff --git a/data/templates/https/nginx.default.j2 b/data/templates/https/nginx.default.j2 index dbb08e187..753c3a5c9 100644 --- a/data/templates/https/nginx.default.j2 +++ b/data/templates/https/nginx.default.j2 @@ -34,7 +34,7 @@ server {          ssl_protocols TLSv1.2 TLSv1.3;          # proxy settings for HTTP API, if enabled; 503, if not -        location ~ /(retrieve|configure|config-file|image|generate|show|reset|docs|openapi.json|redoc|graphql) { +        location ~ /(retrieve|configure|config-file|image|container-image|generate|show|reset|docs|openapi.json|redoc|graphql) {  {%     if server.api %}  {%         if server.api.socket %}                  proxy_pass http://unix:/run/api.sock; diff --git a/data/templates/iproute2/static.conf.j2 b/data/templates/iproute2/static.conf.j2 new file mode 100644 index 000000000..10c9bdab7 --- /dev/null +++ b/data/templates/iproute2/static.conf.j2 @@ -0,0 +1,8 @@ +# Generated by VyOS (protocols_static.py), do not edit by hand +{% if table is vyos_defined %} +{%     for t, t_options in table.items() %} +{%         if t_options.description is vyos_defined %} +{{ "%-6s" | format(t) }} {{ "%-40s" | format(t_options.description) }} +{%         endif %} +{%     endfor %} +{% endif %} diff --git a/data/templates/vrf/vrf.conf.j2 b/data/templates/iproute2/vrf.conf.j2 index d31d23574..d31d23574 100644 --- a/data/templates/vrf/vrf.conf.j2 +++ b/data/templates/iproute2/vrf.conf.j2 diff --git a/data/templates/ipsec/swanctl/peer.j2 b/data/templates/ipsec/swanctl/peer.j2 index 837fa263c..9d95271fe 100644 --- a/data/templates/ipsec/swanctl/peer.j2 +++ b/data/templates/ipsec/swanctl/peer.j2 @@ -45,11 +45,7 @@  {% endif %}          }          remote { -{% if peer_conf.authentication.remote_id is vyos_defined %}              id = "{{ peer_conf.authentication.remote_id }}" -{% else %} -            id = "{{ peer }}" -{% endif %}              auth = {{ 'psk' if peer_conf.authentication.mode == 'pre-shared-secret' else 'pubkey' }}  {% if peer_conf.authentication.mode == 'rsa' %}              pubkeys = {{ peer_conf.authentication.rsa.remote_key }}.pem diff --git a/data/templates/ntp/ntpd.conf.j2 b/data/templates/ntp/ntpd.conf.j2 deleted file mode 100644 index 8921826fa..000000000 --- a/data/templates/ntp/ntpd.conf.j2 +++ /dev/null @@ -1,49 +0,0 @@ -### Autogenerated by ntp.py ### - -# -# Non-configurable defaults -# -driftfile /var/lib/ntp/ntp.drift -# By default, only allow ntpd to query time sources, ignore any incoming requests -restrict default noquery nopeer notrap nomodify -# Allow pool associations -restrict source nomodify notrap noquery -# Local users have unrestricted access, allowing reconfiguration via ntpdc -restrict 127.0.0.1 -restrict -6 ::1 - -# -# Configurable section -# -{% if server is vyos_defined %} -{%     for server, config in server.items() %} -{%         set association = 'server' %} -{%         if config.pool is vyos_defined %} -{%             set association = 'pool' %} -{%         endif %} -{{ association }} {{ server | replace('_', '-') }} iburst {{ 'noselect' if config.noselect is vyos_defined }} {{ 'preempt' if config.preempt is vyos_defined }} {{ 'prefer' if config.prefer is vyos_defined }} -{%     endfor %} -{% endif %} - -{% if allow_clients.address is vyos_defined %} -# Allowed clients configuration -restrict default ignore -{%     for address in allow_clients.address %} -restrict {{ address | address_from_cidr }} mask {{ address | netmask_from_cidr }} nomodify notrap nopeer -{%     endfor %} -{% endif %} - -{% if listen_address is vyos_defined or interface is vyos_defined %} -# NTP should listen on configured addresses only -interface ignore wildcard -{%     if listen_address is vyos_defined %} -{%         for address in listen_address %} -interface listen {{ address }} -{%         endfor %} -{%     endif %} -{%     if interface is vyos_defined %} -{%         for ifname in interface %} -interface listen {{ ifname }} -{%         endfor %} -{%     endif %} -{% endif %} diff --git a/data/templates/snmp/etc.snmpd.conf.j2 b/data/templates/snmp/etc.snmpd.conf.j2 index 47bf6878f..a9bbf68ce 100644 --- a/data/templates/snmp/etc.snmpd.conf.j2 +++ b/data/templates/snmp/etc.snmpd.conf.j2 @@ -26,6 +26,9 @@ monitor  -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2  # interface (with different ifIndex) - this is the case on e.g. ppp interfaces  interface_replace_old yes +# T4902: exclude container storage from monitoring +ignoreDisk /usr/lib/live/mount/persistence/container +  ########################  # configurable section #  ######################## diff --git a/data/templates/system/ssh_config.j2 b/data/templates/system/ssh_config.j2 index 1449f95b1..d3ede0971 100644 --- a/data/templates/system/ssh_config.j2 +++ b/data/templates/system/ssh_config.j2 @@ -1,3 +1,6 @@  {% if ssh_client.source_address is vyos_defined %}  BindAddress {{ ssh_client.source_address }}  {% endif %} +{% if ssh_client.source_interface is vyos_defined %} +BindInterface {{ ssh_client.source_interface }} +{% endif %} diff --git a/data/templates/telegraf/telegraf.j2 b/data/templates/telegraf/telegraf.j2 index 36571ce98..c9f402281 100644 --- a/data/templates/telegraf/telegraf.j2 +++ b/data/templates/telegraf/telegraf.j2 @@ -102,7 +102,7 @@    dirs = ["/proc/sys/net/ipv4/netfilter","/proc/sys/net/netfilter"]  [[inputs.ethtool]]    interface_include = {{ interfaces_ethernet }} -[[inputs.ntpq]] +[[inputs.chrony]]    dns_lookup = true  [[inputs.internal]]  [[inputs.nstat]] diff --git a/debian/control b/debian/control index 696f8902d..1e593d378 100644 --- a/debian/control +++ b/debian/control @@ -39,7 +39,6 @@ Depends:    beep,    bmon,    bsdmainutils, -  charon-systemd,    conntrack,    conntrackd,    conserver-client, @@ -102,8 +101,7 @@ Depends:    nfct,    nftables (>= 0.9.3),    nginx-light, -  ntp, -  ntpdate, +  chrony,    nvme-cli,    ocserv,    opennhrp, diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install index edd090993..a54b3b506 100644 --- a/debian/vyos-1x.install +++ b/debian/vyos-1x.install @@ -3,6 +3,7 @@ etc/ipsec.d  etc/logrotate.d  etc/netplug  etc/opennhrp +etc/modprobe.d  etc/ppp  etc/rsyslog.d  etc/securetty diff --git a/interface-definitions/high-availability.xml.in b/interface-definitions/high-availability.xml.in index 784e51151..d67a142d1 100644 --- a/interface-definitions/high-availability.xml.in +++ b/interface-definitions/high-availability.xml.in @@ -365,7 +365,8 @@              </properties>              <defaultValue>nat</defaultValue>            </leafNode> -          #include <include/port-number.xml.i> +          #include <include/firewall/fwmark.xml.i> +          #include <include/port-number-start-zero.xml.i>            <leafNode name="persistence-timeout">              <properties>                <help>Timeout for persistent connections</help> @@ -404,7 +405,7 @@                <help>Real server address</help>              </properties>              <children> -              #include <include/port-number.xml.i> +              #include <include/port-number-start-zero.xml.i>                <leafNode name="connection-timeout">                  <properties>                    <help>Server connection timeout</help> @@ -417,6 +418,21 @@                    </constraint>                  </properties>                </leafNode> +              <node name="health-check"> +                <properties> +                  <help>Health check script</help> +                </properties> +                <children> +                  <leafNode name="script"> +                    <properties> +                      <help>Health check script file</help> +                      <constraint> +                        <validator name="script"/> +                      </constraint> +                    </properties> +                  </leafNode> +                </children> +              </node>              </children>            </tagNode>          </children> diff --git a/interface-definitions/include/firewall/fwmark.xml.i b/interface-definitions/include/firewall/fwmark.xml.i new file mode 100644 index 000000000..4607ef58f --- /dev/null +++ b/interface-definitions/include/firewall/fwmark.xml.i @@ -0,0 +1,14 @@ +<!-- include start from firewall/fwmark.xml.i --> +<leafNode name="fwmark"> +  <properties> +    <help>Match fwmark value</help> +    <valueHelp> +      <format>u32:1-2147483647</format> +      <description>Match firewall mark value</description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--range 1-2147483647"/> +    </constraint> +  </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/generic-description.xml.i b/interface-definitions/include/generic-description.xml.i index 03fc564e6..b030c2495 100644 --- a/interface-definitions/include/generic-description.xml.i +++ b/interface-definitions/include/generic-description.xml.i @@ -6,6 +6,10 @@        <format>txt</format>        <description>Description</description>      </valueHelp> +    <constraint> +      <regex>[[:ascii:]]{1,256}</regex> +    </constraint> +    <constraintErrorMessage>Description too long (limit 256 characters)</constraintErrorMessage>    </properties>  </leafNode>  <!-- include end --> diff --git a/interface-definitions/include/interface/description.xml.i b/interface-definitions/include/interface/description.xml.i deleted file mode 100644 index de01d22ca..000000000 --- a/interface-definitions/include/interface/description.xml.i +++ /dev/null @@ -1,11 +0,0 @@ -<!-- include start from interface/description.xml.i --> -<leafNode name="description"> -  <properties> -    <help>Interface specific description</help> -    <constraint> -      <regex>.{1,256}</regex> -    </constraint> -    <constraintErrorMessage>Description too long (limit 256 characters)</constraintErrorMessage> -  </properties> -</leafNode> -<!-- include end --> diff --git a/interface-definitions/include/interface/vif-s.xml.i b/interface-definitions/include/interface/vif-s.xml.i index 6d50d7238..fdd62b63d 100644 --- a/interface-definitions/include/interface/vif-s.xml.i +++ b/interface-definitions/include/interface/vif-s.xml.i @@ -12,8 +12,8 @@      <constraintErrorMessage>VLAN ID must be between 0 and 4094</constraintErrorMessage>    </properties>    <children> +    #include <include/generic-description.xml.i>      #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> -    #include <include/interface/description.xml.i>      #include <include/interface/dhcp-options.xml.i>      #include <include/interface/dhcpv6-options.xml.i>      #include <include/interface/disable-link-detect.xml.i> @@ -53,8 +53,8 @@          <constraintErrorMessage>VLAN ID must be between 0 and 4094</constraintErrorMessage>        </properties>        <children> +        #include <include/generic-description.xml.i>          #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> -        #include <include/interface/description.xml.i>          #include <include/interface/dhcp-options.xml.i>          #include <include/interface/dhcpv6-options.xml.i>          #include <include/interface/disable-link-detect.xml.i> diff --git a/interface-definitions/include/interface/vif.xml.i b/interface-definitions/include/interface/vif.xml.i index 3f8f113ea..ec3921bf6 100644 --- a/interface-definitions/include/interface/vif.xml.i +++ b/interface-definitions/include/interface/vif.xml.i @@ -12,8 +12,8 @@      <constraintErrorMessage>VLAN ID must be between 0 and 4094</constraintErrorMessage>    </properties>    <children> +    #include <include/generic-description.xml.i>      #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> -    #include <include/interface/description.xml.i>      #include <include/interface/dhcp-options.xml.i>      #include <include/interface/dhcpv6-options.xml.i>      #include <include/interface/disable-link-detect.xml.i> diff --git a/interface-definitions/include/port-number-start-zero.xml.i b/interface-definitions/include/port-number-start-zero.xml.i new file mode 100644 index 000000000..04a144216 --- /dev/null +++ b/interface-definitions/include/port-number-start-zero.xml.i @@ -0,0 +1,15 @@ +<!-- include start from port-number-start-zero.xml.i --> +<leafNode name="port"> +  <properties> +    <help>Port number used by connection</help> +    <valueHelp> +      <format>u32:0-65535</format> +      <description>Numeric IP port</description> +    </valueHelp> +    <constraint> +      <validator name="numeric" argument="--range 0-65535"/> +    </constraint> +    <constraintErrorMessage>Port number must be in range 0 to 65535</constraintErrorMessage> +  </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/bandwidth-auto.xml.i b/interface-definitions/include/qos/bandwidth-auto.xml.i index 260bd4f7b..a86f28296 100644 --- a/interface-definitions/include/qos/bandwidth-auto.xml.i +++ b/interface-definitions/include/qos/bandwidth-auto.xml.i @@ -33,9 +33,13 @@        <format><number>tbit</format>        <description>Terabits per second</description>      </valueHelp> +    <valueHelp> +      <format><number>%%</format> +      <description>Percentage of interface link speed</description> +    </valueHelp>      <constraint>        <validator name="numeric" argument="--positive"/> -      <regex>(auto|\d+(bit|kbit|mbit|gbit|tbit))</regex> +      <regex>(auto|\d+(bit|kbit|mbit|gbit|tbit)|(100|\d(\d)?)%)</regex>      </constraint>    </properties>    <defaultValue>auto</defaultValue> diff --git a/interface-definitions/include/qos/bandwidth.xml.i b/interface-definitions/include/qos/bandwidth.xml.i index 62ea93b67..f2848f066 100644 --- a/interface-definitions/include/qos/bandwidth.xml.i +++ b/interface-definitions/include/qos/bandwidth.xml.i @@ -26,9 +26,13 @@        <format><number>tbit</format>        <description>Terabits per second</description>      </valueHelp> +    <valueHelp> +      <format><number>%</format> +      <description>Percentage of interface link speed</description> +    </valueHelp>      <constraint>        <validator name="numeric" argument="--positive"/> -      <regex>\d+(bit|kbit|mbit|gbit|tbit)</regex> +      <regex>(\d+(bit|kbit|mbit|gbit|tbit)|(100|\d(\d)?)%)</regex>      </constraint>    </properties>  </leafNode> diff --git a/interface-definitions/include/version/ntp-version.xml.i b/interface-definitions/include/version/ntp-version.xml.i index cc4ff9a1c..9eafbf7f0 100644 --- a/interface-definitions/include/version/ntp-version.xml.i +++ b/interface-definitions/include/version/ntp-version.xml.i @@ -1,3 +1,3 @@  <!-- include start from include/version/ntp-version.xml.i --> -<syntaxVersion component='ntp' version='1'></syntaxVersion> +<syntaxVersion component='ntp' version='2'></syntaxVersion>  <!-- include end --> diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in index a8a558348..6e8c5283a 100644 --- a/interface-definitions/interfaces-bonding.xml.in +++ b/interface-definitions/interfaces-bonding.xml.in @@ -49,7 +49,7 @@                </leafNode>              </children>            </node> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/dhcp-options.xml.i>            #include <include/interface/dhcpv6-options.xml.i>            #include <include/interface/disable-link-detect.xml.i> diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in index d52e213b6..1636411ec 100644 --- a/interface-definitions/interfaces-bridge.xml.in +++ b/interface-definitions/interfaces-bridge.xml.in @@ -34,7 +34,7 @@              </properties>              <defaultValue>300</defaultValue>            </leafNode> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/dhcp-options.xml.i>            #include <include/interface/dhcpv6-options.xml.i>            #include <include/interface/disable-link-detect.xml.i> diff --git a/interface-definitions/interfaces-dummy.xml.in b/interface-definitions/interfaces-dummy.xml.in index 201e9b179..00784fcdf 100644 --- a/interface-definitions/interfaces-dummy.xml.in +++ b/interface-definitions/interfaces-dummy.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            <node name="ip">              <properties> diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in index e9ae0acfe..e7c196c5c 100644 --- a/interface-definitions/interfaces-ethernet.xml.in +++ b/interface-definitions/interfaces-ethernet.xml.in @@ -20,7 +20,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/dhcp-options.xml.i>            #include <include/interface/dhcpv6-options.xml.i>            <leafNode name="disable-flow-control"> diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in index f8e9909f8..ac9794870 100644 --- a/interface-definitions/interfaces-geneve.xml.in +++ b/interface-definitions/interfaces-geneve.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            #include <include/interface/ipv4-options.xml.i>            #include <include/interface/ipv6-options.xml.i> diff --git a/interface-definitions/interfaces-input.xml.in b/interface-definitions/interfaces-input.xml.in index 97502d954..d90cf936f 100644 --- a/interface-definitions/interfaces-input.xml.in +++ b/interface-definitions/interfaces-input.xml.in @@ -17,7 +17,7 @@            </valueHelp>          </properties>          <children> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            #include <include/interface/redirect.xml.i>          </children> diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in index 0ebc3253d..1f0dd3d19 100644 --- a/interface-definitions/interfaces-l2tpv3.xml.in +++ b/interface-definitions/interfaces-l2tpv3.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            <leafNode name="destination-port">              <properties>                <help>UDP destination port for L2TPv3 tunnel</help> diff --git a/interface-definitions/interfaces-loopback.xml.in b/interface-definitions/interfaces-loopback.xml.in index 7f59db543..fe0944467 100644 --- a/interface-definitions/interfaces-loopback.xml.in +++ b/interface-definitions/interfaces-loopback.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            <node name="ip">              <properties>                <help>IPv4 routing parameters</help> diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 441236ec2..4b4f9149d 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -115,7 +115,7 @@                </leafNode>              </children>            </node> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            #include <include/interface/mtu-68-16000.xml.i>            <leafNode name="mtu"> diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in index 7cfb9ee7a..63272a25f 100644 --- a/interface-definitions/interfaces-openvpn.xml.in +++ b/interface-definitions/interfaces-openvpn.xml.in @@ -33,7 +33,7 @@                </leafNode>              </children>            </node> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            <leafNode name="device-type">              <properties>                <help>OpenVPN interface device-type</help> diff --git a/interface-definitions/interfaces-pppoe.xml.in b/interface-definitions/interfaces-pppoe.xml.in index 35c4889ea..490f41471 100644 --- a/interface-definitions/interfaces-pppoe.xml.in +++ b/interface-definitions/interfaces-pppoe.xml.in @@ -22,7 +22,7 @@            #include <include/interface/no-default-route.xml.i>            #include <include/interface/default-route-distance.xml.i>            #include <include/interface/dhcpv6-options.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            <leafNode name="idle-timeout">              <properties> diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in index 2fe07ffd5..5c73825c3 100644 --- a/interface-definitions/interfaces-pseudo-ethernet.xml.in +++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/dhcp-options.xml.i>            #include <include/interface/dhcpv6-options.xml.i>            #include <include/interface/disable-link-detect.xml.i> diff --git a/interface-definitions/interfaces-sstpc.xml.in b/interface-definitions/interfaces-sstpc.xml.in index 30b55a9fa..b569e9bde 100644 --- a/interface-definitions/interfaces-sstpc.xml.in +++ b/interface-definitions/interfaces-sstpc.xml.in @@ -16,7 +16,7 @@            </valueHelp>          </properties>          <children> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            #include <include/interface/authentication.xml.i>            #include <include/interface/no-default-route.xml.i> diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in index 333a5b178..17fe1e285 100644 --- a/interface-definitions/interfaces-tunnel.xml.in +++ b/interface-definitions/interfaces-tunnel.xml.in @@ -16,7 +16,7 @@            </valueHelp>          </properties>          <children> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/address-ipv4-ipv6.xml.i>            #include <include/interface/disable.xml.i>            #include <include/interface/disable-link-detect.xml.i> diff --git a/interface-definitions/interfaces-virtual-ethernet.xml.in b/interface-definitions/interfaces-virtual-ethernet.xml.in index 8059ec33b..864f658da 100644 --- a/interface-definitions/interfaces-virtual-ethernet.xml.in +++ b/interface-definitions/interfaces-virtual-ethernet.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/dhcp-options.xml.i>            #include <include/interface/dhcpv6-options.xml.i>            #include <include/interface/disable.xml.i> diff --git a/interface-definitions/interfaces-vti.xml.in b/interface-definitions/interfaces-vti.xml.in index 11f001dc0..b116f7386 100644 --- a/interface-definitions/interfaces-vti.xml.in +++ b/interface-definitions/interfaces-vti.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            #include <include/interface/ipv4-options.xml.i>            #include <include/interface/ipv6-options.xml.i> diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in index 331f930d3..fb60c93d0 100644 --- a/interface-definitions/interfaces-vxlan.xml.in +++ b/interface-definitions/interfaces-vxlan.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            <leafNode name="external">              <properties> diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in index 35e223588..6342b21cf 100644 --- a/interface-definitions/interfaces-wireguard.xml.in +++ b/interface-definitions/interfaces-wireguard.xml.in @@ -17,7 +17,7 @@          </properties>          <children>            #include <include/interface/address-ipv4-ipv6.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            #include <include/port-number.xml.i>            #include <include/interface/mtu-68-16000.xml.i> diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index 5271df624..aff5071b2 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -467,7 +467,7 @@                <constraintErrorMessage>Invalid ISO/IEC 3166-1 Country Code</constraintErrorMessage>              </properties>            </leafNode> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/dhcp-options.xml.i>            #include <include/interface/dhcpv6-options.xml.i>            <leafNode name="disable-broadcast-ssid"> diff --git a/interface-definitions/interfaces-wwan.xml.in b/interface-definitions/interfaces-wwan.xml.in index 758784540..5fa3be8db 100644 --- a/interface-definitions/interfaces-wwan.xml.in +++ b/interface-definitions/interfaces-wwan.xml.in @@ -28,7 +28,7 @@            #include <include/interface/dhcp-options.xml.i>            #include <include/interface/dhcpv6-options.xml.i>            #include <include/interface/authentication.xml.i> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            #include <include/interface/disable-link-detect.xml.i>            #include <include/interface/mirror.xml.i> diff --git a/interface-definitions/netns.xml.in b/interface-definitions/netns.xml.in index 088985cb6..87880e96a 100644 --- a/interface-definitions/netns.xml.in +++ b/interface-definitions/netns.xml.in @@ -15,7 +15,7 @@            <constraintErrorMessage>Netns name must be alphanumeric and can contain hyphens and underscores.</constraintErrorMessage>          </properties>          <children> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>          </children>        </tagNode>      </children> diff --git a/interface-definitions/ntp.xml.in b/interface-definitions/ntp.xml.in index 85636a50f..65e40ee32 100644 --- a/interface-definitions/ntp.xml.in +++ b/interface-definitions/ntp.xml.in @@ -1,7 +1,7 @@  <?xml version="1.0"?>  <!-- NTP configuration -->  <interfaceDefinition> -  <node name="system"> +  <node name="service">      <children>        <node name="ntp" owner="${vyos_conf_scripts_dir}/ntp.py">          <properties> @@ -43,12 +43,6 @@                    <valueless/>                  </properties>                </leafNode> -              <leafNode name="preempt"> -                <properties> -                  <help>Specifies the association as preemptable rather than the default persistent</help> -                  <valueless/> -                </properties> -              </leafNode>                <leafNode name="prefer">                  <properties>                    <help>Marks the server as preferred</help> @@ -57,24 +51,33 @@                </leafNode>              </children>            </tagNode> -          <node name="allow-clients"> +          <node name="allow-client">              <properties> -              <help>Network Time Protocol (NTP) server options</help> +              <help>Specify NTP clients allowed to access the server</help>              </properties>              <children>                <leafNode name="address">                  <properties>                    <help>IP address</help>                    <valueHelp> +                    <format>ipv4</format> +                    <description>Allowed IPv4 address</description> +                  </valueHelp> +                  <valueHelp>                      <format>ipv4net</format> -                    <description>IP address and prefix length</description> +                    <description>Allowed IPv4 prefix</description> +                  </valueHelp> +                  <valueHelp> +                    <format>ipv6</format> +                    <description>Allowed IPv6 address</description>                    </valueHelp>                    <valueHelp>                      <format>ipv6net</format> -                    <description>IPv6 address and prefix length</description> +                    <description>Allowed IPv6 prefix</description>                    </valueHelp>                    <multi/>                    <constraint> +                    <validator name="ip-address"/>                      <validator name="ip-prefix"/>                    </constraint>                  </properties> diff --git a/interface-definitions/protocols-static.xml.in b/interface-definitions/protocols-static.xml.in index e89433022..ca4ca2d74 100644 --- a/interface-definitions/protocols-static.xml.in +++ b/interface-definitions/protocols-static.xml.in @@ -26,6 +26,13 @@                </constraint>              </properties>              <children> +              <!-- +                iproute2 only considers the first "word" until whitespace in the name field +                but does not complain about special characters. +                We put an artificial limit here to make table descriptions potentially valid node names +                to avoid quoting and simplify future syntax changes if we decide to make any. +              --> +              #include <include/generic-description.xml.i>                #include <include/static/static-route.xml.i>                #include <include/static/static-route6.xml.i>              </children> diff --git a/interface-definitions/qos.xml.in b/interface-definitions/qos.xml.in index 36190949e..8809369ff 100644 --- a/interface-definitions/qos.xml.in +++ b/interface-definitions/qos.xml.in @@ -201,13 +201,13 @@                  <properties>                    <help>Upper limit of the SFQ</help>                    <valueHelp> -                    <format>u32:2-127</format> +                    <format>u32:1-127</format>                      <description>Queue size in packets</description>                    </valueHelp>                    <constraint> -                    <validator name="numeric" argument="--range 2-127"/> +                    <validator name="numeric" argument="--range 1-127"/>                    </constraint> -                  <constraintErrorMessage>Queue limit must greater than 1 and less than 128</constraintErrorMessage> +                  <constraintErrorMessage>Queue limit must be in range 1 to 127</constraintErrorMessage>                  </properties>                  <defaultValue>127</defaultValue>                </leafNode> diff --git a/interface-definitions/service-console-server.xml.in b/interface-definitions/service-console-server.xml.in index fb71538dd..fc6dbe954 100644 --- a/interface-definitions/service-console-server.xml.in +++ b/interface-definitions/service-console-server.xml.in @@ -27,7 +27,7 @@                </constraint>              </properties>              <children> -              #include <include/interface/description.xml.i> +              #include <include/generic-description.xml.i>                <leafNode name="alias">                  <properties>                    <help>Human-readable name for this console</help> diff --git a/interface-definitions/system-option.xml.in b/interface-definitions/system-option.xml.in index a9fed81fe..bb15e467e 100644 --- a/interface-definitions/system-option.xml.in +++ b/interface-definitions/system-option.xml.in @@ -121,6 +121,7 @@               </properties>               <children>                 #include <include/source-address-ipv4-ipv6.xml.i> +               #include <include/source-interface.xml.i>               </children>             </node>             <leafNode name="startup-beep"> diff --git a/interface-definitions/vpn-ipsec.xml.in b/interface-definitions/vpn-ipsec.xml.in index 64966b540..fd74a51d7 100644 --- a/interface-definitions/vpn-ipsec.xml.in +++ b/interface-definitions/vpn-ipsec.xml.in @@ -957,6 +957,7 @@                              <description>ID used for peer authentication</description>                            </valueHelp>                          </properties> +                        <defaultValue>%any</defaultValue>                        </leafNode>                        <leafNode name="use-x509-id">                          <properties> diff --git a/interface-definitions/vrf.xml.in b/interface-definitions/vrf.xml.in index 3604b41c8..96c6d8be2 100644 --- a/interface-definitions/vrf.xml.in +++ b/interface-definitions/vrf.xml.in @@ -26,7 +26,7 @@            </valueHelp>          </properties>          <children> -          #include <include/interface/description.xml.i> +          #include <include/generic-description.xml.i>            #include <include/interface/disable.xml.i>            <node name="ip">              <properties> diff --git a/mibs/IANA-ADDRESS-FAMILY-NUMBERS-MIB.txt b/mibs/IANA-ADDRESS-FAMILY-NUMBERS-MIB.txt new file mode 100644 index 000000000..7995fc4ad --- /dev/null +++ b/mibs/IANA-ADDRESS-FAMILY-NUMBERS-MIB.txt @@ -0,0 +1,166 @@ +  IANA-ADDRESS-FAMILY-NUMBERS-MIB DEFINITIONS ::= BEGIN + +  IMPORTS +      MODULE-IDENTITY, +      mib-2                               FROM SNMPv2-SMI +      TEXTUAL-CONVENTION                  FROM SNMPv2-TC; + +  ianaAddressFamilyNumbers MODULE-IDENTITY +      LAST-UPDATED "201309250000Z"  -- September 25, 2013 +      ORGANIZATION "IANA" +      CONTACT-INFO +          "Postal:    Internet Assigned Numbers Authority +                      Internet Corporation for Assigned Names +		      and Numbers +                      12025 Waterfront Drive, Suite 300 +                      Los Angeles, CA 90094-2536 +                      USA + +          Tel:    +1  310-301-5800 +          E-Mail: iana&iana.org" +      DESCRIPTION +          "The MIB module defines the AddressFamilyNumbers +          textual convention." + +      -- revision history + +      REVISION     "201309250000Z"  -- September 25, 2013 +      DESCRIPTION  "Fixed labels for 16389-16390." + +      REVISION     "201307160000Z"  -- July 16, 2013 +      DESCRIPTION  "Fixed labels for 16389-16390." + +      REVISION     "201306260000Z"  -- June 26, 2013 +      DESCRIPTION  "Added assignments 26-28." + +      REVISION     "201306180000Z"  -- June 18, 2013 +      DESCRIPTION  "Added assignments 16384-16390. Assignment  +                    25 added in 2007 revision." + +      REVISION     "200203140000Z"  -- March 14, 2002 +      DESCRIPTION  "AddressFamilyNumbers assignment 22 to  +                   fibreChannelWWPN. AddressFamilyNumbers  +                   assignment 23 to fibreChannelWWNN. +                   AddressFamilyNumers assignment 24 to gwid." + +      REVISION     "200009080000Z"  -- September 8, 2000 +      DESCRIPTION  "AddressFamilyNumbers assignment 19 to xtpOverIpv4.   +                   AddressFamilyNumbers assignment 20 to xtpOverIpv6.   +                   AddressFamilyNumbers assignment 21 to xtpNativeModeXTP." + +      REVISION     "200003010000Z"  -- March 1, 2000 +      DESCRIPTION  "AddressFamilyNumbers assignment 17 to distinguishedName.  +                   AddressFamilyNumbers assignment 18 to asNumber." + +      REVISION     "200002040000Z"  -- February 4, 2000 +      DESCRIPTION  "AddressFamilyNumbers assignment 16 to dns." + +      REVISION     "9908260000Z"  -- August 26, 1999 +      DESCRIPTION  "Initial version, published as RFC 2677." +      ::= { mib-2 72 } + +  AddressFamilyNumbers ::= TEXTUAL-CONVENTION +      STATUS       current +      DESCRIPTION +          "The definition of this textual convention with the +          addition of newly assigned values is published +          periodically by the IANA, in either the Assigned +          Numbers RFC, or some derivative of it specific to +          Internet Network Management number assignments. +          (The latest arrangements can be obtained by +          contacting the IANA.) + +          The enumerations are described as: + +          other(0),    -- none of the following +          ipV4(1),     -- IP Version 4 +          ipV6(2),     -- IP Version 6 +          nsap(3),     -- NSAP +          hdlc(4),     -- (8-bit multidrop) +          bbn1822(5), +          all802(6),   -- (includes all 802 media +                       --   plus Ethernet 'canonical format') +          e163(7), +          e164(8),     -- (SMDS, Frame Relay, ATM) +          f69(9),      -- (Telex) +          x121(10),    -- (X.25, Frame Relay) +          ipx(11),     -- IPX (Internet Protocol Exchange) +          appleTalk(12),  -- Apple Talk +          decnetIV(13),   -- DEC Net Phase IV +          banyanVines(14),  -- Banyan Vines +          e164withNsap(15), +                       -- (E.164 with NSAP format subaddress) +          dns(16),     -- (Domain Name System) +          distinguishedName(17), -- (Distinguished Name, per X.500) +          asNumber(18), -- (16-bit quantity, per the AS number space) +          xtpOverIpv4(19),  -- XTP over IP version 4 +          xtpOverIpv6(20),  -- XTP over IP version 6 +          xtpNativeModeXTP(21),  -- XTP native mode XTP +          fibreChannelWWPN(22),  -- Fibre Channel World-Wide Port Name  +          fibreChannelWWNN(23),  -- Fibre Channel World-Wide Node Name +          gwid(24),    -- Gateway Identifier  +          afi(25),  -- AFI for L2VPN information +          mplsTpSectionEndpointIdentifier(26),  -- MPLS-TP Section Endpoint Identifier +          mplsTpLspEndpointIdentifier(27),  -- MPLS-TP LSP Endpoint Identifier +          mplsTpPseudowireEndpointIdentifier(28),  -- MPLS-TP Pseudowire Endpoint Identifier +          eigrpCommonServiceFamily(16384),  -- EIGRP Common Service Family +          eigrpIpv4ServiceFamily(16385),  -- EIGRP IPv4 Service Family +          eigrpIpv6ServiceFamily(16386),  -- EIGRP IPv6 Service Family +          lispCanonicalAddressFormat(16387),  -- LISP Canonical Address Format (LCAF) +          bgpLs(16388),  -- BGP-LS +          fortyeightBitMacBitMac(16389),  -- 48-bit MAC +          sixtyfourBitMac(16390),  -- 64-bit MAC +          oui(16391),  -- OUI +          mac24(16392),  -- MAC/24 +          mac40(16393),  -- MAC/40 +          ipv664(16394),  -- IPv6/64 +          rBridgePortID(16395),  -- RBridge Port ID +          reserved(65535) + +          Requests for new values should be made to IANA via +          email (iana&iana.org)." +      SYNTAX  INTEGER { +                  other(0), +                  ipV4(1), +                  ipV6(2), +                  nsap(3), +                  hdlc(4), +                  bbn1822(5), +                  all802(6), +                  e163(7), +                  e164(8), +                  f69(9), +                  x121(10), +                  ipx(11), +                  appleTalk(12), +                  decnetIV(13), +                  banyanVines(14), +                  e164withNsap(15), +                  dns(16), +                  distinguishedName(17), -- (Distinguished Name, per X.500) +                  asNumber(18), -- (16-bit quantity, per the AS number space) +                  xtpOverIpv4(19), +                  xtpOverIpv6(20), +                  xtpNativeModeXTP(21), +                  fibreChannelWWPN(22), +                  fibreChannelWWNN(23), +                  gwid(24), +                  afi(25), +                  mplsTpSectionEndpointIdentifier(26), +                  mplsTpLspEndpointIdentifier(27), +                  mplsTpPseudowireEndpointIdentifier(28), +                  eigrpCommonServiceFamily(16384), +                  eigrpIpv4ServiceFamily(16385), +                  eigrpIpv6ServiceFamily(16386), +                  lispCanonicalAddressFormat(16387), +                  bgpLs(16388), +                  fortyeightBitMac(16389), +                  sixtyfourBitMac(16390), +                  oui(16391), +                  mac24(16392), +                  mac40(16393), +                  ipv664(16394), +                  rBridgePortID(16395), +                  reserved(65535) +              } +      END diff --git a/mibs/IANA-LANGUAGE-MIB.txt b/mibs/IANA-LANGUAGE-MIB.txt new file mode 100644 index 000000000..4b97bdd39 --- /dev/null +++ b/mibs/IANA-LANGUAGE-MIB.txt @@ -0,0 +1,126 @@ +IANA-LANGUAGE-MIB DEFINITIONS ::= BEGIN + +IMPORTS +    MODULE-IDENTITY, OBJECT-IDENTITY, mib-2 +        FROM SNMPv2-SMI; + +ianaLanguages MODULE-IDENTITY +    LAST-UPDATED "201405220000Z" -- May 22, 2014 +    ORGANIZATION "IANA" +    CONTACT-INFO +        "Internet Assigned Numbers Authority (IANA) + +         Postal: ICANN +                 12025 Waterfront Drive, Suite 300 +                 Los Angeles, CA 90094-2536 + +         Tel:    +1 310-301-5800 +         E-Mail: iana&iana.org" +    DESCRIPTION +        "The MIB module registers object identifier values for +         well-known programming and scripting languages. Every +         language registration MUST describe the format used +         when transferring scripts written in this language. + +         Any additions or changes to the contents of this MIB +         module require Designated Expert Review as defined in +         the Guidelines for Writing IANA Considerations Section +         document. The Designated Expert will be selected by +         the IESG Area Director of the OPS Area. + +         Note, this module does not have to register all possible +         languages since languages are identified by object +         identifier values. It is therefore possible to registered  +         languages in private OID trees. The references given below are not +         normative with regard to the language version. Other +         references might be better suited to describe some newer  +         versions of this language. The references are only +         provided as `a pointer into the right direction'." + + -- Revision log, in reverse chronological order + +    REVISION    "201405220000Z" -- May 22, 2014 +    DESCRIPTION "Updated contact info." + +    REVISION    "200005100000Z" -- May 10, 2000 +    DESCRIPTION "Import mib-2 instead of experimental, so that +                 this module compiles" + +    REVISION    "199909090900Z" -- September 9, 1999 +    DESCRIPTION "Initial version as published at time of +                 publication of RFC 2591." +    ::= { mib-2 73 } + +ianaLangJavaByteCode OBJECT-IDENTITY +    STATUS  current +    DESCRIPTION +        "Java byte code to be processed by a Java virtual machine. +         A script written in Java byte code is transferred by using +         the Java archive file format (JAR)." +    REFERENCE +        "The Java Virtual Machine Specification. +         ISBN 0-201-63452-X" +    ::= { ianaLanguages 1 } + +ianaLangTcl OBJECT-IDENTITY +    STATUS  current +    DESCRIPTION +        "The Tool Command Language (Tcl). A script written in the +         Tcl language is transferred in Tcl source code format." +    REFERENCE +        "Tcl and the Tk Toolkit. +         ISBN 0-201-63337-X" +    ::= { ianaLanguages 2 } + +ianaLangPerl OBJECT-IDENTITY +    STATUS  current +    DESCRIPTION +        "The Perl language. A script written in the Perl language +         is transferred in Perl source code format." +    REFERENCE +        "Programming Perl. +         ISBN 1-56592-149-6" +    ::= { ianaLanguages 3 } + +ianaLangScheme OBJECT-IDENTITY +    STATUS  current +    DESCRIPTION +        "The Scheme language. A script written in the Scheme +         language is transferred in Scheme source code format." +    REFERENCE +        "The Revised^4 Report on the Algorithmic Language Scheme. +         MIT Press" +    ::= { ianaLanguages 4 } + +ianaLangSRSL OBJECT-IDENTITY +    STATUS  current +    DESCRIPTION +        "The SNMP Script Language defined by SNMP Research. A +         script written in the SNMP Script Language is transferred +         in the SNMP Script Language source code format." +    ::= { ianaLanguages 5 } + +ianaLangPSL OBJECT-IDENTITY +    STATUS  current +    DESCRIPTION +        "The Patrol Script Language defined by BMC Software. A script +         written in the Patrol Script Language is transferred in the +         Patrol Script Language source code format." +    REFERENCE +        "PATROL Script Language Reference Manual, Version 3.0, +         November 30, 1995. BMC Software, Inc. 2101 City West Blvd., +         Houston, Texas 77042." +    ::= { ianaLanguages 6 } + +ianaLangSMSL OBJECT-IDENTITY +    STATUS  current +    DESCRIPTION +        "The Systems Management Scripting Language. A script written +         in the SMSL language is transferred in the SMSL source code +         format." +    REFERENCE +        "ISO/ITU Command Sequencer. +         ISO 10164-21 or ITU X.753" +    ::= { ianaLanguages 7 } + +END diff --git a/mibs/IANA-RTPROTO-MIB.txt b/mibs/IANA-RTPROTO-MIB.txt new file mode 100644 index 000000000..f7bc1ebc7 --- /dev/null +++ b/mibs/IANA-RTPROTO-MIB.txt @@ -0,0 +1,95 @@ +IANA-RTPROTO-MIB DEFINITIONS ::= BEGIN + +IMPORTS +    MODULE-IDENTITY, mib-2           FROM SNMPv2-SMI +    TEXTUAL-CONVENTION               FROM SNMPv2-TC; + +ianaRtProtoMIB  MODULE-IDENTITY +    LAST-UPDATED "201208300000Z" -- August 30, 2012 +    ORGANIZATION "IANA" +    CONTACT-INFO +            " Internet Assigned Numbers Authority +              Internet Corporation for Assigned Names and Numbers +              12025 Waterfront Drive, Suite 300 +              Los Angeles, CA 90094-2536 + +              Phone: +1 310 301 5800 +              EMail: iana&iana.org" +    DESCRIPTION +            "This MIB module defines the IANAipRouteProtocol and +            IANAipMRouteProtocol textual conventions for use in MIBs +            which need to identify unicast or multicast routing +            mechanisms. + +            Any additions or changes to the contents of this MIB module +            require either publication of an RFC, or Designated Expert +            Review as defined in RFC 2434, Guidelines for Writing an +            IANA Considerations Section in RFCs.  The Designated Expert  +            will be selected by the IESG Area Director(s) of the Routing +            Area." + +    REVISION     "201208300000Z"  -- August 30, 2012  +    DESCRIPTION  "Added dhcp(19)." + +    REVISION     "201107220000Z"  -- July 22, 2011  +    DESCRIPTION  "Added rpl(18) ." + +    REVISION     "200009260000Z"  -- September 26, 2000  +    DESCRIPTION  "Original version, published in coordination +                 with RFC 2932." +    ::= { mib-2 84 } + +IANAipRouteProtocol ::= TEXTUAL-CONVENTION +   STATUS      current +   DESCRIPTION +            "A mechanism for learning routes.  Inclusion of values for +            routing protocols is not intended to imply that those +            protocols need be supported." +   SYNTAX      INTEGER { +                other     (1),  -- not specified +                local     (2),  -- local interface +                netmgmt   (3),  -- static route +                icmp      (4),  -- result of ICMP Redirect + +                        -- the following are all dynamic +                        -- routing protocols + +                egp        (5),  -- Exterior Gateway Protocol +                ggp        (6),  -- Gateway-Gateway Protocol +                hello      (7),  -- FuzzBall HelloSpeak +                rip        (8),  -- Berkeley RIP or RIP-II +                isIs       (9),  -- Dual IS-IS +                esIs       (10), -- ISO 9542 +                ciscoIgrp  (11), -- Cisco IGRP +                bbnSpfIgp  (12), -- BBN SPF IGP +                ospf       (13), -- Open Shortest Path First +                bgp        (14), -- Border Gateway Protocol +                idpr       (15), -- InterDomain Policy Routing +                ciscoEigrp (16), -- Cisco EIGRP +                dvmrp      (17), -- DVMRP +                rpl        (18), -- RPL [RFC-ietf-roll-rpl-19] +                dhcp       (19)  -- DHCP [RFC2132] +               } + +IANAipMRouteProtocol ::= TEXTUAL-CONVENTION +   STATUS      current +   DESCRIPTION +            "The multicast routing protocol.  Inclusion of values for +            multicast routing protocols is not intended to imply that +            those protocols need be supported." +   SYNTAX      INTEGER { +                   other(1),          -- none of the following +                   local(2),          -- e.g., manually configured +                   netmgmt(3),        -- set via net.mgmt protocol +                   dvmrp(4), +                   mospf(5), +                   pimSparseDense(6), -- PIMv1, both DM and SM +                   cbt(7), +                   pimSparseMode(8),  -- PIM-SM +                   pimDenseMode(9),   -- PIM-DM +                   igmpOnly(10), +                   bgmp(11), +                   msdp(12) +               } + +END diff --git a/mibs/IANAifType-MIB.txt b/mibs/IANAifType-MIB.txt new file mode 100644 index 000000000..027a1532f --- /dev/null +++ b/mibs/IANAifType-MIB.txt @@ -0,0 +1,646 @@ +   IANAifType-MIB DEFINITIONS ::= BEGIN + +   IMPORTS +       MODULE-IDENTITY, mib-2      FROM SNMPv2-SMI +       TEXTUAL-CONVENTION          FROM SNMPv2-TC; + +   ianaifType MODULE-IDENTITY +       LAST-UPDATED "201407030000Z" -- July 3, 2014 +       ORGANIZATION "IANA" +       CONTACT-INFO "        Internet Assigned Numbers Authority + +                     Postal: ICANN +                             12025 Waterfront Drive, Suite 300 +                             Los Angeles, CA 90094-2536 + +                     Tel:    +1 310-301-5800 +                     E-Mail: iana&iana.org" +       DESCRIPTION  "This MIB module defines the IANAifType Textual +                     Convention, and thus the enumerated values of +                     the ifType object defined in MIB-II's ifTable." + +       REVISION     "201407030000Z"  -- July 3, 2014 +	   DESCRIPTION  "Registration of new IANAifTypes 277-278." + +       REVISION     "201405220000Z" -- May 22, 2014 +       DESCRIPTION  "Updated contact info." + +       REVISION     "201205170000Z"  -- May 17, 2012 +       DESCRIPTION  "Registration of new IANAifType 272." + +       REVISION     "201201110000Z"  -- January 11, 2012 +       DESCRIPTION  "Registration of new IANAifTypes 266-271." + +       REVISION     "201112180000Z"  -- December 18, 2011 +       DESCRIPTION  "Registration of new IANAifTypes 263-265." + +       REVISION     "201110260000Z"  -- October 26, 2011 +       DESCRIPTION  "Registration of new IANAifType 262." + +       REVISION     "201109070000Z"  -- September 7, 2011 +       DESCRIPTION  "Registration of new IANAifTypes 260 and 261." + +       REVISION     "201107220000Z"  -- July 22, 2011 +       DESCRIPTION  "Registration of new IANAifType 259." + +       REVISION     "201106030000Z"  -- June 03, 2011 +       DESCRIPTION  "Registration of new IANAifType 258." + +       REVISION     "201009210000Z"  -- September 21, 2010 +       DESCRIPTION  "Registration of new IANAifTypes 256 and 257." + +       REVISION     "201007210000Z"  -- July 21, 2010 +       DESCRIPTION  "Registration of new IANAifType 255." + +       REVISION     "201002110000Z"  -- February 11, 2010 +       DESCRIPTION  "Registration of new IANAifType 254." + +       REVISION     "201002080000Z"  -- February 08, 2010 +       DESCRIPTION  "Registration of new IANAifTypes 252 and 253." + +       REVISION     "200905060000Z"  -- May 06, 2009 +       DESCRIPTION  "Registration of new IANAifType 251." + +       REVISION     "200902060000Z"  -- February 06, 2009 +       DESCRIPTION  "Registration of new IANAtunnelType 15." + +       REVISION     "200810090000Z"  -- October 09, 2008 +       DESCRIPTION  "Registration of new IANAifType 250." + +       REVISION     "200808120000Z"  -- August 12, 2008 +       DESCRIPTION  "Registration of new IANAifType 249." + +       REVISION     "200807220000Z"  -- July 22, 2008 +       DESCRIPTION  "Registration of new IANAifTypes 247 and 248." + +       REVISION     "200806240000Z"  -- June 24, 2008 +       DESCRIPTION  "Registration of new IANAifType 246." + +       REVISION     "200805290000Z"  -- May 29, 2008 +       DESCRIPTION  "Registration of new IANAifType 245." + +       REVISION     "200709130000Z"  -- September 13, 2007 +       DESCRIPTION  "Registration of new IANAifTypes 243 and 244." + +       REVISION     "200705290000Z"  -- May 29, 2007 +       DESCRIPTION  "Changed the description for IANAifType 228." + +       REVISION     "200703080000Z"  -- March 08, 2007 +       DESCRIPTION  "Registration of new IANAifType 242." + +       REVISION     "200701230000Z"  -- January 23, 2007 +       DESCRIPTION  "Registration of new IANAifTypes 239, 240, and 241."  + +       REVISION     "200610170000Z"  -- October 17, 2006 +       DESCRIPTION  "Deprecated/Obsoleted IANAifType 230.  Registration of  +                     IANAifType 238."  + +       REVISION     "200609250000Z"  -- September 25, 2006 +       DESCRIPTION  "Changed the description for IANA ifType  +                     184 and added new IANA ifType 237."   + +       REVISION     "200608170000Z"  -- August 17, 2006 +       DESCRIPTION  "Changed the descriptions for IANAifTypes +                     20 and 21."    + +       REVISION     "200608110000Z"  -- August 11, 2006 +       DESCRIPTION  "Changed the descriptions for IANAifTypes +                     7, 11, 62, 69, and 117."    + +       REVISION     "200607250000Z"  -- July 25, 2006 +       DESCRIPTION  "Registration of new IANA ifType 236." + +       REVISION     "200606140000Z"  -- June 14, 2006 +       DESCRIPTION  "Registration of new IANA ifType 235." + +       REVISION     "200603310000Z"  -- March 31, 2006 +       DESCRIPTION  "Registration of new IANA ifType 234." + +       REVISION     "200603300000Z"  -- March 30, 2006 +       DESCRIPTION  "Registration of new IANA ifType 233." + +       REVISION     "200512220000Z"  -- December 22, 2005 +       DESCRIPTION  "Registration of new IANA ifTypes 231 and 232." + +       REVISION     "200510100000Z"  -- October 10, 2005 +       DESCRIPTION  "Registration of new IANA ifType 230." + +       REVISION     "200509090000Z"  -- September 09, 2005 +       DESCRIPTION  "Registration of new IANA ifType 229." + +       REVISION     "200505270000Z"  -- May 27, 2005 +       DESCRIPTION  "Registration of new IANA ifType 228." + +       REVISION     "200503030000Z"  -- March 3, 2005 +       DESCRIPTION  "Added the IANAtunnelType TC and deprecated +	                 IANAifType sixToFour (215) per RFC4087." + +       REVISION     "200411220000Z"  -- November 22, 2004 +       DESCRIPTION  "Registration of new IANA ifType 227 per RFC4631." + +       REVISION     "200406170000Z"  -- June 17, 2004 +       DESCRIPTION  "Registration of new IANA ifType 226." + +       REVISION     "200405120000Z"  -- May 12, 2004 +       DESCRIPTION  "Added description for IANAifType 6, and  +	                 changed the descriptions for IANAifTypes +                     180, 181, and 182." + +       REVISION     "200405070000Z"  -- May 7, 2004 +       DESCRIPTION  "Registration of new IANAifType 225." + +       REVISION     "200308250000Z"  -- Aug 25, 2003 +       DESCRIPTION  "Deprecated IANAifTypes 7 and 11. Obsoleted +                     IANAifTypes 62, 69, and 117.  ethernetCsmacd (6) +                     should be used instead of these values" + +       REVISION     "200308180000Z"  -- Aug 18, 2003 +       DESCRIPTION  "Registration of new IANAifType +                     224." + +       REVISION     "200308070000Z"  -- Aug 7, 2003 +       DESCRIPTION  "Registration of new IANAifTypes +                     222 and 223." + +       REVISION     "200303180000Z"  -- Mar 18, 2003 +       DESCRIPTION  "Registration of new IANAifType +                     221." + +       REVISION     "200301130000Z"  -- Jan 13, 2003 +       DESCRIPTION  "Registration of new IANAifType +                     220." + +       REVISION     "200210170000Z"  -- Oct 17, 2002 +       DESCRIPTION  "Registration of new IANAifType +                     219." + +       REVISION     "200207160000Z"  -- Jul 16, 2002 +       DESCRIPTION  "Registration of new IANAifTypes +                     217 and 218." + +       REVISION     "200207100000Z"  -- Jul 10, 2002 +       DESCRIPTION  "Registration of new IANAifTypes +                     215 and 216." + +       REVISION     "200206190000Z"  -- Jun 19, 2002 +       DESCRIPTION  "Registration of new IANAifType +                     214." + +       REVISION     "200201040000Z"  -- Jan 4, 2002 +       DESCRIPTION  "Registration of new IANAifTypes +                     211, 212 and 213." + +       REVISION     "200112200000Z"  -- Dec 20, 2001 +       DESCRIPTION  "Registration of new IANAifTypes +                     209 and 210." + +       REVISION     "200111150000Z"  -- Nov 15, 2001 +       DESCRIPTION  "Registration of new IANAifTypes +                     207 and 208." + +       REVISION     "200111060000Z"  -- Nov 6, 2001 +       DESCRIPTION  "Registration of new IANAifType +                     206." + +       REVISION     "200111020000Z"  -- Nov 2, 2001 +       DESCRIPTION  "Registration of new IANAifType +                     205." + +       REVISION     "200110160000Z"  -- Oct 16, 2001 +       DESCRIPTION  "Registration of new IANAifTypes +                     199, 200, 201, 202, 203, and 204." + +       REVISION     "200109190000Z"  -- Sept 19, 2001 +       DESCRIPTION  "Registration of new IANAifType +                     198." + +       REVISION     "200105110000Z"  -- May 11, 2001 +       DESCRIPTION  "Registration of new IANAifType +                     197." + +       REVISION     "200101120000Z"  -- Jan 12, 2001 +       DESCRIPTION  "Registration of new IANAifTypes +                     195 and 196." + +       REVISION     "200012190000Z"  -- Dec 19, 2000 +       DESCRIPTION  "Registration of new IANAifTypes +                     193 and 194." + +       REVISION     "200012070000Z"  -- Dec 07, 2000 +       DESCRIPTION  "Registration of new IANAifTypes +                     191 and 192." + +       REVISION     "200012040000Z"  -- Dec 04, 2000 +       DESCRIPTION  "Registration of new IANAifType +                     190." + +       REVISION     "200010170000Z"  -- Oct 17, 2000 +       DESCRIPTION  "Registration of new IANAifTypes +                     188 and 189."   + +       REVISION     "200010020000Z"  -- Oct 02, 2000 +       DESCRIPTION  "Registration of new IANAifType 187."  + +       REVISION     "200009010000Z"  -- Sept 01, 2000 +       DESCRIPTION  "Registration of new IANAifTypes +                     184, 185, and 186."			 + +       REVISION     "200008240000Z"  -- Aug 24, 2000 +       DESCRIPTION  "Registration of new IANAifType 183."  + +       REVISION     "200008230000Z"  -- Aug 23, 2000 +       DESCRIPTION  "Registration of new IANAifTypes +                     174-182." + +       REVISION     "200008220000Z"  -- Aug 22, 2000 +       DESCRIPTION  "Registration of new IANAifTypes 170, +                     171, 172 and 173." + +       REVISION     "200004250000Z"  -- Apr 25, 2000 +       DESCRIPTION  "Registration of new IANAifTypes 168 and 169."        + +       REVISION     "200003060000Z"  -- Mar 6, 2000 +       DESCRIPTION  "Fixed a missing semi-colon in the IMPORT. +                     Also cleaned up the REVISION log a bit. +                     It is not complete, but from now on it will +                     be maintained and kept up to date with each +                     change to this MIB module." + +       REVISION     "199910081430Z"  -- Oct 08, 1999 +       DESCRIPTION  "Include new name assignments up to cnr(85). +                     This is the first version available via the WWW +                     at: ftp://ftp.isi.edu/mib/ianaiftype.mib" + +       REVISION     "199401310000Z"  -- Jan 31, 1994 +       DESCRIPTION  "Initial version of this MIB as published in +                     RFC 1573." +       ::= { mib-2 30 } + +   IANAifType ::= TEXTUAL-CONVENTION +       STATUS       current +       DESCRIPTION +               "This data type is used as the syntax of the ifType +               object in the (updated) definition of MIB-II's +               ifTable. + +               The definition of this textual convention with the +               addition of newly assigned values is published +               periodically by the IANA, in either the Assigned +               Numbers RFC, or some derivative of it specific to +               Internet Network Management number assignments.  (The +               latest arrangements can be obtained by contacting the +               IANA.) + +               Requests for new values should be made to IANA via +               email (iana&iana.org). + +               The relationship between the assignment of ifType +               values and of OIDs to particular media-specific MIBs +               is solely the purview of IANA and is subject to change +               without notice.  Quite often, a media-specific MIB's +               OID-subtree assignment within MIB-II's 'transmission' +               subtree will be the same as its ifType value. +               However, in some circumstances this will not be the +               case, and implementors must not pre-assume any +               specific relationship between ifType values and +               transmission subtree OIDs." +       SYNTAX  INTEGER { +                   other(1),          -- none of the following +                   regular1822(2), +                   hdh1822(3), +                   ddnX25(4), +                   rfc877x25(5), +                   ethernetCsmacd(6), -- for all ethernet-like interfaces, +                                      -- regardless of speed, as per RFC3635 +                   iso88023Csmacd(7), -- Deprecated via RFC3635 +                                      -- ethernetCsmacd (6) should be used instead +                   iso88024TokenBus(8), +                   iso88025TokenRing(9), +                   iso88026Man(10), +                   starLan(11), -- Deprecated via RFC3635 +                                -- ethernetCsmacd (6) should be used instead +                   proteon10Mbit(12), +                   proteon80Mbit(13), +                   hyperchannel(14), +                   fddi(15), +                   lapb(16), +                   sdlc(17), +                   ds1(18),            -- DS1-MIB +                   e1(19),             -- Obsolete see DS1-MIB +                   basicISDN(20),              -- no longer used +                                               -- see also RFC2127 +                   primaryISDN(21),            -- no longer used +                                               -- see also RFC2127 +                   propPointToPointSerial(22), -- proprietary serial +                   ppp(23), +                   softwareLoopback(24), +                   eon(25),            -- CLNP over IP  +                   ethernet3Mbit(26), +                   nsip(27),           -- XNS over IP +                   slip(28),           -- generic SLIP +                   ultra(29),          -- ULTRA technologies +                   ds3(30),            -- DS3-MIB +                   sip(31),            -- SMDS, coffee +                   frameRelay(32),     -- DTE only.  +                   rs232(33), +                   para(34),           -- parallel-port +                   arcnet(35),         -- arcnet +                   arcnetPlus(36),     -- arcnet plus +                   atm(37),            -- ATM cells +                   miox25(38), +                   sonet(39),          -- SONET or SDH  +                   x25ple(40), +                   iso88022llc(41), +                   localTalk(42), +                   smdsDxi(43), +                   frameRelayService(44),  -- FRNETSERV-MIB +                   v35(45), +                   hssi(46), +                   hippi(47), +                   modem(48),          -- Generic modem +                   aal5(49),           -- AAL5 over ATM +                   sonetPath(50), +                   sonetVT(51), +                   smdsIcip(52),       -- SMDS InterCarrier Interface +                   propVirtual(53),    -- proprietary virtual/internal +                   propMultiplexor(54),-- proprietary multiplexing +                   ieee80212(55),      -- 100BaseVG +                   fibreChannel(56),   -- Fibre Channel +                   hippiInterface(57), -- HIPPI interfaces      +                   frameRelayInterconnect(58), -- Obsolete, use either +                                       -- frameRelay(32) or  +                                       -- frameRelayService(44). +                   aflane8023(59),     -- ATM Emulated LAN for 802.3 +                   aflane8025(60),     -- ATM Emulated LAN for 802.5 +                   cctEmul(61),        -- ATM Emulated circuit           +                   fastEther(62),      -- Obsoleted via RFC3635 +                                       -- ethernetCsmacd (6) should be used instead +                   isdn(63),           -- ISDN and X.25            +                   v11(64),            -- CCITT V.11/X.21              +                   v36(65),            -- CCITT V.36                   +                   g703at64k(66),      -- CCITT G703 at 64Kbps +                   g703at2mb(67),      -- Obsolete see DS1-MIB +                   qllc(68),           -- SNA QLLC                     +                   fastEtherFX(69),    -- Obsoleted via RFC3635 +                                       -- ethernetCsmacd (6) should be used instead +                   channel(70),        -- channel                      +                   ieee80211(71),      -- radio spread spectrum        +                   ibm370parChan(72),  -- IBM System 360/370 OEMI Channel +                   escon(73),          -- IBM Enterprise Systems Connection +                   dlsw(74),           -- Data Link Switching +                   isdns(75),          -- ISDN S/T interface +                   isdnu(76),          -- ISDN U interface +                   lapd(77),           -- Link Access Protocol D +                   ipSwitch(78),       -- IP Switching Objects +                   rsrb(79),           -- Remote Source Route Bridging +                   atmLogical(80),     -- ATM Logical Port +                   ds0(81),            -- Digital Signal Level 0 +                   ds0Bundle(82),      -- group of ds0s on the same ds1 +                   bsc(83),            -- Bisynchronous Protocol +                   async(84),          -- Asynchronous Protocol +                   cnr(85),            -- Combat Net Radio +                   iso88025Dtr(86),    -- ISO 802.5r DTR +                   eplrs(87),          -- Ext Pos Loc Report Sys +                   arap(88),           -- Appletalk Remote Access Protocol +                   propCnls(89),       -- Proprietary Connectionless Protocol +                   hostPad(90),        -- CCITT-ITU X.29 PAD Protocol +                   termPad(91),        -- CCITT-ITU X.3 PAD Facility +                   frameRelayMPI(92),  -- Multiproto Interconnect over FR +                   x213(93),           -- CCITT-ITU X213 +                   adsl(94),           -- Asymmetric Digital Subscriber Loop +                   radsl(95),          -- Rate-Adapt. Digital Subscriber Loop +                   sdsl(96),           -- Symmetric Digital Subscriber Loop +                   vdsl(97),           -- Very H-Speed Digital Subscrib. Loop +                   iso88025CRFPInt(98), -- ISO 802.5 CRFP +                   myrinet(99),        -- Myricom Myrinet +                   voiceEM(100),       -- voice recEive and transMit +                   voiceFXO(101),      -- voice Foreign Exchange Office +                   voiceFXS(102),      -- voice Foreign Exchange Station +                   voiceEncap(103),    -- voice encapsulation +                   voiceOverIp(104),   -- voice over IP encapsulation +                   atmDxi(105),        -- ATM DXI +                   atmFuni(106),       -- ATM FUNI +                   atmIma (107),       -- ATM IMA		    +                   pppMultilinkBundle(108), -- PPP Multilink Bundle +                   ipOverCdlc (109),   -- IBM ipOverCdlc +                   ipOverClaw (110),   -- IBM Common Link Access to Workstn +                   stackToStack (111), -- IBM stackToStack +                   virtualIpAddress (112), -- IBM VIPA +                   mpc (113),          -- IBM multi-protocol channel support +                   ipOverAtm (114),    -- IBM ipOverAtm +                   iso88025Fiber (115), -- ISO 802.5j Fiber Token Ring +                   tdlc (116),	       -- IBM twinaxial data link control +                   gigabitEthernet (117), -- Obsoleted via RFC3635 +                                          -- ethernetCsmacd (6) should be used instead +                   hdlc (118),         -- HDLC +                   lapf (119),	       -- LAP F +                   v37 (120),	       -- V.37 +                   x25mlp (121),       -- Multi-Link Protocol +                   x25huntGroup (122), -- X25 Hunt Group +                   transpHdlc (123),   -- Transp HDLC +                   interleave (124),   -- Interleave channel +                   fast (125),         -- Fast channel +                   ip (126),	       -- IP (for APPN HPR in IP networks) +                   docsCableMaclayer (127),  -- CATV Mac Layer +                   docsCableDownstream (128), -- CATV Downstream interface +                   docsCableUpstream (129),  -- CATV Upstream interface +                   a12MppSwitch (130), -- Avalon Parallel Processor +                   tunnel (131),       -- Encapsulation interface +                   coffee (132),       -- coffee pot +                   ces (133),          -- Circuit Emulation Service +                   atmSubInterface (134), -- ATM Sub Interface +                   l2vlan (135),       -- Layer 2 Virtual LAN using 802.1Q +                   l3ipvlan (136),     -- Layer 3 Virtual LAN using IP +                   l3ipxvlan (137),    -- Layer 3 Virtual LAN using IPX +                   digitalPowerline (138), -- IP over Power Lines	 +                   mediaMailOverIp (139), -- Multimedia Mail over IP +                   dtm (140),        -- Dynamic syncronous Transfer Mode +                   dcn (141),    -- Data Communications Network +                   ipForward (142),    -- IP Forwarding Interface +                   msdsl (143),       -- Multi-rate Symmetric DSL +                   ieee1394 (144), -- IEEE1394 High Performance Serial Bus +                   if-gsn (145),       --   HIPPI-6400  +                   dvbRccMacLayer (146), -- DVB-RCC MAC Layer +                   dvbRccDownstream (147),  -- DVB-RCC Downstream Channel +                   dvbRccUpstream (148),  -- DVB-RCC Upstream Channel +                   atmVirtual (149),   -- ATM Virtual Interface +                   mplsTunnel (150),   -- MPLS Tunnel Virtual Interface +                   srp (151),	-- Spatial Reuse Protocol	 +                   voiceOverAtm (152),  -- Voice Over ATM +                   voiceOverFrameRelay (153),   -- Voice Over Frame Relay  +                   idsl (154),		-- Digital Subscriber Loop over ISDN +                   compositeLink (155),  -- Avici Composite Link Interface +                   ss7SigLink (156),     -- SS7 Signaling Link  +                   propWirelessP2P (157),  --  Prop. P2P wireless interface +                   frForward (158),    -- Frame Forward Interface +                   rfc1483 (159),	-- Multiprotocol over ATM AAL5 +                   usb (160),		-- USB Interface +                   ieee8023adLag (161),  -- IEEE 802.3ad Link Aggregate +                   bgppolicyaccounting (162), -- BGP Policy Accounting +                   frf16MfrBundle (163), -- FRF .16 Multilink Frame Relay  +                   h323Gatekeeper (164), -- H323 Gatekeeper +                   h323Proxy (165), -- H323 Voice and Video Proxy +                   mpls (166), -- MPLS                    +                   mfSigLink (167), -- Multi-frequency signaling link +                   hdsl2 (168), -- High Bit-Rate DSL - 2nd generation +                   shdsl (169), -- Multirate HDSL2 +                   ds1FDL (170), -- Facility Data Link 4Kbps on a DS1 +                   pos (171), -- Packet over SONET/SDH Interface +                   dvbAsiIn (172), -- DVB-ASI Input +                   dvbAsiOut (173), -- DVB-ASI Output  +                   plc (174), -- Power Line Communtications +                   nfas (175), -- Non Facility Associated Signaling +                   tr008 (176), -- TR008 +                   gr303RDT (177), -- Remote Digital Terminal +                   gr303IDT (178), -- Integrated Digital Terminal +                   isup (179), -- ISUP +                   propDocsWirelessMaclayer (180), -- Cisco proprietary Maclayer +                   propDocsWirelessDownstream (181), -- Cisco proprietary Downstream +                   propDocsWirelessUpstream (182), -- Cisco proprietary Upstream +                   hiperlan2 (183), -- HIPERLAN Type 2 Radio Interface +                   propBWAp2Mp (184), -- PropBroadbandWirelessAccesspt2multipt +                             -- use of this iftype for IEEE 802.16 WMAN +                             -- interfaces as per IEEE Std 802.16f is +                             -- deprecated and ifType 237 should be used instead. +                   sonetOverheadChannel (185), -- SONET Overhead Channel +                   digitalWrapperOverheadChannel (186), -- Digital Wrapper +                   aal2 (187), -- ATM adaptation layer 2 +                   radioMAC (188), -- MAC layer over radio links +                   atmRadio (189), -- ATM over radio links    +                   imt (190), -- Inter Machine Trunks +                   mvl (191), -- Multiple Virtual Lines DSL +                   reachDSL (192), -- Long Reach DSL +                   frDlciEndPt (193), -- Frame Relay DLCI End Point +                   atmVciEndPt (194), -- ATM VCI End Point +                   opticalChannel (195), -- Optical Channel +                   opticalTransport (196), -- Optical Transport +                   propAtm (197), --  Proprietary ATM        +                   voiceOverCable (198), -- Voice Over Cable Interface +                   infiniband (199), -- Infiniband +                   teLink (200), -- TE Link +                   q2931 (201), -- Q.2931 +                   virtualTg (202), -- Virtual Trunk Group +                   sipTg (203), -- SIP Trunk Group +                   sipSig (204), -- SIP Signaling    +                   docsCableUpstreamChannel (205), -- CATV Upstream Channel +                   econet (206), -- Acorn Econet +                   pon155 (207), -- FSAN 155Mb Symetrical PON interface +                   pon622 (208), -- FSAN622Mb Symetrical PON interface +                   bridge (209), -- Transparent bridge interface +                   linegroup (210), -- Interface common to multiple lines    +                   voiceEMFGD (211), -- voice E&M Feature Group D +                   voiceFGDEANA (212), -- voice FGD Exchange Access North American +                   voiceDID (213), -- voice Direct Inward Dialing +                   mpegTransport (214), -- MPEG transport interface +                   sixToFour (215), -- 6to4 interface (DEPRECATED) +                   gtp (216), -- GTP (GPRS Tunneling Protocol) +                   pdnEtherLoop1 (217), -- Paradyne EtherLoop 1 +                   pdnEtherLoop2 (218), -- Paradyne EtherLoop 2 +                   opticalChannelGroup (219), -- Optical Channel Group +                   homepna (220), -- HomePNA ITU-T G.989 +                   gfp (221), -- Generic Framing Procedure (GFP) +                   ciscoISLvlan (222), -- Layer 2 Virtual LAN using Cisco ISL +                   actelisMetaLOOP (223), -- Acteleis proprietary MetaLOOP High Speed Link  +                   fcipLink (224), -- FCIP Link  +                   rpr (225), -- Resilient Packet Ring Interface Type +                   qam (226), -- RF Qam Interface +                   lmp (227), -- Link Management Protocol +                   cblVectaStar (228), -- Cambridge Broadband Networks Limited VectaStar +                   docsCableMCmtsDownstream (229), -- CATV Modular CMTS Downstream Interface +                   adsl2 (230), -- Asymmetric Digital Subscriber Loop Version 2  +                                -- (DEPRECATED/OBSOLETED - please use adsl2plus 238 instead) +                   macSecControlledIF (231), -- MACSecControlled  +                   macSecUncontrolledIF (232), -- MACSecUncontrolled +                   aviciOpticalEther (233), -- Avici Optical Ethernet Aggregate +                   atmbond (234), -- atmbond +                   voiceFGDOS (235), -- voice FGD Operator Services +                   mocaVersion1 (236), -- MultiMedia over Coax Alliance (MoCA) Interface +                             -- as documented in information provided privately to IANA +                   ieee80216WMAN (237), -- IEEE 802.16 WMAN interface +                   adsl2plus (238), -- Asymmetric Digital Subscriber Loop Version 2,  +                                   -- Version 2 Plus and all variants +                   dvbRcsMacLayer (239), -- DVB-RCS MAC Layer +                   dvbTdm (240), -- DVB Satellite TDM +                   dvbRcsTdma (241), -- DVB-RCS TDMA +                   x86Laps (242), -- LAPS based on ITU-T X.86/Y.1323 +                   wwanPP (243), -- 3GPP WWAN +                   wwanPP2 (244), -- 3GPP2 WWAN +                   voiceEBS (245), -- voice P-phone EBS physical interface +                   ifPwType (246), -- Pseudowire interface type +                   ilan (247), -- Internal LAN on a bridge per IEEE 802.1ap +                   pip (248), -- Provider Instance Port on a bridge per IEEE 802.1ah PBB +                   aluELP (249), -- Alcatel-Lucent Ethernet Link Protection +                   gpon (250), -- Gigabit-capable passive optical networks (G-PON) as per ITU-T G.948 +                   vdsl2 (251), -- Very high speed digital subscriber line Version 2 (as per ITU-T Recommendation G.993.2) +                   capwapDot11Profile (252), -- WLAN Profile Interface +                   capwapDot11Bss (253), -- WLAN BSS Interface +                   capwapWtpVirtualRadio (254), -- WTP Virtual Radio Interface +                   bits (255), -- bitsport +                   docsCableUpstreamRfPort (256), -- DOCSIS CATV Upstream RF Port +                   cableDownstreamRfPort (257), -- CATV downstream RF port +                   vmwareVirtualNic (258), -- VMware Virtual Network Interface +                   ieee802154 (259), -- IEEE 802.15.4 WPAN interface +                   otnOdu (260), -- OTN Optical Data Unit +                   otnOtu (261), -- OTN Optical channel Transport Unit +                   ifVfiType (262), -- VPLS Forwarding Instance Interface Type +                   g9981 (263), -- G.998.1 bonded interface +                   g9982 (264), -- G.998.2 bonded interface +                   g9983 (265), -- G.998.3 bonded interface +                   aluEpon (266), -- Ethernet Passive Optical Networks (E-PON) +                   aluEponOnu (267), -- EPON Optical Network Unit +                   aluEponPhysicalUni (268), -- EPON physical User to Network interface +                   aluEponLogicalLink (269), -- The emulation of a point-to-point link over the EPON layer +                   aluGponOnu (270), -- GPON Optical Network Unit +                   aluGponPhysicalUni (271), -- GPON physical User to Network interface +                   vmwareNicTeam (272), -- VMware NIC Team +                   docsOfdmDownstream (277), -- CATV Downstream OFDM interface +                   docsOfdmaUpstream (278) -- CATV Upstream OFDMA interface +                   } + +IANAtunnelType ::= TEXTUAL-CONVENTION +    STATUS     current +    DESCRIPTION +            "The encapsulation method used by a tunnel. The value +            direct indicates that a packet is encapsulated +            directly within a normal IP header, with no +            intermediate header, and unicast to the remote tunnel +            endpoint (e.g., an RFC 2003 IP-in-IP tunnel, or an RFC +            1933 IPv6-in-IPv4 tunnel). The value minimal indicates +            that a Minimal Forwarding Header (RFC 2004) is +            inserted between the outer header and the payload +            packet. The value UDP indicates that the payload +            packet is encapsulated within a normal UDP packet +            (e.g., RFC 1234). + +            The values sixToFour, sixOverFour, and isatap +            indicates that an IPv6 packet is encapsulated directly +            within an IPv4 header, with no intermediate header, +            and unicast to the destination determined by the 6to4, +            6over4, or ISATAP protocol. + +            The remaining protocol-specific values indicate that a +            header of the protocol of that name is inserted +            between the outer header and the payload header. + +            The assignment policy for IANAtunnelType values is +            identical to the policy for assigning IANAifType +            values." +    SYNTAX     INTEGER { +                   other(1),        -- none of the following +                   direct(2),       -- no intermediate header +                   gre(3),          -- GRE encapsulation +                   minimal(4),      -- Minimal encapsulation +                   l2tp(5),         -- L2TP encapsulation +                   pptp(6),         -- PPTP encapsulation +                   l2f(7),          -- L2F encapsulation +                   udp(8),          -- UDP encapsulation +                   atmp(9),         -- ATMP encapsulation +                   msdp(10),        -- MSDP encapsulation +                   sixToFour(11),   -- 6to4 encapsulation +                   sixOverFour(12), -- 6over4 encapsulation +                   isatap(13),      -- ISATAP encapsulation +                   teredo(14),      -- Teredo encapsulation +                   ipHttps(15)      -- IPHTTPS +               } + +   END diff --git a/op-mode-definitions/container.xml.in b/op-mode-definitions/container.xml.in index 786bd66d3..ada9a4d59 100644 --- a/op-mode-definitions/container.xml.in +++ b/op-mode-definitions/container.xml.in @@ -11,7 +11,7 @@              <properties>                <help>Pull a new image for container</help>              </properties> -            <command>sudo podman image pull "${4}"</command> +            <command>sudo ${vyos_op_scripts_dir}/container.py add_image --name "${4}"</command>            </tagNode>          </children>        </node> @@ -44,7 +44,7 @@                  <script>sudo podman image ls -q</script>                </completionHelp>              </properties> -            <command>sudo podman image rm --force "${4}"</command> +            <command>sudo ${vyos_op_scripts_dir}/container.py delete_image --name "${4}"</command>            </tagNode>          </children>        </node> diff --git a/op-mode-definitions/date.xml.in b/op-mode-definitions/date.xml.in index 15a69dbd9..6d8586025 100644 --- a/op-mode-definitions/date.xml.in +++ b/op-mode-definitions/date.xml.in @@ -37,28 +37,6 @@          </properties>          <command>/bin/date "$3"</command>        </tagNode> -      <node name="date"> -        <properties> -          <help>Set system date and time</help> -        </properties> -        <children> -          <node name="ntp"> -            <properties> -              <help>Set system date and time from NTP server (default: 0.pool.ntp.org)</help> -            </properties> -            <command>/usr/sbin/ntpdate -u 0.pool.ntp.org</command> -          </node> -          <tagNode name="ntp"> -            <properties> -              <help>Set system date and time from NTP server</help> -              <completionHelp> -                <script>${vyos_completion_dir}/list_ntp_servers.sh</script> -              </completionHelp> -            </properties> -            <command>/usr/sbin/ntpdate -u "$4"</command> -          </tagNode> -        </children> -      </node>      </children>    </node>  </interfaceDefinition> diff --git a/op-mode-definitions/include/show-route-summary.xml.i b/op-mode-definitions/include/show-route-summary.xml.i deleted file mode 100644 index 471124562..000000000 --- a/op-mode-definitions/include/show-route-summary.xml.i +++ /dev/null @@ -1,8 +0,0 @@ -<!-- included start from show-route-summary.xml.i --> -<leafNode name="summary"> -  <properties> -    <help>Summary of all routes</help> -  </properties> -  <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> -</leafNode> -<!-- included end --> diff --git a/op-mode-definitions/lldp.xml.in b/op-mode-definitions/lldp.xml.in index 297ccf1f4..07cafa77f 100644 --- a/op-mode-definitions/lldp.xml.in +++ b/op-mode-definitions/lldp.xml.in @@ -11,14 +11,8 @@              <properties>                <help>Show LLDP neighbors</help>              </properties> -            <command>${vyos_op_scripts_dir}/lldp_op.py --all</command> +            <command>${vyos_op_scripts_dir}/lldp.py show_neighbors</command>              <children> -              <node name="detail"> -                <properties> -                  <help>Show LLDP neighbor details</help> -                </properties> -                <command>${vyos_op_scripts_dir}/lldp_op.py --detail</command> -              </node>                <tagNode name="interface">                  <properties>                    <help>Show LLDP for specified interface</help> @@ -26,7 +20,7 @@                      <script>${vyos_completion_dir}/list_interfaces.py</script>                    </completionHelp>                  </properties> -                <command>${vyos_op_scripts_dir}/lldp_op.py --interface $5</command> +                <command>${vyos_op_scripts_dir}/lldp.py show_neighbors --interface $5</command>                </tagNode>              </children>            </node> diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in index c14f45d75..b68047bb9 100644 --- a/op-mode-definitions/monitor-log.xml.in +++ b/op-mode-definitions/monitor-log.xml.in @@ -101,9 +101,15 @@            </leafNode>            <leafNode name="nhrp">              <properties> -              <help>Monitor last lines of NHRP log</help> +              <help>Monitor last lines of Next Hop Resolution Protocol (NHRP) log</help>              </properties> -            <command>journalctl --no-hostname --boot --unit opennhrp.service</command> +            <command>journalctl --no-hostname --boot --follow --unit opennhrp.service</command> +          </leafNode> +          <leafNode name="ntp"> +            <properties> +              <help>Monitor last lines of Network Time Protocol (NTP) log</help> +            </properties> +            <command>journalctl --no-hostname --boot --follow --unit chrony.service</command>            </leafNode>            <node name="pppoe">              <properties> @@ -249,20 +255,20 @@            </node>            <node name="vpn">              <properties> -              <help>Show log for Virtual Private Network (VPN)</help> +              <help>Monitor Virtual Private Network (VPN) services</help>              </properties>              <children>                <leafNode name="all">                  <properties>                    <help>Monitor last lines of ALL VPNs</help>                  </properties> -                <command>journalctl --no-hostname --boot --follow --unit strongswan-starter.service --unit accel-ppp@*.service</command> +                <command>journalctl --no-hostname --boot --follow --unit strongswan-starter.service --unit accel-ppp@*.service --unit ocserv.service</command>                </leafNode>                <leafNode name="ipsec">                  <properties>                    <help>Monitor last lines of IPsec</help>                  </properties> -                <command>journalctl --no-hostname --boot --follow --unit strongswan.service</command> +                <command>journalctl --no-hostname --boot --follow --unit strongswan-starter.service</command>                </leafNode>                <leafNode name="l2tp">                  <properties> @@ -270,6 +276,12 @@                  </properties>                  <command>journalctl --no-hostname --boot --follow --unit accel-ppp@l2tp.service</command>                </leafNode> +              <leafNode name="openconnect"> +                <properties> +                  <help>Monitor last lines of OpenConnect</help> +                </properties> +                <command>journalctl --no-hostname --boot --follow --unit ocserv.service</command> +              </leafNode>                <leafNode name="pptp">                  <properties>                    <help>Monitor last lines of PPTP</help> diff --git a/op-mode-definitions/show-interfaces-bonding.xml.in b/op-mode-definitions/show-interfaces-bonding.xml.in index 6908153dd..c41e7bd5f 100644 --- a/op-mode-definitions/show-interfaces-bonding.xml.in +++ b/op-mode-definitions/show-interfaces-bonding.xml.in @@ -11,13 +11,13 @@                  <path>interfaces bonding</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=bonding</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified bonding interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=bonding</command>                </leafNode>                <leafNode name="detail">                  <properties> @@ -38,13 +38,13 @@                      <path>interfaces bonding ${COMP_WORDS[3]} vif</path>                    </completionHelp>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=bonding</command>                  <children>                    <leafNode name="brief">                      <properties>                        <help>Show summary of specified virtual network interface (vif) information</help>                      </properties> -                    <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6"</command> +                    <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=bonding</command>                    </leafNode>                  </children>                </tagNode> diff --git a/op-mode-definitions/show-interfaces-bridge.xml.in b/op-mode-definitions/show-interfaces-bridge.xml.in index b950c3a17..22cd3ee67 100644 --- a/op-mode-definitions/show-interfaces-bridge.xml.in +++ b/op-mode-definitions/show-interfaces-bridge.xml.in @@ -11,13 +11,13 @@                  <path>interfaces bridge</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=bridge</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified bridge interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=bridge</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-dummy.xml.in b/op-mode-definitions/show-interfaces-dummy.xml.in index 398e00636..958d3483d 100644 --- a/op-mode-definitions/show-interfaces-dummy.xml.in +++ b/op-mode-definitions/show-interfaces-dummy.xml.in @@ -11,13 +11,13 @@                  <path>interfaces dummy</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=dummy</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified dummy interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=dummy</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-ethernet.xml.in b/op-mode-definitions/show-interfaces-ethernet.xml.in index 40d4adbb2..81759c2b6 100644 --- a/op-mode-definitions/show-interfaces-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-ethernet.xml.in @@ -11,13 +11,13 @@                  <path>interfaces ethernet</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=ethernet</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified ethernet interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=ethernet</command>                </leafNode>                <leafNode name="identify">                  <properties> @@ -58,13 +58,13 @@                      <path>interfaces ethernet ${COMP_WORDS[3]} vif</path>                    </completionHelp>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=ethernet</command>                  <children>                    <leafNode name="brief">                      <properties>                        <help>Show summary of specified virtual network interface (vif) information</help>                      </properties> -                    <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6"</command> +                    <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=ethernet</command>                    </leafNode>                  </children>                </tagNode> diff --git a/op-mode-definitions/show-interfaces-geneve.xml.in b/op-mode-definitions/show-interfaces-geneve.xml.in index be3084af3..3cf45878d 100644 --- a/op-mode-definitions/show-interfaces-geneve.xml.in +++ b/op-mode-definitions/show-interfaces-geneve.xml.in @@ -11,13 +11,13 @@                  <path>interfaces geneve</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=geneve</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified GENEVE interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=geneve</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-input.xml.in b/op-mode-definitions/show-interfaces-input.xml.in index 1f8505160..5d93dcee6 100644 --- a/op-mode-definitions/show-interfaces-input.xml.in +++ b/op-mode-definitions/show-interfaces-input.xml.in @@ -11,13 +11,13 @@                  <path>interfaces input</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=input</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified input interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=input</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-l2tpv3.xml.in b/op-mode-definitions/show-interfaces-l2tpv3.xml.in index ff08b8266..713e36dac 100644 --- a/op-mode-definitions/show-interfaces-l2tpv3.xml.in +++ b/op-mode-definitions/show-interfaces-l2tpv3.xml.in @@ -11,13 +11,13 @@                  <path>interfaces l2tpv3</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=l2tpv3</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified L2TPv3 interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=l2tpv3</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-loopback.xml.in b/op-mode-definitions/show-interfaces-loopback.xml.in index 9919bf32b..a24151cc3 100644 --- a/op-mode-definitions/show-interfaces-loopback.xml.in +++ b/op-mode-definitions/show-interfaces-loopback.xml.in @@ -11,13 +11,13 @@                  <path>interfaces loopback</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=loopback</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified Loopback interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=loopback</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-pppoe.xml.in b/op-mode-definitions/show-interfaces-pppoe.xml.in index 80bfd00ff..a34473148 100644 --- a/op-mode-definitions/show-interfaces-pppoe.xml.in +++ b/op-mode-definitions/show-interfaces-pppoe.xml.in @@ -11,7 +11,7 @@                  <path>interfaces pppoe</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=pppoe</command>              <children>                <leafNode name="log">                  <properties> diff --git a/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in b/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in index 0c00dbdd0..cb62639ee 100644 --- a/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in @@ -11,13 +11,13 @@                  <path>interfaces pseudo-ethernet</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=pseudo-ethernet</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified pseudo-ethernet/MACvlan interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=pseudo-ethernet</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-sstpc.xml.in b/op-mode-definitions/show-interfaces-sstpc.xml.in index c473f9822..a619a9fd2 100644 --- a/op-mode-definitions/show-interfaces-sstpc.xml.in +++ b/op-mode-definitions/show-interfaces-sstpc.xml.in @@ -11,7 +11,7 @@                  <path>interfaces sstpc</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=sstpc</command>              <children>                <leafNode name="log">                  <properties> diff --git a/op-mode-definitions/show-interfaces-tunnel.xml.in b/op-mode-definitions/show-interfaces-tunnel.xml.in index 4af90b813..10e10e655 100644 --- a/op-mode-definitions/show-interfaces-tunnel.xml.in +++ b/op-mode-definitions/show-interfaces-tunnel.xml.in @@ -11,13 +11,13 @@                  <path>interfaces tunnel</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=tunnel</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified tunnel interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=tunnel</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in b/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in index 2aa71c687..c743492fb 100644 --- a/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in @@ -11,13 +11,13 @@                  <path>interfaces virtual-ethernet</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=virtual-ethernet</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified virtual-ethernet interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=virtual-ethernet</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-vti.xml.in b/op-mode-definitions/show-interfaces-vti.xml.in index 195e1d5da..d532894b7 100644 --- a/op-mode-definitions/show-interfaces-vti.xml.in +++ b/op-mode-definitions/show-interfaces-vti.xml.in @@ -11,13 +11,13 @@                  <path>interfaces vti</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=vti</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified vti interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=vti</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-vxlan.xml.in b/op-mode-definitions/show-interfaces-vxlan.xml.in index a1d01a6af..fde832551 100644 --- a/op-mode-definitions/show-interfaces-vxlan.xml.in +++ b/op-mode-definitions/show-interfaces-vxlan.xml.in @@ -11,13 +11,13 @@                  <path>interfaces vxlan</path>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=vxlan</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified VXLAN interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=vxlan</command>                </leafNode>              </children>            </tagNode> diff --git a/op-mode-definitions/show-interfaces-wireguard.xml.in b/op-mode-definitions/show-interfaces-wireguard.xml.in index 55879cfff..eba8de568 100644 --- a/op-mode-definitions/show-interfaces-wireguard.xml.in +++ b/op-mode-definitions/show-interfaces-wireguard.xml.in @@ -11,7 +11,7 @@                  <script>${vyos_completion_dir}/list_interfaces.py --type wireguard</script>                </completionHelp>              </properties> -	        <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +	        <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wireguard</command>              <children>                <leafNode name="allowed-ips">                  <properties> diff --git a/op-mode-definitions/show-interfaces-wireless.xml.in b/op-mode-definitions/show-interfaces-wireless.xml.in index 7ae2c8ce4..b0a272225 100644 --- a/op-mode-definitions/show-interfaces-wireless.xml.in +++ b/op-mode-definitions/show-interfaces-wireless.xml.in @@ -31,13 +31,13 @@                  <script>${vyos_completion_dir}/list_interfaces.py --type wireless</script>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wireless</command>              <children>                <leafNode name="brief">                  <properties>                    <help>Show summary of the specified wireless interface information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=wireless</command>                </leafNode>                <node name="scan">                  <properties> @@ -63,13 +63,13 @@                  <properties>                    <help>Show specified virtual network interface (vif) information</help>                  </properties> -                <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6"</command> +                <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=wireless</command>                  <children>                    <leafNode name="brief">                      <properties>                        <help>Show summary of specified virtual network interface (vif) information</help>                      </properties> -                    <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6"</command> +                    <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=wireless</command>                    </leafNode>                  </children>                </tagNode> diff --git a/op-mode-definitions/show-interfaces-wwan.xml.in b/op-mode-definitions/show-interfaces-wwan.xml.in index 8ac5933a2..17d4111a9 100644 --- a/op-mode-definitions/show-interfaces-wwan.xml.in +++ b/op-mode-definitions/show-interfaces-wwan.xml.in @@ -12,7 +12,7 @@                  <script>cd /sys/class/net; ls -d wwan*</script>                </completionHelp>              </properties> -            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4"</command> +            <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wirelessmodem</command>              <children>                <leafNode name="capabilities">                  <properties> diff --git a/op-mode-definitions/show-ip-route.xml.in b/op-mode-definitions/show-ip-route.xml.in index 1e906672d..681aa089f 100644 --- a/op-mode-definitions/show-ip-route.xml.in +++ b/op-mode-definitions/show-ip-route.xml.in @@ -50,10 +50,23 @@                #include <include/show-route-ospf.xml.i>                #include <include/show-route-rip.xml.i>                #include <include/show-route-static.xml.i> -              #include <include/show-route-summary.xml.i>                #include <include/show-route-supernets-only.xml.i>                #include <include/show-route-table.xml.i>                #include <include/show-route-tag.xml.i> +              <node name="summary"> +                <properties> +                  <help>Summary of all routes</help> +                </properties> +                <command>${vyos_op_scripts_dir}/route.py show_summary --family inet</command> +                <children> +                  <tagNode name="table"> +                    <properties> +                      <help>Summary of routes in a particular table</help> +                    </properties> +                    <command>${vyos_op_scripts_dir}/route.py show_summary --family inet --table $6</command> +                  </tagNode> +                </children> +              </node>                <tagNode name="vrf">                  <properties>                    <help>Show IP routes in VRF</help> @@ -64,6 +77,12 @@                  </properties>                  <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>                  <children> +                  <node name="summary"> +                    <properties> +                      <help>Summary of all routes in the VRF</help> +                    </properties> +                    <command>${vyos_op_scripts_dir}/route.py show_summary --family inet --vrf $5</command> +                  </node>                    #include <include/show-route-bgp.xml.i>                    #include <include/show-route-connected.xml.i>                    #include <include/show-route-isis.xml.i> @@ -71,7 +90,6 @@                    #include <include/show-route-ospf.xml.i>                    #include <include/show-route-rip.xml.i>                    #include <include/show-route-static.xml.i> -                  #include <include/show-route-summary.xml.i>                    #include <include/show-route-supernets-only.xml.i>                    #include <include/show-route-tag.xml.i>                  </children> diff --git a/op-mode-definitions/show-ipv6-route.xml.in b/op-mode-definitions/show-ipv6-route.xml.in index 2c5024991..7df1a873a 100644 --- a/op-mode-definitions/show-ipv6-route.xml.in +++ b/op-mode-definitions/show-ipv6-route.xml.in @@ -50,9 +50,22 @@                #include <include/show-route-ospfv3.xml.i>                #include <include/show-route-ripng.xml.i>                #include <include/show-route-static.xml.i> -              #include <include/show-route-summary.xml.i>                #include <include/show-route-table.xml.i>                #include <include/show-route-tag.xml.i> +              <node name="summary"> +                <properties> +                  <help>Summary of all routes</help> +                </properties> +                <command>${vyos_op_scripts_dir}/route.py show_summary --family inet6</command> +                <children> +                  <tagNode name="table"> +                    <properties> +                      <help>Summary of routes in a particular table</help> +                    </properties> +                    <command>${vyos_op_scripts_dir}/route.py show_summary --family inet6 --table $6</command> +                  </tagNode> +                </children> +              </node>                <tagNode name="vrf">                  <properties>                    <help>Show IPv6 routes in VRF</help> @@ -63,6 +76,12 @@                  </properties>                  <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>                  <children> +                  <node name="summary"> +                    <properties> +                      <help>Summary of all routes in the VRF</help> +                    </properties> +                    <command>${vyos_op_scripts_dir}/route.py show_summary --family inet6 --vrf $5</command> +                  </node>                    #include <include/show-route-bgp.xml.i>                    #include <include/show-route-connected.xml.i>                    #include <include/show-route-isis.xml.i> @@ -70,7 +89,6 @@                    #include <include/show-route-ospfv3.xml.i>                    #include <include/show-route-ripng.xml.i>                    #include <include/show-route-static.xml.i> -                  #include <include/show-route-summary.xml.i>                    #include <include/show-route-supernets-only.xml.i>                    #include <include/show-route-table.xml.i>                    #include <include/show-route-tag.xml.i> diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index 70afaaf6e..8114f7377 100644 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -204,7 +204,7 @@            </leafNode>            <leafNode name="lldp">              <properties> -              <help>Show log for LLDP</help> +              <help>Show log for Link Layer Discovery Protocol (LLDP)</help>              </properties>              <command>journalctl --no-hostname --boot --unit lldpd.service</command>            </leafNode> @@ -216,10 +216,16 @@            </leafNode>            <leafNode name="nhrp">              <properties> -              <help>Show log for NHRP</help> +              <help>Show log for Next Hop Resolution Protocol (NHRP)</help>              </properties>              <command>journalctl --no-hostname --boot --unit opennhrp.service</command>            </leafNode> +          <leafNode name="ntp"> +            <properties> +              <help>Show log for Network Time Protocol (NTP)</help> +            </properties> +            <command>journalctl --no-hostname --boot --unit chrony.service</command> +          </leafNode>            <node name="macsec">              <properties>                <help>Show log for MACsec</help> @@ -403,13 +409,13 @@                  <properties>                    <help>Show log for ALL</help>                  </properties> -                <command>journalctl --no-hostname --boot --unit strongswan.service --unit accel-ppp@*.service</command> +                <command>journalctl --no-hostname --boot --unit strongswan-starter.service --unit accel-ppp@*.service --unit ocserv.service</command>                </leafNode>                <leafNode name="ipsec">                  <properties>                    <help>Show log for IPsec</help>                  </properties> -                <command>journalctl --no-hostname --boot --unit strongswan.service</command> +                <command>journalctl --no-hostname --boot --unit strongswan-starter.service</command>                </leafNode>                <leafNode name="l2tp">                  <properties> @@ -417,6 +423,12 @@                  </properties>                  <command>journalctl --no-hostname --boot --unit accel-ppp@l2tp.service</command>                </leafNode> +              <leafNode name="openconnect"> +                <properties> +                  <help>Show log for OpenConnect</help> +                </properties> +                <command>journalctl --no-hostname --boot --unit ocserv.service</command> +              </leafNode>                <leafNode name="pptp">                  <properties>                    <help>Show log for PPTP</help> diff --git a/op-mode-definitions/show-ntp.xml.in b/op-mode-definitions/show-ntp.xml.in index 01f4477d8..0907722af 100644 --- a/op-mode-definitions/show-ntp.xml.in +++ b/op-mode-definitions/show-ntp.xml.in @@ -6,22 +6,13 @@          <properties>            <help>Show peer status of NTP daemon</help>          </properties> -        <command>${vyos_op_scripts_dir}/show_ntp.sh --basic</command> +        <command>${vyos_op_scripts_dir}/show_ntp.sh --sourcestats</command>          <children> -          <tagNode name="server"> +          <node name="system">              <properties> -              <help>Show date and time of specified NTP server</help> -              <completionHelp> -                <script>${vyos_completion_dir}/list_ntp_servers.sh</script> -              </completionHelp> +              <help>Show parameters about the system clock performance</help>              </properties> -            <command>${vyos_op_scripts_dir}/show_ntp.sh --server "$4"</command> -          </tagNode> -          <node name="info"> -            <properties> -              <help>Show NTP operational summary</help> -            </properties> -            <command>${vyos_op_scripts_dir}/show_ntp.sh --info</command> +            <command>${vyos_op_scripts_dir}/show_ntp.sh --tracking</command>            </node>          </children>        </node> diff --git a/python/vyos/configdiff.py b/python/vyos/configdiff.py index 9185575df..ac86af09c 100644 --- a/python/vyos/configdiff.py +++ b/python/vyos/configdiff.py @@ -78,23 +78,34 @@ def get_config_diff(config, key_mangling=None):              isinstance(key_mangling[1], str)):          raise ValueError("key_mangling must be a tuple of two strings") -    diff_t = DiffTree(config._running_config, config._session_config) +    if hasattr(config, 'cached_diff_tree'): +        diff_t = getattr(config, 'cached_diff_tree') +    else: +        diff_t = DiffTree(config._running_config, config._session_config) +        setattr(config, 'cached_diff_tree', diff_t) -    return ConfigDiff(config, key_mangling, diff_tree=diff_t) +    if hasattr(config, 'cached_diff_dict'): +        diff_d = getattr(config, 'cached_diff_dict') +    else: +        diff_d = diff_t.dict +        setattr(config, 'cached_diff_dict', diff_d) + +    return ConfigDiff(config, key_mangling, diff_tree=diff_t, +                                            diff_dict=diff_d)  class ConfigDiff(object):      """      The class of config changes as represented by comparison between the      session config dict and the effective config dict.      """ -    def __init__(self, config, key_mangling=None, diff_tree=None): +    def __init__(self, config, key_mangling=None, diff_tree=None, diff_dict=None):          self._level = config.get_level()          self._session_config_dict = config.get_cached_root_dict(effective=False)          self._effective_config_dict = config.get_cached_root_dict(effective=True)          self._key_mangling = key_mangling          self._diff_tree = diff_tree -        self._diff_dict = diff_tree.dict if diff_tree else {} +        self._diff_dict = diff_dict      # mirrored from Config; allow path arguments relative to level      def _make_path(self, path): @@ -209,9 +220,9 @@ class ConfigDiff(object):              if self._diff_tree is None:                  raise NotImplementedError("diff_tree class not available")              else: -                add = get_sub_dict(self._diff_tree.dict, ['add'], get_first_key=True) -                sub = get_sub_dict(self._diff_tree.dict, ['sub'], get_first_key=True) -                inter = get_sub_dict(self._diff_tree.dict, ['inter'], get_first_key=True) +                add = get_sub_dict(self._diff_dict, ['add'], get_first_key=True) +                sub = get_sub_dict(self._diff_dict, ['sub'], get_first_key=True) +                inter = get_sub_dict(self._diff_dict, ['inter'], get_first_key=True)                  ret = {}                  ret[enum_to_key(Diff.MERGE)] = session_dict                  ret[enum_to_key(Diff.DELETE)] = get_sub_dict(sub, self._make_path(path), @@ -284,9 +295,9 @@ class ConfigDiff(object):              if self._diff_tree is None:                  raise NotImplementedError("diff_tree class not available")              else: -                add = get_sub_dict(self._diff_tree.dict, ['add'], get_first_key=True) -                sub = get_sub_dict(self._diff_tree.dict, ['sub'], get_first_key=True) -                inter = get_sub_dict(self._diff_tree.dict, ['inter'], get_first_key=True) +                add = get_sub_dict(self._diff_dict, ['add'], get_first_key=True) +                sub = get_sub_dict(self._diff_dict, ['sub'], get_first_key=True) +                inter = get_sub_dict(self._diff_dict, ['inter'], get_first_key=True)                  ret = {}                  ret[enum_to_key(Diff.MERGE)] = session_dict                  ret[enum_to_key(Diff.DELETE)] = get_sub_dict(sub, self._make_path(path)) diff --git a/python/vyos/configsession.py b/python/vyos/configsession.py index 3a60f6d92..df44fd8d6 100644 --- a/python/vyos/configsession.py +++ b/python/vyos/configsession.py @@ -34,6 +34,8 @@ REMOVE_IMAGE = ['/opt/vyatta/bin/vyatta-boot-image.pl', '--del']  GENERATE = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'generate']  SHOW = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'show']  RESET = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'reset'] +OP_CMD_ADD = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'add'] +OP_CMD_DELETE = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'delete']  # Default "commit via" string  APP = "vyos-http-api" @@ -204,3 +206,15 @@ class ConfigSession(object):      def reset(self, path):          out = self.__run_command(RESET + path)          return out + +    def add_container_image(self, name): +        out = self.__run_command(OP_CMD_ADD + ['container', 'image'] + [name]) +        return out + +    def delete_container_image(self, name): +        out = self.__run_command(OP_CMD_DELETE + ['container', 'image'] + [name]) +        return out + +    def show_container_image(self): +        out = self.__run_command(SHOW + ['container', 'image']) +        return out diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 519cfc58c..5080144ff 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -239,7 +239,7 @@ class EthernetIf(Interface):          if not isinstance(state, bool):              raise ValueError('Value out of range') -        rps_cpus = '0' +        rps_cpus = 0          queues = len(glob(f'/sys/class/net/{self.ifname}/queues/rx-*'))          if state:              # Enable RPS on all available CPUs except CPU0 which we will not @@ -248,10 +248,16 @@ class EthernetIf(Interface):              # representation of the CPUs which should participate on RPS, we              # can enable more CPUs that are physically present on the system,              # Linux will clip that internally! -            rps_cpus = 'ffffffff,ffffffff,ffffffff,fffffffe' +            rps_cpus = (1 << os.cpu_count()) -1 + +            # XXX: we should probably reserve one core when the system is under +            # high preasure so we can still have a core left for housekeeping. +            # This is done by masking out the lowst bit so CPU0 is spared from +            # receive packet steering. +            rps_cpus &= ~1          for i in range(0, queues): -            self._write_sysfs(f'/sys/class/net/{self.ifname}/queues/rx-{i}/rps_cpus', rps_cpus) +            self._write_sysfs(f'/sys/class/net/{self.ifname}/queues/rx-{i}/rps_cpus', f'{rps_cpus:x}')          # send bitmask representation as hex string without leading '0x'          return True diff --git a/python/vyos/ifconfig/input.py b/python/vyos/ifconfig/input.py index db7d2b6b4..3e5f5790d 100644 --- a/python/vyos/ifconfig/input.py +++ b/python/vyos/ifconfig/input.py @@ -1,4 +1,4 @@ -# Copyright 2020 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>  #  # This library is free software; you can redistribute it and/or  # modify it under the terms of the GNU Lesser General Public @@ -17,6 +17,16 @@ from vyos.ifconfig.interface import Interface  @Interface.register  class InputIf(Interface): +    """ +    The Intermediate Functional Block (ifb) pseudo network interface acts as a +    QoS concentrator for multiple different sources of traffic. Packets from +    or to other interfaces have to be redirected to it using the mirred action +    in order to be handled, regularly routed traffic will be dropped. This way, +    a single stack of qdiscs, classes and filters can be shared between +    multiple interfaces. +    """ + +    iftype = 'ifb'      definition = {          **Interface.definition,          **{ diff --git a/python/vyos/opmode.py b/python/vyos/opmode.py index 5ff768859..30e893d74 100644 --- a/python/vyos/opmode.py +++ b/python/vyos/opmode.py @@ -45,6 +45,10 @@ class PermissionDenied(Error):      """      pass +class UnsupportedOperation(Error): +    """ Requested operation is technically valid but is not implemented yet. """ +    pass +  class IncorrectValue(Error):      """ Requested operation is valid, but an argument provided has an          incorrect value, preventing successful completion. @@ -66,13 +70,13 @@ class InternalError(Error):  def _is_op_mode_function_name(name): -    if re.match(r"^(show|clear|reset|restart)", name): +    if re.match(r"^(show|clear|reset|restart|add|delete|generate)", name):          return True      else:          return False -def _is_show(name): -    if re.match(r"^show", name): +def _capture_output(name): +    if re.match(r"^(show|generate)", name):          return True      else:          return False @@ -199,14 +203,14 @@ def run(module):      # it would cause an extra argument error when we pass the dict to a function      del args["subcommand"] -    # Show commands must always get the "raw" argument, -    # but other commands (clear/reset/restart) should not, +    # Show and generate commands must always get the "raw" argument, +    # but other commands (clear/reset/restart/add/delete) should not,      # because they produce no output and it makes no sense for them. -    if ("raw" not in args) and _is_show(function_name): +    if ("raw" not in args) and _capture_output(function_name):          args["raw"] = False -    if re.match(r"^show", function_name): -        # Show commands are slightly special: +    if _capture_output(function_name): +        # Show and generate commands are slightly special:          # they may return human-formatted output          # or a raw dict that we need to serialize in JSON for printing          res = func(**args) diff --git a/python/vyos/qos/base.py b/python/vyos/qos/base.py index d039bbb0f..28635b5e7 100644 --- a/python/vyos/qos/base.py +++ b/python/vyos/qos/base.py @@ -13,17 +13,21 @@  # You should have received a copy of the GNU Lesser General Public  # License along with this library.  If not, see <http://www.gnu.org/licenses/>. +import os +  from vyos.base import Warning  from vyos.util import cmd  from vyos.util import dict_search  from vyos.util import read_file  class QoSBase: -    _debug = True +    _debug = False      _direction = ['egress']      _parent = 0xffff      def __init__(self, interface): +        if os.path.exists('/tmp/vyos.qos.debug'): +            self._debug = True          self._interface = interface      def _cmd(self, command): @@ -41,7 +45,7 @@ class QoSBase:              return tmp[-1]          return None -    def _tmp_qdisc(self, config : dict, cls_id : int): +    def _build_base_qdisc(self, config : dict, cls_id : int):          """          Add/replace qdisc for every class (also default is a class). This is          a genetic method which need an implementation "per" queue-type. @@ -116,11 +120,14 @@ class QoSBase:              'tbit'  : 1000000000000,          } -        if rate == 'auto': +        if rate == 'auto' or rate.endswith('%'):              speed = read_file(f'/sys/class/net/{self._interface}/speed')              if not speed.isnumeric():                  Warning('Interface speed cannot be determined (assuming 10 Mbit/s)')                  speed = 10 +            if rate.endswith('%'): +                percent = rate.rstrip('%') +                speed = int(speed) * int(percent) // 100              return int(speed) *1000000 # convert to MBit/s          rate_numeric = int(''.join([n for n in rate if n.isdigit()])) @@ -140,8 +147,7 @@ class QoSBase:          if 'class' in config:              for cls, cls_config in config['class'].items(): - -                self._tmp_qdisc(cls_config, int(cls)) +                self._build_base_qdisc(cls_config, int(cls))                  if 'match' in cls_config:                      for match, match_config in cls_config['match'].items(): @@ -240,11 +246,10 @@ class QoSBase:                                  self._cmd(filter_cmd)          if 'default' in config: -            class_id_max = self._get_class_max_id(config) -            default_cls_id = int(class_id_max) +1 - -            if 'default' in config: -                self._tmp_qdisc(config['default'], default_cls_id) +            if 'class' in config: +                class_id_max = self._get_class_max_id(config) +                default_cls_id = int(class_id_max) +1 +                self._build_base_qdisc(config['default'], default_cls_id)              filter_cmd = f'tc filter replace dev {self._interface} parent {self._parent:x}: '              filter_cmd += 'prio 255 protocol all basic' @@ -252,25 +257,26 @@ class QoSBase:              # The police block allows limiting of the byte or packet rate of              # traffic matched by the filter it is attached to.              # https://man7.org/linux/man-pages/man8/tc-police.8.html -            if any(tmp in ['exceed', 'bandwidth', 'burst'] for tmp in cls_config): +            if any(tmp in ['exceed', 'bandwidth', 'burst'] for tmp in config['default']):                  filter_cmd += f' action police' -            if 'exceed' in cls_config: -                action = cls_config['exceed'] +            if 'exceed' in config['default']: +                action = config['default']['exceed']                  filter_cmd += f' conform-exceed {action}' -                if 'not_exceed' in cls_config: -                    action = cls_config['not_exceed'] +                if 'not_exceed' in config['default']: +                    action = config['default']['not_exceed']                      filter_cmd += f'/{action}' -            if 'bandwidth' in cls_config: -                rate = self._rate_convert(cls_config['bandwidth']) +            if 'bandwidth' in config['default']: +                rate = self._rate_convert(config['default']['bandwidth'])                  filter_cmd += f' rate {rate}' -            if 'burst' in cls_config: -                burst = cls_config['burst'] +            if 'burst' in config['default']: +                burst = config['default']['burst']                  filter_cmd += f' burst {burst}' +            if 'class' in config: +                filter_cmd += f' flowid {self._parent:x}:{default_cls_id:x}' -            filter_cmd += f' flowid {self._parent:x}:{default_cls_id:x}'              self._cmd(filter_cmd) diff --git a/python/vyos/qos/priority.py b/python/vyos/qos/priority.py index 72092b7ef..6d4a60a43 100644 --- a/python/vyos/qos/priority.py +++ b/python/vyos/qos/priority.py @@ -33,6 +33,7 @@ class Priority(QoSBase):              self._cmd(tmp)              for cls in config['class']: +                cls = int(cls)                  tmp = f'tc qdisc add dev {self._interface} parent {self._parent:x}:{cls:x} pfifo'                  self._cmd(tmp) diff --git a/python/vyos/qos/roundrobin.py b/python/vyos/qos/roundrobin.py index 4a0cb18aa..80814ddfb 100644 --- a/python/vyos/qos/roundrobin.py +++ b/python/vyos/qos/roundrobin.py @@ -26,10 +26,10 @@ class RoundRobin(QoSBase):          if 'class' in config:              for cls in config['class']:                  cls = int(cls) -                tmp = f'tc class add dev {self._interface} parent 1:1 classid 1:{cls:x} drr' +                tmp = f'tc class replace dev {self._interface} parent 1:1 classid 1:{cls:x} drr'                  self._cmd(tmp) -                tmp = f'tc qdisc add dev {self._interface} parent 1:{cls:x} pfifo' +                tmp = f'tc qdisc replace dev {self._interface} parent 1:{cls:x} pfifo'                  self._cmd(tmp)          if 'default' in config: @@ -37,7 +37,7 @@ class RoundRobin(QoSBase):              default_cls_id = int(class_id_max) +1              # class ID via CLI is in range 1-4095, thus 1000 hex = 4096 -            tmp = f'tc class add dev {self._interface} parent 1:1 classid 1:{default_cls_id:x} drr' +            tmp = f'tc class replace dev {self._interface} parent 1:1 classid 1:{default_cls_id:x} drr'              self._cmd(tmp)          # call base class diff --git a/python/vyos/qos/trafficshaper.py b/python/vyos/qos/trafficshaper.py index 6d465b38e..f42f4d022 100644 --- a/python/vyos/qos/trafficshaper.py +++ b/python/vyos/qos/trafficshaper.py @@ -39,7 +39,6 @@ class TrafficShaper(QoSBase):          # need a bigger r2q if going fast than 16 mbits/sec          if (speed_bps // r2q) >= MAXQUANTUM: # integer division              r2q = ceil(speed_bps // MAXQUANTUM) -            print(r2q)          else:              # if there is a slow class then may need smaller value              if 'class' in config: @@ -59,10 +58,10 @@ class TrafficShaper(QoSBase):          default_minor_id = int(class_id_max) +1 -        tmp = f'tc qdisc add dev {self._interface} root handle {self._parent:x}: htb r2q {r2q} default {default_minor_id:x}' # default is in hex +        tmp = f'tc qdisc replace dev {self._interface} root handle {self._parent:x}: htb r2q {r2q} default {default_minor_id:x}' # default is in hex          self._cmd(tmp) -        tmp = f'tc class add dev {self._interface} parent {self._parent:x}: classid {self._parent:x}:1 htb rate {speed}' +        tmp = f'tc class replace dev {self._interface} parent {self._parent:x}: classid {self._parent:x}:1 htb rate {speed}'          self._cmd(tmp)          if 'class' in config: @@ -75,23 +74,26 @@ class TrafficShaper(QoSBase):                  burst = cls_config['burst']                  quantum = cls_config['codel_quantum'] -                tmp = f'tc class add dev {self._interface} parent {self._parent:x}:1 classid {self._parent:x}:{cls:x} htb rate {rate} burst {burst} quantum {quantum}' +                tmp = f'tc class replace dev {self._interface} parent {self._parent:x}:1 classid {self._parent:x}:{cls:x} htb rate {rate} burst {burst} quantum {quantum}'                  if 'priority' in cls_config:                      priority = cls_config['priority']                      tmp += f' prio {priority}'                  self._cmd(tmp) -                tmp = f'tc qdisc add dev {self._interface} parent {self._parent:x}:{cls:x} sfq' +                tmp = f'tc qdisc replace dev {self._interface} parent {self._parent:x}:{cls:x} sfq'                  self._cmd(tmp)          if 'default' in config: -                tmp = f'tc class add dev {self._interface} parent {self._parent:x}:1 classid {self._parent:x}:{default_minor_id:x} htb rate {rate} burst {burst} quantum {quantum}' +                rate = self._rate_convert(config['default']['bandwidth']) +                burst = config['default']['burst'] +                quantum = config['default']['codel_quantum'] +                tmp = f'tc class replace dev {self._interface} parent {self._parent:x}:1 classid {self._parent:x}:{default_minor_id:x} htb rate {rate} burst {burst} quantum {quantum}'                  if 'priority' in config['default']:                      priority = config['default']['priority']                      tmp += f' prio {priority}'                  self._cmd(tmp) -                tmp = f'tc qdisc add dev {self._interface} parent {self._parent:x}:{default_minor_id:x} sfq' +                tmp = f'tc qdisc replace dev {self._interface} parent {self._parent:x}:{default_minor_id:x} sfq'                  self._cmd(tmp)          # call base class diff --git a/python/vyos/util.py b/python/vyos/util.py index 6a828c0ac..110da3be5 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -348,9 +348,11 @@ def colon_separated_to_dict(data_string, uniquekeys=False):          l = l.strip()          if l:              match = re.match(key_value_re, l) -            if match: +            if match and (len(match.groups()) == 2):                  key = match.groups()[0].strip()                  value = match.groups()[1].strip() +            else: +                raise ValueError(f"""Line "{l}" could not be parsed a colon-separated pair """, l)              if key in data.keys():                  if uniquekeys:                      raise ValueError("Data string has duplicate keys: {0}".format(key)) diff --git a/smoketest/configs/basic-qos b/smoketest/configs/basic-qos deleted file mode 100644 index d9baa4a1f..000000000 --- a/smoketest/configs/basic-qos +++ /dev/null @@ -1,194 +0,0 @@ -interfaces { -    ethernet eth0 { -        address 100.64.0.1/20 -        duplex auto -        smp-affinity auto -        speed auto -    } -    ethernet eth1 { -        duplex auto -        speed auto -        vif 10 { -            traffic-policy { -                in M2 -            } -        } -        vif 20 { -            traffic-policy { -                out FS -            } -        } -        vif 30 { -            traffic-policy { -                out MY-HTB -            } -        } -        vif 40 { -            traffic-policy { -                out SHAPER-FOO -            } -        } -    } -} -system { -    config-management { -        commit-revisions 100 -    } -    console { -        device ttyS0 { -            speed 115200 -        } -    } -    host-name vyos -    login { -        user vyos { -            authentication { -                encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0 -                plaintext-password "" -            } -        } -    } -    name-server 192.168.0.1 -    syslog { -        global { -            archive { -                file 5 -                size 512 -            } -            facility all { -                level info -            } -        } -    } -    time-zone Europe/Berlin -} -traffic-policy { -    limiter M2 { -        class 10 { -            bandwidth 120mbit -            burst 15k -            match ADDRESS10 { -                ip { -                    dscp CS4 -                } -            } -            priority 20 -        } -        default { -            bandwidth 100mbit -            burst 15k -        } -    } -    shaper FS { -        bandwidth auto -        class 10 { -            bandwidth 100% -            burst 15k -            match ADDRESS10 { -                ip { -                    source { -                        address 172.17.1.2/32 -                    } -                } -            } -            queue-type fair-queue -            set-dscp CS4 -        } -        class 20 { -            bandwidth 100% -            burst 15k -            match ADDRESS20 { -                ip { -                    source { -                        address 172.17.1.3/32 -                    } -                } -            } -            queue-type fair-queue -            set-dscp CS5 -        } -        class 30 { -            bandwidth 100% -            burst 15k -            match ADDRESS30 { -                ip { -                    source { -                        address 172.17.1.4/32 -                    } -                } -            } -            queue-type fair-queue -            set-dscp CS6 -        } -        default { -            bandwidth 10% -            burst 15k -            ceiling 100% -            priority 7 -            queue-type fair-queue -        } -    } -    shaper MY-HTB { -        bandwidth 10mbit -        class 30 { -            bandwidth 10% -            burst 15k -            ceiling 50% -            match ADDRESS30 { -                ip { -                    source { -                        address 10.1.1.0/24 -                    } -                } -            } -            priority 5 -            queue-type fair-queue -        } -        class 40 { -            bandwidth 90% -            burst 15k -            ceiling 100% -            match ADDRESS40 { -                ip { -                    dscp CS4 -                    source { -                        address 10.2.1.0/24 -                    } -                } -            } -            priority 5 -            queue-type fair-queue -        } -        class 50 { -            bandwidth 100% -            burst 15k -            match ADDRESS50 { -                ip { -                    dscp CS5 -                } -            } -            queue-type fair-queue -            set-dscp CS7 -        } -        default { -            bandwidth 10% -            burst 15k -            ceiling 100% -            priority 7 -            queue-type fair-queue -            set-dscp CS1 -        } -    } -    shaper SHAPER-FOO { -        bandwidth 1000mbit -        default { -            bandwidth 100mbit -            burst 15k -            queue-type fair-queue -            set-dscp CS4 -        } -    } -} -// Warning: Do not remove the following line. -// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@22:ipoe-server@1:ipsec@5:isis@1:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@8:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@21:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1" -// Release version: 1.3.2 diff --git a/smoketest/configs/qos-basic b/smoketest/configs/qos-basic index 96fa7bef4..c279cbf67 100644 --- a/smoketest/configs/qos-basic +++ b/smoketest/configs/qos-basic @@ -25,16 +25,6 @@ interfaces {      loopback lo {      }  } -protocols { -    static { -        route 0.0.0.0/0 { -            next-hop 10.9.9.2 { -            } -            next-hop 10.1.1.1 { -            } -        } -    } -}  system {      config-management {          commit-revisions 10 @@ -89,13 +79,14 @@ traffic-policy {          class 10 {              bandwidth 100%              burst 15k -            match ADDRESS10 { +            match ssh4 {                  ip { -                    dscp CS4 +                    destination { +                        port 22 +                    }                  }              }              queue-type fair-queue -            set-dscp CS5          }          default {              bandwidth 10mbit @@ -125,7 +116,6 @@ traffic-policy {              ceiling 100%              match ADDRESS40 {                  ip { -                    dscp CS4                      source {                          address 10.2.1.0/24                      } @@ -138,12 +128,13 @@ traffic-policy {              bandwidth 100%              burst 15k              match ADDRESS50 { -                ip { -                    dscp CS5 +                ipv6 { +                    source { +                        address "2001:db8::1/64" +                    }                  }              }              queue-type fair-queue -            set-dscp CS7          }          default {              bandwidth 10% @@ -151,7 +142,6 @@ traffic-policy {              ceiling 100%              priority 7              queue-type fair-queue -            set-dscp CS1          }      }      shaper FS { @@ -167,7 +157,6 @@ traffic-policy {                  }              }              queue-type fair-queue -            set-dscp CS4          }          class 20 {              bandwidth 100% @@ -180,7 +169,6 @@ traffic-policy {                  }              }              queue-type fair-queue -            set-dscp CS5          }          class 30 {              bandwidth 100% @@ -193,7 +181,6 @@ traffic-policy {                  }              }              queue-type fair-queue -            set-dscp CS6          }          default {              bandwidth 10% diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index ed611062a..e53413f0d 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -160,7 +160,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase):                  self.assertFalse(is_intf_addr_assigned(intf, addr['addr']))      def test_offloading_rps(self): -        # enable RPS on all available CPUs, RPS works woth a CPU bitmask, +        # enable RPS on all available CPUs, RPS works with a CPU bitmask,          # where each bit represents a CPU (core/thread). The formula below          # expands to rps_cpus = 255 for a 8 core system          rps_cpus = (1 << os.cpu_count()) -1 diff --git a/smoketest/scripts/cli/test_interfaces_input.py b/smoketest/scripts/cli/test_interfaces_input.py new file mode 100755 index 000000000..c6d7febec --- /dev/null +++ b/smoketest/scripts/cli/test_interfaces_input.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 unittest + +from vyos.util import read_file +from vyos.ifconfig import Interface +from base_vyostest_shim import VyOSUnitTestSHIM + +base_path = ['interfaces', 'input'] + +# add a classmethod to setup a temporaray PPPoE server for "proper" validation +class InputInterfaceTest(VyOSUnitTestSHIM.TestCase): +    @classmethod +    def setUpClass(cls): +        super(InputInterfaceTest, cls).setUpClass() + +        cls._interfaces = ['ifb10', 'ifb20', 'ifb30'] + +    def tearDown(self): +        self.cli_delete(base_path) +        self.cli_commit() + +    def test_01_description(self): +        # Check if PPPoE dialer can be configured and runs +        for interface in self._interfaces: +            self.cli_set(base_path + [interface, 'description', f'foo-{interface}']) + +        # commit changes +        self.cli_commit() + +        # Validate remove interface description "empty" +        for interface in self._interfaces: +            tmp = read_file(f'/sys/class/net/{interface}/ifalias') +            self.assertEqual(tmp, f'foo-{interface}') +            self.assertEqual(Interface(interface).get_alias(), f'foo-{interface}') + +if __name__ == '__main__': +    unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_load_balancning_wan.py b/smoketest/scripts/cli/test_load_balancing_wan.py index 23020b9b1..33c69c595 100755 --- a/smoketest/scripts/cli/test_load_balancning_wan.py +++ b/smoketest/scripts/cli/test_load_balancing_wan.py @@ -46,7 +46,6 @@ def cmd_in_netns(netns, cmd):  def delete_netns(name):      return call(f'sudo ip netns del {name}') -  class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase):      @classmethod      def setUpClass(cls): @@ -61,7 +60,6 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase):          self.cli_commit()      def test_table_routes(self): -          ns1 = 'ns201'          ns2 = 'ns202'          ns3 = 'ns203' @@ -79,6 +77,7 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase):          create_veth_pair(iface1, container_iface1)          create_veth_pair(iface2, container_iface2)          create_veth_pair(iface3, container_iface3) +          move_interface_to_netns(container_iface1, ns1)          move_interface_to_netns(container_iface2, ns2)          move_interface_to_netns(container_iface3, ns3) @@ -125,7 +124,7 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase):          self.assertEqual(tmp, original)          # Delete veth interfaces and netns -        for iface in [iface1, iface2]: +        for iface in [iface1, iface2, iface3, container_iface1, container_iface2, container_iface3]:              call(f'sudo ip link del dev {iface}')          delete_netns(ns1) @@ -196,9 +195,10 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase):          call(f'sudo ip address add 203.0.113.10/24 dev {iface1}')          call(f'sudo ip address add 192.0.2.10/24 dev {iface2}')          call(f'sudo ip address add 198.51.100.10/24 dev {iface3}') -        call(f'sudo ip link set dev {iface1} up') -        call(f'sudo ip link set dev {iface2} up') -        call(f'sudo ip link set dev {iface3} up') + +        for iface in [iface1, iface2, iface3]: +            call(f'sudo ip link set dev {iface} up') +          cmd_in_netns(ns1, f'ip link set {container_iface1} name eth0')          cmd_in_netns(ns2, f'ip link set {container_iface2} name eth0')          cmd_in_netns(ns3, f'ip link set {container_iface3} name eth0') @@ -247,12 +247,11 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase):          self.assertEqual(tmp, nat_vyos_pre_snat_hook)          # Delete veth interfaces and netns -        for iface in [iface1, iface2]: +        for iface in [iface1, iface2, iface3, container_iface1, container_iface2, container_iface3]:              call(f'sudo ip link del dev {iface}')          delete_netns(ns1)          delete_netns(ns2) -  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index debc8270c..e33be6644 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -34,6 +34,10 @@ prefix_list_in6 = 'pfx-foo-in6'  prefix_list_out6 = 'pfx-foo-out6'  bfd_profile = 'foo-bar-baz' +import_afi = 'ipv4-unicast' +import_vrf = 'red' +import_rd = ASN + ':100' +import_vrf_base = ['vrf', 'name']  neighbor_config = {      '192.0.2.1' : {          'bfd'              : '', @@ -189,6 +193,15 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):          # Check for running process          self.assertTrue(process_named_running(PROCESS_NAME)) + +    def create_bgp_instances_for_import_test(self): +        table = '1000' +        self.cli_set(base_path + ['system-as', ASN]) +        # testing only one AFI is sufficient as it's generic code + +        self.cli_set(import_vrf_base + [import_vrf, 'table', table]) +        self.cli_set(import_vrf_base + [import_vrf, 'protocols', 'bgp', 'system-as', ASN]) +      def verify_frr_config(self, peer, peer_config, frrconfig):          # recurring patterns to verify for both a simple neighbor and a peer-group          if 'bfd' in peer_config: @@ -959,6 +972,101 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):          self.assertIn(f' neighbor {neighbor} remote-as {remote_asn}', frrconfig)          self.assertIn(f' neighbor {neighbor} local-as {local_asn}', frrconfig) +    def test_bgp_16_import_rd_rt_compatibility(self): +        # Verify if import vrf and rd vpn export +        # exist in the same address family +        self.create_bgp_instances_for_import_test() +        self.cli_set( +            base_path + ['address-family', import_afi, 'import', 'vrf', +                         import_vrf]) +        self.cli_set( +            base_path + ['address-family', import_afi, 'rd', 'vpn', 'export', +                         import_rd]) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() + +    def test_bgp_17_import_rd_rt_compatibility(self): +        # Verify if vrf that is in import vrf list contains rd vpn export +        self.create_bgp_instances_for_import_test() +        self.cli_set( +            base_path + ['address-family', import_afi, 'import', 'vrf', +                         import_vrf]) +        self.cli_commit() +        frrconfig = self.getFRRconfig(f'router bgp {ASN}') +        frrconfig_vrf = self.getFRRconfig(f'router bgp {ASN} vrf {import_vrf}') + +        self.assertIn(f'router bgp {ASN}', frrconfig) +        self.assertIn(f'address-family ipv4 unicast', frrconfig) +        self.assertIn(f'  import vrf {import_vrf}', frrconfig) +        self.assertIn(f'router bgp {ASN} vrf {import_vrf}', frrconfig_vrf) + +        self.cli_set( +            import_vrf_base + [import_vrf] + base_path + ['address-family', +                                                          import_afi, 'rd', +                                                          'vpn', 'export', +                                                          import_rd]) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() + +    def test_bgp_18_deleting_import_vrf(self): +        # Verify deleting vrf that is in import vrf list +        self.create_bgp_instances_for_import_test() +        self.cli_set( +            base_path + ['address-family', import_afi, 'import', 'vrf', +                         import_vrf]) +        self.cli_commit() +        frrconfig = self.getFRRconfig(f'router bgp {ASN}') +        frrconfig_vrf = self.getFRRconfig(f'router bgp {ASN} vrf {import_vrf}') +        self.assertIn(f'router bgp {ASN}', frrconfig) +        self.assertIn(f'address-family ipv4 unicast', frrconfig) +        self.assertIn(f'  import vrf {import_vrf}', frrconfig) +        self.assertIn(f'router bgp {ASN} vrf {import_vrf}', frrconfig_vrf) +        self.cli_delete(import_vrf_base + [import_vrf]) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() + +    def test_bgp_19_deleting_default_vrf(self): +        # Verify deleting existent vrf default if other vrfs were created +        self.create_bgp_instances_for_import_test() +        self.cli_commit() +        frrconfig = self.getFRRconfig(f'router bgp {ASN}') +        frrconfig_vrf = self.getFRRconfig(f'router bgp {ASN} vrf {import_vrf}') +        self.assertIn(f'router bgp {ASN}', frrconfig) +        self.assertIn(f'router bgp {ASN} vrf {import_vrf}', frrconfig_vrf) +        self.cli_delete(base_path) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() + +    def test_bgp_20_import_rd_rt_compatibility(self): +        # Verify if vrf that has rd vpn export is in import vrf of other vrfs +        self.create_bgp_instances_for_import_test() +        self.cli_set( +            import_vrf_base + [import_vrf] + base_path + ['address-family', +                                                          import_afi, 'rd', +                                                          'vpn', 'export', +                                                          import_rd]) +        self.cli_commit() +        frrconfig = self.getFRRconfig(f'router bgp {ASN}') +        frrconfig_vrf = self.getFRRconfig(f'router bgp {ASN} vrf {import_vrf}') +        self.assertIn(f'router bgp {ASN}', frrconfig) +        self.assertIn(f'router bgp {ASN} vrf {import_vrf}', frrconfig_vrf) +        self.assertIn(f'address-family ipv4 unicast', frrconfig_vrf) +        self.assertIn(f'  rd vpn export {import_rd}', frrconfig_vrf) + +        self.cli_set( +            base_path + ['address-family', import_afi, 'import', 'vrf', +                         import_vrf]) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() + +    def test_bgp_21_import_unspecified_vrf(self): +        # Verify if vrf that is in import is unspecified +        self.create_bgp_instances_for_import_test() +        self.cli_set( +            base_path + ['address-family', import_afi, 'import', 'vrf', +                         'test']) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit()  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index 339713bf6..581959b15 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -74,6 +74,11 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):          self.cli_set(base_path + ['parameters', 'rfc1583-compatibility'])          self.cli_set(base_path + ['log-adjacency-changes', 'detail'])          self.cli_set(base_path + ['default-metric', metric]) +        self.cli_set(base_path + ['passive-interface', 'default']) +        self.cli_set(base_path + ['area', '10', 'area-type', 'stub']) +        self.cli_set(base_path + ['area', '10', 'network', '10.0.0.0/16']) +        self.cli_set(base_path + ['area', '10', 'range', '10.0.1.0/24']) +        self.cli_set(base_path + ['area', '10', 'range', '10.0.2.0/24', 'not-advertise'])          # commit changes          self.cli_commit() @@ -88,6 +93,12 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):          self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults          self.assertIn(f' capability opaque', frrconfig)          self.assertIn(f' default-metric {metric}', frrconfig) +        self.assertIn(f' passive-interface default', frrconfig) +        self.assertIn(f' area 10 stub', frrconfig) +        self.assertIn(f' network 10.0.0.0/16 area 10', frrconfig) +        self.assertIn(f' area 10 range 10.0.1.0/24', frrconfig) +        self.assertNotIn(f' area 10 range 10.0.1.0/24 not-advertise', frrconfig) +        self.assertIn(f' area 10 range 10.0.2.0/24 not-advertise', frrconfig)      def test_ospf_03_access_list(self): @@ -272,6 +283,10 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):          # commit changes          self.cli_commit() +        frrconfig = self.getFRRconfig('router ospf') +        self.assertIn(f'router ospf', frrconfig) +        self.assertIn(f' passive-interface default', frrconfig) +          for interface in interfaces:              config = self.getFRRconfig(f'interface {interface}')              self.assertIn(f'interface {interface}', config) diff --git a/smoketest/scripts/cli/test_qos.py b/smoketest/scripts/cli/test_qos.py index d1fa3d07b..0092473d6 100755 --- a/smoketest/scripts/cli/test_qos.py +++ b/smoketest/scripts/cli/test_qos.py @@ -130,7 +130,7 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):      def test_03_fair_queue(self):          hash_interval = 10 -        queue_limit = 50 +        queue_limit = 5          policy_type = 'fair-queue'          first = True @@ -150,13 +150,13 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):              self.cli_set(base_path + ['policy', policy_type, policy_name, 'queue-limit', str(queue_limit)])              hash_interval += 1 -            queue_limit += 10 +            queue_limit += 1          # commit changes          self.cli_commit()          hash_interval = 10 -        queue_limit = 50 +        queue_limit = 5          for interface in self._interfaces:              tmp = get_tc_qdisc_json(interface) @@ -165,7 +165,7 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):              self.assertEqual(queue_limit, tmp['options']['limit'])              hash_interval += 1 -            queue_limit += 10 +            queue_limit += 1      def test_04_fq_codel(self):          policy_type = 'fq-codel' @@ -222,8 +222,8 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):              # results in: tc -j qdisc show dev eth0              # [{"kind":"fq_codel","handle":"8046:","root":true,"refcnt":3,"options":{"limit":2048,"flows":512,              #   "quantum":1500,"target":4999,"interval":99999,"memory_limit":33554432,"drop_batch":64}}] -            self.assertEqual(interval *1000 -1, tmp['options']['interval']) -            self.assertEqual(target *1000 -1, tmp['options']['target']) +            self.assertAlmostEqual(tmp['options']['interval'], interval *1000, delta=1) +            self.assertAlmostEqual(tmp['options']['target'], target *1000 -1, delta=1)              codel_quantum += 10              flows += 2 @@ -234,13 +234,13 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):      def test_05_limiter(self):          qos_config = {              '1' : { -                'bandwidth' : '100', +                'bandwidth' : '1000000',                  'match4' : {                      'ssh'   : { 'dport' : '22', },                      },                  },              '2' : { -                'bandwidth' : '100', +                'bandwidth' : '1000000',                  'match6' : {                      'ssh'   : { 'dport' : '22', },                      }, @@ -260,7 +260,8 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):                  first = False              self.cli_set(base_path + ['interface', interface, 'ingress', policy_name]) - +            # set default bandwidth parameter for all remaining connections +            self.cli_set(base_path + ['policy', 'limiter', policy_name, 'default', 'bandwidth', '500000'])              for qos_class, qos_class_config in qos_config.items():                  qos_class_base = base_path + ['policy', 'limiter', policy_name, 'class', qos_class] @@ -282,8 +283,6 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):          # commit changes          self.cli_commit() -        self.skipTest('iproute2 bug - invalid JSON') -          for interface in self._interfaces:              for filter in get_tc_filter_json(interface, 'ingress'):                  # bail out early if filter has no attached action diff --git a/smoketest/scripts/cli/test_service_dhcpv6-relay.py b/smoketest/scripts/cli/test_service_dhcpv6-relay.py index fc206435b..8bb58d296 100755 --- a/smoketest/scripts/cli/test_service_dhcpv6-relay.py +++ b/smoketest/scripts/cli/test_service_dhcpv6-relay.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -34,22 +34,30 @@ listen_addr = '2001:db8:ffff::1/64'  interfaces = []  class TestServiceDHCPv6Relay(VyOSUnitTestSHIM.TestCase): -    def setUp(self): -        for tmp in interfaces: +    @classmethod +    def setUpClass(cls): +        super(TestServiceDHCPv6Relay, cls).setUpClass() + +        # ensure we can also run this test on a live system - so lets clean +        # out the current configuration :) +        cls.cli_delete(cls, base_path) + +        for tmp in Section.interfaces('ethernet', vlan=False): +            interfaces.append(tmp)              listen = listen_addr              if tmp == upstream_if:                  listen = upstream_if_addr -            self.cli_set(['interfaces', 'ethernet', tmp, 'address', listen]) +            cls.cli_set(cls, ['interfaces', 'ethernet', tmp, 'address', listen]) -    def tearDown(self): -        self.cli_delete(base_path) +    @classmethod +    def tearDownClass(cls):          for tmp in interfaces:              listen = listen_addr              if tmp == upstream_if:                  listen = upstream_if_addr -            self.cli_delete(['interfaces', 'ethernet', tmp, 'address', listen]) +            cls.cli_delete(cls, ['interfaces', 'ethernet', tmp, 'address', listen]) -        self.cli_commit() +        super(TestServiceDHCPv6Relay, cls).tearDownClass()      def test_relay_default(self):          dhcpv6_server = '2001:db8::ffff' @@ -100,9 +108,5 @@ class TestServiceDHCPv6Relay(VyOSUnitTestSHIM.TestCase):          self.assertTrue(process_named_running(PROCESS_NAME))  if __name__ == '__main__': -    for tmp in Section.interfaces('ethernet'): -        if '.' not in tmp: -            interfaces.append(tmp) -      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_ntp.py b/smoketest/scripts/cli/test_service_ntp.py index a0806acf0..3ccd19a31 100755 --- a/smoketest/scripts/cli/test_system_ntp.py +++ b/smoketest/scripts/cli/test_service_ntp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-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,14 +19,12 @@ import unittest  from base_vyostest_shim import VyOSUnitTestSHIM  from vyos.configsession import ConfigSessionError -from vyos.template import address_from_cidr -from vyos.template import netmask_from_cidr -from vyos.util import read_file +from vyos.util import cmd  from vyos.util import process_named_running -PROCESS_NAME = 'ntpd' -NTP_CONF = '/run/ntpd/ntpd.conf' -base_path = ['system', 'ntp'] +PROCESS_NAME = 'chronyd' +NTP_CONF = '/run/chrony/chrony.conf' +base_path = ['service', 'ntp']  class TestSystemNTP(VyOSUnitTestSHIM.TestCase):      @classmethod @@ -38,6 +36,8 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase):          cls.cli_delete(cls, base_path)      def tearDown(self): +        self.assertTrue(process_named_running(PROCESS_NAME)) +          self.cli_delete(base_path)          self.cli_commit() @@ -46,7 +46,7 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase):      def test_01_ntp_options(self):          # Test basic NTP support with multiple servers and their options          servers = ['192.0.2.1', '192.0.2.2'] -        options = ['noselect', 'preempt', 'prefer'] +        options = ['noselect', 'prefer']          pools = ['pool.vyos.io']          for server in servers: @@ -61,12 +61,14 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase):          self.cli_commit()          # Check generated configuration -        config = read_file(NTP_CONF) -        self.assertIn('driftfile /var/lib/ntp/ntp.drift', config) -        self.assertIn('restrict default noquery nopeer notrap nomodify', config) -        self.assertIn('restrict source nomodify notrap noquery', config) -        self.assertIn('restrict 127.0.0.1', config) -        self.assertIn('restrict -6 ::1', config) +        # this file must be read with higher permissions +        config = cmd(f'sudo cat {NTP_CONF}') +        self.assertIn('driftfile /run/chrony/drift', config) +        self.assertIn('dumpdir /run/chrony', config) +        self.assertIn('clientloglimit 1048576', config) +        self.assertIn('rtcsync', config) +        self.assertIn('makestep 1.0 3', config) +        self.assertIn('leapsectz right/UTC', config)          for server in servers:              self.assertIn(f'server {server} iburst ' + ' '.join(options), config) @@ -80,9 +82,9 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase):          for listen in listen_address:              self.cli_set(base_path + ['listen-address', listen]) -        networks = ['192.0.2.0/24', '2001:db8:1000::/64'] +        networks = ['192.0.2.0/24', '2001:db8:1000::/64', '100.64.0.0', '2001:db8::ffff']          for network in networks: -            self.cli_set(base_path + ['allow-clients', 'address', network]) +            self.cli_set(base_path + ['allow-client', 'address', network])          # Verify "NTP server not configured" verify() statement          with self.assertRaises(ConfigSessionError): @@ -95,18 +97,14 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase):          self.cli_commit()          # Check generated client address configuration -        config = read_file(NTP_CONF) -        self.assertIn('restrict default ignore', config) - +        # this file must be read with higher permissions +        config = cmd(f'sudo cat {NTP_CONF}')          for network in networks: -            network_address = address_from_cidr(network) -            network_netmask = netmask_from_cidr(network) -            self.assertIn(f'restrict {network_address} mask {network_netmask} nomodify notrap nopeer', config) +            self.assertIn(f'allow {network}', config)          # Check listen address -        self.assertIn('interface ignore wildcard', config)          for listen in listen_address: -            self.assertIn(f'interface listen {listen}', config) +            self.assertIn(f'bindaddress {listen}', config)      def test_03_ntp_interface(self):          interfaces = ['eth0', 'eth1'] @@ -120,10 +118,28 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase):          self.cli_commit()          # Check generated client address configuration -        config = read_file(NTP_CONF) -        self.assertIn('interface ignore wildcard', config) +        # this file must be read with higher permissions +        config = cmd(f'sudo cat {NTP_CONF}')          for interface in interfaces: -            self.assertIn(f'interface listen {interface}', config) +            self.assertIn(f'binddevice {interface}', config) + +    def test_04_ntp_vrf(self): +        vrf_name = 'vyos-mgmt' + +        self.cli_set(['vrf', 'name', vrf_name, 'table', '12345']) +        self.cli_set(base_path + ['vrf', vrf_name]) + +        servers = ['time1.vyos.net', 'time2.vyos.net'] +        for server in servers: +            self.cli_set(base_path + ['server', server]) + +        self.cli_commit() + +        # Check for process in VRF +        tmp = cmd(f'ip vrf pids {vrf_name}') +        self.assertIn(PROCESS_NAME, tmp) + +        self.cli_delete(['vrf', 'name', vrf_name])  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_tftp-server.py b/smoketest/scripts/cli/test_service_tftp-server.py index b57c33f26..99d81e203 100755 --- a/smoketest/scripts/cli/test_service_tftp-server.py +++ b/smoketest/scripts/cli/test_service_tftp-server.py @@ -33,15 +33,32 @@ address_ipv6 = '2001:db8::1'  vrf = 'mgmt'  class TestServiceTFTPD(VyOSUnitTestSHIM.TestCase): -    def setUp(self): -        self.cli_set(dummy_if_path + ['address', address_ipv4 + '/32']) -        self.cli_set(dummy_if_path + ['address', address_ipv6 + '/128']) +    @classmethod +    def setUpClass(cls): +        super(TestServiceTFTPD, cls).setUpClass() + +        # ensure we can also run this test on a live system - so lets clean +        # out the current configuration :) +        cls.cli_delete(cls, base_path) + +        cls.cli_set(cls, dummy_if_path + ['address', address_ipv4 + '/32']) +        cls.cli_set(cls, dummy_if_path + ['address', address_ipv6 + '/128']) + +    @classmethod +    def tearDownClass(cls): +        cls.cli_delete(cls, dummy_if_path) +        super(TestServiceTFTPD, cls).tearDownClass()      def tearDown(self): +        # Check for running process +        self.assertTrue(process_named_running(PROCESS_NAME)) +          self.cli_delete(base_path) -        self.cli_delete(dummy_if_path)          self.cli_commit() +        # Check for no longer running process +        self.assertFalse(process_named_running(PROCESS_NAME)) +      def test_01_tftpd_single(self):          directory = '/tmp'          port = '69' # default port @@ -61,9 +78,6 @@ class TestServiceTFTPD(VyOSUnitTestSHIM.TestCase):          # verify upload          self.assertIn('--create --umask 000', config) -        # Check for running process -        self.assertTrue(process_named_running(PROCESS_NAME)) -      def test_02_tftpd_multi(self):          directory = '/tmp'          address = [address_ipv4, address_ipv6] @@ -125,9 +139,6 @@ class TestServiceTFTPD(VyOSUnitTestSHIM.TestCase):          # verify upload          self.assertIn('--create --umask 000', config) -        # Check for running process -        self.assertTrue(process_named_running(PROCESS_NAME)) -          # Check for process in VRF          tmp = cmd(f'ip vrf pids {vrf}')          self.assertIn(PROCESS_NAME, tmp) diff --git a/src/conf_mode/flow_accounting_conf.py b/src/conf_mode/flow_accounting_conf.py index 7e16235c1..f67f1710e 100755 --- a/src/conf_mode/flow_accounting_conf.py +++ b/src/conf_mode/flow_accounting_conf.py @@ -38,7 +38,7 @@ airbag.enable()  uacctd_conf_path = '/run/pmacct/uacctd.conf'  systemd_service = 'uacctd.service' -systemd_override = f'/etc/systemd/system/{systemd_service}.d/override.conf' +systemd_override = f'/run/systemd/system/{systemd_service}.d/override.conf'  nftables_nflog_table = 'raw'  nftables_nflog_chain = 'VYOS_CT_PREROUTING_HOOK'  egress_nftables_nflog_table = 'inet mangle' @@ -192,7 +192,7 @@ def verify(flow_config):                      raise ConfigError("All sFlow servers must use the same IP protocol")              else:                  sflow_collector_ipver = ip_address(server).version -	 +          # check if vrf is defined for Sflow          sflow_vrf = None          if 'vrf' in flow_config: diff --git a/src/conf_mode/high-availability.py b/src/conf_mode/high-availability.py index 8a959dc79..4ed16d0d7 100755 --- a/src/conf_mode/high-availability.py +++ b/src/conf_mode/high-availability.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 @@ -144,8 +144,10 @@ def verify(ha):      # Virtual-server      if 'virtual_server' in ha:          for vs, vs_config in ha['virtual_server'].items(): -            if 'port' not in vs_config: -                raise ConfigError(f'Port is required but not set for virtual-server "{vs}"') +            if 'port' not in vs_config and 'fwmark' not in vs_config: +                raise ConfigError(f'Port or fwmark is required but not set for virtual-server "{vs}"') +            if 'port' in vs_config and 'fwmark' in vs_config: +                raise ConfigError(f'Cannot set both port and fwmark for virtual-server "{vs}"')              if 'real_server' not in vs_config:                  raise ConfigError(f'Real-server ip is required but not set for virtual-server "{vs}"')          # Real-server diff --git a/src/conf_mode/https.py b/src/conf_mode/https.py index 7cd7ea42e..ce5e63928 100755 --- a/src/conf_mode/https.py +++ b/src/conf_mode/https.py @@ -37,7 +37,7 @@ from vyos import airbag  airbag.enable()  config_file = '/etc/nginx/sites-available/default' -systemd_override = r'/etc/systemd/system/nginx.service.d/override.conf' +systemd_override = r'/run/systemd/system/nginx.service.d/override.conf'  cert_dir = '/etc/ssl/certs'  key_dir = '/etc/ssl/private'  certbot_dir = vyos.defaults.directories['certbot'] diff --git a/src/conf_mode/interfaces-input.py b/src/conf_mode/interfaces-input.py new file mode 100755 index 000000000..ad248843d --- /dev/null +++ b/src/conf_mode/interfaces-input.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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/>. + +from sys import exit + +from vyos.config import Config +from vyos.configdict import get_interface_dict +from vyos.configverify import verify_mirror_redirect +from vyos.ifconfig import InputIf +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +def get_config(config=None): +    """ +    Retrive CLI config as dictionary. Dictionary can never be empty, as at +    least the interface name will be added or a deleted flag +    """ +    if config: +        conf = config +    else: +        conf = Config() +    base = ['interfaces', 'input'] +    _, ifb = get_interface_dict(conf, base) + +    return ifb + +def verify(ifb): +    if 'deleted' in ifb: +        return None + +    verify_mirror_redirect(ifb) +    return None + +def generate(ifb): +    return None + +def apply(ifb): +    d = InputIf(ifb['ifname']) + +    # Remove input interface +    if 'deleted' in ifb: +        d.remove() +    else: +        d.update(ifb) + +    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/ntp.py b/src/conf_mode/ntp.py index 0ecb4d736..92cb73aab 100755 --- a/src/conf_mode/ntp.py +++ b/src/conf_mode/ntp.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 @@ -21,26 +21,29 @@ from vyos.configdict import is_node_changed  from vyos.configverify import verify_vrf  from vyos.configverify import verify_interface_exists  from vyos.util import call +from vyos.util import chmod_750  from vyos.util import get_interface_config  from vyos.template import render  from vyos import ConfigError  from vyos import airbag  airbag.enable() -config_file = r'/run/ntpd/ntpd.conf' -systemd_override = r'/etc/systemd/system/ntp.service.d/override.conf' +config_file = r'/run/chrony/chrony.conf' +systemd_override = r'/run/systemd/system/chrony.service.d/override.conf' +user_group = '_chrony'  def get_config(config=None):      if config:          conf = config      else:          conf = Config() -    base = ['system', 'ntp'] +    base = ['service', 'ntp']      if not conf.exists(base):          return None      ntp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)      ntp['config_file'] = config_file +    ntp['user'] = user_group      tmp = is_node_changed(conf, base + ['vrf'])      if tmp: ntp.update({'restart_required': {}}) @@ -52,7 +55,7 @@ def verify(ntp):      if not ntp:          return None -    if 'allow_clients' in ntp and 'server' not in ntp: +    if 'server' not in ntp:          raise ConfigError('NTP server not configured')      verify_vrf(ntp) @@ -77,13 +80,17 @@ def generate(ntp):      if not ntp:          return None -    render(config_file, 'ntp/ntpd.conf.j2', ntp) -    render(systemd_override, 'ntp/override.conf.j2', ntp) +    render(config_file, 'chrony/chrony.conf.j2', ntp, user=user_group, group=user_group) +    render(systemd_override, 'chrony/override.conf.j2', ntp, user=user_group, group=user_group) + +    # Ensure proper permission for chrony command socket +    config_dir = os.path.dirname(config_file) +    chmod_750(config_dir)      return None  def apply(ntp): -    systemd_service = 'ntp.service' +    systemd_service = 'chrony.service'      # Reload systemd manager configuration      call('systemctl daemon-reload') diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index ff568d470..c410258ee 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -14,8 +14,6 @@  # 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 sys import argv @@ -57,13 +55,18 @@ def get_config(config=None):      # instead of the VRF instance.      if vrf: bgp.update({'vrf' : vrf}) +    bgp['dependent_vrfs'] = conf.get_config_dict(['vrf', 'name'], +                                                 key_mangling=('-', '_'), +                                                 get_first_key=True, +                                                 no_tag_node_value_mangle=True) + +    bgp['dependent_vrfs'].update({'default': {'protocols': { +        'bgp': conf.get_config_dict(base_path, key_mangling=('-', '_'), +                                    get_first_key=True, +                                    no_tag_node_value_mangle=True)}}})      if not conf.exists(base): +        # If bgp instance is deleted then mark it          bgp.update({'deleted' : ''}) -        if not vrf: -            # We are running in the default VRF context, thus we can not delete -            # our main BGP instance if there are dependent BGP VRF instances. -            bgp['dependent_vrfs'] = conf.get_config_dict(['vrf', 'name'], -                key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True)          return bgp      # We also need some additional information from the config, prefix-lists @@ -74,9 +77,91 @@ def get_config(config=None):      tmp = conf.get_config_dict(['policy'])      # Merge policy dict into "regular" config dict      bgp = dict_merge(tmp, bgp) -      return bgp + +def verify_vrf_as_import(search_vrf_name: str, afi_name: str, vrfs_config: dict) -> bool: +    """ +    :param search_vrf_name: search vrf name in import list +    :type search_vrf_name: str +    :param afi_name: afi/safi name +    :type afi_name: str +    :param vrfs_config: configuration dependents vrfs +    :type vrfs_config: dict +    :return: if vrf in import list retrun true else false +    :rtype: bool +    """ +    for vrf_name, vrf_config in vrfs_config.items(): +        import_list = dict_search( +            f'protocols.bgp.address_family.{afi_name}.import.vrf', +            vrf_config) +        if import_list: +            if search_vrf_name in import_list: +               return True +    return False + +def verify_vrf_import_options(afi_config: dict) -> bool: +    """ +    Search if afi contains one of options +    :param afi_config: afi/safi +    :type afi_config: dict +    :return: if vrf contains rd and route-target options return true else false +    :rtype: bool +    """ +    options = [ +        f'rd.vpn.export', +        f'route_target.vpn.import', +        f'route_target.vpn.export', +        f'route_target.vpn.both' +    ] +    for option in options: +        if dict_search(option, afi_config): +            return True +    return False + +def verify_vrf_import(vrf_name: str, vrfs_config: dict, afi_name: str) -> bool: +    """ +    Verify if vrf exists and contain options +    :param vrf_name: name of VRF +    :type vrf_name: str +    :param vrfs_config: dependent vrfs config +    :type vrfs_config: dict +    :param afi_name: afi/safi name +    :type afi_name: str +    :return: if vrf contains rd and route-target options return true else false +    :rtype: bool +    """ +    if vrf_name != 'default': +        verify_vrf({'vrf': vrf_name}) +    if dict_search(f'{vrf_name}.protocols.bgp.address_family.{afi_name}', +                   vrfs_config): +        afi_config = \ +        vrfs_config[vrf_name]['protocols']['bgp']['address_family'][ +            afi_name] +        if verify_vrf_import_options(afi_config): +            return True +    return False + +def verify_vrflist_import(afi_name: str, afi_config: dict, vrfs_config: dict) -> bool: +    """ +    Call function to verify +    if scpecific vrf contains rd and route-target +    options return true else false + +    :param afi_name: afi/safi name +    :type afi_name: str +    :param afi_config: afi/safi configuration +    :type afi_config: dict +    :param vrfs_config: dependent vrfs config +    :type vrfs_config:dict +    :return: if vrf contains rd and route-target options return true else false +    :rtype: bool +    """ +    for vrf_name in afi_config['import']['vrf']: +        if verify_vrf_import(vrf_name, vrfs_config, afi_name): +            return True +    return False +  def verify_remote_as(peer_config, bgp_config):      if 'remote_as' in peer_config:          return peer_config['remote_as'] @@ -113,12 +198,22 @@ def verify_afi(peer_config, bgp_config):      return False  def verify(bgp): -    if not bgp or 'deleted' in bgp: -        if 'dependent_vrfs' in bgp: -            for vrf, vrf_options in bgp['dependent_vrfs'].items(): -                if dict_search('protocols.bgp', vrf_options) != None: -                    raise ConfigError('Cannot delete default BGP instance, ' \ -                                      'dependent VRF instance(s) exist!') +    if 'deleted' in bgp: +        if 'vrf' in bgp: +            # Cannot delete vrf if it exists in import vrf list in other vrfs +            for tmp_afi in ['ipv4_unicast', 'ipv6_unicast']: +                if verify_vrf_as_import(bgp['vrf'],tmp_afi,bgp['dependent_vrfs']): +                    raise ConfigError(f'Cannot delete vrf {bgp["vrf"]} instance, ' \ +                                      'Please unconfigure import vrf commands!') +        else: +            # We are running in the default VRF context, thus we can not delete +            # our main BGP instance if there are dependent BGP VRF instances. +            if 'dependent_vrfs' in bgp: +                for vrf, vrf_options in bgp['dependent_vrfs'].items(): +                    if vrf != 'default': +                        if dict_search('protocols.bgp', vrf_options): +                            raise ConfigError('Cannot delete default BGP instance, ' \ +                                              'dependent VRF instance(s) exist!')          return None      if 'system_as' not in bgp: @@ -324,9 +419,43 @@ def verify(bgp):                                           f'{afi} administrative distance {key}!')              if afi in ['ipv4_unicast', 'ipv6_unicast']: -                if 'import' in afi_config and 'vrf' in afi_config['import']: -                    # Check if VRF exists -                    verify_vrf(afi_config['import']['vrf']) + +                vrf_name = bgp['vrf'] if dict_search('vrf', bgp) else 'default' +                # Verify if currant VRF contains rd and route-target options +                # and does not exist in import list in other VRFs +                if dict_search(f'rd.vpn.export', afi_config): +                    if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']): +                        raise ConfigError( +                            'Command "import vrf" conflicts with "rd vpn export" command!') + +                if dict_search('route_target.vpn.both', afi_config): +                    if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']): +                        raise ConfigError( +                            'Command "import vrf" conflicts with "route-target vpn both" command!') + +                if dict_search('route_target.vpn.import', afi_config): +                    if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']): +                        raise ConfigError( +                            'Command "import vrf conflicts" with "route-target vpn import" command!') + +                if dict_search('route_target.vpn.export', afi_config): +                    if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']): +                        raise ConfigError( +                            'Command "import vrf" conflicts with "route-target vpn export" command!') + +                # Verify if VRFs in import do not contain rd +                # and route-target options +                if dict_search('import.vrf', afi_config) is not None: +                    # Verify if VRF with import does not contain rd +                    # and route-target options +                    if verify_vrf_import_options(afi_config): +                        raise ConfigError( +                            'Please unconfigure "import vrf" commands before using vpn commands in the same VRF!') +                    # Verify if VRFs in import list do not contain rd +                    # and route-target options +                    if verify_vrflist_import(afi, afi_config, bgp['dependent_vrfs']): +                        raise ConfigError( +                            'Please unconfigure import vrf commands before using vpn commands in dependent VRFs!')                      # FRR error: please unconfigure vpn to vrf commands before                      # using import vrf commands @@ -339,7 +468,6 @@ def verify(bgp):                      tmp = dict_search(f'route_map.vpn.{export_import}', afi_config)                      if tmp: verify_route_map(tmp, bgp) -      return None  def generate(bgp): diff --git a/src/conf_mode/protocols_failover.py b/src/conf_mode/protocols_failover.py index 048ba7a89..85e984afe 100755 --- a/src/conf_mode/protocols_failover.py +++ b/src/conf_mode/protocols_failover.py @@ -31,7 +31,7 @@ airbag.enable()  service_name = 'vyos-failover'  service_conf = Path(f'/run/{service_name}.conf') -systemd_service = '/etc/systemd/system/vyos-failover.service' +systemd_service = '/run/systemd/system/vyos-failover.service'  rt_proto_failover = '/etc/iproute2/rt_protos.d/failover.conf' diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py index ee4eaf59d..ed0a8fba2 100755 --- a/src/conf_mode/protocols_ospfv3.py +++ b/src/conf_mode/protocols_ospfv3.py @@ -117,6 +117,10 @@ def verify(ospfv3):              if 'area_type' in area_config:                  if len(area_config['area_type']) > 1:                      raise ConfigError(f'Can only configure one area-type for OSPFv3 area "{area}"!') +            if 'range' in area_config: +                for range, range_config in area_config['range'].items(): +                    if {'not_advertise', 'advertise'} <= range_config.keys(): +                        raise ConfigError(f'"not-advertise" and "advertise" for "range {range}" cannot be both configured at the same time!')      if 'interface' in ospfv3:          for interface, interface_config in ospfv3['interface'].items(): diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index 58e202928..3e5ebb805 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021 VyOS maintainers and contributors +# 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 @@ -25,12 +25,15 @@ from vyos.configdict import get_dhcp_interfaces  from vyos.configdict import get_pppoe_interfaces  from vyos.configverify import verify_common_route_maps  from vyos.configverify import verify_vrf +from vyos.template import render  from vyos.template import render_to_string  from vyos import ConfigError  from vyos import frr  from vyos import airbag  airbag.enable() +config_file = '/etc/iproute2/rt_tables.d/vyos-static.conf' +  def get_config(config=None):      if config:          conf = config @@ -94,6 +97,9 @@ def verify(static):  def generate(static):      if not static:          return None + +    # Put routing table names in /etc/iproute2/rt_tables +    render(config_file, 'iproute2/static.conf.j2', static)      static['new_frr_config'] = render_to_string('frr/staticd.frr.j2', static)      return None diff --git a/src/conf_mode/qos.py b/src/conf_mode/qos.py index 2eb03237c..0418e8d82 100755 --- a/src/conf_mode/qos.py +++ b/src/conf_mode/qos.py @@ -187,6 +187,9 @@ def verify(qos):                                  if queue_lim < max_tr:                                      raise ConfigError(f'Policy "{policy}" uses queue-limit "{queue_lim}" < max-threshold "{max_tr}"!') +                if 'default' in policy_config: +                    if 'bandwidth' not in policy_config['default'] and policy_type not in ['priority_queue', 'round_robin']: +                        raise ConfigError('Bandwidth not defined for default traffic!')      # we should check interface ingress/egress configuration after verifying that      # the policy name is used only once - this makes the logic easier! diff --git a/src/conf_mode/service_console-server.py b/src/conf_mode/service_console-server.py index ee4fe42ab..60eff6543 100755 --- a/src/conf_mode/service_console-server.py +++ b/src/conf_mode/service_console-server.py @@ -27,7 +27,7 @@ from vyos.xml import defaults  from vyos import ConfigError  config_file = '/run/conserver/conserver.cf' -dropbear_systemd_file = '/etc/systemd/system/dropbear@{port}.service.d/override.conf' +dropbear_systemd_file = '/run/systemd/system/dropbear@{port}.service.d/override.conf'  def get_config(config=None):      if config: diff --git a/src/conf_mode/service_monitoring_telegraf.py b/src/conf_mode/service_monitoring_telegraf.py index aafece47a..363408679 100755 --- a/src/conf_mode/service_monitoring_telegraf.py +++ b/src/conf_mode/service_monitoring_telegraf.py @@ -38,7 +38,7 @@ cache_dir = f'/etc/telegraf/.cache'  config_telegraf = f'/run/telegraf/telegraf.conf'  custom_scripts_dir = '/etc/telegraf/custom_scripts'  syslog_telegraf = '/etc/rsyslog.d/50-telegraf.conf' -systemd_override = '/etc/systemd/system/telegraf.service.d/10-override.conf' +systemd_override = '/run/systemd/system/telegraf.service.d/10-override.conf'  def get_nft_filter_chains():      """ Get nft chains for table filter """ diff --git a/src/conf_mode/service_sla.py b/src/conf_mode/service_sla.py index e7c3ca59c..b1e22f37b 100755 --- a/src/conf_mode/service_sla.py +++ b/src/conf_mode/service_sla.py @@ -27,15 +27,13 @@ from vyos import ConfigError  from vyos import airbag  airbag.enable() -  owamp_config_dir = '/etc/owamp-server'  owamp_config_file = f'{owamp_config_dir}/owamp-server.conf' -systemd_override_owamp = r'/etc/systemd/system/owamp-server.d/20-override.conf' +systemd_override_owamp = r'/run/systemd/system/owamp-server.d/20-override.conf'  twamp_config_dir = '/etc/twamp-server'  twamp_config_file = f'{twamp_config_dir}/twamp-server.conf' -systemd_override_twamp = r'/etc/systemd/system/twamp-server.d/20-override.conf' - +systemd_override_twamp = r'/run/systemd/system/twamp-server.d/20-override.conf'  def get_config(config=None):      if config: diff --git a/src/conf_mode/service_webproxy.py b/src/conf_mode/service_webproxy.py index 41a1deaa3..658e496a6 100755 --- a/src/conf_mode/service_webproxy.py +++ b/src/conf_mode/service_webproxy.py @@ -246,7 +246,7 @@ def apply(proxy):      if os.path.exists(squidguard_db_dir):          chmod_755(squidguard_db_dir) -    call('systemctl restart squid.service') +    call('systemctl reload-or-restart squid.service')      return None diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py index 5cd24db32..914ec245c 100755 --- a/src/conf_mode/snmp.py +++ b/src/conf_mode/snmp.py @@ -40,7 +40,7 @@ config_file_client  = r'/etc/snmp/snmp.conf'  config_file_daemon  = r'/etc/snmp/snmpd.conf'  config_file_access  = r'/usr/share/snmp/snmpd.conf'  config_file_user    = r'/var/lib/snmp/snmpd.conf' -systemd_override    = r'/etc/systemd/system/snmpd.service.d/override.conf' +systemd_override    = r'/run/systemd/system/snmpd.service.d/override.conf'  systemd_service     = 'snmpd.service'  def get_config(config=None): diff --git a/src/conf_mode/ssh.py b/src/conf_mode/ssh.py index 8746cc701..8de0617af 100755 --- a/src/conf_mode/ssh.py +++ b/src/conf_mode/ssh.py @@ -32,7 +32,7 @@ from vyos import airbag  airbag.enable()  config_file = r'/run/sshd/sshd_config' -systemd_override = r'/etc/systemd/system/ssh.service.d/override.conf' +systemd_override = r'/run/systemd/system/ssh.service.d/override.conf'  sshguard_config_file = '/etc/sshguard/sshguard.conf'  sshguard_whitelist = '/etc/sshguard/whitelist' diff --git a/src/conf_mode/system-option.py b/src/conf_mode/system-option.py index 36dbf155b..e6c7a0ed2 100755 --- a/src/conf_mode/system-option.py +++ b/src/conf_mode/system-option.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2022 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 @@ -22,17 +22,19 @@ from time import sleep  from vyos.config import Config  from vyos.configdict import dict_merge +from vyos.configverify import verify_source_interface  from vyos.template import render  from vyos.util import cmd  from vyos.util import is_systemd_service_running  from vyos.validate import is_addr_assigned +from vyos.validate import is_intf_addr_assigned  from vyos.xml import defaults  from vyos import ConfigError  from vyos import airbag  airbag.enable()  curlrc_config = r'/etc/curlrc' -ssh_config = r'/etc/ssh/ssh_config' +ssh_config = r'/etc/ssh/ssh_config.d/91-vyos-ssh-client-options.conf'  systemd_action_file = '/lib/systemd/system/ctrl-alt-del.target'  def get_config(config=None): @@ -68,8 +70,17 @@ def verify(options):      if 'ssh_client' in options:          config = options['ssh_client']          if 'source_address' in config: +            address = config['source_address']              if not is_addr_assigned(config['source_address']): -                raise ConfigError('No interface with give address specified!') +                raise ConfigError('No interface with address "{address}" configured!') + +        if 'source_interface' in config: +            verify_source_interface(config) +            if 'source_address' in config: +                address = config['source_address'] +                interface = config['source_interface'] +                if not is_intf_addr_assigned(interface, address): +                    raise ConfigError(f'Address "{address}" not assigned on interface "{interface}"!')      return None diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index 04e2f2939..3af2af4d9 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -95,6 +95,7 @@ def get_config(config=None):      del default_values['esp_group']      del default_values['ike_group']      del default_values['remote_access'] +    del default_values['site_to_site']      ipsec = dict_merge(default_values, ipsec)      if 'esp_group' in ipsec: @@ -143,6 +144,14 @@ def get_config(config=None):              ipsec['remote_access']['radius']['server'][server] = dict_merge(default_values,                  ipsec['remote_access']['radius']['server'][server]) +    # XXX: T2665: we can not safely rely on the defaults() when there are +    # tagNodes in place, it is better to blend in the defaults manually. +    if dict_search('site_to_site.peer', ipsec): +        default_values = defaults(base + ['site-to-site', 'peer']) +        for peer in ipsec['site_to_site']['peer']: +            ipsec['site_to_site']['peer'][peer] = dict_merge(default_values, +              ipsec['site_to_site']['peer'][peer]) +      ipsec['dhcp_no_address'] = {}      ipsec['install_routes'] = 'no' if conf.exists(base + ["options", "disable-route-autoinstall"]) else default_install_routes      ipsec['interface_change'] = leaf_node_changed(conf, base + ['interface']) @@ -622,7 +631,7 @@ def wait_for_vici_socket(timeout=5, sleep_interval=0.1):          sleep(sleep_interval)  def apply(ipsec): -    systemd_service = 'strongswan.service' +    systemd_service = 'strongswan-starter.service'      if not ipsec:          call(f'systemctl stop {systemd_service}')      else: diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index 1b4156895..c17cca3bd 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2022 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -140,11 +140,9 @@ def verify(vrf):  def generate(vrf): -    render(config_file, 'vrf/vrf.conf.j2', vrf) +    render(config_file, 'iproute2/vrf.conf.j2', vrf)      # Render nftables zones config -      render(nft_vrf_config, 'firewall/nftables-vrf-zones.j2', vrf) -      return None diff --git a/src/etc/modprobe.d/ifb.conf b/src/etc/modprobe.d/ifb.conf new file mode 100644 index 000000000..2dcfb6af4 --- /dev/null +++ b/src/etc/modprobe.d/ifb.conf @@ -0,0 +1 @@ +options ifb numifbs=0 diff --git a/src/helpers/vyos-failover.py b/src/helpers/vyos-failover.py index 1ac193423..0de945f20 100755 --- a/src/helpers/vyos-failover.py +++ b/src/helpers/vyos-failover.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 @@ -28,6 +28,17 @@ from systemd import journal  my_name = Path(__file__).stem +def is_route_exists(route, gateway, interface, metric): +    """Check if route with expected gateway, dev and metric exists""" +    rc, data = rc_cmd(f'sudo ip --json route show protocol failover {route} ' +                      f'via {gateway} dev {interface} metric {metric}') +    if rc == 0: +        data = json.loads(data) +        if len(data) > 0: +            return True +    return False + +  def get_best_route_options(route, debug=False):      """      Return current best route ('gateway, interface, metric) @@ -137,7 +148,7 @@ if __name__ == '__main__':          for route, route_config in config.get('route').items(): -            exists_route = exists_gateway, exists_iface, exists_metric =  get_best_route_options(route, debug=debug) +            exists_gateway, exists_iface, exists_metric =  get_best_route_options(route, debug=debug)              for next_hop, nexthop_config in route_config.get('next_hop').items():                  conf_iface = nexthop_config.get('interface') @@ -148,8 +159,8 @@ if __name__ == '__main__':                  target = nexthop_config.get('check').get('target')                  timeout = nexthop_config.get('check').get('timeout') -                # Best route not fonund in the current routing table -                if exists_route == (None, None, None): +                # Route not found in the current routing table +                if not is_route_exists(route, next_hop, conf_iface, conf_metric):                      if debug: print(f"    [NEW_ROUTE_DETECTED] route: [{route}]")                      # Add route if check-target alive                      if is_target_alive(target, conf_iface, proto, port, debug=debug): @@ -172,7 +183,7 @@ if __name__ == '__main__':                  # Route was added, check if the target is alive                  # We should delete route if check fails only if route exists in the routing table                  if not is_target_alive(target, conf_iface, proto, port, debug=debug) and \ -                        exists_route != (None, None, None): +                        is_route_exists(route, next_hop, conf_iface, conf_metric):                      if debug:                          print(f'Nexh_hop {next_hop} fail, target not response')                          print(f'    [ DEL ] -- ip route del {route} via {next_hop} dev {conf_iface} ' diff --git a/src/migration-scripts/ntp/1-to-2 b/src/migration-scripts/ntp/1-to-2 new file mode 100755 index 000000000..4a701e7e5 --- /dev/null +++ b/src/migration-scripts/ntp/1-to-2 @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +# Copyright (C) 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/>. + +# T3008: move from ntpd to chrony and migrate "system ntp" to "service ntp" + +import sys + +from vyos.configtree import ConfigTree + +if (len(sys.argv) < 1): +    print("Must specify file name!") +    sys.exit(1) + +file_name = sys.argv[1] + +with open(file_name, 'r') as f: +    config_file = f.read() + +config = ConfigTree(config_file) + +base_path = ['system', 'ntp'] +new_base_path = ['service', 'ntp'] +if not config.exists(base_path): +    # Nothing to do +    sys.exit(0) + +# copy "system ntp" to "service ntp" +config.copy(base_path, new_base_path) +config.delete(base_path) + +# chrony does not support the preempt option, drop it +for server in config.list_nodes(new_base_path + ['server']): +    server_base =  new_base_path + ['server', server] +    if config.exists(server_base + ['preempt']): +        config.delete(server_base + ['preempt']) + +# Rename "allow-clients" -> "allow-client" +if config.exists(new_base_path + ['allow-clients']): +    config.rename(new_base_path + ['allow-clients'], 'allow-client') + +# By default VyOS 1.3 allowed NTP queries for all networks - in chrony we +# explicitly disable this behavior and clients need to be specified using the +# allow-client CLI option. In order to be fully backwards compatible, we specify +# 0.0.0.0/0 and ::/0 as allow networks if not specified otherwise explicitly. +if not config.exists(new_base_path + ['allow-client']): +    config.set(new_base_path + ['allow-client', 'address'], value='0.0.0.0/0', replace=False) +    config.set(new_base_path + ['allow-client', 'address'], value='::/0', replace=False) + +try: +    with open(file_name, 'w') as f: +        f.write(config.to_string()) +except OSError as e: +    print("Failed to save the modified config: {}".format(e)) +    sys.exit(1) diff --git a/src/migration-scripts/qos/1-to-2 b/src/migration-scripts/qos/1-to-2 index 6f4c08a50..41026cbd6 100755 --- a/src/migration-scripts/qos/1-to-2 +++ b/src/migration-scripts/qos/1-to-2 @@ -98,49 +98,19 @@ config.set(['qos'])  config.copy(base, ['qos', 'policy'])  config.delete(base) -# TODO -# - remove burst from network emulator - -def change_cli_bandwidth(config, path): -    if config.exists(path + ['bandwidth']): -        bw = config.return_value(path + ['bandwidth']) -        if bw.endswith('%'): -            bw = bandwidth_percent_to_val(interface, bw.rstrip('%')) -            config.set(path + ['bandwidth'], value=bw) -    return -  # Now map the interface policy binding to the new CLI syntax +if len(iface_config): +    config.set(['qos', 'interface']) +    config.set_tag(['qos', 'interface']) +  for interface, interface_config in iface_config.items(): +    config.set(['qos', 'interface', interface]) +    config.set_tag(['qos', 'interface', interface])      if 'ingress' in interface_config:          config.set(['qos', 'interface', interface, 'ingress'], value=interface_config['ingress'])      if 'egress' in interface_config:          config.set(['qos', 'interface', interface, 'egress'], value=interface_config['egress']) -    # QoS policy <-> interface binding is now established - we now can adjust some -    # CLI values like bandwidth in percent -    for direction in ['ingress', 'egress']: -        if direction not in interface_config: -            continue -        # Convert % bandwidth values to absolute values -        for policy in config.list_nodes(['qos', 'policy']): -            for policy_name in config.list_nodes(['qos', 'policy', policy]): -                if policy_name == interface_config[direction]: -                    policy_base = ['qos', 'policy', policy, policy_name] -                    # This is for the toplevel bandwidth node on a policy -                    change_cli_bandwidth(config, policy_base) - -                    # This is for class based bandwidth value -                    if config.exists(policy_base + ['class']): -                        for cls in config.list_nodes(policy_base + ['class']): -                            cls_base = policy_base + ['class', cls] -                            change_cli_bandwidth(config, cls_base) - -                    # This is for the bandwidth value specified under the -                    # policy "default" tree -                    if config.exists(policy_base + ['default']): -                        default_base = policy_base + ['default'] -                        change_cli_bandwidth(config, default_base) -  # Remove "burst" CLI node from network emulator  netem_base = ['qos', 'policy', 'network-emulator']  if config.exists(netem_base): diff --git a/src/op_mode/container.py b/src/op_mode/container.py index ecefc556e..d48766a0c 100755 --- a/src/op_mode/container.py +++ b/src/op_mode/container.py @@ -35,6 +35,19 @@ def _get_raw_data(command: str) -> list:      data = json.loads(json_data)      return data +def add_image(name: str): +    from vyos.util import rc_cmd + +    rc, output = rc_cmd(f'podman image pull {name}') +    if rc != 0: +        raise vyos.opmode.InternalError(output) + +def delete_image(name: str): +    from vyos.util import rc_cmd + +    rc, output = rc_cmd(f'podman image rm --force {name}') +    if rc != 0: +        raise vyos.opmode.InternalError(output)  def show_container(raw: bool):      command = 'podman ps --all' diff --git a/src/op_mode/ipsec.py b/src/op_mode/ipsec.py index e0d204a0a..f6417764a 100755 --- a/src/op_mode/ipsec.py +++ b/src/op_mode/ipsec.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 @@ -173,7 +173,7 @@ def _get_parent_sa_proposal(connection_name: str, data: list) -> dict:      for sa in data:          # check if parent SA exist          if connection_name not in sa.keys(): -            return {} +            continue          if 'encr-alg' in sa[connection_name]:              encr_alg = sa.get(connection_name, '').get('encr-alg')              cipher = encr_alg.split('_')[0] @@ -203,16 +203,17 @@ def _get_parent_sa_state(connection_name: str, data: list) -> str:      Returns:          Parent SA connection state      """ +    ike_state = 'down'      if not data: -        return 'down' +        return ike_state      for sa in data:          # check if parent SA exist -        if connection_name not in sa.keys(): -            return 'down' -        if sa[connection_name]['state'].lower() == 'established': -            return 'up' -        else: -            return 'down' +        for connection, connection_conf in sa.items(): +            if connection_name != connection: +                continue +            if connection_conf['state'].lower() == 'established': +                ike_state = 'up' +    return ike_state  def _get_child_sa_state(connection_name: str, tunnel_name: str, @@ -227,19 +228,20 @@ def _get_child_sa_state(connection_name: str, tunnel_name: str,      Returns:          str: `up` if child SA state is 'installed' otherwise `down`      """ +    child_sa = 'down'      if not data: -        return 'down' +        return child_sa      for sa in data:          # check if parent SA exist          if connection_name not in sa.keys(): -            return 'down' +            continue          child_sas = sa[connection_name]['child-sas']          # Get all child SA states          # there can be multiple SAs per tunnel          child_sa_states = [              v['state'] for k, v in child_sas.items() if v['name'] == tunnel_name          ] -        return 'up' if 'INSTALLED' in child_sa_states else 'down' +        return 'up' if 'INSTALLED' in child_sa_states else child_sa  def _get_child_sa_info(connection_name: str, tunnel_name: str, @@ -257,7 +259,7 @@ def _get_child_sa_info(connection_name: str, tunnel_name: str,      for sa in data:          # check if parent SA exist          if connection_name not in sa.keys(): -            return {} +            continue          child_sas = sa[connection_name]['child-sas']          # Get all child SA data          # Skip temp SA name (first key), get only SA values as dict diff --git a/src/op_mode/lldp.py b/src/op_mode/lldp.py new file mode 100755 index 000000000..dc2b1e0b5 --- /dev/null +++ b/src/op_mode/lldp.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 jmespath +import json +import sys +import typing + +from tabulate import tabulate + +from vyos.configquery import ConfigTreeQuery +from vyos.util import cmd +from vyos.util import dict_search + +import vyos.opmode +unconf_message = 'LLDP is not configured' +capability_codes = """Capability Codes: R - Router, B - Bridge, W - Wlan r - Repeater, S - Station +                  D - Docsis, T - Telephone, O - Other + +""" + +def _verify(func): +    """Decorator checks if LLDP config exists""" +    from functools import wraps + +    @wraps(func) +    def _wrapper(*args, **kwargs): +        config = ConfigTreeQuery() +        if not config.exists(['service', 'lldp']): +            raise vyos.opmode.UnconfiguredSubsystem(unconf_message) +        return func(*args, **kwargs) +    return _wrapper + +def _get_raw_data(interface=None, detail=False): +    """ +    If interface name is not set - get all interfaces +    """ +    tmp = 'lldpcli -f json show neighbors' +    if detail: +        tmp += f' details' +    if interface: +        tmp += f' ports {interface}' +    output = cmd(tmp) +    data = json.loads(output) +    if not data: +        return [] +    return data + +def _get_formatted_output(raw_data): +    data_entries = [] +    for neighbor in dict_search('lldp.interface', raw_data): +        for local_if, values in neighbor.items(): +            tmp = [] + +            # Device field +            if 'chassis' in values: +                tmp.append(next(iter(values['chassis']))) +            else: +                tmp.append('') + +            # Local Port field +            tmp.append(local_if) + +            # Protocol field +            tmp.append(values['via']) + +            # Capabilities +            cap = '' +            capabilities = jmespath.search('chassis.[*][0][0].capability', values) +            if capabilities: +                for capability in capabilities: +                    if capability['enabled']: +                        if capability['type'] == 'Router': +                            cap += 'R' +                        if capability['type'] == 'Bridge': +                            cap += 'B' +                        if capability['type'] == 'Wlan': +                            cap += 'W' +                        if capability['type'] == 'Station': +                            cap += 'S' +                        if capability['type'] == 'Repeater': +                            cap += 'r' +                        if capability['type'] == 'Telephone': +                            cap += 'T' +                        if capability['type'] == 'Docsis': +                            cap += 'D' +                        if capability['type'] == 'Other': +                            cap += 'O' +            tmp.append(cap) + +            # Remote software platform +            platform = jmespath.search('chassis.[*][0][0].descr', values) +            tmp.append(platform[:37]) + +            # Remote interface +            interface = jmespath.search('port.descr', values) +            if not interface: +                interface = jmespath.search('port.id.value', values) +            if not interface: +                interface = 'Unknown' +            tmp.append(interface) + +            # Add individual neighbor to output list +            data_entries.append(tmp) + +    headers = ["Device", "Local Port", "Protocol", "Capability", "Platform", "Remote Port"] +    output = tabulate(data_entries, headers, numalign="left") +    return capability_codes + output + +@_verify +def show_neighbors(raw: bool, interface: typing.Optional[str], detail: typing.Optional[bool]): +    lldp_data = _get_raw_data(interface=interface, detail=detail) +    if raw: +        return lldp_data +    else: +        return _get_formatted_output(lldp_data) + +if __name__ == "__main__": +    try: +        res = vyos.opmode.run(sys.modules[__name__]) +        if res: +            print(res) +    except (ValueError, vyos.opmode.Error) as e: +        print(e) +        sys.exit(1) diff --git a/src/op_mode/lldp_op.py b/src/op_mode/lldp_op.py deleted file mode 100755 index 17f6bf552..000000000 --- a/src/op_mode/lldp_op.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2019-2020 VyOS maintainers and contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. - -import argparse -import jinja2 -import json - -from sys import exit -from tabulate import tabulate - -from vyos.util import cmd -from vyos.config import Config - -parser = argparse.ArgumentParser() -parser.add_argument("-a", "--all", action="store_true", help="Show LLDP neighbors on all interfaces") -parser.add_argument("-d", "--detail", action="store_true", help="Show detailes LLDP neighbor information on all interfaces") -parser.add_argument("-i", "--interface", action="store", help="Show LLDP neighbors on specific interface") - -# Please be careful if you edit the template. -lldp_out = """Capability Codes: R - Router, B - Bridge, W - Wlan r - Repeater, S - Station -                  D - Docsis, T - Telephone, O - Other - -Device ID                 Local     Proto  Cap   Platform             Port ID ----------                 -----     -----  ---   --------             ------- -{% for neighbor in neighbors %} -{%   for local_if, info in neighbor.items() %} -{{ "%-25s" | format(info.chassis) }} {{ "%-9s" | format(local_if) }} {{ "%-6s" | format(info.proto) }} {{ "%-5s" | format(info.capabilities) }} {{ "%-20s" | format(info.platform[:18]) }} {{ info.remote_if }} -{%   endfor %} -{% endfor %} -""" - -def get_neighbors(): -    return cmd('/usr/sbin/lldpcli -f json show neighbors') - -def parse_data(data, interface): -    output = [] -    if not isinstance(data, list): -        data = [data] - -    for neighbor in data: -        for local_if, values in neighbor.items(): -            if interface is not None and local_if != interface: -                continue -            cap = '' -            for chassis, c_value in values.get('chassis', {}).items(): -                # bail out early if no capabilities found -                if 'capability' not in c_value: -                    continue -                capabilities = c_value['capability'] -                if isinstance(capabilities, dict): -                    capabilities = [capabilities] - -                for capability in capabilities: -                    if capability['enabled']: -                        if capability['type'] == 'Router': -                            cap += 'R' -                        if capability['type'] == 'Bridge': -                            cap += 'B' -                        if capability['type'] == 'Wlan': -                            cap += 'W' -                        if capability['type'] == 'Station': -                            cap += 'S' -                        if capability['type'] == 'Repeater': -                            cap += 'r' -                        if capability['type'] == 'Telephone': -                            cap += 'T' -                        if capability['type'] == 'Docsis': -                            cap += 'D' -                        if capability['type'] == 'Other': -                            cap += 'O' - -            remote_if = 'Unknown' -            if 'descr' in values.get('port', {}): -                remote_if = values.get('port', {}).get('descr') -            elif 'id' in values.get('port', {}): -                remote_if = values.get('port', {}).get('id').get('value', 'Unknown') - -            output.append({local_if: {'chassis': chassis, -                                       'remote_if': remote_if, -                                       'proto': values.get('via','Unknown'), -                                       'platform': c_value.get('descr', 'Unknown'), -                                       'capabilities': cap}}) - -    output = {'neighbors': output} -    return output - -if __name__ == '__main__': -    args = parser.parse_args() -    tmp = { 'neighbors' : [] } - -    c = Config() -    if not c.exists_effective(['service', 'lldp']): -        print('Service LLDP is not configured') -        exit(0) - -    if args.detail: -        print(cmd('/usr/sbin/lldpctl -f plain')) -        exit(0) -    elif args.all or args.interface: -        tmp = json.loads(get_neighbors()) -        neighbors = dict() - -        if 'interface' in tmp.get('lldp'): -            neighbors = tmp['lldp']['interface'] - -    else: -        parser.print_help() -        exit(1) - -    tmpl = jinja2.Template(lldp_out, trim_blocks=True) -    config_text = tmpl.render(parse_data(neighbors, interface=args.interface)) -    print(config_text) - -    exit(0) diff --git a/src/op_mode/nat.py b/src/op_mode/nat.py index a46571bd5..cf06de0e9 100755 --- a/src/op_mode/nat.py +++ b/src/op_mode/nat.py @@ -316,14 +316,20 @@ def show_statistics(raw: bool, direction: str, family: str):  @_verify -def show_translations(raw: bool, direction: str, family: str, address: typing.Optional[str]): +def show_translations(raw: bool, direction: +                      str, family: str, +                      address: typing.Optional[str], +                      verbose: typing.Optional[bool]):      family = 'ipv6' if family == 'inet6' else 'ipv4' -    nat_translation = _get_raw_translation(direction, family=family, address=address) +    nat_translation = _get_raw_translation(direction, +                                           family=family, +                                           address=address)      if raw:          return nat_translation      else: -        return _get_formatted_translation(nat_translation, direction, family, verbose) +        return _get_formatted_translation(nat_translation, direction, family, +                                          verbose)  if __name__ == '__main__': diff --git a/src/op_mode/route.py b/src/op_mode/route.py index d07a34180..7f0f9cbac 100755 --- a/src/op_mode/route.py +++ b/src/op_mode/route.py @@ -54,16 +54,43 @@ frr_command_template = Template("""  {% endif %}  """) -def show_summary(raw: bool): +def show_summary(raw: bool, family: str, table: typing.Optional[int], vrf: typing.Optional[str]):      from vyos.util import cmd +    if family == 'inet': +        family_cmd = 'ip' +    elif family == 'inet6': +        family_cmd = 'ipv6' +    else: +        raise ValueError(f"Unsupported address family {family}") + +    if (table is not None) and (vrf is not None): +        raise ValueError("table and vrf options are mutually exclusive") + +    # Replace with Jinja if it ever starts growing +    if table: +        table_cmd = f"table {table}" +    else: +        table_cmd = "" + +    if vrf: +        vrf_cmd = f"vrf {vrf}" +    else: +        vrf_cmd = "" +      if raw:          from json import loads -        output = cmd(f"vtysh -c 'show ip route summary json'") -        return loads(output) +        output = cmd(f"vtysh -c 'show {family_cmd} route {vrf_cmd} summary {table_cmd} json'").strip() + +        # If there are no routes in a table, its "JSON" output is an empty string, +        # as of FRR 8.4.1 +        if output: +            return loads(output) +        else: +            return {}      else: -        output = cmd(f"vtysh -c 'show ip route summary'") +        output = cmd(f"vtysh -c 'show {family_cmd} route {vrf_cmd} summary {table_cmd}'")          return output  def show(raw: bool, diff --git a/src/op_mode/show_ntp.sh b/src/op_mode/show_ntp.sh index e9dd6c5c9..85f8eda15 100755 --- a/src/op_mode/show_ntp.sh +++ b/src/op_mode/show_ntp.sh @@ -1,39 +1,34 @@  #!/bin/sh -basic=0 -info=0 +sourcestats=0 +tracking=0  while [[ "$#" -gt 0 ]]; do      case $1 in -        --info) info=1 ;; -        --basic) basic=1 ;; -        --server) server=$2; shift ;; +        --sourcestats) sourcestats=1 ;; +        --tracking) tracking=1 ;;          *) echo "Unknown parameter passed: $1" ;;      esac      shift  done -if ! ps -C ntpd &>/dev/null; then +if ! ps -C chronyd &>/dev/null; then      echo NTP daemon disabled      exit 1  fi -PID=$(pgrep ntpd) -VRF_NAME=$(ip vrf identify ${PID}) +PID=$(pgrep chronyd | head -n1) +VRF_NAME=$(ip vrf identify )  if [ ! -z ${VRF_NAME} ]; then      VRF_CMD="sudo ip vrf exec ${VRF_NAME}"  fi -if [ $basic -eq 1 ]; then -    $VRF_CMD ntpq -n -c peers -elif [ $info -eq 1 ]; then -    echo "=== sysingo ===" -    $VRF_CMD ntpq -n -c sysinfo -    echo -    echo "=== kerninfo ===" -    $VRF_CMD ntpq -n -c kerninfo -elif [ ! -z $server ]; then -    $VRF_CMD /usr/sbin/ntpdate -q $server +if [ $sourcestats -eq 1 ]; then +    $VRF_CMD chronyc sourcestats -v +elif [ $tracking -eq 1 ]; then +    $VRF_CMD chronyc tracking -v +else +    echo "Unknown option"  fi diff --git a/src/services/api/graphql/libs/op_mode.py b/src/services/api/graphql/libs/op_mode.py index 211f8ce19..c1eb493db 100644 --- a/src/services/api/graphql/libs/op_mode.py +++ b/src/services/api/graphql/libs/op_mode.py @@ -30,7 +30,7 @@ def load_op_mode_as_module(name: str):      return load_as_module(name, path)  def is_op_mode_function_name(name): -    if re.match(r"^(show|clear|reset|restart)", name): +    if re.match(r"^(show|clear|reset|restart|add|delete)", name):          return True      return False diff --git a/src/services/api/graphql/session/errors/op_mode_errors.py b/src/services/api/graphql/session/errors/op_mode_errors.py index 7bc1d1d81..4029fd0a1 100644 --- a/src/services/api/graphql/session/errors/op_mode_errors.py +++ b/src/services/api/graphql/session/errors/op_mode_errors.py @@ -4,12 +4,14 @@ op_mode_err_msg = {      "UnconfiguredSubsystem": "subsystem is not configured or not running",      "DataUnavailable": "data currently unavailable",      "PermissionDenied": "client does not have permission", -    "IncorrectValue": "argument value is incorrect" +    "IncorrectValue": "argument value is incorrect", +    "UnsupportedOperation": "operation is not supported (yet)",  }  op_mode_err_code = {      "UnconfiguredSubsystem": 2000,      "DataUnavailable": 2001,      "PermissionDenied": 1003, -    "IncorrectValue": 1002 +    "IncorrectValue": 1002, +    "UnsupportedOperation": 1004,  } diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server index 60ea9a5ee..f59e089ae 100755 --- a/src/services/vyos-http-api-server +++ b/src/services/vyos-http-api-server @@ -175,6 +175,19 @@ class ImageModel(ApiModel):              }          } +class ContainerImageModel(ApiModel): +    op: StrictStr +    name: StrictStr = None + +    class Config: +        schema_extra = { +            "example": { +                "key": "id_key", +                "op": "add | delete | show", +                "name": "imagename", +            } +        } +  class GenerateModel(ApiModel):      op: StrictStr      path: List[StrictStr] @@ -389,7 +402,7 @@ class MultipartRoute(APIRoute):                  if endpoint in ('/retrieve','/generate','/show','/reset'):                      if request.ERR_NO_OP or request.ERR_NO_PATH:                          return error(400, "Missing required field. \"op\" and \"path\" fields are required") -                if endpoint in ('/config-file', '/image'): +                if endpoint in ('/config-file', '/image', '/container-image'):                      if request.ERR_NO_OP:                          return error(400, "Missing required field \"op\"") @@ -581,6 +594,37 @@ def image_op(data: ImageModel):      return success(res) +@app.post('/container-image') +def image_op(data: ContainerImageModel): +    session = app.state.vyos_session + +    op = data.op + +    try: +        if op == 'add': +            if data.name: +                name = data.name +            else: +                return error(400, "Missing required field \"name\"") +            res = session.add_container_image(name) +        elif op == 'delete': +            if data.name: +                name = data.name +            else: +                return error(400, "Missing required field \"name\"") +            res = session.delete_container_image(name) +        elif op == 'show': +            res = session.show_container_image() +        else: +            return error(400, "\"{0}\" is not a valid operation".format(op)) +    except ConfigSessionError as e: +        return error(400, str(e)) +    except Exception as e: +        logger.critical(traceback.format_exc()) +        return error(500, "An internal error occured. Check the logs for details.") + +    return success(res) +  @app.post('/generate')  def generate_op(data: GenerateModel):      session = app.state.vyos_session | 
